文章目录

  • CryptoUtil工具类
  • CashierPaySignServlet数据处理Servlet
  • sandPayConfig.properties 配置文件
  • web.xml配置
  • pom.xml配置
  • 项目结构

CryptoUtil工具类

/*** 工具类--来自官方Demo*/
package cn.com.sandpay.util;import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.X509Certificate;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;/*** @version 2.0.0* @ClassName: CryptoUtil* @Description: sdk加解密工具类,主要用于签名、验证、RSA加解密等*/public class CryptoUtil {public static Logger logger = LoggerFactory.getLogger(CryptoUtil.class);/*** 数字签名函数入口** @param plainBytes    待签名明文字节数组* @param privateKey    签名使用私钥* @param signAlgorithm 签名算法* @return 签名后的字节数组* @throws Exception*/public static byte[] digitalSign(byte[] plainBytes, PrivateKey privateKey, String signAlgorithm) throws Exception {try {Signature signature = Signature.getInstance(signAlgorithm);signature.initSign(privateKey);signature.update(plainBytes);byte[] signBytes = signature.sign();return signBytes;} catch (NoSuchAlgorithmException e) {throw new Exception(String.format("数字签名时没有[%s]此类算法", signAlgorithm));} catch (InvalidKeyException e) {throw new Exception("数字签名时私钥无效", e);} catch (SignatureException e) {throw new Exception("数字签名时出现异常", e);}}/*** 验证数字签名函数入口** @param plainBytes    待验签明文字节数组* @param signBytes     待验签签名后字节数组* @param publicKey     验签使用公钥* @param signAlgorithm 签名算法* @return 验签是否通过* @throws Exception*/public static boolean verifyDigitalSign(byte[] plainBytes, byte[] signBytes, PublicKey publicKey, String signAlgorithm) throws Exception {boolean isValid = false;try {Signature signature = Signature.getInstance(signAlgorithm);signature.initVerify(publicKey);signature.update(plainBytes);isValid = signature.verify(signBytes);return isValid;} catch (NoSuchAlgorithmException e) {throw new Exception(String.format("验证数字签名时没有[%s]此类算法", signAlgorithm), e);} catch (InvalidKeyException e) {throw new Exception("验证数字签名时公钥无效", e);} catch (SignatureException e) {throw new Exception("验证数字签名时出现异常", e);}}/*** 验证数字签名函数入口** @param plainBytes    待验签明文字节数组* @param signBytes     待验签签名后字节数组* @param signAlgorithm 签名算法* @return 验签是否通过* @throws Exception*/public static boolean verifyDigitalSign(byte[] plainBytes, byte[] signBytes, X509Certificate cert, String signAlgorithm) throws Exception {boolean isValid = false;try {Signature signature = Signature.getInstance(signAlgorithm);signature.initVerify(cert);signature.update(plainBytes);isValid = signature.verify(signBytes);return isValid;} catch (NoSuchAlgorithmException e) {throw new Exception(String.format("验证数字签名时没有[%s]此类算法", signAlgorithm));} catch (InvalidKeyException e) {throw new Exception("验证数字签名时公钥无效", e);} catch (SignatureException e) {throw new Exception("验证数字签名时出现异常", e);}}/*** RSA加密** @param plainBytes      明文字节数组* @param publicKey       公钥* @param keyLength       密钥bit长度* @param reserveSize     padding填充字节数,预留11字节* @param cipherAlgorithm 加解密算法,一般为RSA/ECB/PKCS1Padding* @return 加密后字节数组,不经base64编码* @throws Exception*/public static byte[] RSAEncrypt(byte[] plainBytes, PublicKey publicKey, int keyLength, int reserveSize, String cipherAlgorithm)throws Exception {int keyByteSize = keyLength / 8; // 密钥字节数int encryptBlockSize = keyByteSize - reserveSize; // 加密块大小=密钥字节数-padding填充字节数int nBlock = plainBytes.length / encryptBlockSize;// 计算分段加密的block数,向上取整if ((plainBytes.length % encryptBlockSize) != 0) { // 余数非0,block数再加1nBlock += 1;}try {Cipher cipher = Cipher.getInstance(cipherAlgorithm);cipher.init(Cipher.ENCRYPT_MODE, publicKey);// 输出buffer,大小为nBlock个keyByteSizeByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * keyByteSize);// 分段加密for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) {int inputLen = plainBytes.length - offset;if (inputLen > encryptBlockSize) {inputLen = encryptBlockSize;}// 得到分段加密结果byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen);// 追加结果到输出buffer中outbuf.write(encryptedBlock);}outbuf.flush();outbuf.close();return outbuf.toByteArray();} catch (NoSuchAlgorithmException e) {throw new Exception(String.format("没有[%s]此类加密算法", cipherAlgorithm));} catch (NoSuchPaddingException e) {throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm));} catch (InvalidKeyException e) {throw new Exception("无效密钥", e);} catch (IllegalBlockSizeException e) {throw new Exception("加密块大小不合法", e);} catch (BadPaddingException e) {throw new Exception("错误填充模式", e);} catch (IOException e) {throw new Exception("字节输出流异常", e);}}/*** RSA解密** @param encryptedBytes  加密后字节数组* @param privateKey      私钥* @param keyLength       密钥bit长度* @param reserveSize     padding填充字节数,预留11字节* @param cipherAlgorithm 加解密算法,一般为RSA/ECB/PKCS1Padding* @return 解密后字节数组,不经base64编码* @throws Exception*/public static byte[] RSADecrypt(byte[] encryptedBytes, PrivateKey privateKey, int keyLength, int reserveSize, String cipherAlgorithm)throws Exception {int keyByteSize = keyLength / 8; // 密钥字节数int decryptBlockSize = keyByteSize - reserveSize; // 解密块大小=密钥字节数-padding填充字节数int nBlock = encryptedBytes.length / keyByteSize;// 计算分段解密的block数,理论上能整除try {Cipher cipher = Cipher.getInstance(cipherAlgorithm);cipher.init(Cipher.DECRYPT_MODE, privateKey);// 输出buffer,大小为nBlock个decryptBlockSizeByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * decryptBlockSize);// 分段解密for (int offset = 0; offset < encryptedBytes.length; offset += keyByteSize) {// block大小: decryptBlock 或 剩余字节数int inputLen = encryptedBytes.length - offset;if (inputLen > keyByteSize) {inputLen = keyByteSize;}// 得到分段解密结果byte[] decryptedBlock = cipher.doFinal(encryptedBytes, offset, inputLen);// 追加结果到输出buffer中outbuf.write(decryptedBlock);}outbuf.flush();outbuf.close();return outbuf.toByteArray();} catch (NoSuchAlgorithmException e) {throw new Exception(String.format("没有[%s]此类解密算法", cipherAlgorithm));} catch (NoSuchPaddingException e) {throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm));} catch (InvalidKeyException e) {throw new Exception("无效密钥", e);} catch (IllegalBlockSizeException e) {throw new Exception("解密块大小不合法", e);} catch (BadPaddingException e) {throw new Exception("错误填充模式", e);} catch (IOException e) {throw new Exception("字节输出流异常", e);}}public static PublicKey toPublicKey(BigInteger exponent, BigInteger modulus) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance("RSA");RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modulus, exponent);PublicKey key = keyFactory.generatePublic(pubSpec);return key;}public static PrivateKey toPrivateKey(BigInteger exponent, BigInteger modulus) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance("RSA");RSAPrivateKeySpec prispec = new RSAPrivateKeySpec(modulus, exponent);PrivateKey key = keyFactory.generatePrivate(prispec);return key;}/*** AES加密** @param plainBytes      明文字节数组* @param keyBytes        密钥字节数组* @param keyAlgorithm    密钥算法* @param cipherAlgorithm 加解密算法* @param IV              随机向量* @return 加密后字节数组,不经base64编码* @throws Exception*/public static byte[] AESEncrypt(byte[] plainBytes, byte[] keyBytes, String keyAlgorithm, String cipherAlgorithm, String IV)throws Exception {try {// AES密钥长度为128bit、192bit、256bit,默认为128bitif (keyBytes.length % 8 != 0 || keyBytes.length < 16 || keyBytes.length > 32) {throw new Exception("AES密钥长度不合法");}Cipher cipher = Cipher.getInstance(cipherAlgorithm);SecretKey secretKey = new SecretKeySpec(keyBytes, keyAlgorithm);if (StringUtils.trimToNull(IV) != null) {IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes());cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);} else {cipher.init(Cipher.ENCRYPT_MODE, secretKey);}byte[] encryptedBytes = cipher.doFinal(plainBytes);return encryptedBytes;} catch (NoSuchAlgorithmException e) {throw new Exception(String.format("没有[%s]此类加密算法", cipherAlgorithm));} catch (NoSuchPaddingException e) {throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm));} catch (InvalidKeyException e) {throw new Exception("无效密钥", e);} catch (InvalidAlgorithmParameterException e) {throw new Exception("无效密钥参数", e);} catch (BadPaddingException e) {throw new Exception("错误填充模式", e);} catch (IllegalBlockSizeException e) {throw new Exception("加密块大小不合法", e);}}/*** AES解密** @param encryptedBytes  密文字节数组,不经base64编码* @param keyBytes        密钥字节数组* @param keyAlgorithm    密钥算法* @param cipherAlgorithm 加解密算法* @param IV              随机向量* @return 解密后字节数组* @throws Exception*/public static byte[] AESDecrypt(byte[] encryptedBytes, byte[] keyBytes, String keyAlgorithm, String cipherAlgorithm, String IV)throws Exception {try {// AES密钥长度为128bit、192bit、256bit,默认为128bitif (keyBytes.length % 8 != 0 || keyBytes.length < 16 || keyBytes.length > 32) {throw new Exception("AES密钥长度不合法");}Cipher cipher = Cipher.getInstance(cipherAlgorithm);SecretKey secretKey = new SecretKeySpec(keyBytes, keyAlgorithm);if (IV != null && StringUtils.trimToNull(IV) != null) {IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes());cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec);} else {cipher.init(Cipher.DECRYPT_MODE, secretKey);}byte[] decryptedBytes = cipher.doFinal(encryptedBytes);return decryptedBytes;} catch (NoSuchAlgorithmException e) {throw new Exception(String.format("没有[%s]此类加密算法", cipherAlgorithm));} catch (NoSuchPaddingException e) {throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm));} catch (InvalidKeyException e) {throw new Exception("无效密钥", e);} catch (InvalidAlgorithmParameterException e) {throw new Exception("无效密钥参数", e);} catch (BadPaddingException e) {throw new Exception("错误填充模式", e);} catch (IllegalBlockSizeException e) {throw new Exception("解密块大小不合法", e);}}public static byte[] hexString2ByteArr(String hexStr) {return new BigInteger(hexStr, 16).toByteArray();}public static final byte[] hexStrToBytes(String s) {byte[] bytes;bytes = new byte[s.length() / 2];for (int i = 0; i < bytes.length; i++) {bytes[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2), 16);}return bytes;}/*** 字符数组16进制字符** @param bytes* @return*/public static String bytes2string(byte[] bytes, int radix) {int size = 2;if (radix == 2) {size = 8;}StringBuilder sb = new StringBuilder(bytes.length * size);for (int i = 0; i < bytes.length; i++) {int integer = bytes[i];while (integer < 0) {integer = integer + 256;}String str = Integer.toString(integer, radix);sb.append(StringUtils.leftPad(str.toUpperCase(), size, "0"));}return sb.toString();}
}

CashierPaySignServlet数据处理Servlet

package cn.com.sandpay.demo;import cn.com.sand.pay.online.sdk.encrypt.CertUtil;
import cn.com.sand.pay.online.sdk.util.ConfigurationManager;
import cn.com.sand.pay.online.sdk.util.DynamicPropertyHelper;
import cn.com.sandpay.util.CryptoUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;/*** 支付下单签名方法** @author sandpay*/
public class CashierPaySignServlet extends HttpServlet {private static final Logger logger = LoggerFactory.getLogger(CashierPaySignServlet.class);private static final long serialVersionUID = 1L;/*** 加载公私钥并初始化*/@Overridepublic void init() throws ServletException {super.init();try {ConfigurationManager.loadProperties(new String[]{"sandPayConfig"});} catch (Exception e) {e.printStackTrace();}}//开放get请求方式@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) {Map<String, String[]> params = req.getParameterMap();Map<String, String> map = new HashMap<String, String>();for (String key : params.keySet()) {String[] values = params.get(key);if (values.length > 0) {map.put(key, values[0]);}}Object ddd=JSONObject.toJSON(map);System.out.println("==================="+ddd.toString());//报文由头部(公共参数),主体部分(商户参数)组成// 组后台报文JSONObject head = new JSONObject();//版本号//head.put("version", map.get("version"));head.put("version", "1.0");//接口名称//head.put("method", map.get("method"));head.put("method", "sandpay.trade.orderCreate");//产品编码//head.put("productId", map.get("productId"));head.put("productId", "00002000");//接入类型//head.put("accessType", map.get("accessType"));head.put("accessType", "1");//商户id//head.put("mid", map.get("mid"));head.put("mid", "100211701160001");//平台id//head.put("plMid", map.get("plMid"));head.put("plMid", "");//渠道类型07互联网08移动端//head.put("channelType", map.get("channelType"));head.put("channelType", "07");//请求时间 格式:yyyyMMddhhmmss//head.put("reqTime", map.get("reqTime"));head.put("reqTime", "20191030164628");//主体部分JSONObject body = new JSONObject();//商户订单号body.put("orderCode", map.get("orderCode"));//付款方idbody.put("userId", map.get("userId"));//订单金额body.put("totalAmount", map.get("totalAmount"));//订单标题body.put("subject", map.get("subject"));//订单描述//订单信息详细描述JSON格式:{mallOrderCode:商城订单号 receiveAddress:收货地址 goodsDesc:商品描述 }body.put("body", map.get("body"));//订单超时时间body.put("txnTimeOut", map.get("txnTimeOut"));//支付方式列表body.put("payModeList", map.get("payModeList"));//异步通知地址body.put("notifyUrl", map.get("notifyUrl"));//前台通知地址body.put("frontUrl", map.get("frontUrl"));//商户门店编号body.put("storeId", map.get("storeId"));//商户终端标号body.put("terminalId", map.get("terminalId"));//操作员编号body.put("operatorId", map.get("operatorId"));//清算模式body.put("clearCycle", map.get("clearCycle"));//入账模式body.put("accountingMode", map.get("accountingMode"));//风控信息域body.put("riskRateInfo", map.get("riskRateInfo"));//业务扩展参数body.put("bizExtendParams", map.get("bizExtendParams"));//商户扩展参数body.put("merchExtendParams", map.get("merchExtendParams"));//扩展域body.put("extend", map.get("extend"));//传入参数示例
//        //订单描述
//        JSONObject test = new JSONObject();
//        test.put("mallOrderCode","mall00000000001");
//        test.put("receiveAddress","上海市徐汇区田林路487号宝石园22号2楼");
//        test.put("goodsDesc","杉德卡1张");//        JSONObject body = new JSONObject();
//        body.put("orderCode", "sandpay20191030164628");
//        body.put("userId", "C0908992");
//        body.put("totalAmount", "000000000001");
//        body.put("subject", "杉德收银台统测试订单标题");
//        body.put("body",test);
//        body.put("txnTimeOut", "");
//        body.put("payModeList", "[b2b,b2c,qrpay,qppay,rempay]");
//        body.put("notifyUrl", "http://127.0.0.1/WebGateway/stateChangeServlet");
//        body.put("frontUrl", "http://61.129.71.103:8003/jspsandpay/payReturn.jsp");
//        body.put("storeId", "shmdbh001");
//        body.put("terminalId", "shzdbh001");
//        body.put("operatorId", "czybh001");
//        body.put("clearCycle", "0");
//        body.put("accountingMode", "02");
//        body.put("riskRateInfo", "fkxxy");
//        body.put("bizExtendParams", "yykzcs");
//        body.put("merchExtendParams", "shkzcs");
//        body.put("extend", "kzy");JSONObject data = new JSONObject();data.put("head", head);data.put("body", body);try {// 获取报文签名String reqSign = digitalSign(data.toJSONString());JSONObject respJson = new JSONObject();//写入参数和签名respJson.put("data", JSON.toJSONString(data));respJson.put("sign", reqSign);//重定向请求到上的支付收银台接口resp.sendRedirect("https://cashier.sandpay.com.cn/gw/web/order/create?charset=UTF-8&data="+JSON.toJSONString(data)+"&signType=01&sign="+reqSign+"&extend=kzy");} catch (Exception e) {logger.error("CashierPayServlet post error <<<", e);}}/*** 签名方法** @param data 待签名数据* @return* @throws Exception*/public static String digitalSign(String data) throws Exception {if (null == data) {return null;} else {try {// 获取密钥配置String publicKeyPath = DynamicPropertyHelper.getStringProperty("sandpay.public.key", "").get();String privateKeyPath = DynamicPropertyHelper.getStringProperty("sandpay.private.key", "").get();String keyPassword = DynamicPropertyHelper.getStringProperty("sandpay.private.key.password", "").get();// 初始化密钥信息CertUtil.init(publicKeyPath, privateKeyPath, keyPassword);byte[] dataBytes = data.getBytes("UTF-8");// 签名String signData = new String(Base64.encodeBase64(CryptoUtil.digitalSign(dataBytes, CertUtil.getPrivateKey(), "SHA1WithRSA")), "UTF-8");logger.info("digitalSign(String) =>>sign:{}", signData);return URLEncoder.encode(signData, "UTF-8");} catch (Exception var6) {logger.error("digitalSign(String, String)", var6);throw new Exception("签名异常", var6);}}}
}

sandPayConfig.properties 配置文件

#--杉德公钥-放入resources目录下的对应公钥文件
sandpay.public.key=classpath:sand.cer#--商户号对应的私钥和密码-放入resources目录下的对应私钥文件
sandpay.private.key=classpath:MID_RSA_PRIVATE_KEY_100211701160001.pfx
##--私钥密码--导出私钥时设置的密码--导出方法官方有介绍
sandpay.private.key.password=123456#--商户基础信息
#sandpay.merch.mid=16640704
sandpay.merch.mid=S6848437//商户号
sandpay.merch.plmid=           //平台商户号
sandpay.merch.productcode=00002000     //平台编号#--支付网关地址
sandpay.gateWay.url=https://cashier.sandpay.com.cn/gw/
sandpay.gateWay.front.url=http://商户前台跳转地址
sandpay.gateWay.backnotice.url=http\://\u00E5\u0095\u0086\u00E6\u0088\u00B7\u00E5\u0090\u008E\u00E7\u00AB\u00AF\u00E9\u0080\u009A\u00E7\u009F\u00A5\u00E6\u008E\u00A5\u00E6\u0094\u00B6\u00E5\u009C\u00B0\u00E5\u009D\u0080

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"id="WebApp_ID" version="3.0">//设置servlet为启动项<welcome-file-list><welcome-file>/cashierPay</welcome-file><welcome-file>/cashierPay</welcome-file></welcome-file-list><servlet><servlet-name>cashierPay</servlet-name><servlet-class>cn.com.sandpay.demo.CashierPaySignServlet</servlet-class></servlet><servlet-mapping><servlet-name>cashierPay</servlet-name><url-pattern>/cashierPay</url-pattern></servlet-mapping></web-app>

pom.xml配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.com.sand.pay</groupId><artifactId>sandpay-cashier-demo</artifactId><version>1.0.0</version><packaging>war</packaging><name>sandpay-cashier-demo</name><url>http://maven.apache.org</url><repositories><repository><id>mvnrepository2</id><url>http://172.28.250.84:8084/nexus/content/groups/public/</url></repository></repositories><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!-- 测试核心包 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version></dependency><!-- servlet核心包 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!-- http核心包 --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.4.1</version></dependency><!-- 接口集成sdk --><dependency><groupId>cn.com.sand.pay</groupId><artifactId>sandpay-online-sdk</artifactId><version>2.0.1</version><scope>system</scope><systemPath>${project.basedir}/sandpay-online-sdk-2.0.1.jar</systemPath></dependency><!-- fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.3</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>com.netflix.archaius</groupId><artifactId>archaius-core</artifactId><version>0.6.0</version></dependency><dependency><groupId>net.iharder</groupId><artifactId>base64</artifactId><version>2.3.9</version></dependency><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.13</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency></dependencies><build><plugins><!-- compiler插件, 设定JDK版本 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.7</source><target>1.7</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.mortbay.jetty</groupId><artifactId>maven-jetty-plugin</artifactId><version>6.1.26</version><configuration><stopKey>foo</stopKey><stopPort>9966</stopPort><scanIntervalSeconds>10</scanIntervalSeconds><connectors><connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"><port>8081</port><maxIdleTime>60000</maxIdleTime></connector></connectors></configuration></plugin><plugin><artifactId>maven-resources-plugin</artifactId><configuration><nonFilteredFileExtensions><nonFilteredFileExtension>pfx</nonFilteredFileExtension><nonFilteredFileExtension>cer</nonFilteredFileExtension></nonFilteredFileExtensions></configuration></plugin></plugins></build></project>

项目结构



注意在搭建项目时使用阿里maven仓库。对应官方sdk请自行下载。

杉德支付收银台支付Demo解析,聚合支付相关推荐

  1. 2022最新独立版智狐聚合支付v1.0.5.21_聚合支付系统源码

    源码下载:2022最新独立版智狐聚合支付v1.0.5.21_聚合支付系统源码-小程序文档类资源-CSDN下载 PHP聚合支付源码 独立版智狐聚合支付v1.0.5.21 1.在宝塔新建个站点,php版本 ...

  2. 2020支付行业七大预测:聚合支付牌照有望正式落地

    2020年的支付行业将迈入高质量发展阶段, 未来支付机构的发展应该更重视质量.效益.效率.以科技金融为基础的"支付+生态"的业务模式对行业影响会日益加深,支付行业的竞争不再是单一维 ...

  3. 支付精灵-支付宝-微信-聚合支付-给大家分享一个聚合支付的工具

    想必很多人个人开发者和我有同样的感触,想要在自己开发的app中接入微信支付和支付宝支付,仅仅是去申请支付接口就把我们挡在了门外,微信和支付宝都只对接企业的,那不是想逼死我们个人开发者吗?一开始使用过w ...

  4. php支付宝聚合支付源码,ThinkPHP5.1聚合支付源码

    资源介绍 目前已经接入支付渠道:微信(扫码支付).支付宝(电脑网站支付.手机网站支付): ### 项目结构 ``` project                             应用部署目录 ...

  5. 小微支付平台,支付宝/微信聚合支付

    前言 现在如果产品要接入支付,支付宝和微信都规定必须公司才能申请,对个人而言就没办法了. 小微支付平台 最近在使用一个小微支付平台,感觉还不错,在这里上些干货. 官方介绍:微豆付平台 官方清算 / 安 ...

  6. 【支付专区】之解析微信支付返回xml

    public static Map<String,Object> parseBodyXml2Map(String xml){Map<String,Object> map = n ...

  7. 聚合支付码 一码支付的大时代到来

    一码支付也叫"聚合支付",就是一个将多种互联网移动支付方式整合起来的支付交易接口,简称聚合支付码它借助银行.非银行支付机构以及转接清算组织组织的支付通道,通过自身技术与服务的集成, ...

  8. 聚合支付收款码怎么申请

    目前消费者的付款方式多样,聚合支付成了商家的必须,不然得来回切换收款方式,这是很麻烦的.聚合支付收款码可以避免在一个收银台放置较多二维码,节省了空间.而且避免了提现,直接进入银行卡后可以让用户及时了解 ...

  9. 银联--网联--聚合支付

    易联和网联的区别 说起银联相信大家都不会陌生,但是谈及"网联"相信大家并不那么了解,其实"网联"与银联相似,是个清算平台. 银联,它是线下刷银行卡时的清算平台. ...

  10. 聚合支付”为什么很多游戏商家选择他

    一个小游戏运营商,接入一个微信支付,支付宝支付,需要的流程 1.官方申请微信支付,首先先申请个微信服务号,然后再缴费300元支付开通微信支付,如果是游戏的,还需要国家网络文化经营许可证,有些企业并不具 ...

最新文章

  1. 收藏!最新大数据产业地图 十大生态金矿百大公司起底【附下载】
  2. WebSocket 学习
  3. 【Linux】时间同步设置+防火墙设置+SELinux设置
  4. 国际10-20标准电极位置
  5. [Swift]LeetCode388. 文件的最长绝对路径 | Longest Absolute File Path
  6. 【UEditor】自定义插件:按钮
  7. uploadify HTTP 302 错误如何解决?
  8. 生成跨语言的类型声明和接口绑定的工具(Djinni )
  9. CSV格式数据如何导入MySQL?
  10. Axios实现异步通信
  11. signature=4abdf782f13579fc1b57d94a0c6ce95c,β-lactam-associated eosinophilic colitis
  12. HiveSQL解析过程详解
  13. 远程控制软件和木马的区别——病毒木马 001
  14. 各种门锁的内部结构图_有没有这种执手门锁的内部结构图?
  15. 中职计算机专业英语说课稿,中职英语基础模块说课
  16. C++用户的Cplex使用指南(三)——Cutting stock problem求解
  17. Android Library的创建及使用详解
  18. 冯提出的计算机工作原理是,冯诺依曼提出的计算机的基本工作原理是什么
  19. JPA、Hibernate和Spring Data JPA区别
  20. NEO4J的安装配置及使用总结

热门文章

  1. mvc 路由 .html 404,部署ASP.NET的MVC网站到IIS 6.0中,发现路由无法解析而出现404错误解决方案...
  2. “缺位”已久的欧洲,正在补齐自动驾驶这门课
  3. win10安装vue
  4. 中软国际实训全记录——第七天
  5. 免ROOT使用Frida(不修改源代码)
  6. root才能修改数据的软件,root怎么修改
  7. 【NOJ1326】【算法实验三】推箱子
  8. 京东618是失守还是主动放弃开辟新战略,今年的店庆不是618
  9. “任何特殊资源”都能搜,可别乱搜哦~
  10. python图片横向合并_使用python进行图片横向拼接