forked from rayunstop/alipay
/
client.go
125 lines (110 loc) · 2.97 KB
/
client.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
package alipay
import (
"encoding/json"
"github.com/huandu/xstrings"
"github.com/z-ray/alipay/api/constants"
"github.com/z-ray/alipay/api/logger"
"github.com/z-ray/alipay/api/request"
"github.com/z-ray/alipay/api/response"
"github.com/z-ray/alipay/api/sign"
"github.com/z-ray/alipay/api/utils"
"github.com/z-ray/log"
"io/ioutil"
"net/http"
"strings"
"time"
)
// default
const (
format = "json"
signType = "RSA"
connectTimeout = 3000
readTimeout = 15000
)
// AlipayClient 客户端接口
type AlipayClient interface {
Execute(r request.AlipayRequest) (response.AlipayResponse, error)
// 使用token
ExecuteWithToken(r request.AlipayRequest, token string) (response.AlipayResponse, error)
}
// DefaultAlipayClient 默认的client
type DefaultAlipayClient struct {
AppId string
ServerURL string
PrivKey string
Format string
ConTimeOut int32
ReadTimeOut int32
SignType string
Charset string
}
// 实现接口
func (d *DefaultAlipayClient) Execute(r request.AlipayRequest) (response.AlipayResponse, error) {
return d.ExecuteWithToken(r, "")
}
// 实现接口
func (d *DefaultAlipayClient) ExecuteWithToken(r request.AlipayRequest, token string) (response.AlipayResponse, error) {
// 请求
msg, rp, err := d.post(r, token)
if err != nil {
return nil, err
}
log.Debugf("alipay return : %s", msg)
// body
resp := r.GetResponse()
resp.SetBody(msg)
// replace
k := xstrings.ToSnakeCase(resp.ToStr())
if strings.Contains(msg, k) {
msg = strings.Replace(msg, k, "response", 1)
} else {
msg = strings.Replace(msg, "error_response", "response", 1)
}
// convert
var t = &struct {
Response response.AlipayResponse `json:"response"`
Sign string `json:"sign"`
}{
resp, "",
}
err = json.Unmarshal([]byte(msg), t)
if err != nil {
log.Error(err)
}
// 当发生安全机制接入错误时
// 详细见https://fuwu.alipay.com/platform/doc.htm#c09
if !resp.IsSuccess() {
logger.SecureError(rp, resp)
}
return resp, nil
}
func (d *DefaultAlipayClient) post(r request.AlipayRequest, token string) (string, map[string]string, error) {
// 获取必须参数
rp := make(map[string]string)
rp[constants.AppId] = d.AppId
rp[constants.Method] = r.GetApiMethod()
rp[constants.SignType] = signType // TODO
rp[constants.Timestamp] = time.Now().Format("2006-01-02 15:03:04")
rp[constants.Version] = r.GetApiVersion()
rp[constants.Charset] = d.Charset
utils.PutAll(rp, r.GetTextParams())
// 可选参数
// rp[constants.Format] = d.Format
// 请求报文
content := utils.PrepareContent(rp)
// 签名
signed, err := sign.RsaSign(content, d.PrivKey)
rp[constants.Sign] = signed
// 编码查询参数
values := utils.BuildQuery(rp)
// 请求
result, err := http.Post(d.ServerURL, "application/x-www-form-urlencoded;charset=utf-8", strings.NewReader(values.Encode()))
if err != nil {
log.Error(err)
}
msg, err := ioutil.ReadAll(result.Body)
if err != nil {
log.Error(err)
}
return string(msg), rp, err
}