B2B电商平台--ChinaPay银联电子支付功能(实战)

                                          奇迹每天都在发生,而你能把握的便是当下,未来已来.............

                                --------------------------------------------------------------------------------------------------------------

           

一、概念简介

理解什么是UnionPay、ChinaPay

这两个概念如果搞不清楚,绝对够你瞎折腾一段时间的。讲真,拿到这个改换ChinaPay银联支付需求时,我还以为产品经理给错我们官网地址了。

1、UnionPay

中国银联,最大的机构;他本身也提供系统接口但都是B2B的,对于单个商户他们不提供客服,也不提供技术解决,更不会提供商户后台(可查消费记录等);但他的技术接口文档比较齐全,而且也可以使用,警惕不要使用这些接口。

官网:https://open.unionpay.com

2、ChinaPay

银联电子支付公司,第三方的支付公司,UnionPay的所有接口和服务都托管给类似的第三方公司,ChinaPay再向商户服务,ChinaPay有自己的接口标准,但是技术很老,JSP + Servlet 等,官网提供的资料列表很乱,代码样例 for java版本可以说没有,下图中的是Java版示例,但是和接口文档完全不对应,后面是发邮件问才给一个Java示例,与最新接口开发文档也是有出入的;并且从UnionPay官网开通商户后,默认根据地区会自动转到诸如“ChinaPay”这样的第三方支付公司,后面的事情全由ChinaPay代管。

官网:https://service.chinapay.com

             

二、ChinaPay商户后台

开通商户之后,一般销售会发送邮件给你,一般邮件内容包含开户名称、技术支持联系方式等,另附带一些压缩包,商户登录账号信息,多个账号,不同的账号对应不同的业务接口,略坑,还有接口开发文档,不同语言的SDK、logo等。

主要包括如下内容:

                    

拿到ChinaPay销售发邮件提供的商户号之后,需要到官网登录“商户服务管理系统”,自行申请、下载证书签名等文件,这个也够折腾一段时间的,各种浏览器不支持它们的插件...

注:商户服务管理系统仅支持IE(8、9、10、11)、Firefox、Safari浏览器,其他浏览器暂不支持。

         

三、获取交易证书

登录商户服务管理系统地址

生产:https://merchant.chinapay.com

测试:https://newpayment-test.chinapay.com

建议用IE或者FireFox登录,需要先下载和安装证书,安装ActiveX控件,登录证书只提供两份,多余两份的请联系销售;登录成功之后可以看到订单、退款单等账单;要实现支付接口,必须先获取一个“交易证书”,如下,到交易证书管理下,点击,弹出选项配置,然后下载即可生成一个 xxx.pfx 交易证书:

                

点击交易申请证书,获取到证书之后,需要将证书的上传回商户后台,同时本地需要导出证书私钥(带密码),以备用。

四、RSA公钥私钥加密

平台商城与ChinaPay接口通信的时候,都需要对数据进行签名与验签,验证对方身份。这里就涉及到加密算法的知识,其中,RSA加密算法是一种非对称加密算法,在公开密钥加密和电子商业中RSA被广泛使用。

RSA公钥私钥知识只需要记住下面这三点即可:

  1. 一个端有公钥和私钥两个文件(或者两个字符串),通信时候可以用公钥或者私钥加密。

  2. 公钥加密数据发送,私钥解密:保证信息的完整性和保密性,保证加密后的信息第三方劫持后无法查看内容,例如邮件等。

  3. 私钥加密数据发送,公钥解密:保证数据来源可靠,对信息进行签名,ChinaPay即是利用此方式,常用于公告、群发等操作。

五、消费类交易流程

参考接口文档

                   

B2C 、 B2B 、无卡支付交易流程:

                   

支付查询与退款流程图:

                

demo运行测试:

                  

交易查询:

                    

六、支付接口开发

新建一个SpringBoot测试工程,调试测试成功再整合移动到实际项目中,将ChinaPay提供的xxx.cer、xxx.pfx证书文件拷贝放到指定的路径下,新建一个security.properties放到resources下,便于读取,加载ChinaPay的配置等信息。

                      

1、security.properties

                          

2、导入SDK

将ChinaPay提供的SDK jar包导入本地maven仓库,然后在工程pom文件引入:

                      

注:IDEA 导入Jar 到本地 maven 仓库:                   

                             

                            

3、支付请求接口

@Slf4j
@Controller
@RequestMapping("/chinaPay")
public class ChinaPayController {public static final String url = "https://sfj-test.chinapay.com/dac/BatchPayTrade";public static final String frontPayUrl = "https://newpayment-test.chinapay.com/CTITS/service/rest/page/nref/000000000017/0/0/0/0/0";public static final String endPayUrl = "https://newpayment-test.chinapay.com/CTITS/service/rest/forward/syn/000000000017/0/0/0/0/0";@RequestMapping("/toChinaPay")@ResponseBodypublic String toChinaPay(HttpServletRequest req, HttpServletResponse resp) throws Exception {log.info("####################开始支付####################");Map<String, Object> paramMap = new TreeMap<>();Date nowDate = new Date();paramMap.put("Version", "20140728");paramMap.put("AccessType","0"); //接入类型  0:商户身份接入(默认)1:机构身份接入paramMap.put("MerId", "换成cp提供的商户号");
//        paramMap.put("MerId", "000091908248636");paramMap.put("MerOrderNo", "换成订单流水号");paramMap.put("TranDate", TimeUtil.dateToStr(nowDate,TimeUtil.YYYYMMDD));paramMap.put("TranTime", TimeUtil.dateToStr(nowDate,TimeUtil.HHMMSS));paramMap.put("OrderAmt", "1");//单位:分
        paramMap.put("BusiType", "0001");//业务类型,固定值paramMap.put("CommodityMsg","大米100斤");paramMap.put("MerBgUrl", "http://yl.foodsyoyo.com/chinaPay/notify");//支付异步通知地址:用来接收交易结果后台通知的地址paramMap.put("MerPageUrl", "http://yl.foodsyoyo.com/chinaPay/payResult");//支付完成跳转的页面paramMap.put("RemoteAddr", "xxxIP");System.out.println("==============订单号===========:"+paramMap.get("MerOrderNo"));SecssUtil secssUtil = ChinaPayUtil.secssUtil;//签名secssUtil.sign(paramMap);if (!SecssConstants.SUCCESS.equals(secssUtil.getErrCode())){log.error(secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());return secssUtil.getErrMsg();}String signature = secssUtil.getSign();paramMap.put("Signature", signature);System.out.println("####################请求总参数####################");System.out.println(paramMap);//必须构建成【自动提交form表单】html,返回商城前端自动跳转到网银支付页面String buildRequest = MerchantApiUtil.buildRequest(paramMap,frontPayUrl, "post", "确定");System.out.println("####################构建的表单####################");System.out.println(buildRequest);req.setAttribute("result",buildRequest);//请求--不能直接使用http工具发起支付请求,需要构建form表单请求自动提交
//        String result = HttpUtils.send(frontPayUrl, paramMap);
//        System.out.println("返回结果:"+result);
//        return "toPay";return buildRequest;
}

}

注意:支付接口,ChinaPay要求必须构建成【自动提交form表单】html,返回商城前端自动跳转到网银支付页面,,不能直接使用Http工具发起post支付请求,否则报错。

其中,ChinaPayUtil 工具类如下,主要是初始化商户签名、验签配置信息:

@Slf4j
public class ChinaPayUtil {public static final SecssUtil secssUtil;//初始化static {secssUtil = new SecssUtil();Resource resource = new ClassPathResource("./security.properties");File file = null;try {file = resource.getFile();} catch (IOException e) {e.printStackTrace();}boolean bool = secssUtil.init(file.getPath());if (bool) {
           PaymentLog.info("ChinaPay交易证书、验签证书初始化成功!");} else {PaymentLog.error("ChinaPay交易证书、验签证书初始化失败:"+secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());}   }
}

NetPayClient for Java  使用说明:

详细请参考ChinaPay开发接口文档说明。

ChinaPay 针对不同的开发平台和运行平台提供对应的 NetPayClient 版本,实现消费者、商户和银行间的网上安全支付。功能如下:

  • 商户对交易请求信息进行签名

  • 商户对 ChinaPay 返回的交易应答信息进行签名验证

  • 商户对一段字符串进行签名

(1)核心文件清单:

                  

(2)SecssUtil

我们实际开发,主要是调用SDK的SecssUtil中的方法即可:

                    

4、支付请求-结果通知(异步)

分前台与后台地址回调:当交易完成时,ChinaPay 会通过 http post 方式将应答信息发送给商户发送请求报文中提供的前、后台地址(MerPageUrl 、MerBgUrl),应答的数据包括如下内容:

(参数形式是 key-value 形式,用&分割, 注意大小写, 编码方式统一用 UTF-8) 

                               

注:具体参考接口文档,这里就不一一贴出来了,对着接口文档从request中读取返回的参数解析、验签、处理后续业务即可。

5、Signature说明:

商户发送给 ChinaPay 的信息均需要用商户的交易证书进行数字签名。ChinaPay 收

到商户的信息后会用商户的公钥证书进行验签,以确定是商户发送的信息。支付交易完成后,支付应答会分前台页面跳转和后台 Http 通知方式返回给商户,商户收到应答信息后,需要用 ChinaPay 提供的证书对返回信息进行验签,以确定此报文是由 ChinaPay 发出。

后台返回字段需要通过 urldecode 进行解码后还原原始报文,前台返回报文无需此操作。

 

  • JAVA 解码方法:URLDecoder.decode(value, "utf-8")

  • PHP 解码方法:urldecode(value)

  • .NET 解码方法:HttpUtility.UrlDecode(value,"utf-8");

因此这里,针对后台回调,在取出返回的数据时,需要验证签名,以确定此报文是由 ChinaPay 发出,如下,验签方法:

 

/**

* 回调验签--验证 chinapay 返回的应答数据
* 参考文档Signature说明:后台返回的所有字段每个都需要通过 urldecode 进行解码后还原原始报文,
* 前台返回报文无需此操作
*
* @param jsonObject
* @param notifyMap 支付回调的信息
* @return
*/
@Override
public boolean verifyNotify(JSONObject jsonObject, Map<String, String> notifyMap) {
SecssUtil secssUtil = ChinaPayUtil.secssUtil;
try {
//验签
String sign = notifyMap.get("Signature");
if (StringUtils.isNotEmpty(sign)) {
secssUtil.verify(notifyMap);//入参:返回商户报文中的所有参数
}
if (!SecssConstants.SUCCESS.equals(secssUtil.getErrCode())) {
PaymentLog.error(secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());
PaymentLog.info("ChinaPay返回的应答数据【验签】失败:{}", secssUtil.getErrMsg());
return false;
}
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}

至于post回调,ChinaPay返回的数据,从request中取出解析即可:

Map<String, String[]> requestParams = httpServletRequest.getParameterMap();

6、订单交易查询接口:

/*** 订单查询* @return*/@RequestMapping("/orderQuery")@ResponseBodypublic QueryOrderResultDto orderQuery(){QueryOrderResultDto orderResultDto = new QueryOrderResultDto();orderResultDto.setFlowTradeNo("xxxxxx");orderResultDto.setResult(false);Map<String, String> paramMap = new TreeMap<>();paramMap.put("Version", "20140728");paramMap.put("TranType", "0502");//交易类型,固定值:0502paramMap.put("BusiType", "0001");//业务类型,固定值// 商户订单号可包含字母和数字,与 MerId 和 TranDate 一起,ChinaPay是根据这三个字段唯一确定一笔订单paramMap.put("MerOrderNo", "xxxxxxx");paramMap.put("MerId", "xxxxxxxxxx");// 原交易日期 , 格式 :yyyyMMdd TODO 替换paramMap.put("TranDate", TimeUtil.dateToStr(new Date(), TimeUtil.YYYYMMDD));//签名SecssUtil secssUtil = ChinaPayUtil.secssUtil;secssUtil.sign(paramMap);if (!SecssConstants.SUCCESS.equals(secssUtil.getErrCode())) {log.error("ChinaPay签名失败:" + secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());orderResultDto.setMessage("ChinaPay签名失败");return orderResultDto;}// TODO 商户向ChinaPay的支付接入地址提交订单信息,【表单】采用“post”方式提交//String buildFormRequest = MerchantApiUtil.buildRequest(paramMap,payQueryUrl, "post", "确定");// TODO 同步请求String resp = HttpUtils.send(payQueryUrl, paramMap);log.info("################交易查询结果:{}",resp);// 解析同步应答字段String[] strs = resp.split("&", -1);Map<String, String> resultMap = new TreeMap<String, String>();for (String str : strs) {String[] keyValues = str.split("=", -1);if (keyValues.length < 2) {continue;}String key = keyValues[0];String value = keyValues[1];if (StringUtil.isEmpty(value)) {continue;}//响应字段解码try {value = URLDecoder.decode(value, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}resultMap.put(key, value);}//返回数据验签boolean verifyFlag = verifyNotify(resultMap);if (!verifyFlag) {log.error("ChinaPay支付查询--返回数据验签失败!");orderResultDto.setMessage("ChinaPay支付查询--返回数据验签失败!");return orderResultDto;}orderResultDto.setResult(true);orderResultDto.setMessage("查询成功");orderResultDto.setPayType("ChinaPay银联支付");
//        orderResultDto.setTradeState(OrderStatus);return orderResultDto;}

注:其它接口开发参考ChinaPay文档就可以,这里就不一一粘贴示例了0.0

七、测试支付

点击ChinaPay银联支付,商城后台会组装请求参数到form表单,自动提交到ChinaPay

                     

这里测试的商户号只开通了企业网银(B2B),所以只显示一个

                     

这里因为是ChinaPay测试环境,所以可以不填写任何信息,直接点击“支付成功”或“支付失败”即可,完成后续的回调测试:

                           

八、总结

这里演示了一个支付请求接口,包括核心的配置与接口参数详解,只要调通一个,后面的支付查询、退款、扫码支付、分账等就基本类似的套路。主要是ChinaPay的技术支持只提供邮件沟通,沟通效率太慢,遇到对接问题时,发邮件,他们的回答很简单,主要是去多看接口文档,然而接口文档写得马马哈哈,文档有些地方过于简略,只能去尝试调试,有些坑自己踩过才知道,多问ChinaPay。

九、附录-常见接入问题

  1. 开发过程中,商户签名报 SecurityException 异常

    检查交易证书密码是否配置正确,并检查配置文件 security.properties 是否配置正确。需要将 security.properties 放在类路径下,详细配置请参考上面。

  2. 开发过程中,商户签名报“未初始化配置”异常

    检查签名或验签之前是否调用 SecssUtil.init();方法,如果未调用,则调用SecssUtil.init()方法初始化安全签名配置

  3. 签名过程出现 Illegal key size 错误

    请检查下载的 pfx 证书是否正确,或者重新申请 CFCA 交易证书

  4. 交易失败!错误信息:证书未配置

    这个报错通常有两个原因,一是没有申请交易证书,二是交易地址提交错误,测试地址和正式地址搞错了。

  5. 交易失败!错误信息:验签失败

    需要确认交易证书在 Internet 选项---内容---证书---颁发给的名字和在商户服务管理系统里面查到的交易证书的证书名称是一样的。证书确认没有问题,需要确认参加签名的字段和传过来的字段是一样的。

  6. 支付请求,结果通知(异步)回调,验签失败

    请参考Signature字段说明,后台返回的所有字段每个都需要通过 urldecode 进行解码后还原原始报文,前台返回报文无需此操作。

注:当然,开发中还会遇到其它各种不同的问题,请参考文档,解决不了请及时询问ChinaPay技术人员。

 

                                               

                                           

 

 

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

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

相关文章

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

一、背景 银联支付能给满足绝大部分银行支付渠道&#xff0c;所以接入银联无卡支付&#xff0c;是很多系统应用需要做的事情。银联支付的类型分很多种&#xff0c;网关支付&#xff08;带token请求实现&#xff0c;下次有空再分享&#xff09;、无卡支付&#xff08;带证书请求…

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;。其实…