引言

如果还不了解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
@RequestMapping
public 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 工具类如下,主要是初始化商户签名、验签配置信息:

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

四、测试退款

先调用银联支付请求,交易一张订单(银联支付还不知道,请查看此文《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分布式锁方案

ChinaPay银联电子支付-退款功能相关推荐

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

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

  2. chinapay 新版php接口,银联电子支付(chinapay)接口配置

    /** * ECSHOP 银联电子支付(ChinaPay)接口配置 * ---------------------------------------------------------------- ...

  3. chinapay java_ECSHOP 银联电子支付(ChinaPay)插件 掉用JAVA签名

    帮客户集成接口时候发现客户网站PHP版本达不到要求 只要调用JAVA来解决问题<?php /** * ECSHOP 银联电子支付(ChinaPay)插件 * ================== ...

  4. 银联电子支付ChinaPay支付回调验证问题

    注意是ChinaPay,银联电子支付,不是UnionPay,不是银联支付,详情请参考这篇文章 https://www.cnblogs.com/qidian10/p/4885038.html 支付回调验 ...

  5. 讲讲在银联电子支付工作时加解密、签名验签的那些事(纯粹的干货)。

    今天我们来讲讲系统间的交互需要哪些必要的东西才能确保互相通信会没有问题呢? 首先来看看最传统的系统交互,即两者直接互相明文传送,在这种情况下,若是被第三方拦截,会造成不可预估的影响.那么针对这种情况我 ...

  6. 微信小程序支付退款功能

    微信小程序支付退款功能 2022年02月做了一个微信小程序前端+ASP.NET后台的微信退款功能.功能的基本原理是使用JSAPI方式,对接之前的微信支付功能差不多.也是要签名,校验等.只不过它的退款传 ...

  7. 记在银联电子支付的上线感想

    20170725第二次在银联电子支付中心上线了.给我一个感觉,任何东西都得来个先来后到一说法....... ----------------------------------华丽的分割线 不知不觉时 ...

  8. java 中实现微信支付退款功能案例

    微信支付功能做了太多,今天又做了支付.退款.查询.提现等等,顺便把支付和退款代码贴出来,希望对初学者有点帮助. 首先调用微信支付退款 API 地址 https://pay.weixin.qq.com/ ...

  9. 银联电子支付 php chinapay

    之前看我博客百度关键字的时候,很多人都是因为银联搜到我这里,一直想做一个demo 给大家,可惜没商户申请不到,这次机缘巧合帮朋友做支付三部曲:微信支付,支付宝支付和银联支付,其他两个支付都烂大街的,这 ...

  10. 银联快捷支付退款 Pay

    public void refundPay(){logger.info("=====银联快捷退款开始=====");// 银联退款逻辑String hdurl = "ht ...

最新文章

  1. python程序实例教程基础-Python简单基础小程序的实例代码
  2. eclipse The current branch is not configured for pull No value for key remote.origin
  3. 《C语言编程——零基础初学者指南(第3版)》一第1章 什么是C程序设计1.1 什么是程序...
  4. 4-8岁那些最难的数学概念,美国老师用一套绘本让孩子秒懂
  5. leetcode —— 1038. 从二叉搜索树到更大和树
  6. 2018年中国AI行业研究报告
  7. Java中/和/*和/**的区别简述
  8. 小巧数据库 Apache Derby 使用攻略
  9. Redis 数据类型及应用场景
  10. P5231 [JSOI2012]玄武密码
  11. java证明角谷猜想_Java 代码界 3% 的王者?看我是如何解错这 5 道题的
  12. 超小股票行情查看软件
  13. 中国移动MM,你需要了解
  14. CAD两条曲线如何连接成平滑的波浪线?
  15. matlab仿真step模块讲解,Simulink仿真教程(最好)
  16. PyQt学习随笔:重写组件的event方法捕获组件的事件
  17. 计算机应用发展史的第四代,1.1.1 计算机的概念及其发展史
  18. 使用ESP8266和MPU6050制作倾斜角度监控器
  19. PHP的implode函数运用,什么是PHP中的implode()函数?
  20. 【电子水尺】高精度测量、免布线、远程传输数据

热门文章

  1. 【虹科免费直播预告】光电技术直播月重磅来袭!
  2. 影视后期好学吗?C4D精品教学合集,看完必成大神!(附链接)
  3. funcode拍飞虫C语言报告,【逻辑游戏面试题】面试问题:funcode… - 看准网
  4. ztree 右键菜单功能
  5. FCPX内置音效库汉化版
  6. 线性移位寄存器序列(m序列)之MATLAB实现
  7. Linux扫描工具rootkit部署
  8. 2016年最火的15款HTML5游戏引擎
  9. 试用officescan 10.5
  10. Android框架揭秘-Android Service Framework