参考自   https://blog.csdn.net/a1036645146/article/details/100585393

chinapay不是银联支付 , chinapay不是银联支付, chinapay不是银联支付

重要的事情说三遍, chinapay 是银联的一部分 接口对接方式相仿但完全是另一套操作流程

此文主要为记录最后的注意点 代码次要,

公共方法:

 // 验签@Overridepublic Boolean verifyNotify(Map<String, String> notifyMap, PayTypeEnum payTypeEnum) throws Exception {SecssUtil secssUtil = ChinaPayUtil.secssUtil;try {//验签String sign = notifyMap.get("Signature");if (!StringUtils.isEmpty(sign)) {secssUtil.verify(notifyMap);//入参:返回商户报文中的所有参数}if (!SecssConstants.SUCCESS.equals(secssUtil.getErrCode())) {log.error(secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());log.info("ChinaPay返回的应答数据【验签】失败:{}", secssUtil.getErrMsg());return false;}return true;} catch (Exception e) {e.printStackTrace();}return null;}/*** @Description 获取签名* @param paramMap  发送请求时携带的参数**/private void getSign(Map<String,Object> paramMap) {//签名SecssUtil secssUtil = ChinaPayUtil.secssUtil;secssUtil.sign(paramMap);if (!SecssConstants.SUCCESS.equals(secssUtil.getErrCode())) {log.error("ChinaPay签名失败:" + secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());throw new ValidateException("签名失败:" + secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());}String signature = secssUtil.getSign();paramMap.put("Signature", signature);}/*** @Description 接口返回参数转map* @param resp      response返回参数**/private Map<String, String> getRespMap(String resp) {if (resp == null) {return new HashMap();}
//        log.info("################交易查询结果, 解码后:{}", respDec);Map<String, String> resultMap = new TreeMap<String, String>();for (String str : resp.split("&", -1)) {String[] keyValues = str.split("=", -1);if (keyValues.length < 2) {continue;}String key = keyValues[0];String value = keyValues[1];if (StringUtils.isEmpty(value)) {continue;}//响应字段解码try {value = URLDecoder.decode(value, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}resultMap.put(key, value);}return resultMap;}/*** @Description 将有卡交易信息域 加密* @param cardTranData  有卡交易信息域数据**/private String encryptCardTranData(JSONObject cardTranData ){// 有卡交易信息域 base64编码后 RSA加密String cardTranDataStr = cardTranData.toJSONString();String cardTranDataBase64 = Base64.getEncoder().encodeToString((cardTranDataStr == null ? "" : cardTranDataStr).getBytes());ChinaPayUtil.secssUtil.encryptData(cardTranDataBase64);return ChinaPayUtil.secssUtil.getEncValue();}/*** @Description 将返回的有卡交易信息域 解密* @param cardTranData  有卡交易信息域数据**/private JSONObject decryptCardTranData(String cardTranData){// 有卡交易信息域 在应答中获取我司返回的该字段后,采用 RSA 解密,再 Base64 解码,解密时// 调用方法 decryptData,调用 getDecValue 获取解密后的结果// 文档中上面两句话是在 噗噗噗 不用管log.info("有卡交易信息域 解密 前参数: " + cardTranData);String value = null;ChinaPayUtil.secssUtil.decryptData(cardTranData);if (SecssConstants.SUCCESS.equals(ChinaPayUtil.secssUtil.getErrCode())) {value = ChinaPayUtil.secssUtil.getDecValue();} else {throw new ValidateException(ChinaPayUtil.secssUtil.getErrMsg());}log.info("有卡交易信息域 解密 后参数: " + value);return JSONObject.parseObject(value);}private static RequestConfig requestConfig;private static PoolingHttpClientConnectionManager connMgr;/*** 发送 SSL POST 请求(HTTPS),K-V形式** @param apiUrl API接口URL* @param params 参数map*/public static String doPostSSL(String apiUrl, Map<String, Object> params, Map<String, String> headers) {CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();HttpPost httpPost = new HttpPost(apiUrl);CloseableHttpResponse response = null;String httpStr = null;try {List<NameValuePair> pairList = new ArrayList<NameValuePair>(params.size());for (Map.Entry<String, Object> entry : params.entrySet()) {NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue().toString());pairList.add(pair);}httpPost.setEntity(new UrlEncodedFormEntity(pairList, StandardCharsets.UTF_8));if (headers != null) {for (String key : headers.keySet()) {httpPost.setHeader(key, headers.get(key));}}response = httpClient.execute(httpPost);int statusCode = response.getStatusLine().getStatusCode();if (statusCode != HttpStatus.SC_OK) {return null;}HttpEntity entity = response.getEntity();if (entity == null) {return null;}httpStr = EntityUtils.toString(entity, "utf-8");} catch (Exception e) {log.error(e.getMessage(), e);} finally {if (response != null) {try {EntityUtils.consume(response.getEntity());} catch (IOException e) {log.error(e.getMessage(), e);}}}return httpStr;}/*** 创建SSL安全连接** @return*/private static SSLConnectionSocketFactory createSSLConnSocketFactory() {SSLConnectionSocketFactory sslsf = null;try {SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial(null, (chain, authType) -> true).build();sslsf = new SSLConnectionSocketFactory(sslContext);} catch (GeneralSecurityException e) {log.error(e.getMessage(), e);}return sslsf;}

请求代码如下

1.签约查询接口

// 签约查询接口@Overridepublic ResponseResult querySign(String bankCardNo) {Map<String, Object> paramMap = new TreeMap<>();paramMap.put("Version", "20150922");paramMap.put("MerId", chinaPayConfig.getMerId());paramMap.put("BusiType", "0001");// 业务类型,固定值paramMap.put("TranType", "0504");// 交易类型,固定值:0504paramMap.put("OriTranType", "9904");// 待查交易类型: 9901 认证开通 9904 快捷签约 9910 商业委托签约JSONObject cardTranData = new JSONObject();cardTranData.put("CardNo", bankCardNo);paramMap.put("CardTranData", encryptCardTranData(cardTranData));// 有卡交易信息域getSign(paramMap);log.info("################签约查询接口, 请求报文:{}", paramMap);Map<String, String> headerMap = new HashMap<>();String resp = HttpClientUtil.doPostSSL(chinaPayConfig.getBackUrl(), paramMap, headerMap);// 解析同步应答字段if (resp == null) {throw new ValidateException("签约查询接口返回错误");}Map<String, String> resultMap = getRespMap(resp);if (!resultMap.get("respCode").equals("0000")) {return ResponseResult.errorResult("签约查询接口错误", new ValidateException(resultMap.get("respCode") + resultMap.get("respMsg")));}if (resultMap.get("SignState").equals("01")) {  // 签约状态 00 未签约 01 签约成功if (resultMap.containsKey("CardTranData")){resultMap.put("CardTranData", decryptCardTranData(resultMap.get("CardTranData")).toJSONString());log.info("################签约查询接口, 已签约返回报文, 解码后:{}", resultMap);}Map<String, String> dealFactorMap = queryDealFactor(bankCardNo, "0004");return ResponseResult.successResult(dealFactorMap, "已签约");}log.info("################签约查询接口, 未签约返回报文:{}", resultMap);Map<String, String> dealFactorMap = queryDealFactor(bankCardNo, "9904");return ResponseResult.successResult(dealFactorMap, "查询成功");}

2.交易要素查询接口

/*** @Description  交易要素查询接口* @param   bankCardNo 银行卡号* @return void* @Author dongxiangwei* @Date 13:57 2021/4/20**/private Map<String, String> queryDealFactor(String bankCardNo, String oriTranType){Map<String, Object> paramMap = new TreeMap<>();paramMap.put("Version", "20150922");paramMap.put("MerId", chinaPayConfig.getMerId());paramMap.put("BusiType", "0001");// 业务类型,固定值paramMap.put("TranType", "0505");// 交易类型 0505 支付要素查询paramMap.put("OriTranType", oriTranType);// 待查交易类型 9904 快捷签约 0004 快捷支付JSONObject cardTranData = new JSONObject();cardTranData.put("CardNo", bankCardNo);paramMap.put("CardTranData", encryptCardTranData(cardTranData));// 有卡交易信息域getSign(paramMap);log.info("==============交易要素查询接口, 请求报文: {}", paramMap);Map<String, String> headerMap = new HashMap<>();String resp = HttpClientUtil.doPostSSL(chinaPayConfig.getBackUrl(), paramMap, headerMap);// 解析同步应答字段if (resp == null) {throw new ValidateException("交易要素查询接口 返回null");}Map<String, String> resultMap = getRespMap(resp);log.info("################交易要素查询接口, 返回报文:{}", resultMap);if (!resultMap.containsKey("respCode") || !resultMap.get("respCode").equals("0000")) {throw new ValidateException(resultMap.get("respMsg"));}return resultMap;}

3.签约短信接口

// 签约短信接口@Overridepublic ResponseResult signSms(ChinaPaySignVo chinaPaySignVo){Order order = orderMapper.selectByPrimaryKey(chinaPaySignVo.getOrderId());Assert.notNull(order, "该订单不存在");String signNum = order.getSignNum();Assert.notNull(signNum, "签约号不存在, 请重新下单后再发送签约短信");Map<String, Object> paramMap = new TreeMap<>();paramMap.put("Version", "20150922");                // 版本号paramMap.put("MerId", chinaPayConfig.getMerId());   // 商户号paramMap.put("MerOrderNo", signNum);    // 商户签约号paramMap.put("TranDate", DateUtil.getFormatTime(order.getCreateTime(), "yyyyMMdd"));    // 商户交易日期paramMap.put("TranTime", DateUtil.getFormatTime(order.getCreateTime(), "HHmmss"));  // 商户交易时间paramMap.put("BusiType", "0001");// 业务类型,固定值paramMap.put("TranType", "0608");// 交易类型 0608 快捷签约短信JSONObject cardTranData = new JSONObject();cardTranData.put("CertNo", chinaPaySignVo.getCertNo());cardTranData.put("CardNo", chinaPaySignVo.getCardNo());cardTranData.put("CertType", chinaPaySignVo.getCertType());cardTranData.put("AccName", chinaPaySignVo.getAccName());cardTranData.put("MobileNo", chinaPaySignVo.getMobileNo());// 这三项返回项 不需要 加上后会导致短信发送错误
//        cardTranData.put("FrontFlag", "1");
//        cardTranData.put("SmsFlag", "00");
//        cardTranData.put("ParamKey", "SignAndPayFlag");log.info("--------------签约短信接口, CardTranData: {}", cardTranData);paramMap.put("CardTranData", encryptCardTranData(cardTranData));// 有卡交易信息域getSign(paramMap);log.info("==============签约短信接口, 请求报文: {}", paramMap);Map<String, String> headerMap = new HashMap<>();String resp = HttpClientUtil.doPostSSL(chinaPayConfig.getBackUrl(), paramMap, headerMap);// 解析同步应答字段if (resp == null) {throw new ValidateException("签约短信接口 返回null");}Map<String, String> resultMap = getRespMap(resp);log.info("################签约短信接口, 返回报文:{}", resultMap);if (!resultMap.containsKey("respCode") || !resultMap.get("respCode").equals("0000")) {throw new ValidateException(resultMap.get("respMsg"));}return ResponseResult.successResult(resultMap, resultMap.get("respMsg"));}

4.签约接口

// 签约接口// 签约规则: 一个银行卡号 对应一个签约协议号, 与解不解绑无关@Overridepublic ResponseResult signBankCard(ChinaPaySignVo chinaPaySignVo){Order order = orderMapper.selectByPrimaryKey(chinaPaySignVo.getOrderId());Assert.notNull(order, "该订单不存在");String signNum = order.getSignNum();Assert.notNull(signNum, "签约号不存在, 请重新下单后再进行签约操作");Map<String, Object> paramMap = new TreeMap<>();paramMap.put("Version", "20150922");                // 版本号paramMap.put("MerId", chinaPayConfig.getMerId());   // 商户号paramMap.put("MerOrderNo", signNum);    // 商户签约号paramMap.put("TranDate", DateUtil.getFormatTime(order.getCreateTime(), "yyyyMMdd"));    // 商户交易日期paramMap.put("TranTime", DateUtil.getFormatTime(order.getCreateTime(), "HHmmss"));  // 商户交易时间paramMap.put("BusiType", "0001");// 业务类型,固定值paramMap.put("TranType", "9904");// 交易类型 快捷签约 9904paramMap.put("MerBgUrl", chinaPayConfig.getSignNotifyUrl());// 商户后台通知地址JSONObject cardTranData = new JSONObject();cardTranData.put("CertNo", chinaPaySignVo.getCertNo());cardTranData.put("CardNo", chinaPaySignVo.getCardNo());cardTranData.put("CertType", chinaPaySignVo.getCertType());cardTranData.put("AccName", chinaPaySignVo.getAccName());cardTranData.put("MobileNo", chinaPaySignVo.getMobileNo());cardTranData.put("MobileAuthCode", chinaPaySignVo.getMobileAuthCode());log.info("--------------签约接口, CardTranData: {}", cardTranData);paramMap.put("CardTranData", encryptCardTranData(cardTranData));// 有卡交易信息域  商户页面收集卡号的交易 必填getSign(paramMap);log.info("==============签约接口, 请求报文: {}", paramMap);Map<String, String> headerMap = new HashMap<>();String resp = HttpClientUtil.doPostSSL(chinaPayConfig.getBackUrl(), paramMap, headerMap);// 解析同步应答字段if (resp == null) {throw new ValidateException("签约接口 返回null");}Map<String, String> resultMap = getRespMap(resp);log.info("################签约接口, 返回报文:{}", resultMap);if (!resultMap.containsKey("respCode") || !resultMap.get("respCode").equals("0000")) {throw new ValidateException(resultMap.get("respMsg"));}String CardTranDataStr = resultMap.get("CardTranData");JSONObject cardTranDataResp = decryptCardTranData(CardTranDataStr);resultMap.put("CardTranData", cardTranDataResp.toJSONString());log.info("################签约接口, 返回报文, 解码后:{}", resultMap);// 成功 存储用户签约记录  TODO 可优化  异步回调中进行此操作addOrUpdateUserSignRecord(order, chinaPaySignVo, cardTranDataResp.getString("ProtocolNo"), "sign");// 进行 交易要素查询Map<String, String> dealFactorMap = queryDealFactor(chinaPaySignVo.getCardNo(), "0004");// 返回return ResponseResult.successResult(dealFactorMap, dealFactorMap.get("respMsg"));}

4. 解约接口

// 解约接口@Overridepublic ResponseResult relieveSignBankCard(ChinaPayVo chinaPayVo) {Order order = orderMapper.selectByPrimaryKey(chinaPayVo.getOrderId());Assert.notNull(order, "该订单不存在");String signNum = order.getSignNum();Assert.notNull(signNum, "签约号不存在, 请重新下单后再进行签约操作");Map<String, Object> paramMap = new TreeMap<>();paramMap.put("Version", "20150922");                // 版本号paramMap.put("MerId", chinaPayConfig.getMerId());   // 商户号paramMap.put("MerOrderNo", signNum);    // 商户签约号paramMap.put("TranDate", DateUtil.getFormatTime(order.getCreateTime(), "yyyyMMdd"));    // 商户交易日期paramMap.put("TranTime", DateUtil.getFormatTime(order.getCreateTime(), "HHmmss"));  // 商户交易时间paramMap.put("BusiType", "0001");// 业务类型,固定值paramMap.put("TranType", "9905");// 交易类型 9905 卡解绑paramMap.put("OriTranType", "9904");// 需要解约的原始交易类型 9904 快捷签约JSONObject cardTranData = new JSONObject();cardTranData.put("ProtocolNo", chinaPayVo.getProtocolNo());log.info("--------------解约接口, CardTranData: {}", cardTranData);paramMap.put("CardTranData", encryptCardTranData(cardTranData));// 有卡交易信息域  商户页面收集卡号的交易 必填getSign(paramMap);log.info("--------------解约接口, 请求报文: {}", paramMap);Map<String, String> headerMap = new HashMap<>();String resp = HttpClientUtil.doPostSSL(chinaPayConfig.getBackUrl(), paramMap, headerMap);// 解析同步应答字段if (resp == null) {throw new ValidateException("解约接口 返回null");}Map<String, String> resultMap = getRespMap(resp);log.info("################解约接口, 返回报文:{}", resultMap);if (!resultMap.containsKey("respCode") || !resultMap.get("respCode").equals("0000")) {throw new ValidateException(resultMap.get("respMsg"));}// 成功 修改用户签约记录addOrUpdateUserSignRecord(order, null, chinaPayVo.getProtocolNo(), "unSign");return ResponseResult.successResult(resultMap, resultMap.get("respMsg"));}

5.支付短信接口

// 支付短信接口@Overridepublic ResponseResult paySms(ChinaPayVo chinaPayVo){Order order = orderMapper.selectByPrimaryKey(chinaPayVo.getOrderId());Assert.notNull(order, "该订单不存在");Map<String, Object> paramMap = new TreeMap<>();paramMap.put("Version", "20150922");                // 版本号paramMap.put("MerId", chinaPayConfig.getMerId());   // 商户号paramMap.put("MerOrderNo", order.getOrderNum());    // 商户订单号paramMap.put("TranDate", DateUtil.getFormatTime(order.getCreateTime(), "yyyyMMdd"));    // 商户交易日期paramMap.put("TranTime", DateUtil.getFormatTime(order.getCreateTime(), "HHmmss"));  // 商户交易时间// TODO 订单金额整体测试通过后需要替换paramMap.put("OrderAmt", new Double(order.getSettleAmount() * 100).intValue() + "");// 订单金额 单位:分paramMap.put("TranType", "0606");// 交易类型 0606 快捷支付短信 0607 认证支付短信paramMap.put("BusiType", "0001");// 业务类型,固定值JSONObject cardTranData = new JSONObject();cardTranData.put("ProtocolNo", chinaPayVo.getProtocolNo());log.info("--------------支付短信接口, CardTranData: {}", cardTranData);paramMap.put("CardTranData", encryptCardTranData(cardTranData));// 有卡交易信息域  交易的卡号或协议号getSign(paramMap);log.info("==============支付短信接口, 请求报文: {}", paramMap);Map<String, String> headerMap = new HashMap<>();String resp = HttpClientUtil.doPostSSL(chinaPayConfig.getBackUrl(), paramMap, headerMap);// 解析同步应答字段if (resp == null) {throw new ValidateException("支付短信接口 返回null");}Map<String, String> resultMap = getRespMap(resp);log.info("################支付短信接口, 返回报文:{}", resultMap);if (!resultMap.containsKey("respCode") || !resultMap.get("respCode").equals("0000")) {throw new ValidateException(resultMap.get("respMsg"));}return ResponseResult.successResult(resultMap, resultMap.get("respMsg"));}

6.支付接口

// 支付接口private String payOrder(PayVO payVO){Order order = orderMapper.selectByPrimaryKey(payVO.getOrderId());Assert.notNull(order, "该订单不存在");Map<String, Object> paramMap = new TreeMap<>();paramMap.put("Version", "20150922");                // 版本号paramMap.put("MerId", chinaPayConfig.getMerId());   // 商户号paramMap.put("MerOrderNo", order.getOrderNum());    // 商户订单号paramMap.put("TranDate", DateUtil.getFormatTime(order.getCreateTime(), "yyyyMMdd"));    // 商户交易日期paramMap.put("TranTime", DateUtil.getFormatTime(order.getCreateTime(), "HHmmss"));  // 商户交易时间// TODO 订单金额整体测试通过后需要替换paramMap.put("OrderAmt", new Double(order.getSettleAmount() * 100).intValue() + "");// 订单金额 单位:分paramMap.put("TranType", "0004");// 交易类型 0004 快捷支付paramMap.put("BusiType", "0001");// 业务类型,固定值paramMap.put("MerBgUrl", chinaPayConfig.getNotifyUrl());// 商户后台通知地址JSONObject cardTranData = new JSONObject();cardTranData.put("ProtocolNo", payVO.getProtocolNo());  // 签约协议号cardTranData.put("MobileAuthCode", payVO.getMobileAuthCode());paramMap.put("CardTranData", encryptCardTranData(cardTranData));// 有卡交易信息域  交易的卡号或协议号paramMap.put("RemoteAddr", payVO.getRemoteAddr());// 防钓鱼客户浏览器 IPgetSign(paramMap);log.info("==============支付接口, CardTranData: {}", cardTranData);log.info("==============支付接口, 请求报文: {}", paramMap);Map<String, String> headerMap = new HashMap<>();String resp = HttpClientUtil.doPostSSL(chinaPayConfig.getBackUrl(), paramMap, headerMap);// 解析同步应答字段if (resp == null) {throw new ValidateException("支付接口返回null");}Map<String, String> resultMap = getRespMap(resp);log.info("################支付接口, 返回报文:{}", resultMap);if (!resultMap.containsKey("respCode") || !resultMap.get("respCode").equals("0014")) {  // 支付失败throw new ValidateException(resultMap.get("respMsg"));}return "支付成功";}

7.签约回调

 // 签约回调@Overridepublic ResponseResult<String> notifySign(HttpServletRequest request) {Map<String, String[]> requestMap = request.getParameterMap();Map<String, String> parameterMap = new HashMap<>();Set<Map.Entry<String, String[]>> entries = requestMap.entrySet();entries.forEach(entry -> {try {parameterMap.put(entry.getKey(), entry.getValue() == null ? null : URLDecoder.decode(entry.getValue()[0], "utf-8"));} catch (UnsupportedEncodingException e) {log.info("接收参数url编码错误", e.getMessage());}});log.info("############==============chinaPay签约异步回调: {}", parameterMap);Boolean flag = null;try {flag = verifyNotify(parameterMap, PayTypeEnum.getInstance("CHINAPAY"));} catch (Exception e) {log.info("chinaPay验签错误", e);}if (!flag) {ResponseResult.successResult("签约验签失败");}return ResponseResult.successResult("成功");}

8. 支付回调

// 支付回调@Override@Transactionalpublic ResponseResult<String> notifyPay(HttpServletRequest request) {Map<String, String[]> requestMap = request.getParameterMap();Map<String, String> parameterMap = new HashMap<>();Set<Map.Entry<String, String[]>> entries = requestMap.entrySet();entries.forEach(entry -> {try {parameterMap.put(entry.getKey(), entry.getValue() == null ? null : URLDecoder.decode(entry.getValue()[0], "utf-8"));} catch (UnsupportedEncodingException e) {log.info("接收参数url编码错误", e.getMessage());}});log.info("*------*-------chinaPay支付异步回调接收参数: {}", parameterMap);Boolean flag = null;try {flag = verifyNotify(parameterMap, PayTypeEnum.getInstance("CHINAPAY"));} catch (Exception e) {log.info("chinaPay验签错误", e);}if (flag != null && flag) {if (!parameterMap.get("OrderStatus").equals("0000")) {throw new ValidateException(parameterMap.get("respMsg"));}// 支付成功// 订单后续操作} else {ResponseResult.successResult("验签失败");}return ResponseResult.successResult("成功");}

配置文件及参数:

/*** @author dxw* @description chinaPay支付的配置文件*/
@Configuration
@PropertySource("china-pay.properties")
@ConfigurationProperties("china.pay")
public class ChinaPayConfig {private String merId;   // 商户号private String backUrl;     // 后台通知地址private String frontUrl;     // 前台通知地址private String notifyUrl;     // 支付回调地址private String signNotifyUrl;     // 签约回调地址private String queryUrl;     // 查询地址public String getMerId() {return merId;}public void setMerId(String merId) {this.merId = merId;}public String getBackUrl() {return backUrl;}public void setBackUrl(String backUrl) {this.backUrl = backUrl;}public String getFrontUrl() {return frontUrl;}public void setFrontUrl(String frontUrl) {this.frontUrl = frontUrl;}public String getNotifyUrl() {return notifyUrl;}public void setNotifyUrl(String notifyUrl) {this.notifyUrl = notifyUrl;}public String getSignNotifyUrl() {return signNotifyUrl;}public void setSignNotifyUrl(String signNotifyUrl) {this.signNotifyUrl = signNotifyUrl;}public String getQueryUrl() {return queryUrl;}public void setQueryUrl(String queryUrl) {this.queryUrl = queryUrl;}}

配置文件

#商户号
china.pay.merId=521*************# 后台支付地址/交易要素查询接口/签约查询接口/支付短信接口/签约接口       测试
#china.pay.backUrl=https://newpayment-test.chinapay.com/CTITS/service/rest/forward/syn/000000000017/0/0/0/0/0
## 前台支付地址     测试
#china.pay.frontUrl=https://newpayment-test.chinapay.com/CTITS/service/rest/page/nref/000000000017/0/0/0/0/0
## 查询地址        测试
#china.pay.queryUrl=http://newpayment-test.chinapay.com/CTITS/service/rest/forward/syn/000000000060/0/0/0/0/0
## 回调地址        测试
#china.pay.notifyUrl=https://***********/notifyPay
## 签约回调地址        测试
#china.pay.signNotifyUrl=https://*****************/notifySign# 后台支付地址/交易要素查询接口/签约查询接口/支付短信接口/签约接口    生产
china.pay.backUrl=https://payment.chinapay.com/CTITS/service/rest/forward/syn/000000000017/0/0/0/0/0
# 前台支付地址/签约接口     生产
china.pay.frontUrl=https://payment.chinapay.com/CTITS/service/rest/page/nref/000000000017/0/0/0/0/0
# 查询地址        生产
china.pay.queryUrl=https://payment.chinapay.com/CTITS/service/rest/forward/syn/000000000060/0/0/0/0/0
# 支付回调地址        生产
china.pay.notifyUrl=https://***********/notifyPay
# 签约回调地址        生产
china.pay.signNotifyUrl=https://*************/notifySign

chinapayUtil:


@Slf4j
public class ChinaPayUtil {public static SecssUtil secssUtil;//初始化static {secssUtil = new SecssUtil();boolean bool = secssUtil.init("/root/mortar-app/properties/security.properties");
//        boolean bool = secssUtil.init(file.getPath());if (bool) {log.info("ChinaPay交易证书、验签证书初始化成功!");} else {log.error("ChinaPay交易证书、验签证书初始化失败:" + secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());}}
}

security.properties

# Security properties configuration file
#   本地 --------------------------------------------
## 验签证书路径
verify.file=E:/opt/prod_certs/cp.cer
# 路径
sign.filePath=E:/opt/prod_certs/
# 交易证书路径
sign.file=E:/opt/prod_certs/chinapay.pfx
#   线上  ---------------------------------------------
# 验签证书路径
#verify.file=/root/chinapay/prod_certs/cp.cer
## 路径
#sign.filePath=/root/chinapay/prod_certs
## 交易证书路径
#sign.file=/root/chinapay/prod_certs/chinapay.pfx
# 交易证书密码
sign.file.password=111111
# 交易证书的密钥容器格式
sign.cert.type=PKCS12
# 报文中不参与签名的字段名称,多个字段用逗号进行分隔
sign.invalid.fields=Signature,CertId
# 签名值字段名称
signature.field=Signature

注意点:

1. 由源码中

可知resources下的 文件名称参数名称需要对应上, 否则会出现

初始化失败问题

2.若未集成org/apache/log4j  需要将security.properties中的 去掉, 否则会抛出 找不到class bug

3. 截止目前 chinapay支付 不支持招行借记

4. 支付订单号不能与签约订单号重复

5. 解密方式文档中叙述不准确 按demo中的方式可行, 如果没有DEMO,告知开发语言和参照的接口文档名称,发邮件到cp_operation@chinapay.com索取DEMO

6. 测试环境需要添加ip白名单才能访问

7. 生产环境 只能使用真实银行卡进行测试

8. 生成环境的交易证书的密码是小于等于6位

9. 请求时 必要参数少会返回少参数报错, 但是参数如果多了 返回的通常是验签失败, 一定要注意按官方提供的pdf逐步进行开发

chinapay 对接后台快捷支付交易相关推荐

  1. 支付宝快捷支付 快就不安全了吗?

    为什么80%的码农都做不了架构师?>>>    工行关闭四个快捷支付接口 之前四大行下调支付宝快捷支付额度,另外四大行均回应称,设置转账及交易支付限额的出发点和落脚点都是为了客户资金 ...

  2. 银行制定快捷支付限额原因

    络特莱--4月29日讯,所谓快捷支付,指的是为了满足消费者在网购上,利用小份金额进行虚拟账户系统快捷支付的方式.快捷支付需要消费者填写姓名.身份证号码.银行卡号.手机进行注册,填写之后去人,系统会自动 ...

  3. 快捷支付对银行的冲击及银行应对办法

    为什么80%的码农都做不了架构师?>>>    一. 快捷支付对银行的冲击 1. 加速对网银支付的冲击 快 捷支付,突破柜台,也突破网银,把银行物理网点的支撑功能打碎,把银行在电子渠 ...

  4. java后台 apiV3 对接微信app支付

    因为项目中需要用到微信支付,这里对自己对接的流程做一个记录 一.接入前准备 1.申请应用appId与商户号,配置apiV3秘钥 2.生成商户证书 首先登录微信商家平台,进入"账户中心–> ...

  5. 【转】快捷支付详解--比较详细

    现代支付系统设计相关的博客地址 http://blog.lixf.cn/ 快捷支付指用户在电商网站上执行支付时,不需要输入卡信息,仅根据短信或者其他的验证方式确认身份后,就可以执行扣款的支付方式. 这 ...

  6. 快捷支付各种绑卡鉴权方式

    1.背景 互联网金融平台账户进行开户或者支付业务时,绑卡鉴权环节是必经之路. 那么什么是绑卡鉴权?绑卡是将用户银行卡信息提供给金融平台,以后金融平台就用这个信息去银行完成支付.绑卡实际上是一个授权,让 ...

  7. 第三方支付交易简单流程

    支付网关 支付交易流程: 一般的第三方支付平台,如支付宝.财付通,提供了一个资金支付交易的处理业务.这个支付交易流程可以简单的规划为如下: 1.       操作员通过浏览器发起支付请求: 2.    ...

  8. springboot 银联支付(快捷支付)

    springboot 银联支付(快捷支付) 应用:持卡人预留银行卡号,使用手机验证码等方式完成支付 官方文档:https://open.unionpay.com/tjweb/api/dictionar ...

  9. 游戏平台对接哪种支付公司好(选择标准介绍)

    场上关于游戏平台的支付方式纷繁杂多,那支付公司也是相对较多,究竟哪个支付公司的支付方式更适合自己的游戏平台呢?我们今天首先要了解市场上现在有哪些支付公司以及这些支付公司之间有何区别. 一.各支付公司的 ...

最新文章

  1. OSSIM平台安全事件关联分析实践
  2. 多店铺多用户商城可以用来干嘛?适合什么样的商业模式?
  3. Git的使用---版本控制
  4. 你的 webpack 也需要休息,让你的 webpack 拒绝 996ICU
  5. 模板:使用文件作为输入
  6. matplotlib学习日记(九)-图形样式
  7. python写文件读文件-python(文件读写)
  8. VirtualBox虚拟机导出导入实践
  9. 简易linux修改ip,让Linux修改IP、DNS等可以更简单
  10. 2019-03-14-算法-进化(两个数组的交集 II)
  11. cdr怎么做文字路径_整理128张图片,告诉你文字少的PPT应该怎么做?
  12. docker tomcat:9.0
  13. JS-面向对象-对象的特性-禁止对象扩展 / 对象的特性-封印对象 / 对象的特性-冻结对象
  14. 利用纯粹的CSS3替代小图标---向右箭头
  15. css居中对齐的几种方式
  16. Tomcat中包含的配置文件、名字、作用分析记录
  17. onlyoffice5.4.2删除字体和添加字体
  18. 大数据分析流程步骤都有哪些
  19. linux非lvm分区在线扩容,Linux硬盘扩容(非LVM)
  20. win7系统笔记本配置双屏

热门文章

  1. 高等工程数学(张韵华,汪琥庭,宋立功)—— 第二篇:数值计算
  2. 短视频头部效应加剧,秒拍整军三月强势归来
  3. 现代大学英语精读第二版(第五册)学习笔记(原文及全文翻译)——1 - Who Are you and what are you doing here?(你们是谁?来这儿做什么?)
  4. Jenkins使用2——Jenkins使用时间戳
  5. SciTE更改背景颜色
  6. 一个月面试大厂,中厂,小厂的总结|2021 年中总结
  7. [生存志] 第15节 历代大事件概览 东汉
  8. [已迁移]数据结构-霍夫曼编码
  9. 百度android 升级,百度浏览器app下载_百度浏览器v6.4.21安卓去广告去升级版-这家软件站...
  10. Python编程从入门到实践(第二版)课后习题自写代码