Bläddra i källkod

add 支付通知的参数解析和签名验证

Jerry 6 år sedan
förälder
incheckning
7a8b21f097
3 ändrade filer med 80 tillägg och 45 borttagningar
  1. 27 1
      README.md
  2. 0 41
      wechat_notify.go
  3. 53 3
      wechat_servier_api.go

+ 27 - 1
README.md

@@ -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,无需用户授权
@@ -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)
+```
+
+
 ### 加密数据,解密到指定结构体
 
 > 拿小程序获取手机号为例

+ 0 - 41
wechat_notify.go

@@ -1,41 +0,0 @@
-//==================================
-//  * Name:Jerry
-//  * Tel:18017448610
-//  * DateTime:2019/1/28 20:16
-//==================================
-package gopay
-
-import (
-	"bytes"
-	"encoding/xml"
-	"net/http"
-)
-
-//解析支付完成后的回调信息
-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
-}

+ 53 - 3
wechat_servier_api.go

@@ -16,8 +16,11 @@ import (
 	"encoding/base64"
 	"encoding/hex"
 	"encoding/json"
+	"encoding/xml"
 	"errors"
 	"github.com/parnurzeal/gorequest"
+	"log"
+	"net/http"
 	"reflect"
 	"strings"
 )
@@ -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)
@@ -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()
@@ -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
 }