杉德支付收银台支付Demo解析,聚合支付
文章目录
- 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解析,聚合支付相关推荐
- 2022最新独立版智狐聚合支付v1.0.5.21_聚合支付系统源码
源码下载:2022最新独立版智狐聚合支付v1.0.5.21_聚合支付系统源码-小程序文档类资源-CSDN下载 PHP聚合支付源码 独立版智狐聚合支付v1.0.5.21 1.在宝塔新建个站点,php版本 ...
- 2020支付行业七大预测:聚合支付牌照有望正式落地
2020年的支付行业将迈入高质量发展阶段, 未来支付机构的发展应该更重视质量.效益.效率.以科技金融为基础的"支付+生态"的业务模式对行业影响会日益加深,支付行业的竞争不再是单一维 ...
- 支付精灵-支付宝-微信-聚合支付-给大家分享一个聚合支付的工具
想必很多人个人开发者和我有同样的感触,想要在自己开发的app中接入微信支付和支付宝支付,仅仅是去申请支付接口就把我们挡在了门外,微信和支付宝都只对接企业的,那不是想逼死我们个人开发者吗?一开始使用过w ...
- php支付宝聚合支付源码,ThinkPHP5.1聚合支付源码
资源介绍 目前已经接入支付渠道:微信(扫码支付).支付宝(电脑网站支付.手机网站支付): ### 项目结构 ``` project 应用部署目录 ...
- 小微支付平台,支付宝/微信聚合支付
前言 现在如果产品要接入支付,支付宝和微信都规定必须公司才能申请,对个人而言就没办法了. 小微支付平台 最近在使用一个小微支付平台,感觉还不错,在这里上些干货. 官方介绍:微豆付平台 官方清算 / 安 ...
- 【支付专区】之解析微信支付返回xml
public static Map<String,Object> parseBodyXml2Map(String xml){Map<String,Object> map = n ...
- 聚合支付码 一码支付的大时代到来
一码支付也叫"聚合支付",就是一个将多种互联网移动支付方式整合起来的支付交易接口,简称聚合支付码它借助银行.非银行支付机构以及转接清算组织组织的支付通道,通过自身技术与服务的集成, ...
- 聚合支付收款码怎么申请
目前消费者的付款方式多样,聚合支付成了商家的必须,不然得来回切换收款方式,这是很麻烦的.聚合支付收款码可以避免在一个收银台放置较多二维码,节省了空间.而且避免了提现,直接进入银行卡后可以让用户及时了解 ...
- 银联--网联--聚合支付
易联和网联的区别 说起银联相信大家都不会陌生,但是谈及"网联"相信大家并不那么了解,其实"网联"与银联相似,是个清算平台. 银联,它是线下刷银行卡时的清算平台. ...
- 聚合支付”为什么很多游戏商家选择他
一个小游戏运营商,接入一个微信支付,支付宝支付,需要的流程 1.官方申请微信支付,首先先申请个微信服务号,然后再缴费300元支付开通微信支付,如果是游戏的,还需要国家网络文化经营许可证,有些企业并不具 ...
最新文章
- 收藏!最新大数据产业地图 十大生态金矿百大公司起底【附下载】
- WebSocket 学习
- 【Linux】时间同步设置+防火墙设置+SELinux设置
- 国际10-20标准电极位置
- [Swift]LeetCode388. 文件的最长绝对路径 | Longest Absolute File Path
- 【UEditor】自定义插件:按钮
- uploadify HTTP 302 错误如何解决?
- 生成跨语言的类型声明和接口绑定的工具(Djinni )
- CSV格式数据如何导入MySQL?
- Axios实现异步通信
- signature=4abdf782f13579fc1b57d94a0c6ce95c,β-lactam-associated eosinophilic colitis
- HiveSQL解析过程详解
- 远程控制软件和木马的区别——病毒木马 001
- 各种门锁的内部结构图_有没有这种执手门锁的内部结构图?
- 中职计算机专业英语说课稿,中职英语基础模块说课
- C++用户的Cplex使用指南(三)——Cutting stock problem求解
- Android Library的创建及使用详解
- 冯提出的计算机工作原理是,冯诺依曼提出的计算机的基本工作原理是什么
- JPA、Hibernate和Spring Data JPA区别
- NEO4J的安装配置及使用总结
热门文章
- mvc 路由 .html 404,部署ASP.NET的MVC网站到IIS 6.0中,发现路由无法解析而出现404错误解决方案...
- “缺位”已久的欧洲,正在补齐自动驾驶这门课
- win10安装vue
- 中软国际实训全记录——第七天
- 免ROOT使用Frida(不修改源代码)
- root才能修改数据的软件,root怎么修改
- 【NOJ1326】【算法实验三】推箱子
- 京东618是失守还是主动放弃开辟新战略,今年的店庆不是618
- “任何特殊资源”都能搜,可别乱搜哦~
- python图片横向合并_使用python进行图片横向拼接