目录:

  1. 场景介绍
  2. 接入指引
    2.1 准备工作
    2.2 接口调用规范
    2.2.1 请求说明
  3. API列表
    3.1 支付宝微信医保支付下单
    3.2 查询医保卡信息
    3.3 获取绑卡链接
    3.4 微信授权、支付宝实名信息查询
    3.5 交易结果查询接口
    3.6 交易退款接口
    3.7 交易退款结果查询接口
    3.8 交易结果通知
  4. 附录

1. 场景介绍

医保患者通过手机微信输入一次支付密码,即可完成医保、自费的混合支付,便捷就医无需排队。

2. 接入指引

2.1 准备工作

第一步、获取开发者数据

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

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

第二步、获取平台商户号

每个商户对接聚合支付平台,在第三方平台想要拥有的支付能力,需要在支付宝或者微信签约对应的支付方式,平台的商务会为每个商户分配一个平台商户号(merchantNo),该商户号账户下所有的交易流水都会进入到对应的支付宝和微信的账户下,并且平台账单流水都是以商户号进行隔离,这是一个非常重要的参数。

第三步、下载demo

2.2 接口调用规范

2.2.1 请求说明
  • 接口通信地址:
    测试环境:http://onlinetest.bsoftpay.com/gatewayOnline/gateway/portal/execute
    正式环境:由平台商务对接人员提供

  • http请求格式:

    Content-type:application/xml

    实体对象为 xml 格式,严格区分大小写,xml格式如下:

    <?xml version='1.0' encoding='UTF-8'?>
    <Root>
      <Head></Head>
      <Body> </Body>
    </Root>
  • 公共参数说明:

参数 类型 是否必填 最大长度 描述 示例
MerchantNo String 10 注意:这是开发者id(developerId) 12345
FuncId String 20 功能码 P7005
Signature String 100 签名 Sa/hb9jaTZZZq89mN62DDooLv/YTvfE9ayrbzgOMsucfIPZfJGmhUia6YWK8vQ5/NQana3Pub7BDswEenm0sBg==
Timestamp String 100 当前时间戳(自1970-1-01 00:00:00.000 到当前时刻的时间距离【精确到毫秒】) 1564120486130
RetCode String 30 0000:表示接口业务调用正常,9999:表示处理失败,如参数错误,验签失败等(注:RetCode并不表示交易行为成功或失败,某笔交易是否成功请根据对应接口返回报文的状态字段来判定 0000
RetMsg String 100 接口调用异常返回信息 验签失败

注意:Signature签名的生成过程,是先通过‘对称秘钥’对<Body>中的数据域进行DES加密,得到密文之后,再用‘私钥’对密文进行RSA加密

  • 请求报文示例:

    <?xml version='1.0' encoding='UTF-8'?>
    <Root>
      <Head>
          <MerchantNo>开发者id</MerchantNo>
          <FuncId>P7006</FuncId>
          <Timestamp>12312312312324</Timestamp>            
          <Signature>kLRyaxQXe6yLu+ktZUOiB+afVgeY5Doq9fTB27rAkW7/MBMK10tcxWM7eVVtmzxju0Xi1rtW16D7cV5PgM+zDA==</Signature>
      </Head>
      <Body>ql1e6Mhtmrq7yA6wGuE4biskwAEq8ALzOFr5kJxbVoP7VuaeoasTxHkdf8GTwlLihUhSk+ZcGsnJWNJHfMCtr9valAWD/y8sOAQut1/sWhg=</Body>
    </Root>
  • 返回报文示例:

    <?xml version="1.0" encoding="UTF-8"?>
    <Root>
      <Head>
          <MerchantNo>开发者id</MerchantNo>
          <FuncId>P7006</FuncId>
          <Timestamp>1533718324024</Timestamp>        
          <Signature><![CDATA[hNCUjy30FibXT8YuqhEwaMFv6dzERMRWAVa0XjcKDmzjZ
    jkQ1DPXzJtJooe43QfLLmW+38eDLmeUK7Y17nMfjA==]]>
          </Signature>
          <RetCode>0000</RetCode>
          <RetMsg></RetMsg>
      </Head>
      <Body>
      <![CDATA[NLB9nF8xXHoJgCgwYtRkMG9vhJlpSl9hjIF6LMQduYoaNNwmDqKKhBfUVBn
    u6ZPH33q3DLWEfnzUP5E2Mvzz2gK7riCvIfe1yJ/D5b3Ia67vFkHI6HBPhykm6uVLsbdW
    7Q1xSLuEv2jGqfwzSl35GPAJrwrd8wylCRp6B2aLv4x3DYmUROKXVk+fPObHTb0nU7a1Z
    Hkw7Nhj+15CPHnMLDj/s4jK9OOdkhKrWg/NTDvnZR65jFXsvqPfitPmkYsTEzuXwQSq88GF
    9YAmP+dcVeHHxBpaYkcV0N+JdN9h1TJg+uENaZIgU4ayDF2N7dVhYO54+vgSd/3HLHloow
    zXUVo2XdPVZgrvDRpmyqpk3YA8Pe4njAgZnA7/RRXvqX1ueOyQVEt1br7i4F5mGwnSuM9
    KOCDIkTNre9rvCdbsui5U0CpxgeM3WQ==]]>
      </Body>
    </Root>

    注意:这里的返回数据域为密文,需要接入方使用‘对称秘钥’进行DES解密,即可得到原文数据。如果需要验证数据的有效性,可以利用‘公钥’对Signature进行验签
    注意:返回信息中 MerchantNo 是 开发者id

    利用java工具类解密示例:

    String xml = SecurityUtil.decryptDes(Body,[your desKey], "utf-8");

    利用java工具类验签示例:

    boolean verify = SecurityUtil.verifyRSA(data, [your publicKey], Signature, "utf-8");

3. API列表

3.1 支付宝微信医保支付下单

  • 功能码:P8005
  • 接口说明:该接口提供微信医保支付下单,可以同时通过自费+医保的方式进行支付
  • 请求参数:<xml>
参数 名称 类型 长度 必填 说明 示例
merchant_no 收款商户号 String 30 创业聚合支付系统为医院分配的平台商户号 809900000001
sub_merchant 分店号 String 30 商户内部区分订单字段 001
order_no 业务单号 String 30 商户业务系统的唯一订单号 BX20190722902141
paytype 支付渠道 String 2 2=支付宝,3=微信 3
trade_type 交易类型 String 2 6=医保线上支付 6
openid 用户唯一标识 String 128 微信公众号用户(openid);支付宝生活号用户(uid) obzBc1MlzBaU_kjt6eJvdSqs2qbA
total_amt 支付金额 Price 20.2 以元为单位,商品总价 自费金额+医保金额 0.01
timeout_express 支付超时时间 Integer 4 以“分钟”为单位,缺省5分钟,不能小于5 6
spbill_create_ip 用户IP String 10 客户端实际外网ip 微信必填 183.156.115.113
order_subject 商品标题 String 150 订单信息 深圳平乐骨伤科医院微信医保支付
order_detail 商品详情 String 150 订单详情 支付宝必填 支付宝医保支付
order_type 医保业务类型 String 2 1:挂号 2:诊间 3:住院 支付宝 4:非医院 支付宝 1
card_org_no 用户医保卡机构编号 String 2 查询用户医保获取 支付宝必传 SZHRSS
pay_way 支付方式 String 2 1:自费 2:医保 3:自费+医保(缺省)
总金额必填
传 1:自费金额必填
传 2:医保金额必填
传 3: 自费和医保金额必填
3
cash_amt 自费金额 Price 20.2 以元为单位 0.01
cash_reduced_amt 医院减免的自费部分金额 Price 20.2 以元为单位 0.01
allow_fee_change 是否允许预结算费用发生变化 String 2 0:不允许(缺省) 1:允许 0
return_url 支付后回跳的页面 String 200 不论成功失败均会回跳(建议在链接中加上支付单号,方便查询订单状态)微信有效 http://xxx.merchantno.com/pay/returnurl
consume_type 医保部分扣费类型 String 2 默认:0:统筹+个账 1:个账 2:统筹 微信医保字段 0
insurance_amt 医保金额 Price 20.2 以元为单位 微信医保支付必填 0.01
card_type 证件类型 String 2 详见证件类型 医保支付必填 1
card_no 证件号 String 30 证件号码 医保支付必填 10001199901011111
user_name 真实姓名 String 30 医保姓名 医保支付必填 张三
mobile 用户手机号 String 30 手机号 13211112222
child_card_no 少儿证件号 String 30 少儿证件号码 少儿医保支付必填 10001199901011111
child_user_name 少儿真实姓名 String 30 少儿医保姓名 少儿医保支付必填 张四
org_no 医疗机构编码 String 64 人社局提供的医疗机构编码 123456
org_name 医疗机构名称 String 64 医疗机构名称 深圳平乐骨伤科医院
request_content 医保请求结构体(透传体) String 2000 1 挂号支付必传 2 诊间支付分两种情况 ①线上预结算模式必填 ②线下预结算模式非必填 医保支付必填 {"registration_order_pay":{"yljgbm":" 医院编号","ylzh":"医疗证号","czybm":"操作员编码"...
bill_no 业务单据号 String 32 诊间支付线下预结算模式必传 123456
extends 扩展字段 String 200 扩展字段
city_id 城市id String 32 可不填,默认为公众号申请接入的城市 440300
payment_extends 平台扩展字段 String 2000 用于各个省市医保需要的增补字段 {“channelNo”:”1234”,”isDept”:”4”,”consumeType”:0,”serialNo”:”1234”,”useSandbox”:1}
notifyURL 自定义支付结果通知地址 String 单独为此订单配置的支付结果通知地址 http://test.com/callback
  • 响应参数:
参数 名称 类型 长度 必输 说明 示例
return_code 返回状态码 String 16 SUCCESS代表成功 FAIL 代表失败 SUCCESS
return_msg 返回信息 String 128 返回信息 OK
med_trans_id 微信诊疗单id String 64 微信生成的医疗订单 id 11111
pay_url 支付链接 String 256 下单后跳转到此 url,用户完成支付 weixin://xxx
pay_appid 支付小程序 String 64 当使用医院小程序进行下单时,会返回此参数,医院小程序跳转至该支付小程序进行支付 11111
pay_text 支付宝小程序支付字符串 String 1024 支付宝小程序支付字符串 xxxx
  • Java请求示例:

    String data = "<xml>\n" +
              "    <order_no>mpTest202104191550216000</order_no>\n" +
              "    <paytype>3</paytype>\n" +
              "    <openid>obzBc1MlzBaU_kjt6eJvdSqs2qbA</openid>\n" +
              "    <merchant_no>109900130000</merchant_no>\n" +
              "    <trade_type>6</trade_type>\n" +
              "    <order_type>1</order_type>\n" +
              "    <pay_way>2</pay_way>\n" +
              "    <total_amt>0.01</total_amt>\n" +
              "    <cash_amt>0.0</cash_amt>\n" +
              "    <spbill_create_ip>127.0.0.1</spbill_create_ip>\n" +
              "    <order_subject>挂号支付</order_subject>\n" +
              "    <return_url>http://xxx.merchantno.com/pay/returnurl</return_url>\n" +
              "    <insurance_amt>0.01</insurance_amt>\n" +
              "    <card_type>1</card_type>\n" +
              "    <card_no>患者身份证号</card_no>\n" +
              "    <user_name>患者姓名</user_name>\n" +
              "    <org_no>123</org_no>\n" +
              "    <org_name>123</org_name>\n" +
              "    <request_content>{}</request_content>\n" +
              "    <city_id>511700</city_id>\n" +
              "    <timeout_express>6</timeout_express>\n" +
              "    <payment_extends>{\"channelNo\":\"AAGG2rOJ0Qvc5-4FUWYrur81\",\"isDept\":\"4\",\"consumeType\":0}</payment_extends>\n" +
              "</xml>"
          String desKey = "";
          HeaderDTO header = new HeaderDTO();
          header.setFuncId("P8005");
          header.setMerchantNo(developerId);
          header.setTimestamp(System.currentTimeMillis() + "");
          header.setSignature(SecurityUtil.signRSA(data, privateKey, "UTF-8"));
          DataDTO dataDTO = new DataDTO();
          dataDTO.setHeader(header);
          dataDTO.setBody(SecurityUtil.encryptDes(data, desKey , "UTF-8"));
          String content = JaxbMapper.toXml(dataDTO, DataDTO.class, "UTF-8");
    
          String resData = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://onlinetest.bsoftpay.com/gatewayOnline/gateway/portal/execute").setEntity(new StringEntity(content, ContentType.APPLICATION_XML.withCharset(Consts.UTF_8))).build());
              String res = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
              System.out.println(res);
              //解析返回xml
              DataDTO resultData = JaxbMapper.fromXml(res, DataDTO.class);
              //回调成功-获取body内容
              if ("0000".equals(resultData.getHeader().getRetCode())) {
                  //解密body
                  resData = SecurityUtil.decryptDes(resultData.getBody(), desKey,"UTF-8");
              }else{
                  //异常信息
                  resData = resultData.getHeader().getRetMsg();
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(resData);
  • 返回示例

    <?xml version="1.0" encoding="UTF-8"?><root>
    <Head>
      <MerchantNo>开发者id</MerchantNo>
      <FuncId>P8005</FuncId>
      <Timestamp>1566981115522</Timestamp>
      <Signature>B5nbh7acyJdeoD663ndVpY/rHwX1HEZR+of+Oy47R6KioObX6jCajtFc3PpVJyDwPhLHUH12EEl/cdDnV+VI6A==</Signature>
      <RetCode>0000</RetCode>
      <RetMsg></RetMsg>
    </Head>
    <Body></Body>
    </root>

    注意:返回参数中MerchantNo 是开发者id

    3.2 支付宝微信查询医保卡信息

  • 功能码:P8007

  • 接口说明:该接口提供微信查询医保卡信息

  • 请求参数:<xml>

参数 名称 类型 长度 必填 说明 示例
merchant_no 收款商户号 String 30 创业聚合支付系统为医院分配的平台商户号 809900000001
pay_channel 支付通道 String 1 2支付宝 3微信 2
name 用户名称 String 32 用户姓名 张三
idcard 用户身份证 String 64 证件号码,目前只支持身份证 44030019000101123x
openid 用户唯一标识 String 128 公众号支付是微信用户的(openid);支付宝uid obzBc1MlzBaU_kjt6eJvdSqs2qbA
child_name 少儿实名 String 32 需要查询少儿时填入
child_idcard 少儿身份证 String 64 需要查询少儿时填入
  • 响应参数:
参数 名称 类型 长度 必输 说明 示例
return_code 返回状态码 String 16 SUCCESS代表成功 FAIL 代表失败 SUCCESS
return_msg 返回信息 String 128 返回信息 OK
need_bind 是否需要绑卡 Boolean true/false判断是否调用获取绑卡链接接口
medical_card_no 社保卡号 String 32 社保卡号 BBS70130X
medical_card_id 医疗证号 String 32 用户的医疗证号,对应ylzh字段 6055168908
medical_comp_no 电脑号 String 32 用户的社保电脑号为空表示无此数据 11111
medical_insurance_type 参保类型 String 16 用户的参保类型,为空表示未知
1:基本医疗保险(一档)
2:基本医疗保险(二档)
3:特殊
4:基本医疗保险(三档)
5:医疗保险二档(少儿)
6:统筹保险
1
medical_user_id 用户医保平台id String 32 用户医保平台id
city_id 社保卡绑定的城市ID String 32 社保卡绑定的城市ID
child_medical_card_id 少儿医疗证号 String 32 输入中有少儿信息时返回,可能为空
child_medical_card_no 少儿社保卡号 String 32 输入中有少儿信息时返回,可能为空
aggreement_no 签约协议号 String 32 支付宝有效。必输
buyer_user_id 买家支付宝账用户号 String 32 支付宝有效。必输
medical_card_type 医保类型 String 32 市医保:CITY_INS; 省医保:PROVINCE_INS; 县医保:COUNTY_INS 支付宝有效。必输
out_user_name 姓名 String 32 持卡人的姓名(脱敏)支付宝有效。必输
out_user_card_no 持卡人证件号(脱敏) String 32 支付宝有效
card_org_name 卡颁发机构名称 String 32 支付宝有效。必输
card_org_no 卡颁发机构编号 String 32 支付宝有效。必输
extend_params 业务扩展参数 String 32 支付宝有效
extend_cards 支付宝账号绑定的其他医保卡信息 (除本人外) String 32 支付宝有效
–|need_bind 是否需要绑卡 Boolean true/false判断是否调用获取绑卡链接接口
–|medical_card_id 医疗证号 String 32 用户的医疗证号 6055168908
–|medical_card_no 社保卡号 String 32 社保卡号 BBS70130X
–| medical_card_type 医保类型 String 32 市医保:CITY_INS; 省医保:PROVINCE_INS; 县医保:COUNTY_INS
–|out_user_name 姓名 String 32 持卡人的姓名(脱敏)
–|out_user_card_no 证件号(脱敏) String 32 持卡人的证件号
–|card_org_no 机构编号 String 32 医保卡颁发机构编号
–|city_id 城市编码 String 32 440100
–|city_id 城市编码 String 32 440100
–|extend_params 业务扩展参数 String 32
  • Java请求示例:

    String data ="<xml>" +
                  "<openid></openid>" +
                  "<merchant_no>809900000001</merchant_no>" +
                  "<pay_channel>3</pay_channel>" +
                  "<name></name>" +
                  "<idcard_md5></idcard_md5>" +
                  "</xml>";
          String desKey = "";
          HeaderDTO header = new HeaderDTO();
          header.setFuncId("P8007");
          header.setMerchantNo(developerId);
          header.setTimestamp(System.currentTimeMillis() + "");
          header.setSignature(SecurityUtil.signRSA(data, privateKey, "UTF-8"));
          DataDTO dataDTO = new DataDTO();
          dataDTO.setHeader(header);
          dataDTO.setBody(SecurityUtil.encryptDes(data, desKey , "UTF-8"));
          String content = JaxbMapper.toXml(dataDTO, DataDTO.class, "UTF-8");
    
          String resData = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://onlinetest.bsoftpay.com/gatewayOnline/gateway/portal/execute").setEntity(new StringEntity(content, ContentType.APPLICATION_XML.withCharset(Consts.UTF_8))).build());
              String res = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
              System.out.println(res);
              //解析返回xml
              DataDTO resultData = JaxbMapper.fromXml(res, DataDTO.class);
              //回调成功-获取body内容
              if ("0000".equals(resultData.getHeader().getRetCode())) {
                  //解密body
                  resData = SecurityUtil.decryptDes(resultData.getBody(), desKey,"UTF-8");
              }else{
                  //异常信息
                  resData = resultData.getHeader().getRetMsg();
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(resData);
  • 返回示例

    <?xml version="1.0" encoding="UTF-8"?><root>
    <Head>
      <MerchantNo>开发者id</MerchantNo>
      <FuncId>P8007</FuncId>
      <Timestamp>1566981115522</Timestamp>
      <Signature>B5nbh7acyJdeoD663ndVpY/rHwX1HEZR+of+Oy47R6KioObX6jCajtFc3PpVJyDwPhLHUH12EEl/cdDnV+VI6A==</Signature>
      <RetCode>0000</RetCode>
      <RetMsg></RetMsg>
    </Head>
    <Body></Body>
    </root>

    注意:返回信息中 MerchantNo 是 开发者id

    3.3 微信获取绑卡链接

  • 功能码:P8008

  • 接口说明:该接口提供微信获取绑卡链接

  • 请求参数:<xml>

参数 名称 类型 长度 必填 说明 示例
merchant_no 收款商户号 String 30 创业聚合支付系统为医院分配的平台商户号 809900000001
pay_channel 支付通道 String 1 2支付宝 3微信 2
openid 用户唯一标识 String 128 公众号支付是微信用户的(openid)微信医保支付必填 obzBc1MlzBaU_kjt6eJvdSqs2qbA
url 绑卡完成后的跳转url String 512 微信医保支付必填
from 来源统计 String 512 来源统计
city_id 城市ID String 32 城市ID
  • 响应参数:
参数 名称 类型 长度 必输 说明 示例
return_code 返回状态码 String 16 SUCCESS代表成功 FAIL 代表失败 SUCCESS
return_msg 返回信息 String 128 返回信息 OK
bind_url 绑卡链接 String 512 绑卡链接微信医保支付必输
expires_in 有效时间 String 32 单位:秒 微信医保支付必输 3600
bind_appid 绑卡跳转小程序的appid String 64 如果调用方为小程序则会返回该参数
  • Java请求示例:

          String data = "<xml>" +
                  "<openid></openid>" +
                  "<merchant_no></merchant_no>" +
                  "<pay_channel>3</pay_channel>" +
                  "<url></url>" +
                  "</xml>";
          String desKey = "";
          HeaderDTO header = new HeaderDTO();
          header.setFuncId("P8008");
          header.setMerchantNo(developerId);
          header.setTimestamp(System.currentTimeMillis() + "");
          header.setSignature(SecurityUtil.signRSA(data, privateKey, "UTF-8"));
          DataDTO dataDTO = new DataDTO();
          dataDTO.setHeader(header);
          dataDTO.setBody(SecurityUtil.encryptDes(data, desKey , "UTF-8"));
          String content = JaxbMapper.toXml(dataDTO, DataDTO.class, "UTF-8");
    
          String resData = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://onlinetest.bsoftpay.com/gatewayOnline/gateway/portal/execute").setEntity(new StringEntity(content, ContentType.APPLICATION_XML.withCharset(Consts.UTF_8))).build());
              String res = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
              System.out.println(res);
              //解析返回xml
              DataDTO resultData = JaxbMapper.fromXml(res, DataDTO.class);
              //回调成功-获取body内容
              if ("0000".equals(resultData.getHeader().getRetCode())) {
                  //解密body
                  resData = SecurityUtil.decryptDes(resultData.getBody(), desKey,"UTF-8");
              }else{
                  //异常信息
                  resData = resultData.getHeader().getRetMsg();
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(resData);
  • 返回示例

    <?xml version="1.0" encoding="UTF-8"?><root>
    <Head>
      <MerchantNo>开发者id</MerchantNo>
      <FuncId>P8008</FuncId>
      <Timestamp>1566981115522</Timestamp>
      <Signature>B5nbh7acyJdeoD663ndVpY/rHwX1HEZR+of+Oy47R6KioObX6jCajtFc3PpVJyDwPhLHUH12EEl/cdDnV+VI6A==</Signature>
      <RetCode>0000</RetCode>
      <RetMsg></RetMsg>
    </Head>
    <Body></Body>
    </root>

    注意:返回参数 MerchantNo 是 开发者id

3.4 微信授权、支付宝实名信息查询

  • 功能码:P8009
  • 接口说明:该接口提供微信授权查询
  • 请求参数:<xml>
参数 名称 类型 长度 必填 说明 示例
merchant_no 收款商户号 String 30 创业聚合支付系统为医院分配的平台商户号 809900000001
pay_channel 支付通道 String 1 2支付宝 3微信 2
openid 用户唯一标识 String 128 微信必填公众号支付是微信用户的(openid) obzBc1MlzBaU_kjt6eJvdSqs2qbA
authCode 微信授权码 String 512 微信必填 微信免密授权回调页面返回的authCode
支付宝必填 支付宝返回的accessToken
  • 响应参数:
参数 名称 类型 长度 必输 说明 示例
code 返回状态码 String 16 微信成功时返回:
0 成功,小于0 系统错误,大于0 逻辑错误
0
message 返回信息 String 128 返回信息 OK
mi_card_type 用户授权类型 String 128 微信成功时返回:
1”CERITIFICATE”=国家电子凭证
2 ”DEPART”=人社部电子社卡
3 ”LOCAL”=地方卡
user_name 用户姓名 String 128 用户姓名 3600
userCardNo 用户证件号 String 128 用户证件号 3600
auth_code 电子凭证授权码 String 128 电子凭证授权码
city_id 用户参保地代码 String 128 微信成功时返回:
仅当mi_card_type=CERITIFICATE 时,才返回有效值,多地参保用户若未选择主参地,则该字段未空,并且不可使用后续业务。;
mi_card_no 医保卡号 String 128 微信成功时返回:
仅当mi_card_type=LOCAL 时,才返回医保卡号
contract_no 签发号 String 128 微信成功时返回:
仅当mi_card_type=DEPART 时,才返回签发号
mi_card_channel 签发渠道号 String 128 微信成功时返回:
当mi_card_type=DEPART 时,返回渠道号
  • 请求示例:
    <xml>
      <openid>o10ldt4o_0j6v4DzW0y0eAIgc8xg</openid>
      <authCode>1234</authCode>
      <merchant_no>109900130000</merchant_no>
      <pay_channel>3</pay_channel>
    </xml>
  • 返回示例
    <?xml version="1.0" encoding="UTF-8"?><root>
    <Head>
      <MerchantNo>开发者id</MerchantNo>
      <FuncId>P8008</FuncId>
      <Timestamp>1566981115522</Timestamp>
      <Signature>B5nbh7acyJdeoD663ndVpY/rHwX1HEZR+of+Oy47R6KioObX6jCajtFc3PpVJyDwPhLHUH12EEl/cdDnV+VI6A==</Signature>
      <RetCode>0000</RetCode>
      <RetMsg></RetMsg>
    </Head>
    <Body></Body>
    </root>
    注意:返回参数 MerchantNo 是 开发者id

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
InsuranceAmt 医保支付金额 当insurance_self_fee 和 insurance_fund_fee 存在时InsuranceAmt=insurance_self_fee+ insurance_fund_fee Price 16.2 使用了医保时返回 医保支付 0.01
CashAmt 自费支付金额 Price 16.2 使用了医保时返回 医保支付 0.01
insurance_self_fee 医保个人账户支付金额 Price 16.2 使用了医保时返回 医保支付 0.01
insurance_fund_fee 医保统筹账户支付金额 Price 16.2 使用了医保时返回 医保支付 0.01
ReducedAmt 优惠金额 Price 16.2 下单使用了优惠金额时返回 医保支付 0.01
refundAmt 退款金额 Price 16.2 医保订单 存在退费时存在 退款金额 0.01
insurance_bill_no 医保结算单号 string 32 医保结算单号 *02100121051300000186
response_content 医保返回的结算信息 string 1024 医保返回的结算信息 {“XXXXXX”:”YYYYY”}
  • JAVA请求示例:

    String data = "<Data>" +
                  "<order_no>WX2019072200001</order_no>\n" +
                  "<merchant_no>809900000001</merchant_no>\n"+
                  "</Data>";
           String desKey = "";
          HeaderDTO header = new HeaderDTO();
          header.setFuncId("P2005");
          header.setMerchantNo(developerId);
          header.setTimestamp(System.currentTimeMillis() + "");
          header.setSignature(SecurityUtil.signRSA(data, privateKey, "UTF-8"));
          DataDTO dataDTO = new DataDTO();
          dataDTO.setHeader(header);
          dataDTO.setBody(SecurityUtil.encryptDes(data, desKey , "UTF-8"));
          String content = JaxbMapper.toXml(dataDTO, DataDTO.class, "UTF-8");
    
          String resData = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://onlinetest.bsoftpay.com/gatewayOnline/gateway/portal/execute").setEntity(new StringEntity(content, ContentType.APPLICATION_XML.withCharset(Consts.UTF_8))).build());
              String res = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
              System.out.println(res);
              //解析返回xml
              DataDTO resultData = JaxbMapper.fromXml(res, DataDTO.class);
              //回调成功-获取body内容
              if ("0000".equals(resultData.getHeader().getRetCode())) {
                  //解密body
                  resData = SecurityUtil.decryptDes(resultData.getBody(), desKey,"UTF-8");
              }else{
                  //异常信息
                  resData = resultData.getHeader().getRetMsg();
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(resData);
  • 返回示例:

    <?xml version="1.0" encoding="UTF-8"?><root>
    <Head>
      <MerchantNo>开发者id</MerchantNo>
      <FuncId>P2005</FuncId>
      <Timestamp>1566981115522</Timestamp>
      <Signature>B5nbh7acyJdeoD663ndVpY/rHwX1HEZR+of+Oy47R6KioObX6jCajtFc3PpVJyDwPhLHUH12EEl/cdDnV+VI6A==</Signature>
      <RetCode>0000</RetCode>
      <RetMsg></RetMsg>
    </Head>
    <Body></Body>
    </root>
  • 注意: P2005功能中请求参数是用<Data></Data>包围,不是<xml></xml>

  • 注意: 返回参数中 MerchantNo 是 开发者id

    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
cancel_bill_no 撤销单据号 String 20 医保诊间退款必填人社无要求则由医院自定义 109900000001
part_refund_type 部分退款 String 2 医保退款相关
1:自费部分退款
2:只退医保(只能全退)
3:单退医保个账部分
4:单退医保统筹部分(只能全退)
不填写医保和现金一起退
1
request_content 透传人社 String 医保退款相关 有需要透传数据到人社时填写

注:微信医保退款,全额退还自费部分金额或者退还自费+医保的总支付金额,无法自定义金额进行多次退款

  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
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>" +
              "<cancel_bill_no>10000000000000000001</cancel_bill_no>" +
          "</Data>";
          String desKey = "";
          HeaderDTO header = new HeaderDTO();
          header.setFuncId("P2008");
          header.setMerchantNo(developerId);
          header.setTimestamp(System.currentTimeMillis() + "");
          header.setSignature(SecurityUtil.signRSA(data, privateKey, "UTF-8"));
          DataDTO dataDTO = new DataDTO();
          dataDTO.setHeader(header);
          dataDTO.setBody(SecurityUtil.encryptDes(data, desKey , "UTF-8"));
          String content = JaxbMapper.toXml(dataDTO, DataDTO.class, "UTF-8");
    
          String resData = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://onlinetest.bsoftpay.com/gatewayOnline/gateway/portal/execute").setEntity(new StringEntity(content, ContentType.APPLICATION_XML.withCharset(Consts.UTF_8))).build());
              String res = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
              System.out.println(res);
              //解析返回xml
              DataDTO resultData = JaxbMapper.fromXml(res, DataDTO.class);
              //回调成功-获取body内容
              if ("0000".equals(resultData.getHeader().getRetCode())) {
                  //解密body
                  resData = SecurityUtil.decryptDes(resultData.getBody(), desKey,"UTF-8");
              }else{
                  //异常信息
                  resData = resultData.getHeader().getRetMsg();
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(resData);
  • 返回示例:

    <?xml version="1.0" encoding="UTF-8"?><root>
    <Head>
      <MerchantNo>开发者id</MerchantNo>
      <FuncId>P2008</FuncId>
      <Timestamp>1566981115522</Timestamp>
      <Signature>B5nbh7acyJdeoD663ndVpY/rHwX1HEZR+of+Oy47R6KioObX6jCajtFc3PpVJyDwPhLHUH12EEl/cdDnV+VI6A==</Signature>
      <RetCode>0000</RetCode>
      <RetMsg></RetMsg>
    </Head>
    <Body></Body>
    </root>
  • 注意: P2008功能中请求参数是用<Data></Data>包围,不是<xml></xml>

  • 注意: 返回信息中 MerchantNo 是 开发者id

    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
CashRefundAmt 自费退款金额 Price 16.2 当code为1时这里会显示退款金额 0.01
InsuranceRefundAmt 医保退款金额 Price 16.2 当code为1时这里会显示退款金额 0.01
Code 退款状态 String 2 -1交易不存在 1 成功 2 失败 1
Msg 错误信息描述 String 100 当code为2时这里会显示错误信息 0.01
  • 返回示例:
    <?xml version="1.0" encoding="UTF-8"?><root>
    <Head>
      <MerchantNo>22290</MerchantNo>
      <FuncId>P2009</FuncId>
      <Timestamp>1566981115522</Timestamp>
      <Signature>B5nbh7acyJdeoD663ndVpY/rHwX1HEZR+of+Oy47R6KioObX6jCajtFc3PpVJyDwPhLHUH12EEl/cdDnV+VI6A==</Signature>
      <RetCode>0000</RetCode>
      <RetMsg></RetMsg>
    </Head>
    <Body></Body>
    </root>
  • 注意: P2009功能中请求参数是用<Data></Data>包围,不是<xml></xml>
  • 注意: 返回信息中 MerchantNo 是 开发者id

    3.8 交易结果通知

  • 功能码:P3001
  • 接口说明:支付状态改变(支付或作废)后,平台异步通知用户端(平台不保证异步通知能够准时到达,建议接入方有自己的定时主动查询策略,以异步通知作为辅助查询)。交易结果通知的地址,需要提前告知平台商务对接人员进行配置。

注意:商户在接受到支付平台回调后,如果业务成功,返回 success ,失败返回 fail ,注意都是小写,不要用空格或者换行。

支付平台服务器在没有收到业务成功回调信息时,会尝试重发消息,总共3次通知(通知的间隔频率一般是:30s,1m,2m),3 次以后将不再通知,所以不保证通知最终能成功(建议以交易结果查询接口为主,异步通知为辅,如果 3 秒左右还没有接受到异步通知,就应该主动调用交易结果查询接口)

  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
TradeNo 支付平台交易流水号 String 32 支付平台交易流水号 32013134
PayTradeNo 渠道流水号 String 32 第三方支付渠道流水号 20192323971391918391121
OrderNo 业务单号 String 32 商户内部业务单号 wx201907150001
Amt 支付金额 医保订单为总金额 Price 16.2 支付金额 0.01
CashAmt 自费支付金额 Price 16.2 医保订单时存在 自费支付金额 0.01
InsuranceAmt 医保支付金额 当insurance_self_fee 和 insurance_fund_fee 存在时InsuranceAmt=insurance_self_fee+ insurance_fund_fee Price 16.2 医保订单时存在 医保支付金额 0.01
insurance_self_fee 医保个人账户支付金额 Price 16.2 使用了医保时返回 医保支付 0.01
insurance_fund_fee 医保统筹账户支付金额 Price 16.2 使用了医保时返回 医保支付 0.01
PayTime 实际支付时间 String 16 yyyy-MM-dd hh:mm:ss 2019-07-25 12:30:12
PayStatus 支付状态 String 6 0=未支付;1=支付成功;2=支付失败;-1=关闭或撤销 1
insurance_bill_no 医保结算单号 String 32 *02100121051300000186
response_content 医保返回的结算信息 string 1024 医保返回的结算信息 {“XXXXXX”:”YYYYY”}
  • 返回示例:
    <?xml version="1.0" encoding="UTF-8"?><root>
    <Head>
      <MerchantNo>22290</MerchantNo>
      <FuncId>P3001</FuncId>
      <Timestamp>1566981115522</Timestamp>
      <Signature>B5nbh7acyJdeoD663ndVpY/rHwX1HEZR+of+Oy47R6KioObX6jCajtFc3PpVJyDwPhLHUH12EEl/cdDnV+VI6A==</Signature>
      <RetCode>0000</RetCode>
      <RetMsg></RetMsg>
    </Head>
    <Body></Body>
    </root>
    注:返回参数数据在<body>已经被DES加密,需要接入方利用对接时获取的“对称密钥”,对密文使用下载的加解密工具进行解密
    注意:返回信息中MerchantNo 是 开发者id

    4. 附录

  • 证件类型字典:
证件类型 证件名 适用说明
1 身份证 通用
2 护照 支付宝
3 军官证 支付宝
4 士兵证 支付宝
5 户口本 通用
6 警官证 支付宝
7 台湾居民来往大陆通行证(台胞证) 通用
8 香港居民来往内地通行证(回乡证) 通用
9 澳门居民来往内地通行证(回乡证) 通用
10 临时身份证 支付宝
11 港澳通行证 支付宝
12 营业执照 支付宝
13 外国人永久居留证 微信
14 外 国 人 护 照 微信
文档更新时间: 2023-09-25 11:13   作者:甘世敏