简要描述
本文主要面向有一定开发基础的用户查阅对接,请仔细接口文档,如有疑问可以下载支付DEMO查看对接代码样例。 接口支持收款码通道、签约接口通道支付方式。 免签和签约接口相同,不同处为创建支付订单参数“支付方式 payType”的传值。
接口测试推荐工具:Postmam 或在线工具 https://getman.cn
接口地址
提供
HTTP
与HTTPS
两种协议接口,功能一样,您可以按需选择。
本地址在支付FM商户后台【用户中心】处可查看。
请求方式
请求方法:
POST
参数传递:Query
请求地址URL拼接参数
query指该参数需在请求URL传参
参数拼接示例:
http://接口地址?orderNo=20190629023134U93661199&amount=1&payType=wechat&merchantNum=tencent&sign=febf5e0e46fcc6bcadfc94c5fb46b0c2¬ifyUrl=https://zfapi.nnt.ltd/api/paySuccessNoticeTest
请求参数值说明
参数 | 必须 | 类型 | 说明 |
---|---|---|---|
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)开头的公网地址,若携带参数请先urlEncode编码后传入。 请勿用作支付成功验证,更不要和notifyUrl值传入一样。 顾客支付成功后会查看到的网址,系统自动跳转打开,常见为业务系统的支付成功提示、订单中心、会员中心网址等,又称同步跳转地址。 |
payType | 是 | string | query支付方式。 请根据所需对接的支付方式正确传值,需要在商户后台配置相应的收款号,参数请查看下文的payType可选值说明 |
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 传值说明
支付方式收款号配置的在商户后台,名称一致。
值 | 是否默认 | 类型 | 说明 | 通道类型 |
---|---|---|---|---|
否 | string | 收款码 - 微信 | 免签 | |
alipay | 否 | string | 收款码 - 支付宝(上传模式和动态码模式) | 免签 |
unipay | 否 | string | 收款码 - 云闪付 | 免签 |
qujie.qrcode | 否 | string | 收款码 - 趣街小二商家版 | 免签 |
jsnx.qrcode | 否 | string | 收款码 - 农商行收银宝 | 免签 |
bankapp | 否 | string | 网银APP收款 | 免签 |
alipaysign | 否 | string | 支付宝网站支付接口(电脑或手机自适应) | 签约 |
alipay.direct.pc | 否 | string | 支付宝电脑网站支付 | 签约 |
alipay.direct.wap | 否 | string | 支付宝手机网站支付 | 签约 |
alipay-facetoface | 否 | string | 支付宝当面付 | 签约 |
wxpayh5 | 否 | string | 微信支付H5 | 签约 |
wxpaynative | 否 | string | 微信支付Native | 签约 |
wxpayjsapi | 否 | string | 微信支付JSAPI | 签约 |
返回参数值说明
支付订单创建成功后,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:非FORM表单POST直接请求URL:
http://接口地址URL?orderNo=20190629023134U93661199&amount=1&payType=wechat&merchantNum=tencent&sign=febf5e0e46fcc6bcadfc94c5fb46b0c2¬ifyUrl=https://zfapi.nnt.ltd/api/paySuccessNoticeTes&payDuration=5
示例2 :form表单POST提交
<html><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>跳转支付中……</title></head><body><form style="display:none" id="fPay" method="post" action="接口地址URL"><input name="merchantNum" type="text" value="$merchantNum"/> <input name="amount" type="text" value="$amount"/> <input name="payType" type="text" value="$payType"/> <input name="returnUrl" type="text" value="$returnUrl"/> <input name="notifyUrl" type="text" value="$notifyUrl"/> <input name="orderNo" type="text" value="$orderID"/> <input name="subject" type="text" value="$subject"/> <input type="hidden" name="returnType" value="$returnType"/> <input name="sign" type="text" value="$sign"/></form><script type="text/javascript"> // 自动提交也可以手动通过按钮触发表单提交 = function(){document.getElementById("fPay").submit();}</script></body></html>
示例3:PHP构造curl方式提交,可以参考demo
$url="接口地址URL";
$native = array("merchantNum" => $merchantNum,
"payType" => $payType,
"amount" => $amount,
"orderNo" => $orderNo,
"notifyUrl" => $notifyUrl,
"returnUrl" => $returnUrl,
"sign" => $sign,
"returnType" => $returnType);
$param = http_build_query($native);
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$response = curl_exec($ch);
curl_close($ch);
return array($response);
推荐方式
示例4:php的json方式,完成的参考demo
<?php $returnType = "json"; $api_url = "接口地址"; //在用户中心页面查看 接口地址 $native = array( "merchantNum" => $merchantNum, "payType" => $payType, "amount" => $amount, "orderNo" => $orderNo, "notifyUrl" => $notifyUrl, "returnUrl" => $returnUrl, "sign" => $sign, "returnType" => $returnType ); $param = http_build_query($native); $return = http_request($api_url, $param, 'application/x-www-form-urlencoded;charset=utf-8');//http_request方法源码参考完整版本demo if(strpos($return,'{') === 0){ $return = json_decode($return, true); if($return['success']){ //json方式展示支付链接有如下几种 //header("location:".$return['data']['payUrl']); header("Refresh:0.1;url=" . $return['data']['payUrl']); //会在0.1秒后执行跳转 }else{ echo "请求异常"; } }else{ echo "请求异常"; } exit;?>
推荐方式
示例5:JAVA控制类核心代码,完整可参考demo
Map<String, Object> paramMap = new HashMap<>();// post请求的参数paramMap.put("merchantNum", merchantNum);paramMap.put("orderNo", orderNo);paramMap.put("amount", amount);paramMap.put("notifyUrl", notifyUrl);paramMap.put("returnUrl", returnUrl);paramMap.put("payType", payType);paramMap.put("attch", attch);paramMap.put("sign", sign);paramMap.put("subject", "测试商品标题");paramMap.put("body", "测试商品说明");String paramStr = HttpUtil.toParams(paramMap);System.out.println(paramStr);HttpClient httpclient = HttpClientBuilder.create().build();HttpPost httpost = new HttpPost(url + "?" + paramStr); // 设置响应头信息HttpResponse retResp;String result;JSONObject ret = new JSONObject();try { retResp = httpclient.execute(httpost); result = EntityUtils.toString(retResp.getEntity(), "UTF-8"); System.out.println(result);}catch (ClientProtocolException e1) { e1.printStackTrace();}catch (IOException e1) { e1.printStackTrace();}catch (ParseException e1) { e1.printStackTrace();}
返回示例
正确时返回:
returnType传值为json返回如下格式内容:HTTP状态码为200
{ "success": true, "msg": "success", "code": 200, "timestamp": 1624553174921, "data": { "id": "1408103748495998976", "payUrl": "http://XXXXX/pay?orderNo=1408103748495998976" }}
错误时返回:
其他返回错误代码请根据描述信息排查
HTTP状态码为400
{ "success": false, "msg": "签名不正确", "code": 500, "timestamp": 1584413776852, "data": null}
备注
返回值说明
msg | 说明 |
---|---|
success | 调用接口成功 |
用户账号无权限使用 | 调用接口传入的商户号不正确或者用户账号被限制使用 |
金额格式不正确 | 金额格式要为标准数值类型 |
金额不能小于或等于0 | 订单金额不能小于或等于0,请检查金额 |
免签通道订单金额不能小于1元 | 免签通道的接口调用订单金额至少为1元 |
签名不正确 | 签名不正确,请根据API签名规则检查MD5签名参数和结果是否正确 |
发起订单失败,通道不存在 | 通道不存在,请检查支付方式传值是否正确 |
商户接口额度不足,请充值 | 商户接口额度不足,请登录支付FM充值可收款接口额度 |
XXX:must not be blank或XXX:不能为空 | 请求参数值没有按照规范传递到我们接口,一般为请求方式或请求数据不合法导致。请检查参数名是否和文档要求一致,请求方式是post,参数是param方式不是json等 |
returnUrl保留参数说明
订单为已支付状态时,系统会根据传入的 returnUrl进行页面重定向跳转,以下参数为跳转时候系统默认携带,请勿携带传入。
携带参数初衷用于配合业务系统的页面展示,请勿用于订单已支付校验判断。
参数 | 说明 |
---|---|
orderNo | 商户订单号 |
mchOrderNo | 商户订单号 |
platformOrderNo | 平台订单号 |
amount | 商户订单金额 |
actualPayAmount | 实际支付金额 |
MD5签名示例
支付DEMO中有完整说明和建议使用的工具包,以下只是签名示例(JAVA),其他语言可以用示例参数签名,签名结果一致表示签名函数是可用的。 供技术调试对比MD5算法用:abc123456的MD5加密串:大写:0659C7992E268962384EB17FAFE88364,小写:0659c7992e268962384eb17fafe88364
package ltd.nnt.zhifu.test;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Utils {
/**
* 使用md5的算法进行加密
*/
public static String md5(String plainText) {
byte[] secretBytes = null;
try {
secretBytes = MessageDigest.getInstance("md5").digest(
plainText.getBytes());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("没有md5这个算法!");
}
String md5code = new BigInteger(1, secretBytes).toString(16);// 16进制数字
// 如果生成数字未满32位,需要前面补0
for (int i = 0; i < 32 - md5code.length(); i++) {
md5code = "0" + md5code;
}
return md5code;
}
public static void main(String[] args) {
System.out.println(md5("abc123456"));
}
}
API说明 - 《支付FM文档中心》:https://docs.nephalem.cn/read/zhifufm/api