Skip to content

Commit 9940221

Browse files
authored
增加微信v3 的掌纹支付相关接口 (#433)
* map to smap * 增加掌纹支付预授权查询接口
1 parent 6042c74 commit 9940221

12 files changed

+113
-37
lines changed

body_map_test.go

-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package gopay
22

33
import (
4-
"container/list"
54
"encoding/json"
65
"encoding/xml"
76
"testing"
@@ -173,7 +172,3 @@ func TestOutSlice(t *testing.T) {
173172
xlog.Debugf("%s", bm.GetString(""))
174173
xlog.Debugf("%s", bm.JsonBody())
175174
}
176-
177-
func TestLruCache(t *testing.T) {
178-
list.New()
179-
}

constant.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const (
77
OK = "OK"
88
DebugOff = 0
99
DebugOn = 1
10-
Version = "v1.5.106"
10+
Version = "v1.5.107"
1111
)
1212

1313
type DebugSwitch int8

doc/wechat_v3.md

+3
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,9 @@ wechat.V3DecryptCombineNotifyCipherText()
445445
* 查询省份列表:`client.V3BankSearchProvinceList()`
446446
* 查询城市列表:`client.V3BankSearchCityList()`
447447
* 查询支行列表:`client.V3BankSearchBranchList()`
448+
* <font color='#07C160' size='4'>掌纹支付</font>
449+
* 用户自主录掌&预授权:`client.V3PalmServicePreAuthorize()`
450+
* 预授权状态查询:`client.V3PalmServiceOpenidQuery()`
448451

449452

450453
### 微信v3公共 API

go.mod

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ go 1.21
44

55
require (
66
github.com/go-pay/crypto v0.0.1
7-
github.com/go-pay/errgroup v0.0.2
7+
github.com/go-pay/errgroup v0.0.3
8+
github.com/go-pay/smap v0.0.2
89
github.com/go-pay/util v0.0.4
910
github.com/go-pay/xlog v0.0.3
1011
github.com/go-pay/xtime v0.0.2
11-
golang.org/x/crypto v0.28.0
12+
golang.org/x/crypto v0.29.0
1213
)

go.sum

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
github.com/go-pay/crypto v0.0.1 h1:B6InT8CLfSLc6nGRVx9VMJRBBazFMjr293+jl0lLXUY=
22
github.com/go-pay/crypto v0.0.1/go.mod h1:41oEIvHMKbNcYlWUlRWtsnC6+ASgh7u29z0gJXe5bes=
3-
github.com/go-pay/errgroup v0.0.2 h1:5mZMdm0TDClDm2S3G0/sm0f8AuQRtz0dOrTHDR9R8Cc=
4-
github.com/go-pay/errgroup v0.0.2/go.mod h1:0+4b8mvFMS71MIzsaC+gVvB4x37I93lRb2dqrwuU8x8=
3+
github.com/go-pay/errgroup v0.0.3 h1:DB4s8e8oWYDyETKQ1y1riMJ7y29zE1uIsMCSjEOFSbU=
4+
github.com/go-pay/errgroup v0.0.3/go.mod h1:0+4b8mvFMS71MIzsaC+gVvB4x37I93lRb2dqrwuU8x8=
5+
github.com/go-pay/smap v0.0.2 h1:kKflYor5T5FgZltPFBMTFfjJvqYMHr5VnIFSEyhVTcA=
6+
github.com/go-pay/smap v0.0.2/go.mod h1:HW9oAo0okuyDYsbpbj5fJFxnNj/BZorRGFw26SxrNWw=
57
github.com/go-pay/util v0.0.4 h1:TuwSU9o3Qd7m9v1PbzFuIA/8uO9FJnA6P7neG/NwPyk=
68
github.com/go-pay/util v0.0.4/go.mod h1:Tsdhs8Ib9J9b4+NKNO1PHh5hWHhlg98PthsX0ckq6PM=
79
github.com/go-pay/xlog v0.0.3 h1:avyMhCL/JgBHreoGx/am/kHxfs1udDOAeVqbmzP/Yes=
810
github.com/go-pay/xlog v0.0.3/go.mod h1:mH47xbobrdsSHWsmFtSF5agWbMHFP+tK0ZbVCk5OAEw=
911
github.com/go-pay/xtime v0.0.2 h1:7YR4/iuELsEHpJ6LUO0SVK80hQxDO9MLCfuVYIiTCRM=
1012
github.com/go-pay/xtime v0.0.2/go.mod h1:W1yRbJaSt4CSBcdAtLBQ8xajiN/Pl5hquGczUcUE9xE=
11-
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
12-
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
13+
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
14+
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=

release_note.txt

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
版本号:v1.5.107
2+
修改记录:
3+
(1) 微信V3:新增掌纹支付相关接口。
4+
15
版本号:v1.5.106
26
修改记录:
37
(1) 支付宝:支付宝支持V3接口,接口还在完善中,欢迎提PR一起建设。

wechat/v3/cert.go

+8-9
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,11 @@ func (c *ClientV3) WxPublicKey() (wxPublicKey *rsa.PublicKey) {
153153
// 获取 微信平台证书 Map(readonly)
154154
// wxPublicKeyMap: key:SerialNo, value:WxPublicKey
155155
func (c *ClientV3) WxPublicKeyMap() (wxPublicKeyMap map[string]*rsa.PublicKey) {
156-
wxPublicKeyMap = make(map[string]*rsa.PublicKey, len(c.SnCertMap))
157-
for k, v := range c.SnCertMap {
156+
wxPublicKeyMap = make(map[string]*rsa.PublicKey)
157+
c.SnCertMap.Range(func(k string, v *rsa.PublicKey) bool {
158158
wxPublicKeyMap[k] = v
159-
}
159+
return true
160+
})
160161
return wxPublicKeyMap
161162
}
162163

@@ -328,19 +329,17 @@ func (c *ClientV3) autoCheckCertProc() {
328329
if err != nil {
329330
return err
330331
}
331-
snPkMap := make(map[string]*rsa.PublicKey)
332332
for sn, cert := range snCertMap {
333333
pubKey, err := xpem.DecodePublicKey([]byte(cert))
334334
if err != nil {
335335
return err
336336
}
337-
snPkMap[sn] = pubKey
337+
c.SnCertMap.Store(sn, pubKey)
338+
if sn == serialNo {
339+
c.wxPublicKey = pubKey
340+
}
338341
}
339-
c.rwMu.Lock()
340-
c.SnCertMap = snPkMap
341342
c.WxSerialNo = serialNo
342-
c.wxPublicKey = snPkMap[serialNo]
343-
c.rwMu.Unlock()
344343
return nil
345344
}, 3, time.Second)
346345
if err != nil {

wechat/v3/client.go

+7-10
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/go-pay/crypto/xpem"
1010
"github.com/go-pay/gopay"
1111
"github.com/go-pay/gopay/pkg/xhttp"
12+
"github.com/go-pay/smap"
1213
"github.com/go-pay/xlog"
1314
)
1415

@@ -27,7 +28,7 @@ type ClientV3 struct {
2728
DebugSwitch gopay.DebugSwitch
2829
requestIdFunc xhttp.RequestIdHandler
2930
logger xlog.XLogger
30-
SnCertMap map[string]*rsa.PublicKey // key: serial_no
31+
SnCertMap smap.Map[string, *rsa.PublicKey] // key: serial_no
3132
}
3233

3334
// NewClientV3 初始化微信客户端 V3
@@ -72,19 +73,18 @@ func (c *ClientV3) AutoVerifySign(autoRefresh ...bool) (err error) {
7273
if err != nil {
7374
return err
7475
}
75-
if len(c.SnCertMap) <= 0 {
76-
c.SnCertMap = make(map[string]*rsa.PublicKey)
77-
}
7876
for sn, cert := range certMap {
7977
// decode cert
8078
pubKey, err := xpem.DecodePublicKey([]byte(cert))
8179
if err != nil {
8280
return err
8381
}
84-
c.SnCertMap[sn] = pubKey
82+
c.SnCertMap.Store(sn, pubKey)
83+
if sn == wxSerialNo {
84+
c.wxPublicKey = pubKey
85+
}
8586
}
8687
c.WxSerialNo = wxSerialNo
87-
c.wxPublicKey = c.SnCertMap[wxSerialNo]
8888
if len(autoRefresh) == 1 && !autoRefresh[0] {
8989
return nil
9090
}
@@ -103,10 +103,7 @@ func (c *ClientV3) AutoVerifySignByCert(wxPublicKeyContent []byte, wxPublicKeyID
103103
if pubKey == nil {
104104
return errors.New("xpem.DecodePublicKey() failed, pubKey is nil")
105105
}
106-
if len(c.SnCertMap) <= 0 {
107-
c.SnCertMap = make(map[string]*rsa.PublicKey)
108-
}
109-
c.SnCertMap[wxPublicKeyID] = pubKey
106+
c.SnCertMap.Store(wxPublicKeyID, pubKey)
110107
c.wxPublicKey = pubKey
111108
c.WxSerialNo = wxPublicKeyID
112109
c.autoSign = true

wechat/v3/constant.go

+4
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ const (
304304
// 扣款服务-直连模式(其他相关接口在v2接口中)
305305
v3EntrustPayNotify = "/v3/papay/contracts/%s/notify" // contract_id 预扣费通知 POST
306306

307+
// 刷掌支付
308+
v3PalmServicePreAuthorize = "/v3/palmservice/authorization/preauthorize" // 用户自主录掌&预授权 POST
309+
v3PalmServiceOpenidQuery = "/v3/palmservice/authorization/openid/%s" // organization_id 预授权状态查询 GET
310+
307311
// 特约商户进件申请单状态
308312
ApplyStateEditing = "APPLYMENT_STATE_EDITTING" // 编辑中
309313
ApplyStateAuditing = "APPLYMENT_STATE_AUDITING" // 审核中

wechat/v3/model.go

+25
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@ type EntrustPayNotifyRsp struct {
6565
Error string `json:"-"`
6666
}
6767

68+
type PalmServicePreAuthorizeRsp struct {
69+
Code int `json:"-"`
70+
SignInfo *SignInfo `json:"-"`
71+
Response *PalmServicePreAuthorize `json:"response,omitempty"`
72+
Error string `json:"-"`
73+
}
74+
75+
type PalmServiceOpenidQueryRsp struct {
76+
Code int `json:"-"`
77+
SignInfo *SignInfo `json:"-"`
78+
Response *PalmServiceOpenidQuery `json:"response,omitempty"`
79+
Error string `json:"-"`
80+
}
81+
6882
// =========================================================分割=========================================================
6983

7084
type JSAPIPayParams struct {
@@ -299,3 +313,14 @@ type WithdrawStatus struct {
299313
AccountBank string `json:"account_bank"` // 服务商提现入账的开户银行
300314
BankName string `json:"bank_name"` // 服务商提现入账的开户银行全称(含支行)
301315
}
316+
317+
type PalmServicePreAuthorize struct {
318+
PermissionToken string `json:"permission_token"` // 预授权token,跳转小程序使用
319+
}
320+
321+
type PalmServiceOpenidQuery struct {
322+
OrganizationId string `json:"organization_id"`
323+
Openid string `json:"openid"`
324+
State string `json:"state"`
325+
AuthorizeTime string `json:"authorize_time"`
326+
}

wechat/v3/palm.go

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package wechat
2+
3+
import (
4+
"context"
5+
"net/http"
6+
7+
"github.com/go-pay/gopay"
8+
)
9+
10+
// 用户自主录掌&预授权
11+
// Code = 0 is success
12+
func (c *ClientV3) V3PalmServicePreAuthorize(ctx context.Context, bm gopay.BodyMap) (wxRsp *PalmServicePreAuthorizeRsp, err error) {
13+
authorization, err := c.authorization(MethodPost, v3PalmServicePreAuthorize, bm)
14+
if err != nil {
15+
return nil, err
16+
}
17+
res, si, bs, err := c.doProdPost(ctx, bm, v3PalmServicePreAuthorize, authorization)
18+
if err != nil {
19+
return nil, err
20+
}
21+
wxRsp = &PalmServicePreAuthorizeRsp{Code: Success, SignInfo: si}
22+
if res.StatusCode != http.StatusOK {
23+
wxRsp.Code = res.StatusCode
24+
wxRsp.Error = string(bs)
25+
return wxRsp, nil
26+
}
27+
return wxRsp, c.verifySyncSign(si)
28+
}
29+
30+
// 预授权状态查询
31+
// Code = 0 is success
32+
func (c *ClientV3) V3PalmServiceOpenidQuery(ctx context.Context, bm gopay.BodyMap) (wxRsp *PalmServiceOpenidQueryRsp, err error) {
33+
uri := v3PalmServiceOpenidQuery + "?" + bm.EncodeURLParams()
34+
authorization, err := c.authorization(MethodGet, uri, nil)
35+
if err != nil {
36+
return nil, err
37+
}
38+
res, si, bs, err := c.doProdGet(ctx, uri, authorization)
39+
if err != nil {
40+
return nil, err
41+
}
42+
wxRsp = &PalmServiceOpenidQueryRsp{Code: Success, SignInfo: si}
43+
if res.StatusCode != http.StatusOK {
44+
wxRsp.Code = res.StatusCode
45+
wxRsp.Error = string(bs)
46+
return wxRsp, nil
47+
}
48+
return wxRsp, c.verifySyncSign(si)
49+
}

wechat/v3/sign.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -268,17 +268,14 @@ func (c *ClientV3) verifySyncSign(si *SignInfo) (err error) {
268268
if si == nil {
269269
return errors.New("auto verify sign, but SignInfo is nil")
270270
}
271-
c.rwMu.RLock()
272-
wxPublicKey, exist := c.SnCertMap[si.HeaderSerial]
273-
c.rwMu.RUnlock()
271+
272+
wxPublicKey, exist := c.SnCertMap.Load(si.HeaderSerial)
274273
if !exist {
275274
err = c.AutoVerifySign(false)
276275
if err != nil {
277276
return fmt.Errorf("[get all public key err]: %v", err)
278277
}
279-
c.rwMu.RLock()
280-
wxPublicKey, exist = c.SnCertMap[si.HeaderSerial]
281-
c.rwMu.RUnlock()
278+
wxPublicKey, exist = c.SnCertMap.Load(si.HeaderSerial)
282279
if !exist {
283280
return errors.New("auto verify sign, but public key not found")
284281
}

0 commit comments

Comments
 (0)