API接口文档
首页
支付业务
首页
支付业务
  • 说明

    • 概述
    • 接口说明
  • JSAPI支付

    • 二维码支付
    • JSAPI支付
    • JSAPI调起支付
    • JSAPI支付通知
    • 付款码支付
  • 交易管理

    • 交易查询
    • 申请退款
    • 退款查询
    • 统一交易通知
  • 商户进件
    • 进件概述
    • 图片上传
    • 进件申请
    • 进件状态查询
    • 进件信息修改
    • 认证状态查询
    • MCC行业编码
    • 创建自定义表单定义
    • 申请固定二维码

接口说明

简介

此 API 用于提供聚合支付相关的api接口,所有请求均采用 POST 方法,并使用 SHA256withRSA 进行签名认证。

基础 URL

  • 基础路径: https://test-api.fuiouyes.com/

通讯方式

通信采用 HTTP 协议(TLSv1.2), POST 发送 JSON 格式的报文。

请求方式

POST

测试参数

merchantNo:0002270F8017406
shopId: 212628


通用请求参数

合作方系统调用平台 API 接口时,参数需要以通用请求报文格式上送。 上送前,合作方系统需要把业务参数组装成 json 串,赋值到通用请求报文中的 biz_content 字段;然后对通用请求报文进行签名

参数类型必填描述
app_idString是平台开发者应用 Id
biz_contentJson是每个接口的业务参数,需先组装成 json 串
timestampString是Unix 时间戳(秒),10 位数字
nonce_strString是随机字符串,固定 32 位
versionString是接口版本号,默认值:1.0
sign_typeString是签名类型,默认值:RSA
signString是签名字符串,通过对通用请求报文进行签名得到

通用响应参数

合作方系统成功调用 API 接口之后,平台将以通用响应报文格式返回结果数据。 被调用接口的业务数据需要从 data 字段中解析。

参数类型必填说明
codeString是请求响应码
messageString是响应信息
dataJson条件业务数据返回值,当 code 为"000000"时必须返回,表示请求成功
signString是响应签名

签名说明

1. 签名机制

采用 RSA 签名保证数据安全。开发者生成密钥对并与开放平台交换公钥,通讯时请求方使用己方私钥签名,响应方使用对方公钥验签。

2. 生成签名密钥

代码生成版:推荐使用命令行方式生成 RSA 公私钥,示例如下:


输入 openssl 进入 OpenSSL>模式 #生成私钥,2048 是密钥长度
OpenSSL> genrsa -out rsa_private_key.pem 2048 #将私钥转换成 PKCS8 格式(C#对应 PKCS1 格式)
OpenSSL> pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_private_key_pkcs8.pem #根据生成的私钥生成公钥
OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem #退出
OpenSSL> exit #在当前目录下可以找到对应的公钥和私钥文件

提示

生成的私钥贵司自行保存好;公钥发到群里,相关同事会给贵司配置参数,方便后续的交易操作。

3. 请求参数加签步骤

(1)步骤:

步骤一:待签名的请求参数,设为数据 D;

步骤二:对请求参数 D,进行参数名 ASCII 码从小到大排序,得到排序后的字符(去前后空格);

步骤三:加签——签名=RSA 签名方法("排序后字符串","自己生成私钥");

步骤四:得到签名后的报文。

请求域名

请联系技术人员获取

签名示例

假设传送的参数如下:

字段名 变量名必填类型示例值
app_id是String(32)开发者Idfy20190821aq1tzmv65j
version是String(32)版本号,目前固定为1.01.0
timestamp是String(32)Unix时间戳1573428705
nonce_str是String(32)随机字符串5K8264ILTKCH16CQ2502SI8ZNMTM67VS
sign_type是String(32)加密方式RSA
biz_content是JSON业务参数{"merchant_no":"001001F888888"}
sign是String(32)签名

第一步: 将请求参数中除 sign 外的多个键值对,按照 key=value 的格式,并按照参数名 ASCII 字典序排序如下:

import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

// 使用 TreeMap 自动按 key 的 ASCII 字典序排序
Map<String, String> params = new TreeMap<>();
params.put("app_id", "fy20190821aq1tzmv65j");
params.put("biz_content", "{\"merchant_no\":\"001001F888888\"}");
params.put("nonce_str", "5K8264ILTKCH16CQ2502SI8ZNMTM67VS");
params.put("sign_type", "RSA");
params.put("timestamp", "1573428705");
params.put("version", "1.0");

// 拼接成 key=value&key=value 格式
String stringA = params.entrySet().stream()
    .map(e -> e.getKey() + "=" + e.getValue())
    .collect(Collectors.joining("&"));

注意

nonce_str 必须参与签名计算。

第二步: 使用私钥进行签名计算

import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

// 读取私钥并签名
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKeyObj = keyFactory.generatePrivate(keySpec);

Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKeyObj);
signature.update(stringA.getBytes("UTF-8"));
byte[] signBytes = signature.sign();
String sign = Base64.getEncoder().encodeToString(signBytes);

第三步: 得到最终发送的数据:

{
  "app_id": "fy20190821aq1tzmv65j",
  "timestamp": "1573428705",
  "nonce_str": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS",
  "version": "1.0",
  "sign_type": "RSA",
  "biz_content": { "merchant_no": "001001F888888" },
  "sign": "hASzWUheJyT9q0Ikd+pjdZ+ee4ZG2umKdbY7JSttZs5+64TQTOvHuiGEfdqpFEmwoPUVy2yuwy6+9FzesjWG5lERqogpRtjiHFfznBUYSaDv2GBQIWUMejB0y+3EveNRqIuHbYZvqYXAjpmQc+dSQPBcJwC/X6D53nQfU/uUI3rKujatl6bDyNeVcomhael0nyulh++SY1g9TQPw1deg5VQ1ai2mgs5uGvIrX8grJQbRuNQuf/Dh0TXPvJAoUSqxHIemiC2Hwfo+MOhxlkvNYrnYVW4WvLIl4km7mZqKnVAHVVgN1G9LnqAFgxh1eObqwfz0hw+d79ypjjBJBEAd5Q=="
}

第四步: 发送请求,请求成功,得到响应数据包,开发者需要使用开放平台提供的公钥进行验签。

错误码说明

  • 501002:请求已过期,请检查 timestamp
  • 501003:重复请求,请更换 nonce_str
Prev
概述