-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmch_req.go
134 lines (120 loc) · 3.1 KB
/
mch_req.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2020 YBCZ, Inc. All rights reserved.
//
// Use of this source code is governed by a MIT license
// that can be found in the LICENSE file in the root of the source
// tree.
package wx
import (
"bytes"
"encoding/xml"
"errors"
"fmt"
"github.com/blusewang/wx/mch_api"
"net/http"
"reflect"
"strings"
)
// 商户请求
type mchReq struct {
account MchAccount
//privateClient *http.Client // 私有加密传输客户端
api mch_api.MchApi
appId string
isHmacSign bool
isPrivateClient bool
sendData interface{}
res interface{}
err error
}
// Send 填充POST里的Body数据
func (mr *mchReq) Send(data interface{}) *mchReq {
mr.sendData = data
return mr
}
// UseHMacSign 使用 HMAC-SHA256 签名
// 默认采用 MD5 签名
func (mr *mchReq) UseHMacSign() *mchReq {
mr.isHmacSign = true
return mr
}
// UsePrivateCert 使用私有证书通信
func (mr *mchReq) UsePrivateCert() *mchReq {
mr.isPrivateClient = true
return mr
}
// Bind 绑定请求结果的解码数据体
func (mr *mchReq) Bind(data interface{}) *mchReq {
mr.res = data
return mr
}
// Do 执行
func (mr *mchReq) Do() (err error) {
if err = mr.sign(); err != nil {
return
}
var buf = new(bytes.Buffer)
if err = xml.NewEncoder(buf).Encode(mr.sendData); err != nil {
return
}
api := fmt.Sprintf("https://api.mch.weixin.qq.com/%v", mr.api)
if strings.HasPrefix(string(mr.api), "http") {
api = string(mr.api)
}
var cli *http.Client
if mr.isPrivateClient {
cli, err = mr.account.newPrivateClient()
if err != nil {
return err
}
} else {
cli = client()
}
resp, err := cli.Post(api, "application/xml", buf)
defer resp.Body.Close()
if err != nil {
return
}
if resp.StatusCode != http.StatusOK {
return errors.New(resp.Status)
}
if err = xml.NewDecoder(resp.Body).Decode(&mr.res); err != nil {
return
}
return
}
func (mr *mchReq) sign() (err error) {
if mr.sendData == nil {
return errors.New("the data to be sign is not set")
}
vf := reflect.ValueOf(mr.sendData)
if vf.Kind() != reflect.Ptr {
return errors.New("the send data must be ptr")
}
if vf.Elem().FieldByName("MchBase").IsValid() {
var base = vf.Elem().FieldByName("MchBase")
base.FieldByName("MchId").SetString(mr.account.MchId)
base.FieldByName("AppId").SetString(mr.appId)
base.FieldByName("NonceStr").SetString(NewRandStr(32))
var sign string
if mr.isHmacSign {
base.FieldByName("SignType").SetString(mch_api.MchSignTypeHMACSHA256)
sign = mr.account.signHmacSha256(mr.sendData)
} else {
sign = mr.account.signMd5(mr.sendData)
}
base.FieldByName("Sign").SetString(sign)
} else if vf.Elem().FieldByName("Sign").IsValid() && vf.Elem().FieldByName("NonceStr").IsValid() {
vf.Elem().FieldByName("NonceStr").SetString(NewRandStr(32))
var sign string
if mr.isHmacSign {
if vf.Elem().FieldByName("SignType").IsValid() {
vf.Elem().FieldByName("SignType").SetString(mch_api.MchSignTypeHMACSHA256)
sign = mr.account.signHmacSha256(mr.sendData)
}
} else {
sign = mr.account.signMd5(mr.sendData)
}
vf.Elem().FieldByName("Sign").SetString(sign)
}
return
}