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 }