简要描述

本文主要面向有一定开发基础的用户查阅对接,请仔细接口文档,如有疑问可以下载支付DEMO查看对接代码样例。 接口支持收款码类型、签约接口类型支付方式。 免签和签约接口相同,不同处为创建支付订单参数“支付方式 payType”的传值。
接口测试推荐工具:Postmam 或在线工具 https://getman.cn

接口地址

支持HTTPHTTPS,您可按需选择。
在支付FM商户后台【用户中心】处查看【接口地址】对应的值。 如果你的业务网站开启了https访问,请使用https开头的接口地址请求接口。

请求方式

请求方法:POST
参数传递:Query
Content-Type:application/x-www-form-urlencoded
query:参数在接口地址中拼接传参或form表单提交

请求参数值说明

参数 必须 类型 说明
merchantNum string query商户号。在支付FM商户后台【用户中心】处可查看,该值不是用户名。
orderNo string query商户订单号。仅允许字母或纯数字,建议不超过32字符,不能有中文
amount number query订单金额。请求的支付金额(单位:元),最多小数点后保留2位
returnType string query接口内容返回类型。
参数请查看下文的returnType可选值说明
notifyUrl string query支付结果通知网址又称异步回调网址。200字符以内,
http(s)开头的网址。商户业务系统用来接收支付结果通知数据的回调地址,通知url必须为外网可直接访问的网址,且不能携带参数,收到通知后请根据规范返回成功标志,请根据通知参数规范使用Postmam等工具功能测试后传入。
示例值:https://www.xxxx.com/payfm/payCalback.php
returnUrl string query成功后展示网址。200字符以内,
http(s)开头的公网地址。请勿用作支付成功验证,更不要和notifyUrl值传入一样。顾客支付成功后会查看到的网址,系统自动跳转打开,常见为业务系统的支付成功提示、订单中心、会员中心网址等,又称同步跳转地址。
payType string query支付方式。
请根据所需对接的支付方式正确传值,需要在商户后台配置相应的收款号,参数请查看下文的支付方式payType选值说明
payee string query指定收款号。
该值为在本平台设置的 免签类型的手机编号/签约类型的微信系的账号标识/签约类型的支付宝系的支付宝账号 的值。
attch string query附加信息,回调时候原样回传。空内容会被忽略不再回传。
subject string query商品标题。100字符以内,签约类型会原样传到支付平台
body string query商品描述。200字符以内,签约类型会原样传到支付平台
payDuration integer query订单支付有效期,单位:分钟;默认值5,最大值15。例:payDuration=5表示订单支付有效期5分钟
sign string query签名。待签名字符串进行MD5加密得出的32位签名值,小写。待签名字符串=商户号+商户订单号+支付金额+异步通知地址+接入密钥;其中“+”表示字符串拼接,请注意拼接顺序。接入密钥在支付FM商户后台【用户中心】处可查看。
returnType 传值说明

是否默认 类型 说明
json string 接口返回json数据
page string 接口直接重定向到支付页面,部分开发语言非页面form表单直接提交的有可能无法重定向,请通过json获取支付链接自行跳转。
payType 传值说明

支付方式的收款号配置在商户后台,分别在我们平台后台的【免签类型】和【签约类型】(旧称【免签类型】和【签约类型】)功能菜单下,调用接口前请确保已经配置了对应的收款账号。

是否默认 类型 说明 类型类型
wechat string 收款码 - 微信 免签
alipay string 收款码 - 支付宝(上传模式和动态码模式) 免签
unipay string 收款码 - 云闪付 免签
qujie.qrcode string 收款码 - 趣街小二商家版 免签
jsnx.qrcode string 收款码 - 农商行收银宝 免签
bankapp string 网银APP收款 免签
sqb.qrcode string 收钱吧APP收款码 免签
fubei.qrcode string 付呗APP收款码 免签
qdl.qrcode string 钱到啦APP收款码 免签
alipaysign string 支付宝网站支付接口(电脑或手机自适应) 签约
alipay.direct.pc string 支付宝电脑网站支付 签约
alipay.direct.wap string 支付宝手机网站支付 签约
alipay-facetoface string 支付宝当面付,跨地区收款不推荐使用 签约
wxpayh5 string 微信支付H5 签约
wxpaynative string 微信支付Native 签约
wxpayjsapi string 微信支付JSAPI 签约
fuyou-aliqr string 富友支付-支付宝扫码 ,跨地区收款不推荐使用 签约
fuyou-wxqr string 富友支付-微信扫码 签约
fuyou-bankqr string 富友支付-网银APP扫码 签约

返回参数值说明

支付订单创建成功后,returnType传值为json时HTTP状态码为200且返回JSON数据; 支付订单未成功创建HTTP状态码为400且返回JSON数据。常见返回内容说明请参考本文末“返回值说明”。

参数 必须 类型 说明
success boolean 正常标志
code number 信息编码。200代表正常。此编码非HTTP状态码,别混淆了。
timestamp number 毫秒时间戳。
msg string 信息描述。
data json 数据内容,支付订单创建成功有值。

data内容参数:

参数 必须 类型 说明
id string 平台订单号。接口请求成功有值
payUrl string 支付链接。 接口请求成功时候有值。顾客访问该网址就可以根据不同支付方式效果进行支付。如您的业务系统为APP,请调用手机浏览器访问此链接,这样支付效果更稳定,不建议在APP内直接访问

参考示例

请求示例

此处罗列一些常用请求的部分代码供参考,完整代码可以参考demo篇章。注意: java系统若使用老版hutool工具请求https接口可能会报错需升级到JDK11或使用http协议请求或使用demo中方法请求。

示例1:php的直接跳转到支付页面写法,page接收方式

  1. // php 自动跳转
  2. // 开发手册:http://docs.zhifux.com/read/zhifufm/step
  3. $amount = "订单金额"; // 获取充值金额
  4. $orderNo = '商户订单号'; // 商户系统创建的订单号
  5. $merchantNum = '商户号'; // 商户号, 商户后台的用户中心页面查看
  6. $secret = '接入密钥'; // 接入密钥, 商户后台的用户中心页面查看
  7. $api_url = '接口地址'; // 接口地址, 商户后台的用户中心页面查看
  8. $payType = "支付方式值"; // 前端传入的支付方式值,查看支付接口文档说明payType的取值
  9. $notifyUrl = '通知接收接口地址'; // XXXX修改为您自己用来接收支付成功的公网地址
  10. $returnUrl = ''; // 已支付订单状态后会跳转,一般为您想让顾客支付后看到的页面
  11. $returnType = "page"; // 接口返回方式 page为直接跳转到支付页面,不传返回json
  12. $sign = md5 ( $merchantNum.$orderNo.$amount.$notifyUrl.$secret); //待签名字符串=商户号+商户订单号+支付金额+异步通知地址+接入密钥
  13. echo '<html>
  14. <head><title>redirect...</title></head>
  15. <body>
  16. <form id="post_data" action="' . $api_url . '" method="post">
  17. <input type="hidden" name="merchantNum" value="' . $merchantNum . '"/>
  18. <input type="hidden" name="payType" value="' . $payType . '"/>
  19. <input type="hidden" name="amount" value="' . $amount . '"/>
  20. <input type="hidden" name="orderNo" value="' . $orderNo . '"/>
  21. <input type="hidden" name="notifyUrl" value="' . $notifyUrl . '"/>
  22. <input type="hidden" name="returnUrl" value="' . $returnUrl . '"/>
  23. <input type="hidden" name="sign" value="' . $sign . '"/>
  24. <input type="hidden" name="returnType" value="' . $returnType . '"/>
  25. </form>
  26. <script>document.getElementById("post_data").submit();</script>
  27. </body>
  28. </html>';

示例2 :form表单直接提交
如果您的网站开启了SSL,请使用https的接口地址。

  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  4. <title>跳转支付中……</title></head>
  5. <body>
  6. <form style="display:none" id="fPay" method="post" action="接口地址URL">
  7. <input name="merchantNum" type="text" value="$merchantNum"/>
  8. <input name="amount" type="text" value="$amount"/>
  9. <input name="payType" type="text" value="$payType"/>
  10. <input name="returnUrl" type="text" value="$returnUrl"/>
  11. <input name="notifyUrl" type="text" value="$notifyUrl"/>
  12. <input name="orderNo" type="text" value="$orderID"/>
  13. <input name="subject" type="text" value="$subject"/>
  14. <input type="hidden" name="returnType" value="$returnType"/>
  15. <input name="sign" type="text" value="$sign"/>
  16. </form>
  17. <script type="text/javascript">
  18. // 自动提交也可以手动通过按钮触发表单提交
  19. window.onload= function(){document.getElementById("fPay").submit();}
  20. </script>
  21. </body>
  22. </html>

推荐方式示例3:php的后台接收支付链接并跳转示例,json接收方式

  1. <?php
  2. $returnType = "json";
  3. $api_url = "接口地址"; //在用户中心页面查看 接口地址
  4. $key = "接入密钥"; //在用户中心页面查看 接入密钥
  5. $sing = md5($merchantNum.$orderNo.$amount.$notifyUrl.$key); //待签名字符串=商户号+商户订单号+支付金额+异步通知地址+接入密钥
  6. $native = array(
  7. "merchantNum" => $merchantNum,
  8. "payType" => $payType,
  9. "amount" => $amount,
  10. "orderNo" => $orderNo,
  11. "notifyUrl" => $notifyUrl,
  12. "returnUrl" => $returnUrl,
  13. "sign" => $sign,
  14. "returnType" => $returnType
  15. );
  16. $param = http_build_query($native);
  17. $ch = curl_init ();
  18. curl_setopt ( $ch, CURLOPT_URL, $url );
  19. curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
  20. curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 );
  21. curl_setopt ( $ch, CURLOPT_POST, 1 );
  22. curl_setopt ( $ch, CURLOPT_POSTFIELDS, $param );
  23. curl_setopt ( $ch, CURLOPT_CONNECTTIMEOUT, 60 );
  24. curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
  25. curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
  26. curl_setopt ( $ch, CURLOPT_HTTPHEADER, array (
  27. 'application/x-www-form-urlencoded;charset=utf-8',
  28. 'Content-Length: ' . strlen ( $param )
  29. ) );
  30. $return = curl_exec ( $ch );
  31. curl_close ( $ch );
  32. if(strpos($return,'{') === 0){
  33. $return = json_decode($return, true);
  34. if($return['success']){
  35. //json方式接收,可以跳转也可以根据你们自己框架处理支付链接
  36. //header("location:".$return['data']['payUrl']);
  37. header("Refresh:0.1;url=" . $return['data']['payUrl']); //会在0.1秒后执行跳转
  38. }else{
  39. echo "请求异常";
  40. }
  41. }else{
  42. echo "请求异常";
  43. }
  44. exit;
  45. ?>

推荐方式示例4:JAVA控制类核心代码,完整可参考demo

  1. Map<String, Object> paramMap = new HashMap<>();// post请求的参数
  2. paramMap.put("merchantNum", merchantNum);
  3. paramMap.put("orderNo", orderNo);
  4. paramMap.put("amount", amount);
  5. paramMap.put("notifyUrl", notifyUrl);
  6. paramMap.put("returnUrl", returnUrl);
  7. paramMap.put("payType", payType);
  8. paramMap.put("attch", attch);
  9. paramMap.put("sign", sign);
  10. paramMap.put("subject", "测试商品标题");
  11. paramMap.put("body", "测试商品说明");
  12. String paramStr = HttpUtil.toParams(paramMap);
  13. System.out.println(paramStr);
  14. HttpClient httpclient = HttpClientBuilder.create().build(); //httpclient-4.5.6.jar
  15. HttpPost httpost = new HttpPost(url + "?" + paramStr); // 设置响应头信息
  16. HttpResponse retResp; //httpcore-4.4.10.jar
  17. String result;
  18. JSONObject ret = new JSONObject();
  19. try {
  20. retResp = httpclient.execute(httpost);
  21. result = EntityUtils.toString(retResp.getEntity(), "UTF-8");
  22. System.out.println(result);
  23. }
  24. catch (ClientProtocolException e1) {
  25. e1.printStackTrace();
  26. }
  27. catch (IOException e1) {
  28. e1.printStackTrace();
  29. }catch (ParseException e1) {
  30. e1.printStackTrace();
  31. }

返回示例

正确时返回:
returnType传值为json返回如下格式内容:
HTTP状态码为200

  1. {
  2. "success": true,
  3. "msg": "success",
  4. "code": 200,
  5. "timestamp": 1624553174921,
  6. "data": {
  7. "id": "1408103748495998976",
  8. "payUrl": "http://XXXXX/pay?orderNo=1408103748495998976"
  9. }
  10. }

错误时返回:

其他返回错误代码请根据描述信息排查
HTTP状态码为400

  1. {
  2. "success": false,
  3. "msg": "签名不正确",
  4. "code": 500,
  5. "timestamp": 1584413776852,
  6. "data": null
  7. }

其他说明

返回值说明

msg 说明
success 调用接口成功
用户账号无权限使用 调用接口传入的商户号不正确或者用户账号被限制使用
金额格式不正确 金额格式要为标准数值类型
金额不能小于或等于0 订单金额不能小于或等于0,请检查金额
免签类型订单金额不能小于1元 免签类型的接口调用订单金额至少为1元
签名不正确 签名不正确,请根据API签名规则检查MD5签名参数和结果是否正确
发起订单失败,类型不存在 类型不存在,请检查支付方式传值是否正确
商户接口额度不足,请充值 商户接口额度不足,请登录支付FM充值可收款接口额度
XXX:must not be blank或XXX:不能为空 请求参数值没有按照规范传递到我们接口,一般为请求方式或请求数据不合法导致。请检查参数名是否和文档要求一致,请求方式是post,参数是param方式不是json等
无可用收款方式的收款账号 检查接口传入的PayType值对应的支付方式的收款号后台有没有正确配置

returnUrl保留参数说明

订单为已支付状态时,系统会根据传入的 returnUrl进行页面重定向跳转,以下参数为跳转时候系统默认携带,请勿携带传入。

携带参数初衷用于配合业务系统的页面展示,请勿用于订单已支付校验判断。回调通知参数接收请参考支付通知接口说明

参数 说明
orderNo 商户订单号
mchOrderNo 商户订单号
platformOrderNo 平台订单号
orderState 跳转状态值
amount 商户订单金额
actualPayAmount 实际支付金额

MD5签名示例

支付DEMO中有完整说明和建议使用的工具包,以下只是签名示例(JAVA),其他语言可以用示例参数签名,签名结果一致表示签名函数是可用的。 供技术调试对比MD5算法用:abc123456的MD5加密串:大写:0659C7992E268962384EB17FAFE88364,小写:0659c7992e268962384eb17fafe88364

  1. package ltd.nnt.zhifu.test;
  2. import java.math.BigInteger;
  3. import java.security.MessageDigest;
  4. import java.security.NoSuchAlgorithmException;
  5. public class MD5Utils {
  6. /**
  7. * 使用md5的算法进行加密
  8. */
  9. public static String md5(String plainText) {
  10. byte[] secretBytes = null;
  11. try {
  12. secretBytes = MessageDigest.getInstance("md5").digest(
  13. plainText.getBytes());
  14. } catch (NoSuchAlgorithmException e) {
  15. throw new RuntimeException("没有md5这个算法!");
  16. }
  17. String md5code = new BigInteger(1, secretBytes).toString(16);// 16进制数字
  18. // 如果生成数字未满32位,需要前面补0
  19. for (int i = 0; i < 32 - md5code.length(); i++) {
  20. md5code = "0" + md5code;
  21. }
  22. return md5code;
  23. }
  24. public static void main(String[] args) {
  25. System.out.println(md5("abc123456"));
  26. }
  27. }