85411418@qq.com před 6 roky
rodič
revize
558d626572
8 změnil soubory, kde provedl 487 přidání a 580 odebrání
  1. 16 2
      README.md
  2. 17 0
      examples/wechat/wx_ServiceApi.go
  3. 2 1
      examples/wechat/wx_UnifiedOrder.go
  4. 68 67
      util.go
  5. 195 262
      wechat_client.go
  6. 13 17
      wechat_client_test.go
  7. 34 48
      wechat_params.go
  8. 142 183
      wechat_service_api.go

+ 16 - 2
README.md

@@ -51,6 +51,7 @@
 * gopay.GetWeChatAppletPaidUnionId() => 微信小程序用户支付完成后,获取该用户的 UnionId,无需用户授权
 * gopay.GetWeChatUserInfo() => 微信公众号:获取用户基本信息(UnionID机制)
 * gopay.DecryptWeChatOpenDataToStruct() => 加密数据,解密到指定结构体
+* gopay.DecryptWeChatOpenDataToBodyMap() => 加密数据,解密到 BodyMap
 * gopay.GetOpenIdByAuthCode() => 授权码查询openid
 * gopay.GetAppWeChatLoginAccessToken() => App应用微信第三方登录,code换取access_token
 * gopay.RefreshAppWeChatLoginAccessToken() => 刷新App应用微信第三方登录后,获取的 access_token
@@ -432,7 +433,6 @@ phone := new(gopay.WeChatUserPhone)
 //    beanPtr:需要解析到的结构体指针,操作完后,声明的结构体会被赋值
 err := gopay.DecryptWeChatOpenDataToStruct(data, iv, session, phone)
 fmt.Println(*phone)
-
 //获取微信小程序用户信息
 sessionKey := "tiihtNczf5v6AKRyjwEUhQ=="
 encryptedData := "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew=="
@@ -440,9 +440,23 @@ iv2 := "r7BXXKkLb8qrSNn05n0qiA=="
 
 //微信小程序 用户信息
 userInfo := new(gopay.WeChatAppletUserInfo)
-
 err = gopay.DecryptWeChatOpenDataToStruct(encryptedData, iv2, sessionKey, userInfo)
 fmt.Println(*userInfo)
+
+data := "Kf3TdPbzEmhWMuPKtlKxIWDkijhn402w1bxoHL4kLdcKr6jT1jNcIhvDJfjXmJcgDWLjmBiIGJ5acUuSvxLws3WgAkERmtTuiCG10CKLsJiR+AXVk7B2TUQzsq88YVilDz/YAN3647REE7glGmeBPfvUmdbfDzhL9BzvEiuRhABuCYyTMz4iaM8hFjbLB1caaeoOlykYAFMWC5pZi9P8uw=="
+iv := "Cds8j3VYoGvnTp1BrjXdJg=="
+session := "lyY4HPQbaOYzZdG+JcYK9w=="
+    
+//解密开放数据到 BodyMap
+//    encryptedData:包括敏感数据在内的完整用户信息的加密数据
+//    iv:加密算法的初始向量
+//    sessionKey:会话密钥
+bm, err := gopay.DecryptWeChatOpenDataToBodyMap(data, iv, session)
+if err != nil {
+     fmt.Println("err:", err)
+     return
+}
+fmt.Println("WeChatUserPhone:", bm)
 ```
 
 * #### 支付宝 公共API

+ 17 - 0
examples/wechat/wx_ServiceApi.go

@@ -143,6 +143,23 @@ func DecryptWeChatOpenDataToStruct() {
 	fmt.Println("Watermark:", userInfo.Watermark)
 }
 
+func DecryptWeChatOpenDataToBodyMap() {
+	data := "Kf3TdPbzEmhWMuPKtlKxIWDkijhn402w1bxoHL4kLdcKr6jT1jNcIhvDJfjXmJcgDWLjmBiIGJ5acUuSvxLws3WgAkERmtTuiCG10CKLsJiR+AXVk7B2TUQzsq88YVilDz/YAN3647REE7glGmeBPfvUmdbfDzhL9BzvEiuRhABuCYyTMz4iaM8hFjbLB1caaeoOlykYAFMWC5pZi9P8uw=="
+	iv := "Cds8j3VYoGvnTp1BrjXdJg=="
+	session := "lyY4HPQbaOYzZdG+JcYK9w=="
+
+	//解密开放数据
+	//    encryptedData:包括敏感数据在内的完整用户信息的加密数据
+	//    iv:加密算法的初始向量
+	//    sessionKey:会话密钥
+	bm, err := gopay.DecryptWeChatOpenDataToBodyMap(data, iv, session)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("WeChatUserPhone:", bm)
+}
+
 func GetOpenIdByAuthCode() {
 	//授权码查询openid
 	//    appId:APPID

+ 2 - 1
examples/wechat/wx_UnifiedOrder.go

@@ -2,9 +2,10 @@ package wechat
 
 import (
 	"fmt"
-	"github.com/iGoogle-ink/gopay"
 	"strconv"
 	"time"
+
+	"github.com/iGoogle-ink/gopay"
 )
 
 func UnifiedOrder() {

+ 68 - 67
util.go

@@ -3,8 +3,6 @@ package gopay
 import (
 	"crypto/tls"
 	"encoding/xml"
-	"fmt"
-	"github.com/parnurzeal/gorequest"
 	"io"
 	"math/rand"
 	"reflect"
@@ -12,6 +10,8 @@ import (
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/parnurzeal/gorequest"
 )
 
 type BodyMap map[string]interface{}
@@ -19,9 +19,7 @@ type BodyMap map[string]interface{}
 //设置参数
 //    value:仅支持类型 string,int,int64,float32,float64,ptr,struct,slice,map 类型,其他类型一律设置空字符串
 func (bm BodyMap) Set(key string, value interface{}) {
-	//验证参数类型
 	vKind := reflect.ValueOf(value).Kind()
-	//fmt.Println("vKind:", vKind)
 	switch vKind {
 	case reflect.String:
 		bm[key] = value.(string)
@@ -51,13 +49,16 @@ func (bm BodyMap) Get(key string) string {
 	if bm == nil {
 		return null
 	}
-	value, ok := bm[key]
-	if !ok {
+	var (
+		value interface{}
+		ok    bool
+		v     string
+	)
+	if value, ok = bm[key]; !ok {
 		return null
 	}
-	_, ok2 := value.(string)
-	if ok2 {
-		return value.(string)
+	if v, ok = value.(string); ok {
+		return v
 	}
 	return jsonToString(value)
 }
@@ -72,21 +73,19 @@ type xmlMapEntry struct {
 	Value   string `xml:",chardata"`
 }
 
-func (bm BodyMap) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+func (bm BodyMap) MarshalXML(e *xml.Encoder, start xml.StartElement) (err error) {
 	if len(bm) == 0 {
 		return nil
 	}
-
-	err := e.EncodeToken(start)
-	if err != nil {
-		return err
+	var (
+		value string
+		vKind reflect.Kind
+	)
+	if err = e.EncodeToken(start); err != nil {
+		return
 	}
-	var value string
 	for k, v := range bm {
-		//验证参数类型
-		fmt.Println("k:", k)
-		vKind := reflect.ValueOf(v).Kind()
-		//fmt.Println("vKind:", vKind)
+		vKind = reflect.ValueOf(v).Kind()
 		switch vKind {
 		case reflect.String:
 			value = v.(string)
@@ -103,29 +102,30 @@ func (bm BodyMap) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
 		}
 		e.Encode(xmlMapEntry{XMLName: xml.Name{Local: k}, Value: value})
 	}
-
 	return e.EncodeToken(start.End())
 }
 
-func (bm *BodyMap) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+func (bm *BodyMap) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
 	for {
 		var e xmlMapEntry
-		err := d.Decode(&e)
+		err = d.Decode(&e)
 		if err == io.EOF {
 			break
 		} else if err != nil {
-			return err
+			return
 		}
 		bm.Set(e.XMLName.Local, e.Value)
-		//(*bm)[e.XMLName.Local] = e.Value
 	}
-	return nil
+	return
 }
 
 // ("bar=baz&foo=quux") sorted by key.
 func (bm BodyMap) EncodeWeChatSignParams(apiKey string) string {
-	var buf strings.Builder
-	keyList := make([]string, 0, len(bm))
+	var (
+		buf     strings.Builder
+		keyList []string
+	)
+	keyList = make([]string, 0, len(bm))
 	for k := range bm {
 		keyList = append(keyList, k)
 	}
@@ -144,8 +144,11 @@ func (bm BodyMap) EncodeWeChatSignParams(apiKey string) string {
 
 // ("bar=baz&foo=quux") sorted by key.
 func (bm BodyMap) EncodeAliPaySignParams() string {
-	var buf strings.Builder
-	keyList := make([]string, 0, len(bm))
+	var (
+		buf     strings.Builder
+		keyList []string
+	)
+	keyList = make([]string, 0, len(bm))
 	for k := range bm {
 		keyList = append(keyList, k)
 	}
@@ -156,25 +159,25 @@ func (bm BodyMap) EncodeAliPaySignParams() string {
 		buf.WriteString(bm.Get(k))
 		buf.WriteByte('&')
 	}
-	s := buf.String()
-	i := buf.Len()
-	return s[:i-1]
+	return buf.String()[:buf.Len()]
 }
 
 //HttpAgent
 func HttpAgent() (agent *gorequest.SuperAgent) {
-	agent = gorequest.New()
-	agent.TLSClientConfig(&tls.Config{InsecureSkipVerify: true})
-	return
+	return gorequest.New().TLSClientConfig(&tls.Config{InsecureSkipVerify: true})
 }
 
 //获取随机字符串
 //    length:字符串长度
 func GetRandomString(length int) string {
 	str := "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
-	b := []byte(str)
-	var result []byte
-	r := rand.New(rand.NewSource(time.Now().UnixNano()))
+	var (
+		result []byte
+		b      []byte
+		r      *rand.Rand
+	)
+	b = []byte(str)
+	r = rand.New(rand.NewSource(time.Now().UnixNano()))
 	for i := 0; i < length; i++ {
 		result = append(result, b[r.Intn(len(b))])
 	}
@@ -187,32 +190,16 @@ func ParseDateTime(timeStr string) (datetime time.Time) {
 	return
 }
 
-//格式化Datetime
-func FormatDateTime(timeStr string) (formatTime string) {
-	//2019-01-04T15:40:00Z
-	//2019-01-18 20:51:30+08:00
-	if timeStr == null {
-		return null
-	}
-	replace := strings.Replace(timeStr, "T", " ", 1)
-	formatTime = replace[:19]
-	return
-}
-
-//格式化
-func FormatDate(dateStr string) (formatDate string) {
-	//2020-12-30T00:00:00+08:00
-	if dateStr == null {
-		return null
-	}
-	split := strings.Split(dateStr, "T")
-	formatDate = split[0]
+//字符串转Float64
+func String2Float64(floatStr string) (floatNum float64) {
+	floatNum, _ = strconv.ParseFloat(floatStr, 64)
 	return
 }
 
-//字符串转Float
-func String2Float(floatStr string) (floatNum float64) {
-	floatNum, _ = strconv.ParseFloat(floatStr, 64)
+//字符串转Float32
+func String2Float32(floatStr string) (floatNum float32) {
+	float, _ := strconv.ParseFloat(floatStr, 32)
+	floatNum = float32(float)
 	return
 }
 
@@ -246,6 +233,13 @@ func String2Int(intStr string) (intNum int) {
 	return
 }
 
+//字符串转Int32
+func String2Int32(intStr string) (int32Num int32) {
+	intNum, _ := strconv.Atoi(intStr)
+	int32Num = int32(intNum)
+	return
+}
+
 //字符串转Int64
 func String2Int64(intStr string) (int64Num int64) {
 	intNum, _ := strconv.Atoi(intStr)
@@ -259,6 +253,13 @@ func Int2String(intNum int) (intStr string) {
 	return
 }
 
+//Int32转字符串
+func Int322String(intNum int32) (int32Str string) {
+	//10, 代表10进制
+	int32Str = strconv.FormatInt(int64(intNum), 10)
+	return
+}
+
 //Int64转字符串
 func Int642String(intNum int64) (int64Str string) {
 	//10, 代表10进制
@@ -270,9 +271,9 @@ func Int642String(intNum int64) (int64Str string) {
 //解密时,需要在最后面去掉加密时添加的填充byte
 func PKCS7UnPadding(origData []byte) (bs []byte) {
 	length := len(origData)
-	unpaddingNumber := int(origData[length-1]) //找到Byte数组最后的填充byte 数字
-	if unpaddingNumber <= 16 {
-		bs = origData[:(length - unpaddingNumber)] //只截取返回有效数字内的byte数组
+	unPaddingNumber := int(origData[length-1]) //找到Byte数组最后的填充byte 数字
+	if unPaddingNumber <= 16 {
+		bs = origData[:(length - unPaddingNumber)] //只截取返回有效数字内的byte数组
 	} else {
 		bs = origData
 	}
@@ -283,9 +284,9 @@ func PKCS7UnPadding(origData []byte) (bs []byte) {
 //解密时,需要在最后面去掉加密时添加的填充byte
 func PKCS5UnPadding(origData []byte) (bs []byte) {
 	length := len(origData)
-	unpaddingNumber := int(origData[length-1]) //找到Byte数组最后的填充byte
-	if unpaddingNumber <= 16 {
-		bs = origData[:(length - unpaddingNumber)] //只截取返回有效数字内的byte数组
+	unPaddingNumber := int(origData[length-1]) //找到Byte数组最后的填充byte
+	if unPaddingNumber <= 16 {
+		bs = origData[:(length - unPaddingNumber)] //只截取返回有效数字内的byte数组
 	} else {
 		bs = origData
 	}

+ 195 - 262
wechat_client.go

@@ -8,6 +8,8 @@ import (
 	"fmt"
 	"io/ioutil"
 	"strings"
+
+	"github.com/parnurzeal/gorequest"
 )
 
 type WeChatClient struct {
@@ -24,421 +26,352 @@ type WeChatClient struct {
 //    apiKey:API秘钥值
 //    isProd:是否是正式环境
 func NewWeChatClient(appId, mchId, apiKey string, isProd bool) (client *WeChatClient) {
-	client = new(WeChatClient)
-	client.AppId = appId
-	client.MchId = mchId
-	client.apiKey = apiKey
-	client.isProd = isProd
-	return client
+	return &WeChatClient{
+		AppId:  appId,
+		MchId:  mchId,
+		apiKey: apiKey,
+		isProd: isProd}
 }
 
 //提交付款码支付 ok
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
-func (this *WeChatClient) Micropay(body BodyMap) (wxRsp *WeChatMicropayResponse, err error) {
-	var bytes []byte
-	if this.isProd {
-		//正式环境
-		bytes, err = this.doWeChat(body, wx_Micropay)
-		if err != nil {
-			return nil, err
-		}
+func (w *WeChatClient) Micropay(body BodyMap) (wxRsp *WeChatMicropayResponse, err error) {
+	var bs []byte
+	if w.isProd {
+		bs, err = w.doWeChat(body, wx_Micropay)
 	} else {
-		bytes, err = this.doWeChat(body, wx_SanBox_Micropay)
-		if err != nil {
-			return nil, err
-		}
+		bs, err = w.doWeChat(body, wx_SanBox_Micropay)
 	}
-
-	wxRsp = new(WeChatMicropayResponse)
-	err = xml.Unmarshal(bytes, wxRsp)
 	if err != nil {
+		return
+	}
+	wxRsp = new(WeChatMicropayResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal:%v", err.Error())
 	}
-	return wxRsp, nil
+	return
 }
 
 //统一下单 ok
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
-func (this *WeChatClient) UnifiedOrder(body BodyMap) (wxRsp *WeChatUnifiedOrderResponse, err error) {
-	var bytes []byte
-	if this.isProd {
-		//正式环境
-		bytes, err = this.doWeChat(body, wx_UnifiedOrder)
-		if err != nil {
-			return nil, err
-		}
+func (w *WeChatClient) UnifiedOrder(body BodyMap) (wxRsp *WeChatUnifiedOrderResponse, err error) {
+	var bs []byte
+	if w.isProd {
+		bs, err = w.doWeChat(body, wx_UnifiedOrder)
 	} else {
 		body.Set("total_fee", 101)
-		bytes, err = this.doWeChat(body, wx_SanBox_UnifiedOrder)
-		if err != nil {
-			return nil, err
-		}
+		bs, err = w.doWeChat(body, wx_SanBox_UnifiedOrder)
 	}
-
-	wxRsp = new(WeChatUnifiedOrderResponse)
-	//fmt.Println("bytes:", string(bytes))
-	err = xml.Unmarshal(bytes, wxRsp)
 	if err != nil {
-		//fmt.Println("xml.Unmarshal.Err:", err)
+		return
+	}
+	wxRsp = new(WeChatUnifiedOrderResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal:%v", err.Error())
 	}
-	return wxRsp, nil
+	return
 }
 
 //查询订单 ok
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
-func (this *WeChatClient) QueryOrder(body BodyMap) (wxRsp *WeChatQueryOrderResponse, err error) {
-	var bytes []byte
-	if this.isProd {
-		//正式环境
-		bytes, err = this.doWeChat(body, wx_OrderQuery)
-		if err != nil {
-			return nil, err
-		}
+func (w *WeChatClient) QueryOrder(body BodyMap) (wxRsp *WeChatQueryOrderResponse, err error) {
+	var bs []byte
+	if w.isProd {
+		bs, err = w.doWeChat(body, wx_OrderQuery)
 	} else {
-		bytes, err = this.doWeChat(body, wx_SanBox_OrderQuery)
-		if err != nil {
-			return nil, err
-		}
+		bs, err = w.doWeChat(body, wx_SanBox_OrderQuery)
 	}
-
-	wxRsp = new(WeChatQueryOrderResponse)
-	err = xml.Unmarshal(bytes, wxRsp)
 	if err != nil {
+		return
+	}
+	wxRsp = new(WeChatQueryOrderResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal:%v", err.Error())
 	}
-	return wxRsp, nil
+	return
 }
 
 //关闭订单 ok
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
-func (this *WeChatClient) CloseOrder(body BodyMap) (wxRsp *WeChatCloseOrderResponse, err error) {
-	var bytes []byte
-	if this.isProd {
-		//正式环境
-		bytes, err = this.doWeChat(body, wx_CloseOrder)
-		if err != nil {
-			return nil, err
-		}
+func (w *WeChatClient) CloseOrder(body BodyMap) (wxRsp *WeChatCloseOrderResponse, err error) {
+	var bs []byte
+	if w.isProd {
+		bs, err = w.doWeChat(body, wx_CloseOrder)
 	} else {
-		bytes, err = this.doWeChat(body, wx_SanBox_CloseOrder)
-		if err != nil {
-			return nil, err
-		}
+		bs, err = w.doWeChat(body, wx_SanBox_CloseOrder)
 	}
-
-	wxRsp = new(WeChatCloseOrderResponse)
-	err = xml.Unmarshal(bytes, wxRsp)
 	if err != nil {
+		return
+	}
+	wxRsp = new(WeChatCloseOrderResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal:%v", err.Error())
 	}
-	return wxRsp, nil
+	return
 }
 
 //撤销订单 ok
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
-func (this *WeChatClient) Reverse(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *WeChatReverseResponse, err error) {
-	var bytes []byte
-	if this.isProd {
-		//正式环境
-		pkcsPool := x509.NewCertPool()
-		pkcs, err := ioutil.ReadFile(pkcs12FilePath)
-		if err != nil {
+func (w *WeChatClient) Reverse(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *WeChatReverseResponse, err error) {
+	var (
+		bs, pkcs    []byte
+		pkcsPool    *x509.CertPool
+		certificate tls.Certificate
+		tlsConfig   *tls.Config
+	)
+	if w.isProd {
+		pkcsPool = x509.NewCertPool()
+		if pkcs, err = ioutil.ReadFile(pkcs12FilePath); err != nil {
 			return nil, fmt.Errorf("ioutil.ReadFile:%v", err.Error())
 		}
 		pkcsPool.AppendCertsFromPEM(pkcs)
-		certificate, err := tls.LoadX509KeyPair(certFilePath, keyFilePath)
-		if err != nil {
+		if certificate, err = tls.LoadX509KeyPair(certFilePath, keyFilePath); err != nil {
 			return nil, fmt.Errorf("tls.LoadX509KeyPair:%v", err.Error())
 		}
-		tlsConfig := new(tls.Config)
-		tlsConfig.Certificates = []tls.Certificate{certificate}
-		tlsConfig.RootCAs = pkcsPool
-		tlsConfig.InsecureSkipVerify = true
-
-		bytes, err = this.doWeChat(body, wx_Reverse, tlsConfig)
-		if err != nil {
-			return nil, err
-		}
+		tlsConfig = &tls.Config{
+			Certificates:       []tls.Certificate{certificate},
+			RootCAs:            pkcsPool,
+			InsecureSkipVerify: true}
+		bs, err = w.doWeChat(body, wx_Reverse, tlsConfig)
 	} else {
-		bytes, err = this.doWeChat(body, wx_SanBox_Reverse)
-		if err != nil {
-			return nil, err
-		}
+		bs, err = w.doWeChat(body, wx_SanBox_Reverse)
 	}
-
-	wxRsp = new(WeChatReverseResponse)
-	err = xml.Unmarshal(bytes, wxRsp)
 	if err != nil {
+		return
+	}
+	wxRsp = new(WeChatReverseResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal:%v", err.Error())
 	}
-	return wxRsp, nil
+	return
 }
 
 //申请退款 ok
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
-func (this *WeChatClient) Refund(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *WeChatRefundResponse, err error) {
-	var bytes []byte
-	if this.isProd {
-		//正式环境
-		pkcsPool := x509.NewCertPool()
-		pkcs, err := ioutil.ReadFile(pkcs12FilePath)
-		if err != nil {
+func (w *WeChatClient) Refund(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *WeChatRefundResponse, err error) {
+	var (
+		bs, pkcs    []byte
+		pkcsPool    *x509.CertPool
+		certificate tls.Certificate
+		tlsConfig   *tls.Config
+	)
+	if w.isProd {
+		pkcsPool = x509.NewCertPool()
+		if pkcs, err = ioutil.ReadFile(pkcs12FilePath); err != nil {
 			return nil, fmt.Errorf("ioutil.ReadFile:%v", err.Error())
 		}
 		pkcsPool.AppendCertsFromPEM(pkcs)
-		certificate, err := tls.LoadX509KeyPair(certFilePath, keyFilePath)
-		if err != nil {
+		if certificate, err = tls.LoadX509KeyPair(certFilePath, keyFilePath); err != nil {
 			return nil, fmt.Errorf("tls.LoadX509KeyPair:%v", err.Error())
 		}
-		tlsConfig := new(tls.Config)
-		tlsConfig.Certificates = []tls.Certificate{certificate}
-		tlsConfig.RootCAs = pkcsPool
-		tlsConfig.InsecureSkipVerify = true
-
-		bytes, err = this.doWeChat(body, wx_Refund, tlsConfig)
-		if err != nil {
-			return nil, err
-		}
+		tlsConfig = &tls.Config{
+			Certificates:       []tls.Certificate{certificate},
+			RootCAs:            pkcsPool,
+			InsecureSkipVerify: true}
+		bs, err = w.doWeChat(body, wx_Refund, tlsConfig)
 	} else {
-		bytes, err = this.doWeChat(body, wx_SanBox_Refund)
-		if err != nil {
-			return nil, err
-		}
+		bs, err = w.doWeChat(body, wx_SanBox_Refund)
 	}
-
-	wxRsp = new(WeChatRefundResponse)
-	err = xml.Unmarshal(bytes, wxRsp)
 	if err != nil {
+		return
+	}
+	wxRsp = new(WeChatRefundResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal:%v", err.Error())
 	}
-	return wxRsp, nil
+	return
 }
 
 //查询退款 ok
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
-func (this *WeChatClient) QueryRefund(body BodyMap) (wxRsp *WeChatQueryRefundResponse, err error) {
-	var bytes []byte
-	if this.isProd {
-		//正式环境
-		bytes, err = this.doWeChat(body, wx_RefundQuery)
-		if err != nil {
-			return nil, err
-		}
+func (w *WeChatClient) QueryRefund(body BodyMap) (wxRsp *WeChatQueryRefundResponse, err error) {
+	var bs []byte
+	if w.isProd {
+		bs, err = w.doWeChat(body, wx_RefundQuery)
 	} else {
-		bytes, err = this.doWeChat(body, wx_SanBox_RefundQuery)
-		if err != nil {
-			return nil, err
-		}
+		bs, err = w.doWeChat(body, wx_SanBox_RefundQuery)
 	}
-
-	wxRsp = new(WeChatQueryRefundResponse)
-	err = xml.Unmarshal(bytes, wxRsp)
 	if err != nil {
+		return
+	}
+	wxRsp = new(WeChatQueryRefundResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal:%v", err.Error())
 	}
-	return wxRsp, nil
+	return
 }
 
 //下载对账单 ok
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6
-func (this *WeChatClient) DownloadBill(body BodyMap) (wxRsp string, err error) {
-	var bytes []byte
-	if this.isProd {
-		//正式环境
-		bytes, err = this.doWeChat(body, wx_DownloadBill)
+func (w *WeChatClient) DownloadBill(body BodyMap) (wxRsp string, err error) {
+	var bs []byte
+	if w.isProd {
+		bs, err = w.doWeChat(body, wx_DownloadBill)
 	} else {
-		bytes, err = this.doWeChat(body, wx_SanBox_DownloadBill)
+		bs, err = w.doWeChat(body, wx_SanBox_DownloadBill)
 	}
-	wxRsp = string(bytes)
 	if err != nil {
-		return wxRsp, err
+		return
 	}
-	return wxRsp, nil
+	wxRsp = string(bs)
+	return
 }
 
 //下载资金账单 ok
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_18&index=7
 //    好像不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
-func (this *WeChatClient) DownloadFundFlow(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp string, err error) {
-	var bytes []byte
-	if this.isProd {
-		//正式环境
-		pkcsPool := x509.NewCertPool()
-		pkcs, err := ioutil.ReadFile(pkcs12FilePath)
-		if err != nil {
+func (w *WeChatClient) DownloadFundFlow(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp string, err error) {
+	var (
+		bs, pkcs    []byte
+		pkcsPool    *x509.CertPool
+		certificate tls.Certificate
+		tlsConfig   *tls.Config
+	)
+	if w.isProd {
+		pkcsPool = x509.NewCertPool()
+		if pkcs, err = ioutil.ReadFile(pkcs12FilePath); err != nil {
 			return null, fmt.Errorf("ioutil.ReadFile:%v", err.Error())
 		}
 		pkcsPool.AppendCertsFromPEM(pkcs)
-		certificate, err := tls.LoadX509KeyPair(certFilePath, keyFilePath)
-		if err != nil {
+		if certificate, err = tls.LoadX509KeyPair(certFilePath, keyFilePath); err != nil {
 			return null, fmt.Errorf("tls.LoadX509KeyPair:%v", err.Error())
 		}
-		tlsConfig := new(tls.Config)
-		tlsConfig.Certificates = []tls.Certificate{certificate}
-		tlsConfig.RootCAs = pkcsPool
-		tlsConfig.InsecureSkipVerify = true
-
-		bytes, err = this.doWeChat(body, wx_DownloadFundFlow, tlsConfig)
+		tlsConfig = &tls.Config{
+			Certificates:       []tls.Certificate{certificate},
+			RootCAs:            pkcsPool,
+			InsecureSkipVerify: true}
+		bs, err = w.doWeChat(body, wx_DownloadFundFlow, tlsConfig)
 	} else {
-		bytes, err = this.doWeChat(body, wx_SanBox_DownloadFundFlow)
+		bs, err = w.doWeChat(body, wx_SanBox_DownloadFundFlow)
 	}
-
 	if err != nil {
-		return null, err
+		return
 	}
-	wxRsp = string(bytes)
-	return wxRsp, nil
+	wxRsp = string(bs)
+	return
 }
 
 //拉取订单评价数据
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_17&index=11
 //    好像不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
-func (this *WeChatClient) BatchQueryComment(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp string, err error) {
-	var bytes []byte
-	if this.isProd {
-		//正式环境
+func (w *WeChatClient) BatchQueryComment(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp string, err error) {
+	var (
+		bs, pkcs    []byte
+		pkcsPool    *x509.CertPool
+		certificate tls.Certificate
+		tlsConfig   *tls.Config
+	)
+	if w.isProd {
 		body.Set("sign_type", SignType_HMAC_SHA256)
-
-		pkcsPool := x509.NewCertPool()
-		pkcs, err := ioutil.ReadFile(pkcs12FilePath)
-		if err != nil {
+		pkcsPool = x509.NewCertPool()
+		if pkcs, err = ioutil.ReadFile(pkcs12FilePath); err != nil {
 			return null, fmt.Errorf("ioutil.ReadFile:%v", err.Error())
 		}
 		pkcsPool.AppendCertsFromPEM(pkcs)
-		certificate, err := tls.LoadX509KeyPair(certFilePath, keyFilePath)
-		if err != nil {
+		if certificate, err = tls.LoadX509KeyPair(certFilePath, keyFilePath); err != nil {
 			return null, fmt.Errorf("tls.LoadX509KeyPair:%v", err.Error())
 		}
-		tlsConfig := new(tls.Config)
-		tlsConfig.Certificates = []tls.Certificate{certificate}
-		tlsConfig.RootCAs = pkcsPool
-		tlsConfig.InsecureSkipVerify = true
-
-		bytes, err = this.doWeChat(body, wx_BatchQueryComment, tlsConfig)
+		tlsConfig = &tls.Config{
+			Certificates:       []tls.Certificate{certificate},
+			RootCAs:            pkcsPool,
+			InsecureSkipVerify: true}
+		bs, err = w.doWeChat(body, wx_BatchQueryComment, tlsConfig)
 	} else {
-		bytes, err = this.doWeChat(body, wx_SanBox_BatchQueryComment)
+		bs, err = w.doWeChat(body, wx_SanBox_BatchQueryComment)
 	}
-
 	if err != nil {
-		return null, err
+		return
 	}
-
-	wxRsp = string(bytes)
-	return wxRsp, nil
+	wxRsp = string(bs)
+	return
 }
 
 //企业向微信用户个人付款
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1
 //    注意:此方法未支持沙箱环境,默认正式环境,转账请慎重
-func (this *WeChatClient) Transfer(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *WeChatTransfersResponse, err error) {
-	var bytes []byte
-	var sign string
-	body.Set("mch_appid", this.AppId)
-	body.Set("mchid", this.MchId)
-
-	agent := HttpAgent()
-
-	//正式环境
-	pkcsPool := x509.NewCertPool()
-	pkcs, err := ioutil.ReadFile(pkcs12FilePath)
-	if err != nil {
+func (w *WeChatClient) Transfer(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *WeChatTransfersResponse, err error) {
+	body.Set("mch_appid", w.AppId)
+	body.Set("mchid", w.MchId)
+	var (
+		bs, pkcs    []byte
+		pkcsPool    *x509.CertPool
+		certificate tls.Certificate
+		tlsConfig   *tls.Config
+		agent       *gorequest.SuperAgent
+		errs        []error
+		res         gorequest.Response
+	)
+	pkcsPool = x509.NewCertPool()
+	if pkcs, err = ioutil.ReadFile(pkcs12FilePath); err != nil {
 		return nil, fmt.Errorf("ioutil.ReadFile:%v", err.Error())
 	}
 	pkcsPool.AppendCertsFromPEM(pkcs)
-	certificate, err := tls.LoadX509KeyPair(certFilePath, keyFilePath)
-	if err != nil {
+	if certificate, err = tls.LoadX509KeyPair(certFilePath, keyFilePath); err != nil {
 		return nil, fmt.Errorf("tls.LoadX509KeyPair:%v", err.Error())
 	}
-	tlsConfig := new(tls.Config)
-	tlsConfig.Certificates = []tls.Certificate{certificate}
-	tlsConfig.RootCAs = pkcsPool
-	tlsConfig.InsecureSkipVerify = true
-
-	agent.TLSClientConfig(tlsConfig)
-
-	//本地计算Sign
-	sign = getWeChatReleaseSign(this.apiKey, SignType_MD5, body)
-
-	body.Set("sign", sign)
-	reqXML := generateXml(body)
-
-	if this.baseURL != null {
-		agent.Post(this.baseURL + wx_Transfers)
+	tlsConfig = &tls.Config{
+		Certificates:       []tls.Certificate{certificate},
+		RootCAs:            pkcsPool,
+		InsecureSkipVerify: true}
+	body.Set("sign", getWeChatReleaseSign(w.apiKey, SignType_MD5, body))
+	agent = HttpAgent().TLSClientConfig(tlsConfig)
+	if w.baseURL != null {
+		agent.Post(w.baseURL + wx_Transfers)
 	} else {
 		agent.Post(wx_base_url_ch + wx_Transfers)
 	}
-	agent.Type("xml")
-	agent.SendString(reqXML)
-
-	_, bytes, errs := agent.EndBytes()
-	if len(errs) > 0 {
+	if res, bs, errs = agent.Type("xml").SendString(generateXml(body)).EndBytes(); len(errs) > 0 {
 		return nil, errs[0]
 	}
-
+	if res.StatusCode != 200 {
+		return nil, fmt.Errorf("HTTP Request Error, StatusCode = %v", res.StatusCode)
+	}
 	wxRsp = new(WeChatTransfersResponse)
-	err = xml.Unmarshal(bytes, wxRsp)
-	if err != nil {
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal:%v", err.Error())
 	}
-	return wxRsp, nil
+	return
 }
 
 //向微信发送请求 ok
-func (this *WeChatClient) doWeChat(body BodyMap, path string, tlsConfig ...*tls.Config) (bytes []byte, err error) {
-	var sign string
-	body.Set("appid", this.AppId)
-	body.Set("mch_id", this.MchId)
-	//===============生成参数===================
+func (w *WeChatClient) doWeChat(body BodyMap, path string, tlsConfig ...*tls.Config) (bytes []byte, err error) {
+	body.Set("appid", w.AppId)
+	body.Set("mch_id", w.MchId)
+	var (
+		sign string
+		errs []error
+		res  gorequest.Response
+	)
 	if body.Get("sign") != null {
 		goto GoRequest
 	}
-
-	//计算Sign值
-	if !this.isProd {
-		//沙箱环境
+	if !w.isProd {
 		body.Set("sign_type", SignType_MD5)
-		//沙箱环境Sign值
-		sign, err = getWeChatSignBoxSign(this.MchId, this.apiKey, body)
-		if err != nil {
-			//fmt.Println("getWeChatSignBoxSign:", err)
-			return nil, err
+		if sign, err = getWeChatSignBoxSign(w.MchId, w.apiKey, body); err != nil {
+			return
 		}
 	} else {
-		//正式环境
-		sign = getWeChatReleaseSign(this.apiKey, body.Get("sign_type"), body)
+		sign = getWeChatReleaseSign(w.apiKey, body.Get("sign_type"), body)
 	}
 	body.Set("sign", sign)
-
 GoRequest:
-	reqXML := generateXml(body)
-	//fmt.Println("reqXML:",reqXML)
-	//===============发起请求===================
 	agent := HttpAgent()
-
-	if this.isProd && tlsConfig != nil {
+	if w.isProd && tlsConfig != nil {
 		agent.TLSClientConfig(tlsConfig[0])
 	}
-
-	if this.baseURL != null {
-		agent.Post(this.baseURL + path)
+	if w.baseURL != null {
+		agent.Post(w.baseURL + path)
 	} else {
 		agent.Post(wx_base_url_ch + path)
 	}
-	agent.Type("xml")
-	agent.SendString(reqXML)
-	res, bytes, errs := agent.EndBytes()
-	if len(errs) > 0 {
-		//fmt.Println("errs[0]:", errs[0])
+	if res, bytes, errs = agent.Type("xml").SendString(generateXml(body)).EndBytes(); len(errs) > 0 {
 		return nil, errs[0]
 	}
-	//fmt.Println("res:", res.StatusCode)
 	if res.StatusCode != 200 {
 		return nil, fmt.Errorf("HTTP Request Error, StatusCode = %v", res.StatusCode)
 	}
 	if strings.Contains(string(bytes), "HTML") {
 		return nil, errors.New(string(bytes))
 	}
-	//fmt.Println("bytes:", string(bytes))
-	return bytes, nil
+	return
 }

+ 13 - 17
wechat_client_test.go

@@ -123,23 +123,19 @@ func TestDecryptWeChatOpenDataToStruct(t *testing.T) {
 	fmt.Println("Watermark:", userInfo.Watermark)
 }
 
-func TestDecryptWeChatOpenDataToStruct2(t *testing.T) {
-	data := "2GvPXomJA5jkyL/iV6hKC/Y2cvYIB0BciH48hATEjqiHG9qWOHBdyu7jmq5gp9knqg5ZuUclpLUdkvI2UPTvFIG4z1IIZWLzmQkEwTIRdCiEnx+Y6ONSHZHXqR6/1CRV91qMMaEc9AheBc0988OX0pKmMhkynVYb7+duJauHqo/rVRc9119bhLRJixUrZcxHVfGzB7OeN6nhsJXd3OCmqlk0QzSRwHhytsWJoMyNrnllITDLJq/4qSXkbI72FwLu1TwjAOiUTvocfMCtMroQ+u7iylSOxSeykASK3DQGcKtXlFPXN7FxSaTNoOkFMSz5QMwzbwcwXTyGnn9VYqX6MqVqJdCOPVx1ohsIClHR7zRllej5okK7/hEsdJuyNZlIKwW109rWoZvwiD7fiOK3LF0pKwE+3dkTy9v2pyJaz4iP+0GAUWJTtSmINUAsvx2kITMRZytt5T4zAZ0GXodaFJh3q9dHX9WH1iAm8tTGXHpPRiWjQJqf3ccu49iWcf22/jFQPxzn22AQnucSer1Rgw=="
-	iv := "r4rE971rDUbd/+BKZgCCIg=="
-	key:="HtBJjHAJu6qPcUFuLoV7CA=="
-	userInfo := new(WeChatAppletUserInfo)
-	err := DecryptWeChatOpenDataToStruct(data,iv,key,userInfo)
+func TestDecryptWeChatOpenDataToBodyMap(t *testing.T) {
+	data := "Kf3TdPbzEmhWMuPKtlKxIWDkijhn402w1bxoHL4kLdcKr6jT1jNcIhvDJfjXmJcgDWLjmBiIGJ5acUuSvxLws3WgAkERmtTuiCG10CKLsJiR+AXVk7B2TUQzsq88YVilDz/YAN3647REE7glGmeBPfvUmdbfDzhL9BzvEiuRhABuCYyTMz4iaM8hFjbLB1caaeoOlykYAFMWC5pZi9P8uw=="
+	iv := "Cds8j3VYoGvnTp1BrjXdJg=="
+	session := "lyY4HPQbaOYzZdG+JcYK9w=="
+
+	//解密开放数据
+	//    encryptedData:包括敏感数据在内的完整用户信息的加密数据
+	//    iv:加密算法的初始向量
+	//    sessionKey:会话密钥
+	bm, err := DecryptWeChatOpenDataToBodyMap(data, iv, session)
 	if err != nil {
-		_ = fmt.Errorf("%v", err)
+		fmt.Println("err:", err)
+		return
 	}
-	fmt.Println("NickName:", userInfo.NickName)
-	fmt.Println("AvatarUrl:", userInfo.AvatarUrl)
-	fmt.Println("Country:", userInfo.Country)
-	fmt.Println("Province:", userInfo.Province)
-	fmt.Println("City:", userInfo.City)
-	fmt.Println("Gender:", userInfo.Gender)
-	fmt.Println("OpenId:", userInfo.OpenId)
-	fmt.Println("UnionId:", userInfo.UnionId)
-	fmt.Println("Watermark:", userInfo.Watermark)
-
+	fmt.Println("WeChatUserPhone:", bm)
 }

+ 34 - 48
wechat_params.go

@@ -7,6 +7,7 @@ import (
 	"encoding/hex"
 	"encoding/xml"
 	"errors"
+	"hash"
 	"strings"
 )
 
@@ -15,55 +16,48 @@ type Country int
 //设置支付国家(默认:中国国内)
 //    根据支付地区情况设置国家
 //    country:<China:中国国内,China2:中国国内(冗灾方案),SoutheastAsia:东南亚,Other:其他国家>
-func (this *WeChatClient) SetCountry(country Country) (client *WeChatClient) {
+func (w *WeChatClient) SetCountry(country Country) (client *WeChatClient) {
 	switch country {
 	case China:
-		this.baseURL = wx_base_url_ch
+		w.baseURL = wx_base_url_ch
 	case China2:
-		this.baseURL = wx_base_url_ch2
+		w.baseURL = wx_base_url_ch2
 	case SoutheastAsia:
-		this.baseURL = wx_base_url_hk
+		w.baseURL = wx_base_url_hk
 	case Other:
-		this.baseURL = wx_base_url_us
+		w.baseURL = wx_base_url_us
 	default:
-		this.baseURL = wx_base_url_ch
+		w.baseURL = wx_base_url_ch
 	}
-	return this
+	return w
 }
 
 //获取微信支付正式环境Sign值
 func getWeChatReleaseSign(apiKey string, signType string, bm BodyMap) (sign string) {
-	signStr := bm.EncodeWeChatSignParams(apiKey)
-	//fmt.Println("signStr:", signStr)
-	var hashSign []byte
+	var h hash.Hash
 	if signType == SignType_HMAC_SHA256 {
-		hash := hmac.New(sha256.New, []byte(apiKey))
-		hash.Write([]byte(signStr))
-		hashSign = hash.Sum(nil)
+		h = hmac.New(sha256.New, []byte(apiKey))
 	} else {
-		hash := md5.New()
-		hash.Write([]byte(signStr))
-		hashSign = hash.Sum(nil)
+		h = md5.New()
 	}
-	sign = strings.ToUpper(hex.EncodeToString(hashSign))
+	h.Write([]byte(bm.EncodeWeChatSignParams(apiKey)))
+	sign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
 	return
 }
 
 //获取微信支付沙箱环境Sign值
 func getWeChatSignBoxSign(mchId, apiKey string, bm BodyMap) (sign string, err error) {
-
-	//从微信接口获取SanBox的ApiKey
-	sanBoxApiKey, err := getSanBoxKey(mchId, GetRandomString(32), apiKey, SignType_MD5)
-	if err != nil {
-		return null, err
+	var (
+		sanBoxApiKey string
+		h            hash.Hash
+	)
+	if sanBoxApiKey, err = getSanBoxKey(mchId, GetRandomString(32), apiKey, SignType_MD5); err != nil {
+		return
 	}
-	signStr := bm.EncodeWeChatSignParams(sanBoxApiKey)
-	//fmt.Println("signStr:", signStr)
-	hash := md5.New()
-	hash.Write([]byte(signStr))
-	hashSign := hash.Sum(nil)
-	sign = strings.ToUpper(hex.EncodeToString(hashSign))
-	return sign, nil
+	h = md5.New()
+	h.Write([]byte(bm.EncodeWeChatSignParams(sanBoxApiKey)))
+	sign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
+	return
 }
 
 //从微信提供的接口获取:SandboxSignKey
@@ -71,13 +65,9 @@ func getSanBoxKey(mchId, nonceStr, apiKey, signType string) (key string, err err
 	body := make(BodyMap)
 	body.Set("mch_id", mchId)
 	body.Set("nonce_str", nonceStr)
-
-	//计算沙箱参数Sign
-	sanboxSign := getWeChatReleaseSign(apiKey, signType, body)
 	//沙箱环境:获取沙箱环境ApiKey
-	key, err = getSanBoxSignKey(mchId, nonceStr, sanboxSign)
-	if err != nil {
-		return null, err
+	if key, err = getSanBoxSignKey(mchId, nonceStr, getWeChatReleaseSign(apiKey, signType, body)); err != nil {
+		return
 	}
 	return
 }
@@ -88,20 +78,17 @@ func getSanBoxSignKey(mchId, nonceStr, sign string) (key string, err error) {
 	reqs.Set("mch_id", mchId)
 	reqs.Set("nonce_str", nonceStr)
 	reqs.Set("sign", sign)
-
-	reqXml := generateXml(reqs)
-	//fmt.Println("req:::", reqXml)
-	_, byteList, errorList := HttpAgent().
-		Post(wx_SanBox_GetSignKey).
-		Type("xml").
-		SendString(reqXml).EndBytes()
-	if len(errorList) > 0 {
+	var (
+		byteList    []byte
+		errorList   []error
+		keyResponse *getSignKeyResponse
+	)
+	if _, byteList, errorList = HttpAgent().Post(wx_SanBox_GetSignKey).Type("xml").SendString(generateXml(reqs)).EndBytes(); len(errorList) > 0 {
 		return null, errorList[0]
 	}
-	keyResponse := new(getSignKeyResponse)
-	err = xml.Unmarshal(byteList, keyResponse)
-	if err != nil {
-		return null, err
+	keyResponse = new(getSignKeyResponse)
+	if err = xml.Unmarshal(byteList, keyResponse); err != nil {
+		return
 	}
 	if keyResponse.ReturnCode == "FAIL" {
 		return null, errors.New(keyResponse.ReturnMsg)
@@ -113,7 +100,6 @@ func getSanBoxSignKey(mchId, nonceStr, sign string) (key string, err error) {
 func generateXml(bm BodyMap) (reqXml string) {
 	var buffer strings.Builder
 	buffer.WriteString("<xml>")
-
 	for key := range bm {
 		buffer.WriteByte('<')
 		buffer.WriteString(key)

+ 142 - 183
wechat_service_api.go

@@ -12,7 +12,7 @@ import (
 	"encoding/xml"
 	"errors"
 	"fmt"
-	"github.com/parnurzeal/gorequest"
+	"hash"
 	"io/ioutil"
 	"net/http"
 	"reflect"
@@ -28,24 +28,21 @@ import (
 func GetWeChatParamSign(appId, mchId, apiKey string, bm BodyMap) (sign string) {
 	bm.Set("appid", appId)
 	bm.Set("mch_id", mchId)
-	signType := bm.Get("sign_type")
+	var (
+		signType string
+		h        hash.Hash
+	)
+	signType = bm.Get("sign_type")
 	if signType == null {
 		bm.Set("sign_type", SignType_MD5)
 	}
-	signStr := bm.EncodeWeChatSignParams(apiKey)
-	//fmt.Println("signStr:", signStr)
-
-	var hashSign []byte
 	if signType == SignType_HMAC_SHA256 {
-		hash := hmac.New(sha256.New, []byte(apiKey))
-		hash.Write([]byte(signStr))
-		hashSign = hash.Sum(nil)
+		h = hmac.New(sha256.New, []byte(apiKey))
 	} else {
-		hash := md5.New()
-		hash.Write([]byte(signStr))
-		hashSign = hash.Sum(nil)
+		h = md5.New()
 	}
-	sign = strings.ToUpper(hex.EncodeToString(hashSign))
+	h.Write([]byte(bm.EncodeWeChatSignParams(apiKey)))
+	sign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
 	return
 }
 
@@ -59,20 +56,17 @@ func GetWeChatSanBoxParamSign(appId, mchId, apiKey string, bm BodyMap) (sign str
 	bm.Set("appid", appId)
 	bm.Set("mch_id", mchId)
 	bm.Set("sign_type", SignType_MD5)
-
-	//从微信接口获取SanBox的ApiKey
-	sanBoxApiKey, err := getSanBoxKey(mchId, GetRandomString(32), apiKey, SignType_MD5)
-	if err != nil {
-		return null, err
+	var (
+		sanBoxApiKey string
+		hashMd5      hash.Hash
+	)
+	if sanBoxApiKey, err = getSanBoxKey(mchId, GetRandomString(32), apiKey, SignType_MD5); err != nil {
+		return
 	}
-	signStr := bm.EncodeWeChatSignParams(sanBoxApiKey)
-	//fmt.Println("signStr:", signStr)
-
-	hash := md5.New()
-	hash.Write([]byte(signStr))
-	hashSign := hash.Sum(nil)
-	sign = strings.ToUpper(hex.EncodeToString(hashSign))
-	return sign, nil
+	hashMd5 = md5.New()
+	hashMd5.Write([]byte(bm.EncodeWeChatSignParams(sanBoxApiKey)))
+	sign = strings.ToUpper(hex.EncodeToString(hashMd5.Sum(nil)))
+	return
 }
 
 //解析微信支付异步通知的结果到BodyMap
@@ -80,18 +74,14 @@ func GetWeChatSanBoxParamSign(appId, mchId, apiKey string, bm BodyMap) (sign str
 //    返回参数bm:Notify请求的参数
 //    返回参数err:错误信息
 func ParseWeChatNotifyResultToBodyMap(req *http.Request) (bm BodyMap, err error) {
-	bs, err := ioutil.ReadAll(req.Body)
-	defer req.Body.Close()
-	if err != nil {
+	var bs []byte
+	if bs, err = ioutil.ReadAll(req.Body); err != nil {
 		return nil, fmt.Errorf("ioutil.ReadAll:%v", err.Error())
 	}
-	//获取Notify请求参数
 	bm = make(BodyMap)
-	err = xml.Unmarshal(bs, &bm)
-	if err != nil {
+	if err = xml.Unmarshal(bs, &bm); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal:%v", err.Error())
 	}
-
 	return
 }
 
@@ -101,9 +91,7 @@ func ParseWeChatNotifyResultToBodyMap(req *http.Request) (bm BodyMap, err error)
 //    返回参数err:错误信息
 func ParseWeChatNotifyResult(req *http.Request) (notifyReq *WeChatNotifyRequest, err error) {
 	notifyReq = new(WeChatNotifyRequest)
-	defer req.Body.Close()
-	err = xml.NewDecoder(req.Body).Decode(notifyReq)
-	if err != nil {
+	if err = xml.NewDecoder(req.Body).Decode(notifyReq); err != nil {
 		return nil, fmt.Errorf("xml.NewDecoder:%v", err.Error())
 	}
 	return
@@ -148,7 +136,6 @@ func VerifyWeChatResultSign(apiKey, signType string, notifyReq *WeChatNotifyRequ
 	body.Set("out_trade_no", notifyReq.OutTradeNo)
 	body.Set("attach", notifyReq.Attach)
 	body.Set("time_end", notifyReq.TimeEnd)
-
 	newBody := make(BodyMap)
 	for key := range body {
 		vStr := body.Get(key)
@@ -156,9 +143,7 @@ func VerifyWeChatResultSign(apiKey, signType string, notifyReq *WeChatNotifyRequ
 			newBody.Set(key, vStr)
 		}
 	}
-
 	sign = getWeChatReleaseSign(apiKey, signType, newBody)
-
 	ok = sign == notifyReq.Sign
 	return
 }
@@ -174,31 +159,27 @@ func VerifyWeChatSign(apiKey, signType string, bean interface{}) (ok bool, err e
 		return false, errors.New("bean is nil")
 	}
 	var (
-		bm BodyMap
-		bs []byte
+		bm       BodyMap
+		bs       []byte
+		kind     reflect.Kind
+		bodySign string
 	)
-	kind := reflect.ValueOf(bean).Kind()
+	kind = reflect.ValueOf(bean).Kind()
 	if kind == reflect.Map {
 		bm = bean.(BodyMap)
 		goto Verify
 	}
-
-	bs, err = json.Marshal(bean)
-	if err != nil {
+	if bs, err = json.Marshal(bean); err != nil {
 		return false, fmt.Errorf("json.Marshal:%v", err.Error())
 	}
-
 	bm = make(BodyMap)
-	err = json.Unmarshal(bs, &bm)
-	if err != nil {
+	if err = json.Unmarshal(bs, &bm); err != nil {
 		return false, fmt.Errorf("json.Unmarshal:%v", err.Error())
 	}
 Verify:
-	bodySign := bm.Get("sign")
+	bodySign = bm.Get("sign")
 	bm.Remove("sign")
-	sign := getWeChatReleaseSign(apiKey, signType, bm)
-	//fmt.Println("sign:", sign)
-	return sign == bodySign, nil
+	return getWeChatReleaseSign(apiKey, signType, bm) == bodySign, nil
 }
 
 type WeChatNotifyResponse struct {
@@ -207,14 +188,13 @@ type WeChatNotifyResponse struct {
 }
 
 //返回数据给微信
-func (this *WeChatNotifyResponse) ToXmlString() (xmlStr string) {
+func (w *WeChatNotifyResponse) ToXmlString() (xmlStr string) {
 	var buffer strings.Builder
 	buffer.WriteString("<xml><return_code><![CDATA[")
-	buffer.WriteString(this.ReturnCode)
+	buffer.WriteString(w.ReturnCode)
 	buffer.WriteString("]]></return_code>")
-
 	buffer.WriteString("<return_msg><![CDATA[")
-	buffer.WriteString(this.ReturnMsg)
+	buffer.WriteString(w.ReturnMsg)
 	buffer.WriteString("]]></return_msg></xml>")
 	xmlStr = buffer.String()
 	return
@@ -227,42 +207,31 @@ func (this *WeChatNotifyResponse) ToXmlString() (xmlStr string) {
 //    signType:签名类型
 //    timeStamp:时间
 //    apiKey:API秘钥值
-//
 //    微信小程序支付API:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html
 func GetMiniPaySign(appId, nonceStr, prepayId, signType, timeStamp, apiKey string) (paySign string) {
-	var buffer strings.Builder
+	var (
+		buffer strings.Builder
+		h      hash.Hash
+	)
 	buffer.WriteString("appId=")
 	buffer.WriteString(appId)
-
 	buffer.WriteString("&nonceStr=")
 	buffer.WriteString(nonceStr)
-
 	buffer.WriteString("&package=")
 	buffer.WriteString(prepayId)
-
 	buffer.WriteString("&signType=")
 	buffer.WriteString(signType)
-
 	buffer.WriteString("&timeStamp=")
 	buffer.WriteString(timeStamp)
-
 	buffer.WriteString("&key=")
 	buffer.WriteString(apiKey)
-
-	signStr := buffer.String()
-
-	var hashSign []byte
 	if signType == SignType_HMAC_SHA256 {
-		hash := hmac.New(sha256.New, []byte(apiKey))
-		hash.Write([]byte(signStr))
-		hashSign = hash.Sum(nil)
+		h = hmac.New(sha256.New, []byte(apiKey))
 	} else {
-		hash := md5.New()
-		hash.Write([]byte(signStr))
-		hashSign = hash.Sum(nil)
+		h = md5.New()
 	}
-	paySign = strings.ToUpper(hex.EncodeToString(hashSign))
-	return
+	h.Write([]byte(buffer.String()))
+	return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
 }
 
 //微信内H5支付,统一下单获取支付参数后,再次计算出微信内H5支付需要用的paySign
@@ -272,41 +241,31 @@ func GetMiniPaySign(appId, nonceStr, prepayId, signType, timeStamp, apiKey strin
 //    signType:签名类型
 //    timeStamp:时间
 //    apiKey:API秘钥值
-//
 //    微信内H5支付官方文档:https://pay.weixin.qq.com/wiki/doc/api/external/jsapi.php?chapter=7_7&index=6
 func GetH5PaySign(appId, nonceStr, packages, signType, timeStamp, apiKey string) (paySign string) {
-	var buffer strings.Builder
+	var (
+		buffer strings.Builder
+		h      hash.Hash
+	)
 	buffer.WriteString("appId=")
 	buffer.WriteString(appId)
-
 	buffer.WriteString("&nonceStr=")
 	buffer.WriteString(nonceStr)
-
 	buffer.WriteString("&package=")
 	buffer.WriteString(packages)
-
 	buffer.WriteString("&signType=")
 	buffer.WriteString(signType)
-
 	buffer.WriteString("&timeStamp=")
 	buffer.WriteString(timeStamp)
-
 	buffer.WriteString("&key=")
 	buffer.WriteString(apiKey)
-
-	signStr := buffer.String()
-
-	var hashSign []byte
 	if signType == SignType_HMAC_SHA256 {
-		hash := hmac.New(sha256.New, []byte(apiKey))
-		hash.Write([]byte(signStr))
-		hashSign = hash.Sum(nil)
+		h = hmac.New(sha256.New, []byte(apiKey))
 	} else {
-		hash := md5.New()
-		hash.Write([]byte(signStr))
-		hashSign = hash.Sum(nil)
+		h = md5.New()
 	}
-	paySign = strings.ToUpper(hex.EncodeToString(hashSign))
+	h.Write([]byte(buffer.String()))
+	paySign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
 	return
 }
 
@@ -318,89 +277,114 @@ func GetH5PaySign(appId, nonceStr, packages, signType, timeStamp, apiKey string)
 //    signType:此处签名方式,务必与统一下单时用的签名方式一致
 //    timeStamp:时间
 //    apiKey:API秘钥值
-//
 //    APP支付官方文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12
 func GetAppPaySign(appid, partnerid, noncestr, prepayid, signType, timestamp, apiKey string) (paySign string) {
-	var buffer strings.Builder
+	var (
+		buffer strings.Builder
+		h      hash.Hash
+	)
 	buffer.WriteString("appid=")
 	buffer.WriteString(appid)
-
 	buffer.WriteString("&noncestr=")
 	buffer.WriteString(noncestr)
-
 	buffer.WriteString("&package=Sign=WXPay")
-
 	buffer.WriteString("&partnerid=")
 	buffer.WriteString(partnerid)
-
 	buffer.WriteString("&prepayid=")
 	buffer.WriteString(prepayid)
-
 	buffer.WriteString("&timestamp=")
 	buffer.WriteString(timestamp)
-
 	buffer.WriteString("&key=")
 	buffer.WriteString(apiKey)
-
-	signStr := buffer.String()
-
-	var hashSign []byte
 	if signType == SignType_HMAC_SHA256 {
-		hash := hmac.New(sha256.New, []byte(apiKey))
-		hash.Write([]byte(signStr))
-		hashSign = hash.Sum(nil)
+		h = hmac.New(sha256.New, []byte(apiKey))
 	} else {
-		hash := md5.New()
-		hash.Write([]byte(signStr))
-		hashSign = hash.Sum(nil)
+		h = md5.New()
 	}
-	paySign = strings.ToUpper(hex.EncodeToString(hashSign))
+	h.Write([]byte(buffer.String()))
+	paySign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
 	return
 }
 
-//解密开放数据
+//解密开放数据到结构体
 //    encryptedData:包括敏感数据在内的完整用户信息的加密数据,小程序获取到
 //    iv:加密算法的初始向量,小程序获取到
 //    sessionKey:会话密钥,通过  gopay.Code2Session() 方法获取到
 //    beanPtr:需要解析到的结构体指针,操作完后,声明的结构体会被赋值
 //    文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html
 func DecryptWeChatOpenDataToStruct(encryptedData, iv, sessionKey string, beanPtr interface{}) (err error) {
-	//验证参数类型
+	var (
+		cipherText []byte
+		aesKey     []byte
+		ivKey      []byte
+		block      cipher.Block
+		blockMode  cipher.BlockMode
+		plainText  []byte
+	)
 	beanValue := reflect.ValueOf(beanPtr)
 	if beanValue.Kind() != reflect.Ptr {
 		return errors.New("传入beanPtr类型必须是以指针形式")
 	}
-	//验证interface{}类型
 	if beanValue.Elem().Kind() != reflect.Struct {
 		return errors.New("传入interface{}必须是结构体")
 	}
-	cipherText, _ := base64.StdEncoding.DecodeString(encryptedData)
-	aesKey, _ := base64.StdEncoding.DecodeString(sessionKey)
-	ivKey, _ := base64.StdEncoding.DecodeString(iv)
-
+	cipherText, _ = base64.StdEncoding.DecodeString(encryptedData)
+	aesKey, _ = base64.StdEncoding.DecodeString(sessionKey)
+	ivKey, _ = base64.StdEncoding.DecodeString(iv)
 	if len(cipherText)%len(aesKey) != 0 {
 		return errors.New("encryptedData is error")
 	}
-	//fmt.Println("cipherText:", string(cipherText))
-	block, err := aes.NewCipher(aesKey)
+	block, err = aes.NewCipher(aesKey)
 	if err != nil {
 		return fmt.Errorf("aes.NewCipher:%v", err.Error())
 	}
-	//解密
-	blockMode := cipher.NewCBCDecrypter(block, ivKey)
-	plainText := make([]byte, len(cipherText))
+	blockMode = cipher.NewCBCDecrypter(block, ivKey)
+	plainText = make([]byte, len(cipherText))
 	blockMode.CryptBlocks(plainText, cipherText)
-	//fmt.Println("plainText1:", plainText)
 	if len(plainText) > 0 {
 		plainText = PKCS7UnPadding(plainText)
 	}
-	//fmt.Println("plainText2:", string(plainText))
-	//解析
-	err = json.Unmarshal(plainText, beanPtr)
-	if err != nil {
+	if err = json.Unmarshal(plainText, beanPtr); err != nil {
 		return fmt.Errorf("json.Unmarshal:%v", err.Error())
 	}
-	return nil
+	return
+}
+
+//解密开放数据到 BodyMap
+//    encryptedData:包括敏感数据在内的完整用户信息的加密数据,小程序获取到
+//    iv:加密算法的初始向量,小程序获取到
+//    sessionKey:会话密钥,通过  gopay.Code2Session() 方法获取到
+//    文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html
+func DecryptWeChatOpenDataToBodyMap(encryptedData, iv, sessionKey string) (bm BodyMap, err error) {
+	var (
+		cipherText []byte
+		aesKey     []byte
+		ivKey      []byte
+		block      cipher.Block
+		blockMode  cipher.BlockMode
+		plainText  []byte
+	)
+	cipherText, _ = base64.StdEncoding.DecodeString(encryptedData)
+	aesKey, _ = base64.StdEncoding.DecodeString(sessionKey)
+	ivKey, _ = base64.StdEncoding.DecodeString(iv)
+	if len(cipherText)%len(aesKey) != 0 {
+		return nil, errors.New("encryptedData is error")
+	}
+	if block, err = aes.NewCipher(aesKey); err != nil {
+		return nil, fmt.Errorf("aes.NewCipher:%v", err.Error())
+	} else {
+		blockMode = cipher.NewCBCDecrypter(block, ivKey)
+		plainText = make([]byte, len(cipherText))
+		blockMode.CryptBlocks(plainText, cipherText)
+		if len(plainText) > 0 {
+			plainText = PKCS7UnPadding(plainText)
+		}
+		bm = make(BodyMap)
+		if err = json.Unmarshal(plainText, &bm); err != nil {
+			return nil, fmt.Errorf("json.Unmarshal:%v", err.Error())
+		}
+		return
+	}
 }
 
 //App应用微信第三方登录,code换取access_token
@@ -410,13 +394,10 @@ func DecryptWeChatOpenDataToStruct(encryptedData, iv, sessionKey string, beanPtr
 func GetAppWeChatLoginAccessToken(appId, appSecret, code string) (accessToken *AppWeChatLoginAccessToken, err error) {
 	accessToken = new(AppWeChatLoginAccessToken)
 	url := "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecret + "&code=" + code + "&grant_type=authorization_code"
-	agent := HttpAgent()
-	_, _, errs := agent.Get(url).EndStruct(accessToken)
-	if len(errs) > 0 {
+	if _, _, errs := HttpAgent().Get(url).EndStruct(accessToken); len(errs) > 0 {
 		return nil, errs[0]
-	} else {
-		return accessToken, nil
 	}
+	return
 }
 
 //刷新App应用微信第三方登录后,获取的 access_token
@@ -426,13 +407,10 @@ func GetAppWeChatLoginAccessToken(appId, appSecret, code string) (accessToken *A
 func RefreshAppWeChatLoginAccessToken(appId, refreshToken string) (accessToken *RefreshAppWeChatLoginAccessTokenRsp, err error) {
 	accessToken = new(RefreshAppWeChatLoginAccessTokenRsp)
 	url := "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + appId + "&grant_type=refresh_token&refresh_token=" + refreshToken
-	agent := HttpAgent()
-	_, _, errs := agent.Get(url).EndStruct(accessToken)
-	if len(errs) > 0 {
+	if _, _, errs := HttpAgent().Get(url).EndStruct(accessToken); len(errs) > 0 {
 		return nil, errs[0]
-	} else {
-		return accessToken, nil
 	}
+	return
 }
 
 //获取微信小程序用户的OpenId、SessionKey、UnionId
@@ -443,13 +421,10 @@ func RefreshAppWeChatLoginAccessToken(appId, refreshToken string) (accessToken *
 func Code2Session(appId, appSecret, wxCode string) (sessionRsp *Code2SessionRsp, err error) {
 	sessionRsp = new(Code2SessionRsp)
 	url := "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code=" + wxCode + "&grant_type=authorization_code"
-	agent := HttpAgent()
-	_, _, errs := agent.Get(url).EndStruct(sessionRsp)
-	if len(errs) > 0 {
+	if _, _, errs := HttpAgent().Get(url).EndStruct(sessionRsp); len(errs) > 0 {
 		return nil, errs[0]
-	} else {
-		return sessionRsp, nil
 	}
+	return
 }
 
 //获取微信小程序全局唯一后台接口调用凭据(AccessToken:157字符)
@@ -459,14 +434,10 @@ func Code2Session(appId, appSecret, wxCode string) (sessionRsp *Code2SessionRsp,
 func GetWeChatAppletAccessToken(appId, appSecret string) (accessToken *AccessToken, err error) {
 	accessToken = new(AccessToken)
 	url := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret
-
-	agent := HttpAgent()
-	_, _, errs := agent.Get(url).EndStruct(accessToken)
-	if len(errs) > 0 {
+	if _, _, errs := HttpAgent().Get(url).EndStruct(accessToken); len(errs) > 0 {
 		return nil, errs[0]
-	} else {
-		return accessToken, nil
 	}
+	return
 }
 
 //授权码查询openid(AccessToken:157字符)
@@ -477,32 +448,27 @@ func GetWeChatAppletAccessToken(appId, appSecret string) (accessToken *AccessTok
 //    nonceStr:随即字符串
 //    文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=9
 func GetOpenIdByAuthCode(appId, mchId, apiKey, authCode, nonceStr string) (openIdRsp *OpenIdByAuthCodeRsp, err error) {
-
-	url := "https://api.mch.weixin.qq.com/tools/authcodetoopenid"
-	body := make(BodyMap)
-	body.Set("appid", appId)
-	body.Set("mch_id", mchId)
-	body.Set("auth_code", authCode)
-	body.Set("nonce_str", nonceStr)
-	sign := getWeChatReleaseSign(apiKey, SignType_MD5, body)
-
-	body.Set("sign", sign)
-	reqXML := generateXml(body)
-	//===============发起请求===================
-	agent := gorequest.New()
-	agent.Post(url)
-	agent.Type("xml")
-	agent.SendString(reqXML)
-	_, bs, errs := agent.EndBytes()
-	if len(errs) > 0 {
+	var (
+		url  string
+		bm   BodyMap
+		bs   []byte
+		errs []error
+	)
+	url = "https://api.mch.weixin.qq.com/tools/authcodetoopenid"
+	bm = make(BodyMap)
+	bm.Set("appid", appId)
+	bm.Set("mch_id", mchId)
+	bm.Set("auth_code", authCode)
+	bm.Set("nonce_str", nonceStr)
+	bm.Set("sign", getWeChatReleaseSign(apiKey, SignType_MD5, bm))
+	if _, bs, errs = HttpAgent().Post(url).Type("xml").SendString(generateXml(bm)).EndBytes(); len(errs) > 0 {
 		return nil, errs[0]
 	}
 	openIdRsp = new(OpenIdByAuthCodeRsp)
-	err = xml.Unmarshal(bs, openIdRsp)
-	if err != nil {
+	if err = xml.Unmarshal(bs, openIdRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal:%v", err.Error())
 	}
-	return openIdRsp, nil
+	return
 }
 
 //微信小程序用户支付完成后,获取该用户的 UnionId,无需用户授权。
@@ -513,14 +479,10 @@ func GetOpenIdByAuthCode(appId, mchId, apiKey, authCode, nonceStr string) (openI
 func GetWeChatAppletPaidUnionId(accessToken, openId, transactionId string) (unionId *PaidUnionId, err error) {
 	unionId = new(PaidUnionId)
 	url := "https://api.weixin.qq.com/wxa/getpaidunionid?access_token=" + accessToken + "&openid=" + openId + "&transaction_id=" + transactionId
-
-	agent := HttpAgent()
-	_, _, errs := agent.Get(url).EndStruct(unionId)
-	if len(errs) > 0 {
+	if _, _, errs := HttpAgent().Get(url).EndStruct(unionId); len(errs) > 0 {
 		return nil, errs[0]
-	} else {
-		return unionId, nil
 	}
+	return
 }
 
 //获取用户基本信息(UnionID机制)
@@ -536,11 +498,8 @@ func GetWeChatUserInfo(accessToken, openId string, lang ...string) (userInfo *We
 	} else {
 		url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN"
 	}
-	agent := HttpAgent()
-	_, _, errs := agent.Get(url).EndStruct(userInfo)
-	if len(errs) > 0 {
+	if _, _, errs := HttpAgent().Get(url).EndStruct(userInfo); len(errs) > 0 {
 		return nil, errs[0]
-	} else {
-		return userInfo, nil
 	}
+	return
 }