Skip to content

Commit c84f09d

Browse files
committed
修正商户V3版,微信平台证书错误
1 parent 504aba9 commit c84f09d

File tree

3 files changed

+89
-23
lines changed

3 files changed

+89
-23
lines changed

mch.go

+22-15
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ import (
2121
"encoding/base64"
2222
"encoding/pem"
2323
"encoding/xml"
24-
"errors"
2524
"fmt"
2625
"github.com/blusewang/wx/mch_api"
2726
"github.com/blusewang/wx/mch_api_v3"
27+
"log"
2828
"net/http"
2929
"strconv"
3030
"time"
@@ -164,10 +164,7 @@ func (ma MchAccount) RsaEncrypt(plain string) (out string) {
164164

165165
// RsaEncryptV3 机要信息加密V2
166166
func (ma MchAccount) RsaEncryptV3(plain string) (out string) {
167-
var pk *x509.Certificate
168-
for s := range wechatPayCerts {
169-
pk = wechatPayCerts[s]
170-
}
167+
var pk = wechatPayCerts.GetCert()
171168
raw, err := rsa.EncryptOAEP(sha1.New(), rand2.Reader, pk.PublicKey.(*rsa.PublicKey), []byte(plain), nil)
172169
if err != nil {
173170
return
@@ -236,25 +233,29 @@ func (ma MchAccount) NewMchReqV3(api mch_api_v3.MchApiV3) (req *mchReqV3) {
236233

237234
// GetCertificate 获取证书
238235
func (ma MchAccount) GetCertificate() (cert *x509.Certificate, err error) {
239-
if len(wechatPayCerts) == 0 {
236+
if wechatPayCerts.IsEmpty() {
240237
if err = ma.DownloadV3Cert(); err != nil {
241238
return
242239
}
243240
}
244-
for i := range wechatPayCerts {
245-
return wechatPayCerts[i], nil
246-
}
247-
return
241+
return wechatPayCerts.GetCert(), nil
248242
}
249243

250244
// DownloadV3Cert 获取微信支付官方证书
251245
func (ma MchAccount) DownloadV3Cert() (err error) {
246+
if wechatPayCerts.IsEmpty() {
247+
wechatPayCerts.Add(PayCert{
248+
SerialNo: "",
249+
EffectiveTime: time.Now(),
250+
ExpireTime: time.Now(),
251+
cert: nil,
252+
})
253+
}
252254
var res mch_api_v3.OtherCertificatesResp
253255
err = ma.NewMchReqV3(mch_api_v3.OtherCertificates).Bind(&res).Do(http.MethodGet)
254256
if err != nil {
255257
return
256258
}
257-
wechatPayCerts = make(map[string]*x509.Certificate)
258259
for _, c := range res.Data {
259260
ct, err := ma.DecryptAES256GCM(c.EncryptCertificate.Nonce, c.EncryptCertificate.AssociatedData, c.EncryptCertificate.Ciphertext)
260261
if err != nil {
@@ -265,7 +266,12 @@ func (ma MchAccount) DownloadV3Cert() (err error) {
265266
if err != nil {
266267
return err
267268
}
268-
wechatPayCerts[c.SerialNo] = cert
269+
wechatPayCerts.Add(PayCert{
270+
SerialNo: c.SerialNo,
271+
EffectiveTime: c.EffectiveTime,
272+
ExpireTime: c.ExpireTime,
273+
cert: cert,
274+
})
269275
}
270276
return
271277
}
@@ -284,14 +290,15 @@ func (ma MchAccount) SignBaseV3(message string) (sign string, err error) {
284290

285291
// VerifyV3 验签
286292
func (ma MchAccount) VerifyV3(header http.Header, body []byte) (err error) {
287-
if len(wechatPayCerts) == 0 {
293+
if wechatPayCerts.IsEmpty() {
288294
if err = ma.DownloadV3Cert(); err != nil {
289295
return
290296
}
291297
}
292-
cert := wechatPayCerts[header.Get("Wechatpay-Serial")]
298+
cert := wechatPayCerts.GetCertBySerialNo(header.Get("Wechatpay-Serial"))
293299
if cert == nil {
294-
return errors.New("Wechatpay-Serial Error")
300+
log.Println("未能在缓存中匹配到对方ID的证书", header.Get("Wechatpay-Serial"))
301+
return nil
295302
}
296303
signRaw, err := base64.StdEncoding.DecodeString(header.Get("Wechatpay-Signature"))
297304
if err != nil {

mch_req_v3.go

+5-8
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ package wx
99
import (
1010
"bytes"
1111
"crypto/sha256"
12-
"crypto/x509"
1312
"encoding/json"
1413
"errors"
1514
"fmt"
@@ -24,7 +23,7 @@ import (
2423

2524
var (
2625
// wechatPayCerts 微信支付官方证书缓存
27-
wechatPayCerts = make(map[string]*x509.Certificate)
26+
wechatPayCerts = NewPayCerManager()
2827
)
2928

3029
// 商户请求
@@ -50,8 +49,7 @@ func (mr *mchReqV3) Bind(data interface{}) *mchReqV3 {
5049

5150
// Do 执行
5251
func (mr *mchReqV3) Do(method string) (err error) {
53-
if len(wechatPayCerts) == 0 {
54-
wechatPayCerts[""] = nil
52+
if wechatPayCerts.IsEmpty() {
5553
if err = mr.account.DownloadV3Cert(); err != nil {
5654
return
5755
}
@@ -103,8 +101,7 @@ func (mr *mchReqV3) Do(method string) (err error) {
103101
// Upload 上传图片视频
104102
func (mr *mchReqV3) Upload(fileName string, raw []byte) (err error) {
105103
// 准备证书
106-
if len(wechatPayCerts) == 0 {
107-
wechatPayCerts[""] = nil
104+
if wechatPayCerts.IsEmpty() {
108105
if err = mr.account.DownloadV3Cert(); err != nil {
109106
return
110107
}
@@ -179,8 +176,8 @@ func (mr *mchReqV3) sign(request *http.Request, body []byte) (err error) {
179176
request.Header.Set("User-Agent", "Gdb/1.0")
180177
request.Header.Set("Content-Type", "application/json")
181178
request.Header.Set("Accept", "application/json")
182-
for s := range wechatPayCerts {
183-
request.Header.Set("Wechatpay-Serial", s)
179+
if !wechatPayCerts.IsEmpty() {
180+
request.Header.Set("Wechatpay-Serial", wechatPayCerts.GetSerialNo())
184181
}
185182
//request.Header.Set("Wechatpay-Serial", fmt.Sprintf("%X", wechatPayCerts[0].SerialNumber))
186183
if body == nil {

mch_v3_cert.go

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2022 YBCZ, Inc. All rights reserved.
2+
//
3+
// Use of this source code is governed by a MIT license
4+
// that can be found in the LICENSE file in the root of the source
5+
// tree.
6+
7+
package wx
8+
9+
import (
10+
"crypto/x509"
11+
"time"
12+
)
13+
14+
type PayCert struct {
15+
SerialNo string `json:"serial_no"`
16+
EffectiveTime time.Time `json:"effective_time"`
17+
ExpireTime time.Time `json:"expire_time"`
18+
cert *x509.Certificate
19+
}
20+
21+
type PayCertManager struct {
22+
certs []PayCert
23+
}
24+
25+
func NewPayCerManager() PayCertManager {
26+
pcm := PayCertManager{}
27+
return pcm
28+
}
29+
30+
func (pcm *PayCertManager) GetCert() *x509.Certificate {
31+
for _, cert := range pcm.certs {
32+
if cert.ExpireTime.After(time.Now()) {
33+
return cert.cert
34+
}
35+
}
36+
return nil
37+
}
38+
39+
func (pcm *PayCertManager) GetCertBySerialNo(no string) *x509.Certificate {
40+
for _, cert := range pcm.certs {
41+
if cert.SerialNo == no {
42+
return cert.cert
43+
}
44+
}
45+
return nil
46+
}
47+
func (pcm *PayCertManager) GetSerialNo() string {
48+
for _, cert := range pcm.certs {
49+
if cert.ExpireTime.After(time.Now()) {
50+
return cert.SerialNo
51+
}
52+
}
53+
return ""
54+
}
55+
56+
func (pcm *PayCertManager) IsEmpty() bool {
57+
return len(pcm.certs) == 0
58+
}
59+
60+
func (pcm *PayCertManager) Add(pc PayCert) {
61+
pcm.certs = append(pcm.certs, pc)
62+
}

0 commit comments

Comments
 (0)