一、背景及效果展示

现如今,诸多的供应链系统需要使用电子钱包功能,所以接入银联B2B无卡支付,是很多系统应用需要做的事情。银联支付的类型分很多种:网关支付(带token请求实现,下次有空再分享)、B2B无卡支付(带证书秘钥请求实现)分商户和机构入网,具体和更详细的内容可以去看中国银联开放平台,今天这里主要针对于企业中所涉及的的B2B无卡快捷支付做介绍与讲解。

二、B2B快捷支付流程

此流程图在商户接入手册中有展示,可以在文档中详细查看

2.1 B2B支付流程介绍

我们正常做的B2B支付对于银联来说,即是前台支付(B2B业务中都是前台支付),后台支付不用管。

整体流程走向:

1.通过后端先将支付请求的参数构建好并返回给到前端,前端请求银联的前台支付地址;

2.前端处理银联的响应信息(银联返回的是页面,可新开页签),后续到支付流程都是银联侧;

**注:**此处没有进行银行的选择,是在进行支付请求时传递了银行的机构码,银联的网关前置功能会自动跳转至对应的银联支付页面

3.填写银行卡密码等信息,填写完成后点击支付

4.支付完成后,银联会回调我们的后端回调接口或前端页面(前端页面回调地址可不传,采用手动关闭银联的页面)

5.接收到银行的支付回调信息后,主动调 交易查询接口 进行当前订单的支付状态

6.对支付回调信息与交易查询的响应信息进行处理,判断支付状态,进行后续的业务操作

**后续(退款类)**交易接口与支付流程基本一致,不过后续(退款类)交易接口是直接通过后端完成即可

三、前置工作

当接入银联无卡支付的时候,会有银联的对接人给你们申请,通过邮件发送开发所需的文件,如下:

1、开发文档ChinaPay新一代商户接入手册_20220616.pdf

2、公钥证书 CP.rar,需要解压此rar文件

3、usexxx.zip,私钥和密码压缩包,需解压后,生成私钥xxxxxxxx.sm2和密码

4、插件包,里面提供了Java、.net、C和PHP的插件包,java核心jar包就是chinapaysecure-sm-1.0.jar,通过此jar中的方法进行签名的生成、验签,加密解密

5、需要联系银联的对接人员开通B2B支付的测试账号

6、让银联方配置测试ip白名单,固定的对外IP

**注:**如果确实需要银联方提供demo参考(不建议),可让对接人员提供,demo本身基于servlet + jsp构建的eclipse项目,注释也很少,有问题建议直接跟银联方沟通,确认好自己的需求,效率会高很多。

四、正式接入

4.1 新建私钥及证书配置文件

在当前项目下,新建security.properties文件,配置好对应的公私钥及密码等信息

#报文中不参与签名的字段名称,多个字段用逗号进行分隔
sign.invalid.fields=Signature,CertId
#报文中签名的字段名称
signature.field=Signature
#是否输出调试日志,true输出,其他只输出错误日志
log.info=false
#私钥算法
secss.privateAlg=SM2
#私钥路径
secss.privatePath=/xxx/xxx.sm2
#私钥密码
secss.privatePwd=a111111
#公钥算法
secss.publicAlg=SM2
#公钥路径
secss.publicPath=/xxx/xxx.cer
#是否排除过期秘钥
secss.excludeExpiredCert=true

注:公私钥路径最好采用文件的绝对路径

4.2 引入chinapaysecure-sm-1.0.jar

项目中使用maven或gradle进行依赖管理时,可先将此jar包解压至本地仓库,后通过maven的gav坐标将其引入(gradle引入依赖与此类似)

<dependency><groupId>com.unionpay</groupId><artifactId>chinapaysecure-sm</artifactId><version>1.0</version>
</dependency>

注:如果maven仓库是采用的私服仓库,上传了这个jar后,如果项目中无法获取,需要检查仓库的更新策略,具体可以联系公司内的相关人员进行处理

4.3 代码接入

4.3.1 核心工具类 SecssUtil 初始化

@Slf4j
@Configuration
public class SecssConfig {@Value("${china.pay.securityUrl}")private String securityUrl;@Beanpublic SecssUtil init(){//执行secss初始化SecssUtil secssUtil = new SecssUtil();boolean bool = secssUtil.init(securityUrl);if (bool) {log.info("ChinaPay交易证书、验签证书初始化成功!");} else {log.error("ChinaPay交易证书、验签证书初始化失败:"+secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());}return secssUtil;}}

4.3.2 构建支付请求参数

@Autowired
private SecssUtil secssUtil;private TreeMap<String,Object> buildPayParams(SendPayReq payReq){TreeMap<String,Object> req = new TreeMap<>();req.put(Constants.VERSION,Constants.REQUEST_VERSION);req.put(Constants.MER_ID,merId);req.put(Constants.MER_ORDER_NO,payReq.getPayOrderId());req.put(Constants.TRAN_DATE, TimeUtil.date2String(LocalDate.now()));req.put(Constants.TRAN_TIME,TimeUtil.time2String(LocalTime.now()));//元转分Long orderAmt = payReq.getRemitterAmt().multiply(new BigDecimal(100)).longValue();req.put(Constants.ORDER_AMT,orderAmt.toString());req.put(Constants.BUSI_TYPE,Constants.BUSINESS_TYPE);//req.put("BankInstNo", param.getAccCode()); // 支付机构号-银联在线支付(这个参数必填,如果是无卡支付前端请求,否则会失败)//req.put("TranType",Constants.PAY_TRAN_TYPE);//支付接口后端回调地址req.put(Constants.MER_BG_URL,backPayUrl);//付款支付完成后跳转至的系统前台展示地址if (StringUtils.isNotEmpty(payReq.getMerPageUrl())){req.put("MerPageUrl",payReq.getMerPageUrl());}req.put(Constants.REMOTE_ADDR,remoteAddr);secssUtil.sign(req);log.info("支付交易签名响应is {},信息 {}",secssUtil.getErrCode(),secssUtil.getErrMsg());String sign = secssUtil.getSign();req.put(Constants.SIGNATURE,sign);return req;}

4.3.3 接收支付回调

支付完成后,银联会回调我们的这个接口,具体内容及接收方法课看下第五大点中的5.3回调接口

4.3.4 构建交易查询接口参数

 /*** 构建银联商务交易查询参数* @param param* @return*/private TreeMap<String,Object> buildQueryPayParams(AccountStorageQueryReq param){TreeMap<String,Object> req = new TreeMap<>();req.put(Constants.VERSION,Constants.REQUEST_VERSION);req.put(Constants.MER_ID,merId);req.put(Constants.MER_ORDER_NO,param.getPayOrderId());req.put(Constants.TRAN_DATE, param.getOriTranDate());req.put(Constants.TRAN_TYPE,Constants.QUERY_TRAN_TYPE);req.put(Constants.BUSI_TYPE,Constants.BUSINESS_TYPE);secssUtil.sign(req);log.info("商务交易签名响应is {},信息 {}",secssUtil.getErrCode(),secssUtil.getErrMsg());String sign = secssUtil.getSign();req.put(Constants.SIGNATURE,sign);return req;}

五、注意点

5.1 参数类型

在向银联发起支付、交易查询、退款类等请求时,虽说文档中每个字段类型各异,但实际上所有参数都是string类型

5.2 字段解密

如果需要对银行的返回信息中某个字段需要进行解密时,需要先注意下返回的加密信息是否含有 “%”,如果含有,则需要先通过url解码对字符串解码,去除该特殊符号,然后继续采用解密方法进行解密

import java.net.URLDecoder;public String getDecData(String encData){try {//对加密内容进行url解码String cardTranData = URLDecoder.decode(encData, Charsets.UTF_8);//调用核心类方法进行解密secssUtil.decryptData(cardTranData);//获取解密后的内容String cardData = secssUtil.getDecValue();if (StringUtils.isNotEmpty(cardData)){Map map = JSONObject.parseObject(cardData, Map.class);return (String)map.get("CardNo");}else {return "";}}catch (Exception e){log.warn("银行账户字段解签错误");return "";}}

5.3 回调接口

我们接收银联回调的接口,地址需要能直接被银联方访问到,(公网地址,并配置银联的白名单)。采用HttpServletRequest接收参数,并用获取paramMap方法拿到所有的响应参数内容

/*** 银联支付接口异步回调* @return*/
@PostMapping("/")
public ApiResult<Void> payCallback(HttpServletRequest request){Map<String, String[]> parameterMap = request.getParameterMap();log.info("4.1支付异步回调响应信息 is {}",parameterMap);if (CollectionUtils.isEmpty(parameterMap)){return ApiResult.fail("4.1支付异步回调响应信息为空");}return ApiResult.ok();
}

5.4 请求参数签名

银联构建的所有参数都需要进行签名(签名字段本身除外),然后一起组装到请求参数中,发送至银联的对应接口

public String getSign(TreeMap<String,Object> req){secssUtil.sign(req);log.info("待签名信息is {},签名响应: {}",secssUtil.getErrCode(),secssUtil.getErrMsg());String sign = secssUtil.getSign();return sign;}
联的对应接口```java
public String getSign(TreeMap<String,Object> req){secssUtil.sign(req);log.info("待签名信息is {},签名响应: {}",secssUtil.getErrCode(),secssUtil.getErrMsg());String sign = secssUtil.getSign();return sign;}

1.Java接入银联支付(chinapay)教程及避坑点相关推荐

  1. Java接入支付宝支付超级详细教程——从入门到精通

    ​ Java接入支付宝支付教程 源码下载 源码获取:点击获取源码 本文介绍了"二维码付款"的代码.其他支付方式的代码都在源码中. 一.创建应用 1.登录支付宝开放平台 支付宝开放平 ...

  2. Java接入支付宝支付教程

    Java接入支付宝支付教程 一.创建应用 1.登录支付宝开放平台 支付宝开放平台网址:https://open.alipay.com/platform/developerIndex.htm 2.创建一 ...

  3. Java写银联支付C扫B经验分享--框架SSM

    用Java写银联支付C扫B经验分享–框架SSM POM.xml <!-- C扫B支付 --><dependency><groupId>org.projectlomb ...

  4. Java接入支付宝支付测试买iPhone13 pro max

    Java接入支付宝支付 一.介绍 二.沙箱 三.支付流程 四.准备支付宝 五.代码 1.前端代码 2.后端代码 六.测试 一.介绍 支付宝官方网站 支付宝(中国)网络技术有限公司是国内的第三方支付平台 ...

  5. eu.org免费域名白嫖教程以及避坑

    title: eu.org免费域名白嫖教程以及避坑 date: 2022-07-06 11:50:53 tags: 网络 博客搭建 白嫖 categories: 我的博客搭建历程 cover: /im ...

  6. UNI-APP/VUE 项目集成 微信SDK /微信开放标签 教程和避坑指南(下)——微信开放标签篇

    UNI-APP/VUE 项目集成 微信开放标签 教程和避坑指南 文章同步发布于

  7. UNI-APP/VUE 项目集成 微信SDK /微信开放标签 教程和避坑指南

    UNI-APP/VUE 项目集成微信SDK教程和避坑指南 文章同步发布于

  8. Java接入微信支付超级详细教程——从入门到精通

    源码下载 源码获取邮箱:xiaoshu1024@qq.com 本文介绍了"二维码付款"的代码.其他微信支付方式的代码都在源码中. 一.准备开发所需的账号以及配置信息 解释:想要接入 ...

  9. chinapay 新版php接口,php最新银联支付chinaPay,最新接口地址

    需要下载这2个文件 再拿到公钥和秘钥 netpayclient_config.php netpayclient.php 目录结构 : 核心代码ChinaPay.php: header('Content ...

最新文章

  1. 视频监控日常使用存在哪些故障
  2. 解决Mac安装tesserocr报错问题 Failed building wheel for
  3. Linux下使用SSH、Crontab、Rsync三工具实现数据自动备份
  4. dt测试软件的学习心得,无线网络优化dt测试心得_适合新手入门,高手进阶_5年项目经验实战经验.docx...
  5. Verilog MIPS32 CPU(八)-- 控制器
  6. 介绍“又一个” Cloud Foundry Gradle插件
  7. html5 应用框架,基于HTML5移动应用框架的研究及应用
  8. matlab:randn函数产生图像高斯噪声
  9. eclipse写代码比jcreator好用多了
  10. activitygroup
  11. Android机顶盒烧录方法
  12. 一个完整的、全面k8s化的集群稳定架构(值得借鉴)
  13. Random Forests预测森林植被类型
  14. 手机屏幕物理点击器是什么原理_手机触摸屏的原理是什么?
  15. TreeSet 和 TreeMap 排序
  16. rovio论文解读,及工程应用经验总结
  17. Build error handing
  18. 宝塔下 nginx 支持图片放缩
  19. 气传导和骨传导耳机哪个好?简单科普这两种蓝牙耳机
  20. 运算放大器(运放)介绍

热门文章

  1. 如何使用ppt导出高清的论文插图
  2. Cardboard虚拟现实开发技巧(一)之放置一个固定在视野中的物体
  3. python3的turtle画模仿3d星空,运动的恒星小宇宙
  4. iOS尺寸单位pt、ppi与px之间换算关系
  5. 4、欧姆定律和焦耳定律
  6. Linux系统中的链接文件
  7. Android 信号强度
  8. scratch编程如何学?
  9. 关于氚云PasS的介绍
  10. MoveWindow和setwindowpos的区别