128 lines
2.6 KiB
Go
128 lines
2.6 KiB
Go
package data
|
|
|
|
import (
|
|
"context"
|
|
"crypto/x509"
|
|
"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" json:"mch_id"`
|
|
MchCertificateSerialNumber string `validate:"required" json:"mch_certificate_serial_number"`
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
var client *core.Client
|
|
// 微信支付平台配置
|
|
wechatPayCertificate, err := utils.LoadCertificateWithPath(fmt.Sprintf("%s/%s", filePath, "wechat_cert.pem"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
client, err = core.NewClient(
|
|
ctx,
|
|
option.WithMerchantCredential(
|
|
c.MchID,
|
|
c.MchCertificateSerialNumber,
|
|
mchPrivateKey,
|
|
),
|
|
option.WithWechatPayCertificate([]*x509.Certificate{wechatPayCertificate}),
|
|
)
|
|
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
|
|
}
|