银联支付(chinapay)java接入避坑指南

一、背景

银联支付能给满足绝大部分银行支付渠道,所以接入银联无卡支付,是很多系统应用需要做的事情。银联支付的类型分很多种,网关支付(带token请求实现,下次有空再分享)、无卡支付(带证书请求实现,本次讲的就是这个)分商户和机构入网,具体请去这里查看中国银联开放平台

二、效果

本次讲解实现的银联无卡支付,实现的效果图即提交订单后进入支付页面的效果图如下

 

三、开发前准备

当你需要接入银联无卡支付的时候,肯定是经过了需求调研,所以会有对接人给你们申请,所以会给你们发邮件,提供相应开发所需的文件,如下

1、开发文档ChinaPay_新一代_商户接入手册_20210412.pdf 

2、证书cp.cer

3、私钥xxxxxxxx.pfx和密码

4、插件包,里面提供了Java、.net、C和PHP的插件包,java的就是chinapaysecure1_5.jar

5、测试账号,请从如下地址获取FAQ列表- 中国银联开放平台

6、让银联方配置测试ip白名单,如果自己本地开发,出口ip需要固定,查询自己的出口ip地址如下用户检测分析工具

注意:如果需要代码参考,可以让银联方提供demo进行参考。这个demo因为是很久之前的,是jsp实现的eclipse项目,所以需要跑起来这个项目需要提前准备好eclipse和tomcat,当然了你会用idea跑eclipse也行。但是有时候稍微不注意,idea跑起来就会有莫名其妙的问题。这种问题经历过的都懂,就不说了。这里要特意说明一点就是,如果想要自己折腾获取xxx.pfx私钥的话,得配置好ip白名单后,登陆他们提供的商户服务管理系统https://newpayment-test.chinapay.com/BIZSS/admin/loginpage.htm后台去申请测试的私钥,即交易证书,这个系统最好用ie去登陆,否则你会因为各种莫名其妙的原因导致下载失败。

四、B2C、B2B、无卡支付交易流程(文档里面有)

 

五、代码

看到到这里了,证明前面的你已经准备好了,下面就开始看代码层面了,这里先给你们截几张demo的图给你们看看

1、跑完demo就会跳转到这个页面。

2、点击B2C会跳转到组交易报文页面,这里需要填写你的商户号和支付机构号700000000000017(pdf文档里面有)

 3、这是组装好的交易报文

 4、提交订单后

好了,看完demo的截图,就到我们自己动手,引用到springboot项目中了。 

 1、新建springboot项目或者直接用你的工作项目,将上面提前准备的xxx.cer、xxx.pfx证书放到项目中指定位置,如在resources下面新建一个文件夹放置这两个证书,在新建一个security.properties放到resources下,后续下单等操作需要签名的时候要获取到这些证书。security.properties的内容如下图。

这里的路径自己定义就好了, security.properties就是为了获取到证书,所以xxx.cer、xxx.pfx证书的路径写在了security.properties文件中。其实这个security.properties文件也可以不放在项目中,可以放在服务器上面,然后需要换证书的时候,直接换服务器文件上的security.properties就好了,不用重启项目,这样就可以做到动态切换证书了。

2、导入chinapaysecure1_5.jar

idea可以用命令导入,如下图

命令如下:

 install:install-file
-Dfile=E:\study\chinapaysecure1_5.jar
-DgroupId=com.chinapay.secure
-DartifactId=chinapay-sdk
-Dversion=1.5.0
-Dpackaging=jar

 pom 文件引入:

<dependency>
    <groupId>com.chinapay.sdk</groupId>
    <artifactId>chinapay-sdk</artifactId>
    <version>1.5.0</version>
</dependency>

这里需要注意一点就是,如果你的maven仓库是私服的话,上传了这个jar后,如果是下不下来的活,就要检查已经仓库的更新策略了,具体请看这里,添加这个就好了<updatePolicy>always</updatePolicy>https://blog.csdn.net/frank1998819/article/details/84813840

3、好了,废话了那么多,开始放下单支付代码

3.1、交易证书、验签证书初始化(因为我这里的正式是放到服务器上面的,所以需要通过url获取)

String securityUrl = upLoadPath + Constant.CHINA_PAY_SECURITY + chinaPayParameters.getMerchantId() + ".properties";
secssUtil = new SecssUtil();
File file = new File(securityUrl);
boolean bool = secssUtil.init(file.getPath());
if (bool) {log.info("ChinaPay交易证书、验签证书初始化成功!");
} else {log.error("ChinaPay交易证书、验签证书初始化失败:"+secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());
}

3.2、构建请求报文及签名

Map<String, Object> paramMap = new TreeMap<>();
paramMap.put("Version", "20140728");
paramMap.put("AccessType","0"); //接入类型  0:商户身份接入(默认)1:机构身份接入
paramMap.put("MerId", "123456"); // 商户号
paramMap.put("MerOrderNo", "abc123465"); // 商户订单号(由字母和数字组成,不要包含下划线)
paramMap.put("TranDate", "20220723"); // YYYYMMDD
paramMap.put("TranTime", "103300"); // HHMMSS
paramMap.put("OrderAmt", "1"); // 单位:分
paramMap.put("TranType", "0001");//交易类型,固定值
paramMap.put("BusiType", "0001");//业务类型,固定值
paramMap.put("BankInstNo", "700000000000017"); // 支付机构号-银联在线支付(这个参数必填,如果是无卡支付前端请求,否则会失败)
paramMap.put("CommodityMsg", "芒果");
paramMap.put("RemoteAddr", ipAddr); // ip地址
paramMap.put("CurryNo", "CNY");
paramMap.put("MerBgUrl", ""); // 后台通知地址
paramMap.put("MerPageUrl", ""); // 前端跳转地址
//签名
secssUtil.sign(paramMap);
if (!SecssConstants.SUCCESS.equals(secssUtil.getErrCode())) {return PayUtil.errorMessage("500", "500", secssUtil.getErrMsg());
}
String signature = secssUtil.getSign();
paramMap.put("Signature", signature);

3.3、构建from表单
System.out.println("####################请求总参数####################");
System.out.println(paramMap);
//必须构建成【自动提交form表单】html,返回商城前端自动跳转到网银支付页面
String buildRequest = MerchantApiUtil.buildRequest(paramMap,frontPayUrl, "post", "确定");
System.out.println("####################构建的表单####################");
System.out.println(buildRequest);
request.setAttribute("result",buildRequest);

3.4、构建from表单代码

public static String buildRequest(Map<String, Object> sParaTemp, String action, String strMethod, String strButtonName) {//待请求参数数组List<String> keys = new ArrayList<String>(sParaTemp.keySet());StringBuffer sbHtml = new StringBuffer();sbHtml.append("<form id=\"rppaysubmit\" name=\"rppaysubmit\" action=\"" + action + "\" method=\"" + strMethod+ "\">");for (int i = 0; i < keys.size(); i++) {String name = (String) keys.get(i);Object object = sParaTemp.get(name);String value = "";if (object != null) {value = String.valueOf(sParaTemp.get(name));}sbHtml.append("<input type=\"hidden\" name=\"" + name + "\" value=\"" + value + "\"/>");}//submit按钮控件请不要含有name属性sbHtml.append("<input type=\"submit\" value=\"" + strButtonName + "\" style=\"display:none;\"></form>");return sbHtml.toString();
}

3.5、vue前端调用下单form表单代码

4、回调接口代码

public String chinaPayNotifyUrl(HttpServletRequest request, HttpServletResponse response) {//获取请求头参数到paramsMapString notifyType = request.getParameter(Constant.SPEC_NOTIFY_TYPE);if(StringUtil.isEmpty(notifyType)) {notifyType = Constant.NOTIFY_TYPE_BACK;}Map<String, String> payNotifyUrlParamsMap = new TreeMap<String, String>();Enumeration<String> paraNames = request.getParameterNames();while (paraNames.hasMoreElements()) {String key = paraNames.nextElement();// 跳过自定义字段if (key.startsWith(Constant.SPEC_PRIFEX)) {continue;}// 跳过空字段String value = request.getParameter(key);if (StringUtil.isEmpty(value)) {continue;}// 后台通知需要解码,正式使用建议前后台接收通知地址分开if(Constant.NOTIFY_TYPE_BACK.equals(notifyType)) {try {value = URLDecoder.decode(value, Constant.ENCODING);} catch (UnsupportedEncodingException e) {e.printStackTrace();}}payNotifyUrlParamsMap.put(key, value);}log.info("当前时间:" + DateUtils.getCurrentTime() + "银联支付回调原始参数:" + payNotifyUrlParamsMap.toString());String outTradeNo = payNotifyUrlParamsMap.get("MerOrderNo") == null ? "" : payNotifyUrlParamsMap.get("MerOrderNo"); // 渠道订单号//返回数据验签boolean verifyFlag = verifyNotify(payNotifyUrlParamsMap);if (!verifyFlag) {System.out.println("ChinaPay支付回调--返回数据验签失败!");throw new JeecgBootException("ChinaPay支付回调返回数据验签失败,支付明细编号为:" + outTradeNo);}

// 这里就写你的业务了

4.1、常量说明

/*** 请求参数-通知类型 0前台 1后台 默认是后台.*/
public static final String SPEC_NOTIFY_TYPE = "__notifyType";/*** 通知类型-后台.*/
public static final String NOTIFY_TYPE_BACK = "1";/*** 特殊字段前缀.*/
public static final String SPEC_PRIFEX = "__";/*** 默认编码.*/
public static final String ENCODING = "UTF-8";

5、验签

public boolean verifyNotify(Map<String, String> notifyMap) {String securityUrl = upLoadPath + Constant.CHINA_PAY_SECURITY + notifyMap.get("MerId") + ".properties";secssUtil = new SecssUtil();File file = new File(securityUrl);boolean bool = secssUtil.init(file.getPath());if (bool) {System.out.println("ChinaPay交易证书、验签证书初始化成功!");} else {System.out.println("ChinaPay交易证书、验签证书初始化失败:"+secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());}try {//验签String sign = notifyMap.get("Signature");if (StringUtil.isNotEmpty(sign)) {secssUtil.verify(notifyMap);//入参:返回商户报文中的所有参数}if (!SecssConstants.SUCCESS.equals(secssUtil.getErrCode())) {System.out.println(secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());System.out.println("ChinaPay返回的应答数据【验签】失败:" + secssUtil.getErrMsg());return false;}return true;} catch (Exception e) {e.printStackTrace();}return false;
}

能给下单获取签名和回调进行验签,那么订单查询、订单退款也就没什么大问题了,以上就是本次分享的银联支付的代码,如有问题,请评论去指出,互相学习,共同进步。

六、总结

现在进行总结一下。

1、进行银联接入,需要提前了解接入后的效果。

2、开发前提前准备好需要的相应参数,否则沟通效率低下,问一个参数就一天了,文档上说不是必填,实际上又是需要必填,导致找不到原因,让银联配合,但是他们效率低下,导致你们接入进度延迟,比如文档上的支付机构号,可能有些情况下不是必填的,但是有些情况下是必填的,但是文档上没有说明,导致踩坑了。

3、form表单提交下单,这里的请求,如果是前端跳转,那么这时的跳转地址是你本地浏览器的地址,无需配置你测试环境的地址,只需要你本地的出口地址在银联的白名单即可。

4、正式环境无需配置白名单,测试环境才需要配置,否则开发的时候联调不了。

5、以上就是接入银联支付的所有,希望后人在接入的时候能给到一些参考,进而避免一些坑,从而提高接入效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/38503.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android接入支持海外的支付,visa,mastercard

为了支持海外的支付&#xff0c;我真的是找遍了各种方法&#xff0c;研究过google支付&#xff0c;最后因为手续费太高放弃。最后还是找到了支付宝海外支付。 sdk文档地址&#xff1a;http://www.alipay-seller.mpymnt.com/node/82&#xff08;对&#xff0c;只有英文文档&…

银联支付接口申请-手机控件支付

前一段时间在帮公司申请各种支付接口&#xff0c;在银联支付接口消耗了不少时间&#xff0c;其实银联支付申请还是比较简单的&#xff08;不用上传app截图什么的&#xff09;&#xff0c;只是申请入口比较难找&#xff0c;还有填写的资料比较多。下面我给大家介绍下银联支付接口…

Android-银联支付开发

转自&#xff1a;http://blog.csdn.net/qq285016127/article/details/38435585 银联支付也是一般比较常用的支付功能,这里简单了介绍android app如果短期快速应用这一方面的东西。直接上代码&#xff1a; 1.导入银联支付的依赖包: 2.在res目录下增加资源包: 3.配置AndroidManif…

西米支付:支付宝/微信支付/银联支付通道的接入介绍

本文以电脑网站支付为例&#xff0c;着重对第三方支付通道的接入进行了分析&#xff0c;包括支付宝支付接入、微信支付接入及银联支付接入。 1、支付宝支付接入 支付宝支付能力主要有当面付、刷脸付、App支付、手机网站支付、电脑网站支付和花呗分期等&#xff0c;本文采用电脑…

网关支付、银联代扣通道、快捷支付、银行卡支付等网上常见支付方式接口说明

一、网关支付 这是在线支付的最普遍形式。 大致支付过程&#xff1a;第三方支付公司作为代理&#xff08;网关&#xff09;&#xff0c;接入一堆银行。用户在网关页面&#xff08;可以在商户端&#xff0c;也可以第三方支付平台端&#xff09;选择银行&#xff0c;页面跳转到第…

HTB soccer

title: HTB_soccer description: HTB靶机 难度&#xff1a;easy date: 2023-05-31 categories: [渗透,靶机] HTB soccer 如果图片转载有问题移步&#xff1a;https://qing3feng.github.io/2023/05/31/HTB%20soccer/ 信息收集 ┌──(kali㉿kali)-[~] └─$ sudo nmap --min…

提高WhatsApp营销效果(1):文案篇

// 综述 在WhatsApp上做营销&#xff0c;最主要有四个因素会影响到转化的效果 分别是&#xff1a; ■ WhatsApp的发送者 ■ 文案 ■ 投放时段 ■ 目标号码 对于发送者来讲&#xff0c;主要影响因素是发送者所在的国家、头像和昵称。 投放时段来讲&#xff0c;自然是在用…

港联证券|半导体接棒AI走强 科创50指数领涨

周四&#xff0c;A股三大指数大幅低开&#xff0c;随后反弹并环绕上一买卖日收盘指数打开震动。沪指收报五连阳&#xff0c;半导体概念股团体大涨带动科创50指数走强&#xff0c;4月以来科创50指数已涨超6%。CPO概念股继续活泼&#xff0c;贵金属板块涨幅居前&#xff0c;AI使用…

【汇正财经】沪深创集体红盘,算力股全线爆发

盘面回顾&#xff1a; 大盘日K线收星涨0.31%&#xff0c;深成指涨0.61%&#xff0c;创业板冲高翻绿再弹起&#xff0c;收盘涨0.2%。CPO概念股午后继续大涨&#xff0c;算力概念股全线爆发&#xff0c;AI芯片、ChatGPT概念、电商概念等科技板块交投活跃&#xff0c;酒店餐饮、钙…

微信小程序会员卡开发跳坑

看了一下文档&#xff0c;大概是这样一个函数&#xff0c;可以让用户领取会员卡 wx.navigateToMiniProgram({appId: wxeb490c6f9b154ef9, //固定为此 appid&#xff0c;不可改动extraData: data, // 包括 encrypt_card_id, outer_str, biz三个字段&#xff0c;须从 step3 中获…

使用uni-app生成微信小程序踩的坑

毕设要求写一个浏览器端&#xff0c;一个APP端&#xff0c;一个微信端&#xff0c;刚开始以为要学三个技术然后写三个客户端&#xff0c;后来知道了uni-app这个神器&#xff0c;一次编写就可以编译生成APP、H5以及各种小程序版本的客户端。然而我比较熟悉的是web的前端开发&…

uni-app APP端-微信登录流程

uni-app APP端-微信登录流程 手把手教学 1.前期准备 在微信开放平台注册账户 微信开放平台 (qq.com)在管理中心中创建移动应用项目&#xff0c;按要求填写相关信息审核通过后即可获得我们所需的 AppID和AppSecret然后才uniapp项目中填写&#xff0c;在manifest.json中的App模…

微信小程序开发笔记 进阶篇②——多个微信小程序一个用户体系,同一个UnionID

目录 一、前言二、微信开放平台绑定小程序三、微信小程序login和getUserInfo四、后台请求auth.code2Session五、后台解密开放数据 一、前言 微信小程序开发笔记——导读 二、微信开放平台绑定小程序 微信官方文档&#xff1a;UnionID 机制说明 我们目前有一个微信开放平台&am…

微信小程序登录,包括uniapp的微信小程序登录

代码&#xff1a; 样式&#xff1a; <button click"login">登入</button> 事件&#xff08;methods中&#xff09;&#xff1a; login() {//判断缓存中是否有用户数据&#xff08;也就是判断有没有登录&#xff09;if (!uni.getStorageSync(encrypte…

桔子拓客是什么?

桔子拓客软件是一款安装在手机上APP智能营销软件&#xff0c;启动软件后可不停的活跃帐号&#xff0c;推送作品给指定的人群&#xff0c;指定区域&#xff0c;以此来达到精准曝光&#xff0c;定向引流&#xff0c;帮助用户实现流量的暴增&#xff01; 桔子拓客软件采用非入侵式…

做一个和瑞幸咖啡一样的小程序,就能3月赚24亿了吗?

2017年我开了一家咖啡店&#xff0c;疫情之前门店生意还比较惬意和滋润&#xff0c;没想到这疫情突如其来&#xff0c;一度要关门大吉。 后来偶然间看到瑞幸咖啡的年度报表&#xff0c;还有5月24日&#xff0c;瑞幸咖啡公布了2022年第一季度业绩&#xff0c;总净收入为24.046亿…

揭秘爆款的小程序,为何一黑到底

文章目录 前言⛳️ 1.什么是小程序?⛳️ 2.小程序发展史⛳️ 3.小程序原理⛳️ 4.如何开发微信小程序⛳️ 5.小程序的学习资源⛳️ 6.第一个微信小程序 前言 小程序&#xff0c;由于其便捷的操作&#xff0c;以及丰富的功能&#xff0c;已经普及到了生活中的各个领域,有很多人…

开始第一个基于uni-app的微信小程序开发

微信小程序 uni-app开发工具创建uni-app项目运行项目页面显示以及调试 uni-app uni-app 是一个使用 Vue.js 开发所有前端应用的框架&#xff0c;开发者编写一套代码&#xff0c;可发布到iOS、Android、H5、以及各种小程序&#xff08;微信/支付宝/百度/头条/QQ/钉钉/淘宝&#…

微信小程序开发大坑盘点

微信小程序开发大坑盘点 起因 前几天心血来潮&#xff0c;想给学校设计个一站式校园小程序&#xff0c;可以查询成绩&#xff0c;考试信息&#xff0c;课表之类的&#xff08;本来想法里是还想包括一些社交功能的&#xff0c;但这个因为资质问题暂且搁置了&#xff09;。其实…

那些年我们在微信小程序遇到的坑

前言 本篇主要记录一下我在开发中遇到的小程序的坑&#xff0c;还有实现的功能。 避坑 坑一&#xff1a;开发工具配置 &#xff08;1&#xff09;控制台如果报proxy代理相关错误&#xff0c;先检查左上角菜单栏中设置>代理设置>使用系统代理 &#xff08;2&#xff09…