voucher/internal/data/wechat.go

131 lines
2.6 KiB
Go

package data
import (
"context"
"fmt"
"github.com/go-playground/validator/v10"
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/core/auth/verifiers"
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
"github.com/wechatpay-apiv3/wechatpay-go/utils"
"os"
"sync"
"voucher/internal/pkg/helper"
)
type Server struct {
MchID string `validate:"required"`
MchCertificateSerialNumber string `validate:"required"`
WechatPayPublicKeyID string `validate:"required"`
}
func (c *Server) Validate() error {
if err := validator.New().Struct(c); err != nil {
for _, err = range err.(validator.ValidationErrors) {
return err
}
}
return nil
}
func NewClient(ctx context.Context, c Server) (*core.Client, error) {
dir, err := os.Getwd()
if err != nil {
return nil, err
}
filePath := fmt.Sprintf("%s/%s/%s/%s", dir, "cert", "wechat", c.MchID)
if !helper.FileExists(filePath) {
return nil, fmt.Errorf("MchID[%s]微信密钥证书信息不存在,请联系技术人员处理", c.MchID)
}
// 商户API私钥
mchPrivateKey, err := utils.LoadPrivateKeyWithPath(fmt.Sprintf("%s/%s", filePath, "wechat_private_key.pem"))
if err != nil {
return nil, err
}
// 微信支付平台配置
wechatPayPublicKey, err := utils.LoadPublicKeyWithPath(fmt.Sprintf("%s/%s", filePath, "pub_key.pem"))
if err != nil {
return nil, err
}
opts := []core.ClientOption{
option.WithWechatPayPublicKeyAuthCipher(
c.MchID,
c.MchCertificateSerialNumber,
mchPrivateKey,
c.WechatPayPublicKeyID,
wechatPayPublicKey,
),
}
client, err := core.NewClient(ctx, opts...)
if err != nil {
return nil, err
}
return client, nil
}
type manager struct {
once sync.Once
mutex sync.RWMutex
clients map[string]*core.Client
}
var instance manager
func init() {
instance = manager{
clients: make(map[string]*core.Client),
}
}
func GetClient(ctx context.Context, c Server) (*core.Client, error) {
instance.mutex.Lock()
defer instance.mutex.Unlock()
if i, ok := instance.clients[c.MchID]; ok {
return i, nil
}
var err error
instance.once.Do(func() {
i, err2 := NewClient(ctx, c)
if err2 != nil {
err = err2
return
}
instance.clients[c.MchID] = i
})
if err != nil {
return nil, err
}
return instance.clients[c.MchID], nil
}
func (s Server) Verify(ctx context.Context, message, signature string) error {
verifier := verifiers.NewSHA256WithRSAVerifier(nil)
if err := verifier.Verify(ctx, s.MchCertificateSerialNumber, message, signature); err != nil {
return err
}
return nil
}