-
Notifications
You must be signed in to change notification settings - Fork 149
/
Copy pathwechatpay_download_certs.go
191 lines (157 loc) · 4.97 KB
/
wechatpay_download_certs.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// Copyright 2021 Tencent Inc. All rights reserved.
package main
import (
"context"
"crypto/x509"
"flag"
"fmt"
"os"
"path/filepath"
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/core/downloader"
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
"github.com/wechatpay-apiv3/wechatpay-go/utils"
)
var (
mchID string
mchSerialNo string
mchPrivateKeyPath string
mchAPIv3Key string
wechatPayCertificatePath string
outputPath string
)
const errCodeParamError = 1
const errCodeRunError = 2
func init() {
flag.StringVar(&mchID, "m", "", "【必传】`商户号`")
flag.StringVar(&mchSerialNo, "s", "", "【必传】`商户证书序列号`")
flag.StringVar(&mchPrivateKeyPath, "p", "", "【必传】`商户私钥路径`")
flag.StringVar(&mchAPIv3Key, "k", "", "【必传】`商户APIv3密钥`")
flag.StringVar(&wechatPayCertificatePath, "c", "", "【可选】`商户平台证书路径`,用于验签。省略则跳过验签")
flag.StringVar(&outputPath, "o", "./", "【可选】`证书下载保存目录`")
}
func main() {
flag.Parse()
flag.Usage = printUsageAndExit
if err := checkArgs(); err != nil {
reportError("参数有误:", err)
printUsageAndExit()
}
ctx := context.Background()
client, err := createClient(ctx)
if err != nil {
reportError("初始化失败:", err)
os.Exit(errCodeRunError)
}
d, err := downloader.NewCertificateDownloaderWithClient(ctx, client, mchAPIv3Key)
if err != nil {
reportError("下载证书失败:", err)
os.Exit(errCodeRunError)
}
err = saveCertificates(ctx, d)
if err != nil {
reportError("保存证书失败:", err)
os.Exit(errCodeRunError)
}
os.Exit(0)
}
func reportError(message string, err error) {
_, _ = fmt.Fprintf(os.Stderr, message+" %v\n", err)
}
func printUsageAndExit() {
_, _ = fmt.Fprintf(os.Stderr, "usage of wechatpay_download_certs:\n")
flag.PrintDefaults()
os.Exit(errCodeParamError)
}
type paramError struct {
name string
value string
message string
}
// Error 输出 paramError
func (e paramError) Error() string {
if e.value != "" {
return fmt.Sprintf("%v(%v) %v", e.name, e.value, e.message)
}
return fmt.Sprintf("%v %v", e.name, e.message)
}
// revive:disable:cyclomatic
func checkArgs() error {
if mchID == "" {
return paramError{"商户号", mchID, "必传"}
}
if mchSerialNo == "" {
return paramError{"商户证书序列号", mchSerialNo, "必传"}
}
if mchPrivateKeyPath == "" {
return paramError{"商户私钥路径", mchPrivateKeyPath, "必传"}
}
fileInfo, err := os.Stat(mchPrivateKeyPath)
if err != nil {
return paramError{"商户私钥路径", mchPrivateKeyPath, fmt.Sprintf("有误: %v", err)}
}
if fileInfo.IsDir() {
return paramError{"商户私钥路径", mchPrivateKeyPath, "不是合法的文件路径"}
}
if mchAPIv3Key == "" {
return paramError{"商户APIv3密钥", mchAPIv3Key, "必传"}
}
if wechatPayCertificatePath != "" {
fileInfo, err := os.Stat(wechatPayCertificatePath)
if err != nil {
return paramError{"商户平台证书路径", wechatPayCertificatePath, fmt.Sprintf("有误:%v", err)}
}
if fileInfo.IsDir() {
return paramError{"商户平台证书路径", wechatPayCertificatePath, "不是合法的文件路径"}
}
}
err = os.MkdirAll(outputPath, os.ModePerm)
if err != nil {
return paramError{"证书下载保存目录", outputPath, fmt.Sprintf("创建失败:%v", err)}
}
return nil
}
// revive:enable:cyclomatic
func saveCertificates(ctx context.Context, d *downloader.CertificateDownloader) error {
for serialNo, certContent := range d.ExportAll(ctx) {
outputFilePath := filepath.Join(outputPath, fmt.Sprintf("wechatpay_%v.pem", serialNo))
f, err := os.Create(outputFilePath)
if err != nil {
return fmt.Errorf("创建证书文件`%v`失败:%v", outputFilePath, err)
}
_, err = f.WriteString(certContent + "\n")
if err != nil {
return fmt.Errorf("写入证书到`%v`失败: %v", outputFilePath, err)
}
fmt.Printf("写入证书到`%v`成功\n", outputFilePath)
}
return nil
}
func createClient(ctx context.Context) (*core.Client, error) {
privateKey, err := utils.LoadPrivateKeyWithPath(mchPrivateKeyPath)
if err != nil {
return nil, fmt.Errorf("商户私钥有误:%v", err)
}
var client *core.Client
if wechatPayCertificatePath != "" {
wechatPayCertificate, err := utils.LoadCertificateWithPath(wechatPayCertificatePath)
if err != nil {
return nil, fmt.Errorf("平台证书有误:%v", err)
}
client, err = core.NewClient(
ctx, option.WithMerchantCredential(mchID, mchSerialNo, privateKey),
option.WithWechatPayCertificate([]*x509.Certificate{wechatPayCertificate}),
)
if err != nil {
return nil, fmt.Errorf("创建 Client 失败:%v", err)
}
} else {
client, err = core.NewClient(
ctx, option.WithMerchantCredential(mchID, mchSerialNo, privateKey), option.WithoutValidator(),
)
if err != nil {
return nil, fmt.Errorf("创建 Client 失败:%v", err)
}
}
return client, nil
}