ChinaPay银联电子支付-退款功能

发布时间:2025-12-09 21:59:14 浏览次数:4

引言

如果还不了解UnionPay、ChinaPay概念与配置的,可以先移步到《B2B电商平台--ChinaPay银联电子支付功能》,此篇文章会带你熟悉ChinaPay支付流程的完整开发步骤。

一、消费类交易流程

本次只讲解退款申请流程,所以上面两个流程简单看下即可,退款流程如下:

二、后续类交易接口

根据ChinaPay银联接口开发文档4.15后续类交易接口说明:

后续类交易主要是指对已发生的交易,做后续的相关的交易处理;包括:退款、退款撤销、消费撤销、预授权撤销、预授权完成撤销、预授权完成、通知分账。退款的相关操作也可以在企业门户系统中进行操作,但是商户只能选择一种方式进行操作。

1、接入地址

  • 测试环境

  •  生产环境

从提供的地址分类,就可以看出,该后续交易类接口,提供退款申请、退款撤销、通知分账、消费撤销、预授权等功能,具体可通过请求参数区分。

2、请求报文

商户向 ChinaPay 的交易平台提交订单,表单采用“post”方式提交,提交页面中表单(FORM)的应该包括如下( 注意各字段的大小写, 编码方式统一用 UTF-8):

注:请求参数很多,这里就不全部截取了,开发者只要将必填字段发送到银联即可。 

3、应答报文(同步)

对于 0401 退款、0402 退款撤销、0403 消费撤销、9908 通知分账的交易,当 ChinaPay交易平台接收商户提交的订单后,会返回商户同步处理结果。包括如下( 响应数据以 以 key=value  形式 ,用 用”&” 符号分隔):

这里可以看出,调用后续类交易接口时,会同步应答响应码、描述、签名,通过响应码确认请求成功与否。其中,退款申请会同步返回“1003:商户已审核”表示退款申请成功,还需要等待银联的异步回调通知真正退款到账成功。

4、结果通知(异步)

当 ChinaPay 交易平台处理完成时,ChinaPay 会将订单信息发送给商户,应答的数据域段包括如下内容:(以页面 Form 数据为例, 注意大小写, 编码方式统一用 UTF-8,后台应答数据的发送的域段名和下面的一致)

其中,上图红框参数容易误解为支付时的交易流水号、交易日期、订单支付完成时间,其实是指本次后续交易请求单的收单流水号、完成时间。比如,我们是在进行退款申请,那么,此次异步回调结果,如下:

  • AcqSeqId:退款受理流水号(由银联生成返回)

  • AcqDate:退款申请受理日期

  • CompleteDate:退款完成日期

  • CompleteTime:退款完成时间

三、退款申请开发

同理,在进行公司实际项目退款功能开发前,最好要先写好测试类,先把银联退款申请功能接口调通,再把测试类整合进自己的项目中,结合实际业务开发,这里只展示测试demo,具体退款业务需要结合自己项目的实际需求哦。

本demo也是基于SpringBoot构建的测试应用,项目结构如下:

1、security.properties 

## Security properties configuration file# 验签证书路径verify.file=E:/my-demo/chinapay-demo/src/main/resources/chinapay/cp-test.cer# 路径sign.filePath=E:/my-demo/chinapay-demo/src/main/resources/chinapay# 交易证书路径sign.file=E:/my-demo/chinapay-demo/src/main/resources/chinapay/cp-test.pfx# 交易证书密码sign.file.password=123456# 交易证书的密钥容器格式sign.cert.type=PKCS12# 报文中不参与签名的字段名称,多个字段用逗号进行分隔sign.invalid.fields=Signature,CertId# 签名值字段名称signature.field=Signature# 日志名称log4j.name=CONSOLE

2、pom 文件引入:

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

3、退款申请接口:

/*** @description: 退款* @author: stwen_gan* @date: 2019/09/24**/@Slf4j@Controller@RequestMappingpublic class RefundController {//退款地址private static String refundUrl = "https://newpayment-test.chinapay.com/CTITS/service/rest/forward/syn/000000000065/0/0/0/0/0";// private static String refundUrl = "https://payment.chinapay.com/CTITS/service/rest/forward/syn/000000000065/0/0/0/0/0";/*** 退款申请、撤销* @param req* @param resp* @return* @throws Exception*/@RequestMapping("/refund")@ResponseBodypublic String refund(HttpServletRequest req, HttpServletResponse resp) throws Exception {log.info("####################开始退款####################");Map<String, String> paramMap = new TreeMap<>();Date nowDate = new Date();paramMap.put("Version", "20140728");paramMap.put("AccessType","0"); //接入类型 0:商户身份接入(默认)1:机构身份接入paramMap.put("MerId", "000091908269337");//测试商户号paramMap.put("BusiType", "0001");//业务类型,固定值:0001//退款订单号paramMap.put("MerOrderNo", TimeUtil.dateToStr(nowDate,TimeUtil.YYYYMMDD)+TimeUtil.dateToStr(nowDate,TimeUtil.HHMMSS));paramMap.put("TranDate", TimeUtil.dateToStr(nowDate,TimeUtil.YYYYMMDD));paramMap.put("TranTime", TimeUtil.dateToStr(nowDate,TimeUtil.HHMMSS));paramMap.put("MerBgUrl", "http://ggzz.ngrok.ygqit.com/refundNotify");//支付异步通知地址:用来接收交易结果后台通知的地址//退款paramMap.put("OriOrderNo", "20190926141435");//原始交易订单号//撤销退款// paramMap.put("OriOrderNo", "20190920153459");//原始交易订单号paramMap.put("OriTranDate", "20190926");//商户原始交易日期paramMap.put("RefundAmt", "1");//退款金额--单位:分,当 TranType=0401 退款交易时 RefundAmt 必填,当 TranType 为其他值时, 交易时不能传 RefundAmtparamMap.put("TranType", "0401");//退款交易// paramMap.put("TranType", "0402");//退款撤销System.out.println("==============退款订单号===========:"+paramMap.get("MerOrderNo"));System.out.println("==============退款申请日期===========:"+paramMap.get("TranDate"));System.out.println("==============退款申请时间===========:"+paramMap.get("TranTime"));//paramMap.put("OrderAmt", "1");//订单金额--单位:分,当 TranType=0202 或 9908 时,OrderAmt 必填,当 TranType 为其他值,交易时不能传 OrderAmt// paramMap.put("CurryNo", "CNY");//交易币种:默认为人民币:CNY// paramMap.put("SplitType", "0001");//分账类型:不分账不填写此域;分账交易退款,此字段传 0001// paramMap.put("SplitMethod", "0401");//订单分账方式:0:按金额分账 ,1:按比例分账// paramMap.put("MerSplitMsg", "0401");//分账信息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("####################请求总参数####################:"+paramMap);//http请求String result = HttpUtils.send(refundUrl, paramMap);System.out.println("返回结果:"+result);Map<String, String> resultMap = ChinaPayUtil.strToMap(result);//返回数据验签boolean verifyFlag = ChinaPayUtil.verifyNotify(resultMap);if (!verifyFlag) {log.error("ChinaPay返回数据验签失败!");return "ChinaPay返回数据验签失败!";}return resultMap.get("respCode")+":"+resultMap.get("respMsg");}}

4、退款异步回调

/*** 退款异步回调* @param request* @param response* @return*/@RequestMapping("/refundNotify")public String refundNotify(HttpServletRequest request,HttpServletResponse response){log.info("退款申请异步回调");Map<String, String[]> requestParams = request.getParameterMap();//ChinaPay后台返回所有字段需要解码Map<String, String> notifyMap = ChinaPayUtil.parseNotifyMsg(requestParams);// 验证退款单状态是否成功:0000-退款成功,其他请参考银联支付接口文档附录BString return_code = notifyMap.get("OrderStatus");log.info("订单状态 return_code:{}" ,return_code);if (!"0000".equals(return_code)) {log.error("退款单号:"+ notifyMap.get("MerOrderNo") +"退款失败。原始订单号:"+ notifyMap.get("OriOrderNo"));}// TODO 具体处理平台后续业务,如更新订单状态、退款状态等return "退款成功";}

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

@Slf4jpublic 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());}}}

四、测试退款

先调用银联支付请求,交易一张订单(银联支付还不知道,请查看此文《B2B电商平台--ChinaPay银联电子支付功能》),记录交易流水号与交易日期,填入退款申请接口请求相应参数中,然后运行应用,访问下该退款接口,成功的话,会返回“1003:商户已审核”,如下:

注:异步回调这里就不测试了,需要等待银联那边退款成功才会回调。

八、总结

这里演示了退款申请的具体步骤,其实,相对于支付对接,都差不多的开发流程,只要按照银联接口文档来开发即可,请求参数有些许疑惑的可以咨询银联技术人员。退款对接并不难,更多的工作量是在平台业务处理这边,比如,我们的是B2B系统,区分预付款与尾款,可能是分多笔退款、部分退款,主要分几块:用户端退款模块(PC与移动端)、商户端退款模块(PC与移动端)、后台管理审核退款模块等。

往期推荐

●Spring Cloud Alibaba Nacos 配置中心对比与实战

●超级全面的MySQL优化--一篇足以【建议收藏】

●Java/JDK 13 新特性详解

●Spring Cloud Alibaba 微服务全家桶体验-2019阿里云峰会PPT

●Spring Cloud Alibaba 完美融合Dubbo-Nacos示例

●如何使用Seata保证Dubbo微服务间的一致性

●B2B电商平台--ChinaPay银联电子支付功能

●学会Zookeeper分布式锁,让面试官对你刮目相看

●SpringCloud电商秒杀微服务-Redisson分布式锁方案

 

需要做网站?需要网络推广?欢迎咨询客户经理 13272073477