赞
踩
微信支付存在多个业务流程,包括微信支付流程、退款流程等。本章节主要介绍微信的支付下单流程,图12-1是微信支付流程的交互图:
重点环节说明
商户系统调用该接口生成预支付交易单。提交支付订单的请求URL为:
https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi
提交支付订单的接口的请求参数如下:
参数名 | 变量 | 描述 |
---|---|---|
服务商应用ID | sp_appid | 必填)服务商申请的公众号appid。 |
服务商户号 | sp_mchid | (必填)服务商户号,由微信支付生成并下发 |
子商户应用ID | sub_appid | (必填)子商户申请的公众号appid。若sub_openid有传的情况下,sub_appid必填,且sub_appid需与sub_openid对应 |
子商户号 | sub_mchid | (必填)子商户的商户号,由微信支付生成并下发。 |
商品描述 | description | (必填)商品描述 |
商户订单号 | out_trade_no | (必填)商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。 |
结束时间 | time_expire | 订单失效时间。 |
附加数据 | attach | 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用 |
通知地址 | notify_url | (必填)通知URL必须为直接可访问的URL,不允许携带查询串。 |
优惠标记 | goods_tag | 订单优惠标记 |
+结算信息 | settle_info | 结算信息 |
-是否分账 | profit_sharing | 是否指定分账,枚举值true:是false:否 |
+订单金额 | amount | (必填)订单金额信息 |
-总金额 | total | (必填)订单总金额,单位为分。 |
-货币类型 | currency | CNY:人民币,境内商户号仅支持人民币。 |
+支付者 | payer | 支付者信息 |
-用户标识 | sp_openid | 用户在服务商appid下的唯一标识。 |
-用户子标识 | sub_openid | 用户在子商户appid下的唯一标识。若传sub_openid,那sub_appid必填 |
调用成功后返回:预支付交易会话标识(prepay_id),该参数用于小程序前端的接口调用中,该值的有效期为2小时。以下是实现提交支付订单的代码逻辑,首先给出的是统一下接口使用的数据结构:
//订单数据 type WxAppOrderData struct { //子商户用ID(服务商) Sub_appid string `json:"sub_appid,omitempty"` //子商户的商户号(服务商) Sub_mchid string `json:"sub_mchid,omitempty"` //商品描述 Description string `json:"description"` //商户系统内部订单号 Out_trade_no string `json:"out_trade_no"` //交易结束时间 Time_expire string `json:"time_expire,omitempty"` //附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用 Attach string `json:"attach,omitempty"` //通知URL必须为直接可访问的URL,不允许携带查询串 Notify_url string `json:"notify_url"` //订单优惠标记 Goods_tag string `json:"goods_tag,omitempty"` //订单金额信息 Amount OrderCreateAmount `json:"amount"` //支付者信息 Payer OrderPayer `json:"payer"` //统一下单结算信息 Settle_info OrderCreateSettle `json:"settle_info"` } //统一下单请求参数 type WxAppOrderCreateReq struct { //应用ID(普通商户) Appid string `json:"appid,omitempty"` //直连商户号(普通商户) Mchid string `json:"mchid,omitempty"` //服务商用ID(服务商) Sp_appid string `json:"sp_appid,omitempty"` //服务商户号(服务商) Sp_mchid string `json:"sp_mchid,omitempty"` //订单数据 WxAppOrderData } //统一下单返回参数 type WxAppOrderCreateRet struct { //详细错误码 Return_code string `json:"code"` //错误描述 Return_msg string `json:"message"` //预支付交易会话标识。用于后续接口调用中使用,该值有效期为2小时 Prepay_id string `json:"prepay_id"` }
微信支付为直连商户模式以及服务商模式提供了不同的调用接口(具有不同的接口地址以及请求参数)。本文中直连商户模式以及服务商模式共用一套数据结构,并通过json的omitempty标签来适应两种模式的区别。接下来给出服务商模式下接口调用的实现逻辑:
//支付统一下单 //data:支付订单信息 func (ent *MchWxapp) createOrderX(data WxAppOrderData) (WxAppPayParam, error) { var preq WxAppOrderCreateReq preq.Sp_appid = ent.Appid preq.Sp_mchid = ent.Mchid preq.WxAppOrderData = data data_body, _ := json.Marshal(preq) var param_ent WxAppPayParam var pret WxAppOrderCreateRet const url = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi" result, err := WxPayPostV3((*MchParam)(ent), url, data_body) if err != nil { return param_ent, err } err = json.Unmarshal([]byte(result), &pret) if err != nil { fmt.Println(err) return param_ent, err } if pret.Prepay_id == "" { return param_ent, errors.New(pret.Return_msg) } //小程序客户端支付参数 param_ent.Appid = preq.Sub_appid param_ent.TimeStamp = fmt.Sprintf("%d", time.Now().Unix()) param_ent.NonceStr, _= GenerateNonce() param_ent.Prepay_id = pret.Prepay_id param_ent.Package = "prepay_id=" + pret.Prepay_id param_ent.SignType = "RSA" param_ent.PaySign, _ = param_ent.GenPaySignV3(ent.MchPrivateKey) return param_ent, nil }
通过JSAPI下单成功获取预支付交易会话标识(prepay_id)后,需要通过小程序调用支付API(wx.requestPayment)来拉起微信客户端进行支付。wx.requestPayment需要将请求参数进行签名,签名计算的逻辑如下:
1)构造签名串
签名串一共有四行,每一行为一个参数。行尾以\n结束,包括最后一行。参与签名字段及格式为:
小程序appId\n时间戳\n随机字符串\n订单详情扩展字符串\n
2)计算签名值
使用商户私钥对签名串进行SHA256 with RSA签名,并对签名结果进行Base64编码得到签名值。
接下来给出小程序参数签名计算的实现代码,首先给出返回给小程序所需的支付数据的数据结构:
type WxAppPayParam struct{
Appid string
TimeStamp string
NonceStr string
Prepay_id string
Package string
SignType string
PaySign string
}
接下来使用商户私钥对签名串进行SHA256 with RSA签名,并对签名结果进行Base64编码来计算签名值:
func (ent *WxAppPayParam)GenPaySignV3(mch_pem_key *rsa.PrivateKey) (string, error) {
SignatureMessageFormat := "%s\n%s\n%s\n%s\n"
message := fmt.Sprintf(SignatureMessageFormat, ent.Appid, ent.TimeStamp, ent.NonceStr, ent.Package)
signatureResult, err := SignSHA256WithRSA(mch_pem_key, message)
if err != nil {
return "", err
}
return signatureResult, nil
}
直连商户的下单接口与服务商下单接口基本一致,除了接口地址不同外,下单时不需要提供子商户号(sub_mchid), 也不需要提供子商户子商户的应用ID(sub_appid)。直连商户下单接口的请求URL为:
https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi
直连商户下单接口的请求参数如下:
参数名 | 变量 | 描述 |
---|---|---|
应用ID | appid | body 由微信生成的应用ID,全局唯一。请求基础下单接口时请注意APPID的应用属性,例如公众号场景下,需使用应用属性为公众号的APPID |
直连商户号 | mchid | body 直连商户的商户号,由微信支付生成并下发。 |
商品描述 | description | body 商品描述 |
商户订单号 | out_trade_no | body 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 |
交易结束时间 | time_expire body | 订单失效时间,time_expire只能第一次下单传值,不允许二次修改,二次修改系统将报错。如用户支付失败后,需再次支付,需更换原订单号重新下单。 |
附加数据 | attach | body 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用 |
通知地址 | notify_url | body异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 公网域名必须为https,如果是走专线接入,使用专线NAT IP或者私有回调域名可使用http |
订单优惠标记 | goods_tag | body 订单优惠标记 |
订单金额 | amount | body 订单金额信息 |
支付者 | payer | body 支付者信息 |
优惠功能 | detail | body 优惠功能 |
场景信息 | scene_info | body 支付场景描述 |
结算信息 | settle_info | body 结算信息 |
以下是直连商户下单接口访问的代码实现:
func (ent *MchWxapp) createOrder(data WxAppOrderData) (WxAppPayParam, error) { var preq WxAppOrderCreateReq preq.Appid = ent.Appid preq.Mchid = ent.Mchid preq.WxAppOrderData = data data_body, _ := json.Marshal(preq) var param_ent WxAppPayParam var pret WxAppOrderCreateRet const url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi" result, err := WxPayPostV3((*MchParam)(ent), url, data_body) if err != nil { return param_ent, err } err = json.Unmarshal([]byte(result), &pret) if err != nil { return param_ent, err } if pret.Prepay_id == "" { return param_ent, errors.New(pret.Return_msg) } //小程序客户端支付参数 param_ent.Appid = preq.Appid param_ent.TimeStamp = fmt.Sprintf("%d", time.Now().Unix()) param_ent.NonceStr, _= GenerateNonce() param_ent.Prepay_id = pret.Prepay_id param_ent.Package = "prepay_id=" + pret.Prepay_id param_ent.SignType = "RSA" param_ent.PaySign, _ = param_ent.GenPaySignV3(ent.MchPrivateKey) return param_ent, nil }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。