Skip to content

Commit

Permalink
add 支付通知的参数解析和签名验证
Browse files Browse the repository at this point in the history
  • Loading branch information
Jerry committed May 29, 2019
1 parent bd40bee commit 7a8b21f
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 45 deletions.
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
* 下载资金账单:gopay.DownloadFundFlow()
* 拉取订单评价数据:gopay.BatchQueryComment()

## 服务端API
## 公共API
* gopay.ParseNotifyResult() => 解析并返回微信支付通知的参数
* gopay.VerifyPayResultSign() => 支付通知的签名验证和参数签名后的Sign
* gopay.Code2Session() => 登录凭证校验:获取微信用户OpenId、UnionId、SessionKey
* gopay.GetAccessToken() => 获取小程序全局唯一后台接口调用凭据
* gopay.GetPaidUnionId() => 用户支付完成后,获取该用户的 UnionId,无需用户授权
Expand Down Expand Up @@ -109,6 +111,30 @@ fmt.Println("signType:", gopay.SignType_MD5)
fmt.Println("paySign:", paySign)
```

### 支付结果通知回调:参数解析和Sign值的验证

> 微信支付后的回调通知文档[支付结果通知](https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8)
```go
//解析支付完成后的回调信息
notifyRsp, err := gopay.ParseNotifyResult(c.Request())
if err != nil {
fmt.Println("err:", err)
}
fmt.Println("notifyRsp:", notifyRsp)

//支付通知的签名验证和参数签名后的Sign
// apiKey:API秘钥值
// signType:签名类型 MD5 或 HMAC-SHA256(默认请填写 MD5)
// notifyRsp:利用 gopay.ParseNotifyResult() 得到的结构体
// 返回参数ok:是否验证通过
// 返回参数sign:根据参数计算的sign值,非微信返回参数中的Sign
ok, sign := gopay.VerifyPayResultSign("192006250b4c09247ec02edce69f6a2d", "MD5", notifyRsp)
log.Println("ok:", ok)
log.Println("sign:", sign)
```


### 加密数据,解密到指定结构体

> 拿小程序获取手机号为例
Expand Down
41 changes: 0 additions & 41 deletions wechat_notify.go

This file was deleted.

56 changes: 53 additions & 3 deletions wechat_servier_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ import (
"encoding/base64"
"encoding/hex"
"encoding/json"
"encoding/xml"
"errors"
"github.com/parnurzeal/gorequest"
"log"
"net/http"
"reflect"
"strings"
)
Expand All @@ -28,7 +31,42 @@ func HttpAgent() (agent *gorequest.SuperAgent) {
return
}

//验证支付成功后通知Sign值
//解析支付完成后的回调信息
func ParseNotifyResult(req *http.Request) (notifyRsp *WeChatNotifyRequest, err error) {
notifyRsp = new(WeChatNotifyRequest)
defer req.Body.Close()
err = xml.NewDecoder(req.Body).Decode(notifyRsp)
if err != nil {
return nil, err
}
return
}

type WeChatNotifyResponse struct {
ReturnCode string `xml:"return_code"`
ReturnMsg string `xml:"return_msg"`
}

//返回数据给微信
func (this *WeChatNotifyResponse) ToXmlString() (xmlStr string) {
buffer := new(bytes.Buffer)
buffer.WriteString("<xml><return_code><![CDATA[")
buffer.WriteString(this.ReturnCode)
buffer.WriteString("]]></return_code>")

buffer.WriteString("<return_msg><![CDATA[")
buffer.WriteString(this.ReturnMsg)
buffer.WriteString("]]></return_msg></xml>")
xmlStr = buffer.String()
return
}

//支付通知的签名验证和参数签名后的Sign
// apiKey:API秘钥值
// signType:签名类型 MD5 或 HMAC-SHA256(默认请填写 MD5)
// notifyRsp:利用 gopay.ParseNotifyResult() 得到的结构体
// 返回参数ok:是否验证通过
// 返回参数sign:根据参数计算的sign值,非微信返回参数中的Sign
func VerifyPayResultSign(apiKey string, signType string, notifyRsp *WeChatNotifyRequest) (ok bool, sign string) {

body := make(BodyMap)
Expand Down Expand Up @@ -61,7 +99,19 @@ func VerifyPayResultSign(apiKey string, signType string, notifyRsp *WeChatNotify
body.Set("attach", notifyRsp.Attach)
body.Set("time_end", notifyRsp.TimeEnd)

signStr := sortSignParams(apiKey, body)
newBody := make(BodyMap)
for k, v := range body {
vStr := convert2String(v)
if vStr != "" && vStr != "0" {
newBody.Set(k, v)
}
}

for key, value := range newBody {
log.Printf("key:%v,value:%v\n", key, value)
}

signStr := sortSignParams(apiKey, newBody)
var hashSign []byte
if signType == SignType_MD5 {
hash := md5.New()
Expand All @@ -73,7 +123,7 @@ func VerifyPayResultSign(apiKey string, signType string, notifyRsp *WeChatNotify
hashSign = hash.Sum(nil)
}
sign = strings.ToUpper(hex.EncodeToString(hashSign))
ok = sign == notifyRsp.SignType
ok = sign == notifyRsp.Sign
return
}

Expand Down

0 comments on commit 7a8b21f

Please sign in to comment.