签名算法

签名生成的通用步骤如下:

第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

特别注意以下重要规则:

  1. ◆ 参数名ASCII码从小到大排序(字典序);
  2. ◆ 如果参数的值为空不参与签名;
  3. ◆ 参数名区分大小写;
  4. ◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
  5. ◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段

第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。

◆ key设置路径:商户中心-->API设置-->API密钥

举例:

假设传送的参数如下:

appid: wxd930ea5d5a258f4f

mch_id: 10000100

device_info: 1000

body: test

nonce_str: ibuaiVcKdpRxkhJA

第一步:对参数按照key=value的格式,并按照参数名ASCII字典序排序如下:

stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA";

第二步:拼接API密钥:

stringSignTemp=stringA+"&key=192006250b4c09247ec02edce69f6a2d" //注:key为商户平台设置的密钥key

sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7" //注:MD5签名方式

最终得到最终发送的数据:

appid=wxd930ea5d5a258f4f&mch_id=10000100&device_info=1000&body=test&nonce_str=ibuaiVcKdpRxkhJA&sign=9A0A8659F005D6984697E2CA0A9CF3B7

统一下单

接口链接

URL地址:{{ api }}/pay/order

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mch_id String(32) 10010 分配的商户号
签名 sign String(32) C380BEC2BFD727A4B6845133519F3AD6 签名,详见签名生成算法
商品标题 subject String(128) 腾讯充值中心-QQ会员充值

商品描述交易字段格式根据不同的应用场景建议按照以下格式上传:

(1)PC网站——传入浏览器打开的网站主页title名-实际商品名称,例如:腾讯充值中心-QQ会员充值;

(2) 公众号——传入公众号名称-实际商品名称,例如:腾讯形象店- image-QQ公仔;

(3) H5——应用在浏览器网页上的场景,传入浏览器打开的移动网页的主页title名-实际商品名称,例如:腾讯充值中心-QQ会员充值;

(4) 线下门店——门店品牌名-城市分店名-实际商品名称,例如: image形象店-深圳腾大- QQ公仔)

(5) APP——需传入应用市场上的APP名字-实际商品名称,天天爱消除-游戏充值。

商品介绍 body String(6000)   商品详细介绍
附加数据 attach String(127) 说明 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
商户订单号 out_trade_no String(32) 1217752501201407033233368018 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*且在同一个商户号下唯一。
总金额 total_fee Int 888 订单总金额,只能为整数,单位分。
用户IP client_ip String(16) 123.12.12.123 创建支付订单用户的真实IP
异步通知地址 notify_url String(256) {{ api }}/notify 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
同步回调地址 return_url String(256) {{ api }}/return 回调url必须为直接可访问的url,不能携带参数。注意:某些支付方式无同步回调
渠道代码 pt String(16) XIAOWEI

XIAOWEI -微信小微商户

ALIPAYSH -支付宝当面付

具体看商户中心》渠道列表

通道代码 channel String(16) NATIVE

JSAPI -JSAPI支付

NATIVE -Native支付

具体看商户中心》渠道列表

微信子商户号 sub_mch_id String(32) 1900000109 小微商户分配的子商户号,channel=JSAPI,此参数必传。必须与【获取用户openid】接口的一致。
用户标识 openid String(128) oUpF8uMuAJO_M2pxb1Q9zNjWeS6o channel=JSAPI,此参数必传,通过我们提供的接口获取的openid。 下单前需要调用【获取用户openid】接口获取到用户的Openid。
花呗分期数 hb_fq_num int(2) 3

channel=HBFQ,此参数可传,默认为3分期

代表花呗分期数,仅支持传入 3、6、12,其他期数暂不支持,传入会报错

授权码 auth_code String(128) 120061098828009406

channel=BARCODE,此参数必传

扫码支付授权码,设备读取用户(微信|支付宝)中的条码或者二维码信息

说明:如遇系统错误,可以调用订单查询接口查询是否支付完成

返回结果

字段名 变量名 必填 类型 示例值 描述
返回状态码 status Int 0

0为成功,其它为失败

channel=BARCODE,status=1,代表支付结果未知,需要自己调用订单查询接口获取订单支付状态

返回信息 message String(128) 签名失败 返回信息
返回数据 data Object

status=0时有返回

data数据内容

字段名 变量名 必填 类型 示例值 描述
商户订订号 out_trade_no String(32) 1217752501201407033233368018 商户系统内部订单号
二维码链接 code_url String(64) weixin://wxpay/bizpayurl/up?pr=NwY5Mz9&groupid=00

此url用于生成支付二维码,然后提供给用户进行扫码支付。

注意:code_url的值并非固定,使用时按照URL格式转成二维码即可

JSPAI支付参数 pay_info String(128) {"appId":"wx2421b1c4370ec43b","timeStamp":"1395712654","nonceStr":"e61463f8efa94090b1f366cccfbbb444","package":"prepay_id=u802345jgfjsdfgsdg888","signType":"MD5","paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89"}

channel=JSAPI,调用成功有返回

JSON格式的字符串,公众号里JS支付需要参数,使用参考【微信内H5调起支付

支付单号 trade_no String(32) 1217752501201407033233368018

支付订单号

channel=BARCODE,支付成功有返回

总金额 total_fee Int 888 订单总金额,只能为整数,单位分。

举例如下:

{
  "status": 0,
  "message": "创建支付订单成功",
  "data": {
    "out_trade_no": "201908220932158296",
    "code_url": "weixin://wxpay/bizpayurl?pr=vcuhPTc",
    "total_fee": 1
  }
}

查询订单

接口链接

{{ api }}/pay/query

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mch_id String(32) 10010 分配的商户号
商户订单号 out_trade_no String(32) 1217752501201407033233368018 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
签名 sign String(32) 5K8264ILTKCH16CQ2502SI8ZNMTM67VS 签名,详见签名生成算法

返回结果

字段名 变量名 必填 类型 示例值 描述
返回状态码 status Int 0 0为成功,其它为失败
返回信息 message String(128) 签名失败 返回信息
返回数据 data Object

status=0时有返回

data数据内容

字段名 变量名 必填 类型 示例值 描述
商户订订号 out_trade_no String(32) 1217752501201407033233368018 商户系统内部订单号
交易状态 status Int 1

0 待支付

1 已支付

2 退款中

3 已退款

总金额 total_fee Int 888 订单总金额,只能为整数,单位分。
支付单号 trade_no String(32) 1217752501201407033233368018 支付订单号
商家数据包 attach String(128) 123456 商家数据包,原样返回
支付完成时间 paid_at String(20) 2019-08-20 09:32:06 订单支付时间,格式为yyyy-MM-dd HH:mm:ss
退款金额 refund_fee Int 888 退款总金额,只能为整数,单位分。

status=2,3(退款中,已退款)时有返回

退款成功时间 refuned_at String(20) 2019-08-20 09:32:06 订单支付时间,格式为yyyy-MM-dd HH:mm:ss

status=3(已退款)时有返回

举例如下:

{
  "status": 0,
  "message": "查询成功",
  "data": {
    "status": 3,
    "out_trade_no": "TEST201908210907303341",
    "trade_no": "4200000355201908210023012340",
    "total_fee": 1,
    "attach": null,
    "paid_at": "2019-08-21 17:07:39",
    "refund_fee": 1,
    "refunded_at": "2019-08-21 17:07:52"
  }
}

申请退款

应用场景

当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。

注意:

1.交易时间超过一年的订单无法提交退款;

2.目前仅支持全额退款

3.调用接口成功,仅代表申请退款成功,此时钱不一定立即退款到账户!请隔一段时间后调用订单查询接口,确认订单状态是否为已退款(status=3)。

接口链接

{{ api }}/pay/refund

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mch_id String(32) 10010 分配的商户号
商户订单号 out_trade_no String(32) 1217752501201407033233368018 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
签名 sign String(32) 5K8264ILTKCH16CQ2502SI8ZNMTM67VS 签名,详见签名生成算法

返回结果

字段名 变量名 必填 类型 示例值 描述
返回状态码 status Int 0 0为成功,其它为失败
返回信息 message String(128) 签名失败 返回信息
返回数据 data Object

status=0时有返回

data数据内容

字段名 变量名 必填 类型 示例值 描述
商户订订号 out_trade_no String(32) 1217752501201407033233368018 商户系统内部订单号
总金额 total_fee Int 888 订单总金额,只能为整数,单位分。
退款金额 refund_fee Int 888 退款金额,只能为整数,单位分。

举例如下:

{
  "status": 0,
  "message": "申请退款成功",
  "data": {
    "out_refund_no": "TEST201908221035561012",
    "refund_fee": 1,
    "total_fee": 1
  }
}

支付结果通知

应用场景

支付完成后,我们会把相关支付结果及用户信息通过数据流的形式发送给商户,商户需要接收处理,并按文档规范返回应答。

注意:

1、同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。

2、在订单状态不明或者没有收到微信支付结果通知的情况下,建议商户主动调用微信支付【查询订单API】确认订单状态。

特别提醒:

1、商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失。

2、当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。

接口链接

该链接是通过【统一下单API】中提交的参数notify_url设置,如果链接无法访问,商户将无法接收到通知。

提交方式

采用POST方法提交

通知参数

商户号 mch_id String(32) 1900000109 分配的商户号
签名 sign String(32) C380BEC2BFD727A4B6845133519F3AD6 签名,详见签名算法

渠道代码 pt String(16) XIAOWEI JSAPI、NATIVE、APP
通道代码 channel String(16) NATIVE JSAPI、NATIVE
交易状态 status Int 1

0 待支付

1 已支付

2 退款中

3 已退款

总金额 total_fee Int 100 订单总金额,单位为分
支付订单号 trade_no String(32) 1217752501201407033233368018 支付订单号
商户订单号 out_trade_no String(32) 1212321211201407033568112322 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
商家数据包 attach String(128) 123456 商家数据包,原样返回
支付完成时间 paid_at String(20) 2019-08-20 09:32:06 订单支付时间,格式为yyyy-MM-dd HH:mm:ss

返回参数

收到支付结果通知后,请严格按照示例返回参数给我们:

字段名 变量名 必填 类型 示例值 描述
返回状态码 status Int 0

请按示例值填写

返回信息 message String(128) OK

请按示例值填写

举例如下:

{"status":0,"message":"OK"}

获取用户Openid

应用场景

在jsapi支付的时候需要用户的openid来下单,所以,在您下单之前,请使用本接口获取用户的openid。

请求地址

URL地址:{{ api }}/pay/openid

请求方式

GET (引导用户微信里打开链接)

请求参数

字段名 变量名 必填 类型 示例值 描述
商户号 mch_id String(32) 10010 分配的商户号
微信子商户号 sub_mch_id String(32) 1900000109 小微商户分配的子商户号。为空时,则会在多个小微商户中轮询,。
签名 sign String(32) C380BEC2BFD727A4B6845133519F3AD6 签名,详见签名生成算法
回调地址 callback String(32) http://www.test.com/openid/ 回调地址,如果用户同意授权,页面将跳转到此回调地址,且URL中附带openid参数

举例如下:

{{ api }}/pay/openid?mch_id&callback=http%3a%2f%2fwww.test.com%2fopenid%2f&sign=C380BEC2BFD727A4B6845133519F3AD6

返回说明:

获取openid后,会跳转到你传递的回调地址,并且附带上openid,sub_mch_id参数。下单时会用到这两个参数!

协议规则

商户接入支付,调用API必须遵循以下规则:

提交方式 采用POST方法提交
编码类型 Content-Type:application/x-www-form-unlencoded
返回数据 返回数据都为JSON格式
字符编码 统一采用UTF-8字符编码
签名算法 MD5
签名要求 请求和接收数据均需要校验签名,详细方法请参考签名算法
判断逻辑 先判断协议字段返回,再判断业务返回,最后判断交易状态

特别提示:

必须严格按照API的说明进行一单一支付,一单一付款,在未得到支付系统明确的回复之前不要换单,防止重复支付或者重复付款