简要描述

支付完成(订单状态为“已支付”)后,支付FM会把相关支付结果信息通过数据流的形式发送给用户系统,用户系统需要接收处理,并按文档规范返回应答。

注意:
1、notifyUrl地址就是您的业务系统的开放接口,请保证可以直接访问请求;不要做301、302等跳转等
2、支付FM请求notifyUrl如返回Read timed out等网络不通畅的情况只会通知一次
3、系统会记录返回异常的部分记录,在商户订单的失败详情中供查阅
4、接口请求默认超时3s,所以您的接口执行时间要在3s内执行完毕
5、这是GET请求,您可以参考请求示例拼接请求串,通过Postman调试您的接口
6、结果通知可能会多次请求,请务必参考下文特别提醒的建议处理
7、若多次回调异常,仍不按照接口规范进行调整,根据《支付FM用户条款》本公司将暂停或终止您对支付FM服务的使用

特别提醒:
1、商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失。
2、当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功暨字符串success。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。

回调URL

创建订单接口传入的notifyUrl

该链接是通过创建订单接口中的请求参数“notifyUrl”来设置的,要求必须为http/https地址。请确保回调URL是外部可正常访问的,且不能携带后缀参数,否则可能导致您的系统无法接收到回调通知信息。

通知规则

顾客支付完成后,支付FM把相关支付结果和相关信息发送给商户的业务系统,商户需要接收处理该消息,并返回应答。

对后台通知交互时,如果支付FM收到商户的应答不符合规范或超时,支付FM认为通知失败,支付FM会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但不保证通知最终能成功。(首次实时通知异常后重发通知频率为15s/30s/3m/10m/20m/30m/60m/3h/6h/ - 总计 11h3m45s)

请求方式

请求方法:GET
参数传递:Query 请求地址URL拼接参数
query指该参数在请求URL传参

请求参数值说明

参数 必须 类型 说明
merchantNum string query商户号。用户中心查看
orderNo string query商户订单号。原样传回
amount number query订单金额。请求的支付金额(单位:元),最多小数点后保留2位
platformOrderNo string query平台订单号。平台生成的唯一订单号
actualPayAmount string query实际支付金额。最多保留小数点后2位。免签通道因浮动原因,此金额可能会不等于订单金额。
state string query付款成功标志。1:付款成功
payTime string query付款时间。日期时间格式:yyyy-MM-dd HH:mm:ss
attch string query附加信息。原样传回
sign string query签名。通过MD5加密指定的值拼接计算得出的签名值。签名值=md5(付款成功状态state的值+商户号merchantNum的值+商户订单号orderNo的值+订单金额amount的值+接入密钥);其中“+”表示字符串拼接。请注意拼接顺序

返回参数值说明

请求收到后,请同步返回字符串 success

必须 类型 说明
success string 表示收到回调且正常返回
  1. //常见写法1(java、php等)
  2. return 'success';
  3. //常见写法2(php等)
  4. echo 'success'; exit;

请求示例

您的notifyUrl?amount=0.2&orderNo=T1584936360806&actualPayAmount=0.2&payTime=2020-03-23 12:51:48&platformOrderNo=1241950691694477312&merchantNum=shanghuhao&sign=4115128010ccff25665524dfd711ffaf&state=1
这是GET请求,您可以参考请求示例拼接请求串,使用PostMan等工具调试您的接口。

接收示例

此处罗列一些业务系统侧接收回调通知的部分代码供参考,完整代码可以参考demo篇章。

JAVA:

  1. //map为请求键值对
  2. @ResponseBody
  3. @GetMapping("/SuccessNotice")
  4. public String SuccessNotice(@RequestParam Map<String, String> map) {
  5. //您的代码块 start
  6. //判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功标志
  7. //您的代码块 end
  8. return "success";
  9. }
  10. 或者
  11. public String SuccessNotice(HttpServletRequest request) {
  12. Map requestParams = request.getParameterMap(); //获取请求键值对requestParams
  13. //您的代码块 start
  14. //判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功标志
  15. //您的代码块 end
  16. return "success";
  17. }

PHP:

  1. $merchantNum = '您的商户号';
  2. $key = '您的接入密钥';
  3. $sign = sign(array($_GET['state'], $merchantNum, $_GET['orderNo'], $_GET['amount'], $key));
  4. // 鉴权
  5. if($merchantNum==$_GET['merchantNum'] && $sign == $_GET['sign']) {
  6. //鉴权通过后的业务代码编写
  7. //您的代码块 start
  8. //判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功标志
  9. //您的代码块 end
  10. echo "success";
  11. exit;
  12. }
  13. /**
  14. *签名方法
  15. */
  16. function sign($data_arr) {
  17. return md5(join('',$data_arr));
  18. };