目录:

  1. 场景介绍
    1.1 医后付场景
  2. 接入指引
    2.1 准备工作
    2.2 接口调用规范
    2.2.1 请求说明
  3. API列表
    3.1 获取签约URL
    3.2 签约查询
    3.3 协议解约
    3.4 代扣支付
    3.5 交易结果查询接口
    3.6 交易退款接口
    3.7 交易退款结果查询接口
    3.8 关闭订单
    3.9 对账文件下载
  4. 修订记录

1. 场景介绍

商户发起获取签约URL请求,并且发送相关参数,商户可以拿到响应的签约URL,制作成二维码用户使用支付宝APP扫描,或者用签约URL唤醒支付宝APP进行扫描完成签约。然后使用签约号可以进行支付,查询,解约等操作

1.2 医后付场景

医后付,商户先对用户进行签约拿到签约号,然后可以进行支付等操作。

注意:用于签约的机器,建议能够访问外网。因为扫码签约的时候,二维码页面是由支付宝重定向生成的,内网环境,需要配置白名单进行测试。

需要开通外网白名单地址:

扫码签约二维码示例:
签约二维码示例

2. 接入指引

2.1 准备工作

第一步、在支付宝/微信的开放平台申请应用

由于第三方平台针对“签约代扣”功能做了限制,“非公立机构”无法开通该功能,创业的聚合支付平台作企业,无法挂载该功能像当面付一样进行接口调用,需要院方以公立机构的主体,使用收款商户号对应的账号支付宝开放平台微信开放平台申请应用得到appid,生成公私钥或者密钥等加签信息,并申请开通“会员”相关功能,通过审核后,接口即可正常调用。

需要提供给平台技术支持人员的数据有:

  • 支付宝
    • appid(应用id)
    • pid(商户号)
    • 支付宝公钥
    • 应用私钥
  • 微信
    • appid(应用id)
    • mchId(商户号)
    • mchKey

第二步、获取开发者数据

调用聚合支付平台接口,需要与平台商务对接后,获取开发者ID(developId),密钥(privateKey),公钥(publicKey)和对称密钥(desKey),这些参数让商户拥有调用平台接口的权限,对请求的数据进行加密以保证数据的安全性。

  • 开发者ID(developerId):
      developerId在所有的请求中都需要传入,与密钥公钥信息相对应,鉴别请求是否是由平台商户发起。
  • 密钥(privateKey):
      密钥在接口请求中用于对数据进行RSA加密,生成签名sign。
  • 公钥(publicKey):
      公钥用于对签名进行解密
  • 对称密钥(desKey):
      在线上支付中,<body>标签的中的参数,需要通过des进行对称加密,得到密文进行请求。

第三步、获取平台商户号

每个商户对接聚合支付平台,在第三方平台想要拥有的支付能力,需要在支付宝或者微信签约对应的支付方式,平台的商务会为每个商户分配一个平台商户号(merchantNo),该商户号账户下所有的交易流水都会进入到对应的支付宝和微信的账户下,并且平台账单流水都是以商户号进行隔离,这是一个非常重要的参数。
由于自助机通过获取设备信息,需要传入平台信息,
因此,除了上述参数,还需要拿到以下信息:
平台应用id(appId)
平台pid(partnerId)

第四步、下载加解密sdk和demo

2.2 接口调用规范

2.2.1 请求说明
参数 类型 是否必填 最大长度 描述 示例
data String 300 请求参数转为xml格式 <xml><paytype>2</paytype><merchant_no>10000</merchant_no></xml>
developerId String 10 开发者id 12345
funcId String 20 功能码 P7001
sign String 100 将公共参数以“参数名”ASCII码顺序排序拼接成新字符串(参数名ASCII码从小到大排序(字典序))得到:“data=value1&developerId=value2&funcId=value3”,再将新的字符串经过RSA签名得到签名后的字符串 Sa/hb9jaTZZZq89mN62DDooLv/YTvfE9ayrbzgOMsucfIPZfJGmhUia6YWK8vQ5/NQana3Pub7BDswEenm0sBg==
  • 公共返回参数说明:
参数 类型 是否必填 最大长度 描述 示例
retCode String 30 0000:表示接口业务调用正常,9999:表示处理失败,如参数错误,验签失败等(注:retCode并不表示交易行为成功或失败,某笔交易是否成功请根据对应接口返回报文的状态字段来判定 0000
retMsg String 100 接口调用异常返回信息 验签失败

3. API列表

3.1 获取签约URL

  • 功能码:P9005

  • 接口说明:通过该接口获得扫码签约的链接,在客户机浏览器中访问该链接,会在页面生成签约二维码,供用户扫码进行签约(注意:每次获取签约URL时,商户给用户分配的商户协议号唯一)

  • 请求参数:<xml>

参数 名称 类型 长度 是否必填 说明 示例
merchant_no 收款商户号 String 30 创业聚合支付系统为医院分配的平台商户号 809900000001
merchant_agreement_no 商户协议号 String 64 商户给用户分配的协议号 商户内唯一 test
channel_type 渠道类型 String 2 2=支付宝 2
sign_type 签约类型 String 2 1=扫码签约, 2=钱包h5页面签约 1
idcard 用户身份证号 String 24 用户身份证号,用户姓名,用户身份证号和用户信息都传才能用于校验用户信息 61102619921108888
username 用户姓名 String 32 用户姓名,用户身份证号和用户信息都传才能用于校验用户信息 张三
mobile 手机号 String 32 用户手机号 13211112222
outer_id 用户唯一标识 String 64 商户端用户唯一标识 1
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
return_code 返回状态码 String 16 SUCCESS/OK代表成功 FAIL=代表失败 SUCCESS
return_msg 返回信息 String 128 返回信息 OK
merchant_agreement_no 商户协议号 String 64 商户给用户分配的协议号 商户内唯一
sign_url 签约url String 1000 用于签约的url, 成功必传使用前先用URLDecoder 解码 1
outerid 用户唯一标识 String 64 商户端用户唯一标识,返回请求传入的值 4200000376201908224052992001
  • Java请求示例:
    String data = "<xml>" +
                  "<merchant_agreement_no>test</merchant_agreement_no>" +
                  "<idcard>61102619921108888</idcard>" +
                  "<username>测试者</username>" +
                  "<mobile>123213213</mobile>" +
                  "<merchant_no>1001003</merchant_no>" +
                  "<channel_type>2</channel_type>" +
                  "<sign_type>1</sign_type>" +
                  "<outer_id>12321</outer_id>" +
                  "</xml>";
          List<NameValuePair> list = new ArrayList<NameValuePair>();
          NameValuePair valu1 = new BasicNameValuePair("data",data);
          NameValuePair valu2 = new BasicNameValuePair("developerId",[your developerId]);
          NameValuePair valu3 = new BasicNameValuePair("funcId","P9005");
          String privateKey = [your privateKey];
          String signData = "data="+data+"&developerId=[your developerId]&funcId=P9005";
          String sign = SecurityUtil.signRSA(signData,privateKey,"utf-8");
          NameValuePair valu4 = new BasicNameValuePair("sign",sign);
          list.add(valu1);
          list.add(valu2);
          list.add(valu3);
          list.add(valu4);
          String xml = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://offlinetest.bsoftpay.com/gatewayOffline/pay/offline/execute").setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8)).build());
              xml = EntityUtils.toString(response.getEntity());
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(xml);
  • 返回示例:
    developerId=12345&funcId=P9005&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <xml>
    <return_code>SUCCESS</return_code>
    <return_msg>生成连接成功</return_msg>
    <merchant_agreement_no>test</merchtestant_agreement_no>
    <sign_url>alipays%3A%2F%2Fplatformapi%2Fstartapp%3FappId%3D60000157%26appClearTop%3Dfalse%26startMultApp%3DYES%26sign_params%3Dalipay_sdk%253Dalipay-sdk-java-3.7.4.ALL%2526app_id%253D2019122060095079%2526biz_content%253D%25257B%252522access_params%252522%25253A%25257B%252522channel%252522%25253A%252522ALIPAYAPP%252522%25257D%25252C%252522external_agreement_no%252522%25253A%25252240%252522%25252C%252522personal_product_code%252522%25253A%252522GENERAL_WITHHOLDING_P%252522%25252C%252522sign_scene%252522%25253A%252522INDUSTRY%25257CMEDICAL%252522%25257D%2526charset%253Dutf-8%2526format%253Djson%2526method%253Dalipay.user.agreement.page.sign%2526sign%253DMFoOTtXEDqrGK1F0nmJ8pQenba8LJ5mlRe5MhivqLeOkpThueIXRLjYaE3Z8U8EUBd5e25khHkhiVcFCjWIdJmWKhFkRKTNzVmZJueV2cZYGOtnaf0ZajWgQJMY3Md2Rhm0o6zT6mH0UBwipcaYv%25252FbxCDAkOTWKNOtP1uZePko5m0N7%25252BSCeBYdGH6dnAOc9tAHpbBmjQyFq0izVtHf4Fyt3Gftux1qXD2vz91qqKfvXoi%25252B80eYt2HH6ovtrSpuDa502YtdTP1gw7tuIandWFCKhvEUeTkDNDEB8izU6e8k9%25252FlFg2YykbKuXR2%25252Be2U4INnSRv1NXOxSuop%25252Bn2rBhOSg%25253D%25253D%2526sign_type%253DRSA2%2526timestamp%253D2019-12-24%252B11%25253A19%25253A52%2526version%253D1.0</sign_url>
    <outerid>1</outerid>
    </xml>
    &sign=Apu4i49RBQkh94n5BVEA/Ao35tjfT8BsTPA9fOqKUmbKJ37Pszfi0sS9R15OLEpXJYo6p2v+uw1fr/BE+PSxHg==
  • 异常返回示例:
    developerId=12345&funcId=P9005&retCode=9999&retMsg=签约功能还未开通&sign=XD1unE4I2pM/jWMXy1o7NwVB2H3yfkmxluH2qz3xRt+mB8VQNSLhKnz79+5PuRfz9Q4y44CKCyL7S21iQzOHbg==
  • 注意:签名sign生成之后,在请求发送之前,需要对签名字符串进行urlEncode编码,否则字符串在传递过程中可能会不完整,从而导致“验证签名失败”

3.2 签约查询

  • 功能码:P9006
  • 接口说明:获取签约协议状态。
  • 请求参数:<xml>
参数 名称 类型 长度 是否必填 说明 示例
merchant_no 收款商户号 String 30 创业聚合支付系统为医院分配的平台商户号 809900000001
merchant_agreement_no 商户协议号 String 64 商户给用户分配的协议号 商户内唯一 test
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
return_code 返回状态码 String 16 SUCCESS/OK代表成功 FAIL=代表失败 SUCCESS
return_msg 返回信息 String 128 返回信息 OK
merchant_agreement_no 商户协议号 String 64 商户给用户分配的协议号 商户内唯一
status 签约状态 String 2 0-未签约,1=已签约 ,2=解约 1
valid_time 渠道生效时间 String 10 签约生效时间 20170520114919
invalid_time 渠道失效时间 String 10 签约失效时间 20170520114919
sign_time 渠道签约时间 String 10 签约失效时间 20170520114919
unsign_time 渠道解约时间 String 10 渠道解约时间 20170520114919
outerid 用户唯一标识 String 64 商户端用户唯一标识,返回请求传入的值 4200000376201908224052992001
  • Java请求示例:
    String data = "<xml>" +
                  "<merchant_no>1001003</merchant_no>" +
                  "<merchant_agreement_no>test</merchant_agreement_no>" +
                  "</xml>";
          List<NameValuePair> list = new ArrayList<NameValuePair>();
          NameValuePair valu1 = new BasicNameValuePair("data",data);
          NameValuePair valu2 = new BasicNameValuePair("developerId",[your developerId]);
          NameValuePair valu3 = new BasicNameValuePair("funcId","P9006");
          String privateKey = [your privateKey];
          String signData = "data="+data+"&developerId=[your developerId]&funcId=P9006";
          String sign = SecurityUtil.signRSA(signData,privateKey,"utf-8");
          NameValuePair valu4 = new BasicNameValuePair("sign",sign);
          list.add(valu1);
          list.add(valu2);
          list.add(valu3);
          list.add(valu4);
          String xml = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://offlinetest.bsoftpay.com/gatewayOffline/pay/offline/execute").setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8)).build());
              xml = EntityUtils.toString(response.getEntity());
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(xml);
  • 返回示例:
    developerId=12345&funcId=P9005&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <xml>
    <return_code>SUCCESS</return_code>
    <return_msg>操作成功</return_msg>
    <return_code>test</merchtestant_agreement_no>
    <valid_time>20170520114919</valid_time>
    <invalid_time>20170520114919</invalid_time>
    <sign_time>1</sign_time>
    <unsign_time>1</unsign_time>
    <outerid>1</outerid>
    </xml>
    &sign=Apu4i49RBQkh94n5BVEA/Ao35tjfT8BsTPA9fOqKUmbKJ37Pszfi0sS9R15OLEpXJYo6p2v+uw1fr/BE+PSxHg==
  • 异常返回示例:
    developerId=12345&funcId=P9005&retCode=9999&retMsg=该商户号不存在&sign=XD1unE4I2pM/jWMXy1o7NwVB2H3yfkmxluH2qz3xRt+mB8VQNSLhKnz79+5PuRfz9Q4y44CKCyL7S21iQzOHbg==

    3.3 协议解约

  • 功能码:P9007
  • 接口说明:保证每次获取签约URL时,商户给用户分配的商户协议号唯一。
  • 请求参数:<xml>
参数 名称 类型 长度 是否必填 说明 示例
merchant_no 收款商户号 String 30 创业聚合支付系统为医院分配的平台商户号 809900000001
merchant_agreement_no 商户协议号 String 64 商户给用户分配的协议号 商户内唯一 test
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
return_code 返回状态码 String 16 SUCCESS/OK代表成功 FAIL=代表失败 SUCCESS
return_msg 返回信息 String 128 返回信息 OK
merchant_agreement_no 商户协议号 String 64 商户给用户分配的协议号 商户内唯一
status 签约状态 String 2 0-未签约,1=已签约 ,2=解约 3
valid_time 渠道生效时间 String 10 签约生效时间 20170520114919
invalid_time 渠道失效时间 String 10 签约失效时间 20170520114919
  • Java请求示例:
    String data = "<xml>" +
                 "<merchant_no>1001003</merchant_no>" +
                 "<merchant_agreement_no>test</merchant_agreement_no>" +
                 "</xml>";
          List<NameValuePair> list = new ArrayList<NameValuePair>();
          NameValuePair valu1 = new BasicNameValuePair("data",data);
          NameValuePair valu2 = new BasicNameValuePair("developerId",[your developerId]);
          NameValuePair valu3 = new BasicNameValuePair("funcId","P9007");
          String privateKey = [your privateKey];
          String signData = "data="+data+"&developerId=[your developerId]&funcId=P9007";
          String sign = SecurityUtil.signRSA(signData,privateKey,"utf-8");
          NameValuePair valu4 = new BasicNameValuePair("sign",sign);
          list.add(valu1);
          list.add(valu2);
          list.add(valu3);
          list.add(valu4);
          String xml = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://offlinetest.bsoftpay.com/gatewayOffline/pay/offline/execute").setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8)).build());
              xml = EntityUtils.toString(response.getEntity());
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(xml);
  • 返回示例:
    developerId=12345&funcId=P9007&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <xml>
    <return_code>SUCCESS</return_code>
    <return_msg>生成连接成功</return_msg>
    <status>3</status>
    <merchant_agreement_no>test</merchtestant_agreement_no>
    <valid_time>20170520114919</valid_time>
    <invalid_time>20170520114919</invalid_time>
    </xml>
    &sign=Apu4i49RBQkh94n5BVEA/Ao35tjfT8BsTPA9fOqKUmbKJ37Pszfi0sS9R15OLEpXJYo6p2v+uw1fr/BE+PSxHg==
  • 异常返回示例:
    developerId=12345&funcId=P9005&retCode=9999&retMsg=该商户号不存在&sign=XD1unE4I2pM/jWMXy1o7NwVB2H3yfkmxluH2qz3xRt+mB8VQNSLhKnz79+5PuRfz9Q4y44CKCyL7S21iQzOHbg==

3.4 代扣支付

  • 功能码:P7001
  • 接口说明:代扣支付,必传签约协议号。
  • 请求参数:<xml>
参数 名称 类型 长度 是否必填 说明 示例
treatment_id 诊疗卡卡号 String 30 患者的诊疗卡卡号 123
merchant_no 收款商户号 String 30 创业聚合支付系统为医院分配的平台商户号 809900000001
username 支付者姓名 String 30 付款者姓名 张三
order_no 业务单号 String 30 商户业务系统的唯一订单号 BX20190722902141
paytype 支付渠道 String 2 2=支付宝; 3=微信 2
trade_type 交易类型 String 2 10=签约代扣 10
total_amt 支付金额 Price 20.2 以元为单位 0.01
spbill_create_ip 用户IP String 10 客户端实际ip(微信需要) 183.156.115.113
order_subject 商品标题 String 150 如:门诊、住院预交、住院结算、自助缴费等 门诊
order_detail 商品描述 String 300 如:门诊挂号、门诊结算、住院预交、住院结算、自助挂号、自助结算、自助住院预交等 门诊挂号
merchant_agreement_no 商户签约协议号 String 64 商户给用户分配的协议号,用户签约的唯一标识 商户内唯一,必传
sub_merchant 分店号 String 30 商户内部区分订单字段 001
paytimeout 订单超时时间 String 3 单位是: m (分钟) 如果不填,默认是 6分钟,如果填,必须大于5分钟 6
mobile 手机号码 String 15 用户手机号 13211112222
remark 备注 String 200 备注
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
return_code 返回状态码 String 16 SUCCESS/OK代表成功 FAIL=代表失败 WAIT=待支付 不能以此作为支付成功标志,支付结果以status为准 SUCCESS
return_msg 返回信息 String 128 返回信息 OK
status 支付状态 String 2 1=成功;0=支付中 需要调用查询接口轮询查询订单状态 1
pay_orderno 支付渠道流水号 String 32 支付宝或微信流水号 4200000376201908224052992001
order_no 平台流水号 String 32 商户内部流水号 34411000
out_tradeno 业务单号 String 32 聚合支付平台流水号 BX20190722902141
time_end 支付完成时间 String 32 支付完成时间,格式:yyyyMMddHHmmss 20190722205306
amt 实际支付金额 Price 16.2 实际支付金额 0.01
receipt_amount 商户收到的金额 Price 16.2 商户收到的金额(相当于订单支付金额) 0.01
  • Java请求示例:
    String data = "<xml>" +
                  "<treatment_id>123123123123</treatment_id>" +
                  "<merchant_no>1001003</merchant_no>" +
                  "<username>测试者</username>" +
                  "<order_no>"+ "xw20190722001"+"</order_no>" +
                  "<paytype>3</paytype>" +
                  "<trade_type>2</trade_type>" +
                  "<total_amt>0.01</total_amt>" +
                  "<spbill_create_ip>192.168.11.1</spbill_create_ip>" +
                  "<order_subject>测试</order_subject>" +
                  "<order_detail>测试</order_detail>" +
                  "<merchant_agreement_no>130195331105619585</merchant_agreement_no>" +
                  "</xml>";
          List<NameValuePair> list = new ArrayList<NameValuePair>();
          NameValuePair valu1 = new BasicNameValuePair("data",data);
          NameValuePair valu2 = new BasicNameValuePair("developerId",[your developerId]);
          NameValuePair valu3 = new BasicNameValuePair("funcId","P7001");
          String privateKey = [your privateKey];
          String signData = "data="+data+"&developerId=[your developerId]&funcId=P7001";
          String sign = SecurityUtil.signRSA(signData,privateKey,"utf-8");
          NameValuePair valu4 = new BasicNameValuePair("sign",sign);
          list.add(valu1);
          list.add(valu2);
          list.add(valu3);
          list.add(valu4);
          String xml = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://offlinetest.bsoftpay.com/gatewayOffline/pay/offline/execute").setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8)).build());
              xml = EntityUtils.toString(response.getEntity());
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(xml);
  • 返回示例:
    developerId=12345&funcId=P7001&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <xml>
    <return_code>SUCCESS</return_code>
    <return_msg>OK</return_msg>
    <status>1</status>
    <pay_orderno>4200000376201907220000000000</pay_orderno>
    <order_no>34411000</order_no>
    <out_tradeno>WX15637998177239200001</out_tradeno>
    <time_end>20190722205306</time_end>
    <amt>0.01</amt>
    <receipt_amount>0.01</receipt_amount>
    </xml>
    &sign=Apu4i49RBQkh94n5BVEA/Ao35tjfT8BsTPA9fOqKUmbKJ37Pszfi0sS9R15OLEpXJYo6p2v+uw1fr/BE+PSxHg==
  • 异常返回示例:
    developerId=12345&funcId=P7001&retCode=9999&retMsg=商户协议号:tet未签约&sign=XD1unE4I2pM/jWMXy1o7NwVB2H3yfkmxluH2qz3xRt+mB8VQNSLhKnz79+5PuRfz9Q4y44CKCyL7S21iQzOHbg==
  • 注意:签名sign生成之后,在请求发送之前,需要对签名字符串进行urlEncode编码,否则字符串在传递过程中可能会不完整,从而导致“验证签名失败”

3.5 交易结果查询接口

  • 功能码:P2005
  • 接口说明:通过该接口获取某个订单的支付结果
  • 请求参数:<Data>
参数 名称 类型 长度 是否必填 说明 示例
order_no 业务单号 String 32 商户内部业务单号 WX2019072200001
merchant_no 收款商户号 String 32 商户号 809900000001
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
TradeNo 平台流水号 String 32 聚合支付平台流水号 34411000
PayTradeNo 渠道流水号 String 32 各个支付渠道返回的流水号 4200000376201907220000000000
OrderNo 业务单号 String 32 商户内部业务单号 WX2019072200001
Amt 实际支付金额 Price 16.2 用户实际付款金额 0.01
PayTime 实际支付时间 String 16 yyyy-MM-dd hh:mm:ss 2019-07-22 21:37:31
PayStatus 支付状态 String 6 0=未支付;1=支付成功;2=支付失败;-1=关闭或撤销 1
receipt_amount 商户收到的金额 Price 16.2 相当于订单支付金额 0.01
  • JAVA请求示例:
    String data = "<Data>" +
                  "<order_no>WX2019072200001</order_no>\n" +
                  "<merchant_no>809900000001</merchant_no>\n"+
                  "</Data>";
          List<NameValuePair> list = new ArrayList<NameValuePair>();
          NameValuePair valu1 = new BasicNameValuePair("data",data);
          NameValuePair valu2 = new BasicNameValuePair("developerId",[your developerId]");
          NameValuePair valu3 = new BasicNameValuePair("funcId","P2005");
          String privateKey = [your privateKey];
          String signData = "data="+data+"&developerId=[your developerId]&funcId=P2005";
          String sign = SecurityUtil.signRSA(signData,privateKey,"utf-8");
          NameValuePair valu4 = new BasicNameValuePair("sign",sign);
          list.add(valu1);
          list.add(valu2);
          list.add(valu3);
          list.add(valu4);
          String xml = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://offlinetest.bsoftpay.com/gatewayOffline/pay/offline/execute").setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8)).build());
              xml = EntityUtils.toString(response.getEntity());
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(xml);
  • 返回示例:
    developerId=66337&funcId=P2005&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Data>
    <TradeNo>34411000</TradeNo>
    <PayTradeNo>4200000376201907220000000000</PayTradeNo>
    <OrderNo>WX2019072200001</OrderNo>
    <Amt>0.01</Amt>
    <receipt_amount>0.01</receipt_amount>
    <PayTime>2019-07-22 21:37:31</PayTime>
    <PayStatus>1</PayStatus>
    </Data>
    &sign=JxUbXFPS4Kp3bS9ipmznDoAwBd3TzLX4Df8xd5VFR97Z1Kyb5XiJNxZ4LXA1RIlOafm+BmmnPXZXDfykss3geg==
  • 注意: P2005功能中请求参数是用<Data></Data>包围,不是<xml></xml>

3.6 交易退款接口

  • 功能码:P2008
  • 接口说明:当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家(原路返回)。注意的地方:微信超过1年的订单无法提交退款,支付宝超过3个月的订单无法提交退款,可以一笔订单多次退款,但是累计金额不能超过原支付金额
  • 请求参数:<Data>
参数 名称 类型 长度 是否必填 说明 示例
RequestNo 退款订单号 String 32 商户内部唯一退款单号 TK20190722001
PayType 退款渠道 String 2 2=支付宝;3=微信 2
Amt 退款金额 Price 16.2 退款金额不得超过原支付金额 0.01
TradeNo 原支付业务单号 String 32 商户原支付订单号 WX2019072200001
merchant_no 商户号 String 32 平台商户号 809900000001
sub_merchant 分店号 String 32 商户内部区分单号 001
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
RequestNo 退款订单号 String 32 申请退款订单号 TK20190722001
Amt 退款金额 Price 16.2 申请退款金额 0.01
  • JAVA请求示例:
    String data =
          "<Data>" +
          "<RequestNo>TK123127893456798765491</RequestNo>" +
          "<PayType>3</PayType>" +
          "<Amt>0.01</Amt>" +
          "<TradeNo>YMP011494322477660</TradeNo>" +
          "<merchant_no>809900000001</merchant_no>" +
          "</Data>";
          List<NameValuePair> list = new ArrayList<NameValuePair>();
          NameValuePair valu1 = new BasicNameValuePair("data",data);
          NameValuePair valu2 = new BasicNameValuePair("developerId",[your developerId]);
          NameValuePair valu3 = new BasicNameValuePair("funcId","P2008");
          String privateKey =[your privateKey];
          String signData = "data="+data+"&developerId=[your developerId]&funcId=P2008";
          String sign = SecurityUtil.signRSA(signData,privateKey,"utf-8");
          NameValuePair valu4 = new BasicNameValuePair("sign",sign);
          list.add(valu1);
          list.add(valu2);
          list.add(valu3);
          list.add(valu4);
          String xml = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://offlinetest.bsoftpay.com/gatewayOffline/pay/offline/execute").setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8)).build());
              xml = EntityUtils.toString(response.getEntity());
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(xml);
  • 返回示例:
    developerId=12345&funcId=P2008&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Data>
    <RequestNo>TK123127893456798765491</RequestNo>
    <Amt>0.01</Amt>
    </Data>
    &sign=XUvpouNiWkQF7bQsS2GTz+x7InmbxNz0reUhi1qqIIVg6AvLv5BKOqRzGpEm/N214pBPmiZpsygsOMKvYgLFqg==
  • 注意: P2008功能中请求参数是用<Data></Data>包围,不是<xml></xml>

3.7 交易退款结果查询接口

  • 功能码:P2009
  • 接口说明:提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用微信零钱或者支付宝余额宝、花呗等支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态(20分钟、3 个工作日都是大概时间,不一定为准,有可能提前,有可能延迟)
  • 请求参数:<Data>
参数 名称 类型 长度 是否必填 说明 示例
RequestNo 退款订单号 String 32 商户内部唯一退款单号 TK20190722001
PayType 退款渠道 String 2 2=支付宝;3=微信 2
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
RequestNo 退款订单号 String 32 申请退款订单号 TK20190722001
Amt 退款金额 Price 16.2 当code为1时这里会显示退款金额 0.01
Code 退款状态 String 2 -1交易不存在 1 成功 2 失败 1
Msg 错误信息描述 String 100 当code为2时这里会显示错误信息 0.01
  • 返回示例:
    developerId=12345&funcId=P2009&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Data>
    <RequestNo>TK20190722001</RequestNo>
    <Amt>0.01</Amt>
    <Code>1</Code>
    <Msg>OK</Msg>
    </Data>
    &sign=pkXTgvceROvF0JPq7Bmwxv654YoAImkSNblr/xTE75h6ZS1hUSSl5OAjEXptiJ0EW5vT9AvmFWGeW6uQGE6aKg==
  • 注意: P2009功能中请求参数是用<Data></Data>包围,不是<xml></xml>

3.8 关闭订单

  • 功能码:P7002

  • 接口说明:需要重新发起支付时,关闭该订单(刷卡付场景,扫码付无需关闭订单)

  • 场景描述:当接入应用系统调用支付指令接口(P7001)后,遇到网络等原因,超时未获取到结果的情况下,可以调用本接口进行关闭(撤销)此次支付订单(用于非正常支付场景
    特别注意:如果是刷卡付(B扫C)的应用场景,若付款人已支付,渠道商会进行退款,聚合支付平台不会有退款记录

    • 情况一实际未支付,订单关闭(撤销), 接入的应用系统一定要作废本地业务单据
    • 情况二实际已支付,若是刷卡付(B扫C)的应用场景,关闭(撤销)订单时,会原路退回支付款,接入的应用系统一定要作废本地业务单据。若是扫码付(C扫B)的应用场景,则系统会提示该笔“已支付不允许关闭”,遇到该情况,接入应用可以继续获取支付结果来同步本地业务单据状态或者重新发起业务付款流程,原业务单据走异常退款方式(接入应用研发异常退款功能直接调用P2008)
  • 请求参数:<xml>

参数 名称 类型 长度 是否必填 说明 示例
order_no 业务单号 String 32 商户内部唯一订单号 ZF20190722001
merchant_no 收款商户号 String 32 平台商户号 809900000001
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
ReturnCode 返回状态码 String 16 SUCCESS=关闭成功;FAIL=关闭失败 SUCCESS
ReturnMsg 返回消息 String 128
  • 请求示例:
    String data = "<xml>" +
                  "<order_no>ZF20190722001</order_no>" +
                  "<merchant_no>809900000001</merchant_no>" +
                  "</xml>";
          List<NameValuePair> list = new ArrayList<NameValuePair>();
          NameValuePair valu1 = new BasicNameValuePair("data",data);
          NameValuePair valu2 = new BasicNameValuePair("developerId",[your developerId]);
          NameValuePair valu3 = new BasicNameValuePair("funcId","P7002");
          String privateKey = [your privateKey];
          String signData = "data="+data+"&developerId=[your developerId]&funcId=P7002";
          String sign = SecurityUtil.signRSA(signData,privateKey,"utf-8");
          NameValuePair valu4 = new BasicNameValuePair("sign",sign);
          list.add(valu1);
          list.add(valu2);
          list.add(valu3);
          list.add(valu4);
          String xml = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://offlinetest.bsoftpay.com/gatewayOffline/pay/offline/execute").setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8)).build());
              xml = EntityUtils.toString(response.getEntity());
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(xml);
  • 返回示例:
    developerId=12345&funcId=P7002&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <xml>
    <ReturnCode>SUCCESS</ReturnCode>
    <ReturnMsg>OK</ReturnMsg>
    </xml>
    &sign=WkYUWPi+bnecNPTrhKnmvVWrnnCGvgxEkqwwrdMmu6LWMwUm6iFOhMlsRdvibFGr9SBqWY4pIew5e732xmXZOw==

    3.9 对账文件下载

  • 功能码:P7003
  • 接口说明:下载对账文件(每日对账文件会第二天12:10左右生成)
  • 请求参数:<xml>
参数 名称 类型 长度 是否必填 说明 示例
MerchantNo 收款商户号 String 32 商户内部唯一订单号 809900000001
BalanceDate 对账日期 String 10 日期格式:yyyymmdd 20190722
SubMerchant 门店号 String 32 平台商户号 001
  • 响应参数:
名称 类型 长度 是否必输 说明 示例
商户号 String 32 平台商户号 809900000001
门店号 String 32 商户内部区分号 001
订单号 String 16 业务订单号 ZF20190722001
支付渠道 String 1 2=支付宝;3=微信 2
交易类型 String 1 1=app支付;2=退款;3=扫码付;4=刷卡付;5=公众号支付;6=H5支付;7=刷脸付;-1=未知支付(造成原因:支付平台掉单,无法确定支付类型,出现这种情况请尽快联系支付平台,查明原因) 1
交易时间 String 16 时间格式:yyyyMMddhhmmss 20190722122134
交易金额 Price 16.2 实际交易金额 医保支付做为总金额 0.01
医保金额 Price 16.2 医保支付金额 医保支付返回 0.01
自费金额 Price 16.2 自费金额 医保支付返回 0.01
  • 请求示例:
    <xml>
      <MerchantNo>809900000001</MerchantNo>
      <BalanceDate>20190722</BalanceDate>
    </xml>
  • 返回文件格式:txt (以TAB键作为分隔符)
      商户号    门店号    订单号    支付渠道    交易类型    交易时间    交易金额
      1243    001    334567    2    1    20170111091233    10.00
      1244    001    334568    3    2    20170111091244    100.00

4. 修订记录

日期 修订内容 修订人
2019-12-19 接入支付宝代扣流程 熊超
文档更新时间: 2022-10-25 18:19   作者:甘世敏