|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- package qq
-
- import (
- "crypto/hmac"
- "crypto/md5"
- "crypto/sha256"
- "crypto/tls"
- "encoding/hex"
- "encoding/pem"
- "encoding/xml"
- "errors"
- "fmt"
- "hash"
- "os"
- "strings"
-
- "github.com/go-pay/gopay"
- "github.com/go-pay/xlog"
- "golang.org/x/crypto/pkcs12"
- )
-
- // 添加QQ证书 Path 路径
- // certFilePath:apiclient_cert.pem 路径
- // keyFilePath:apiclient_key.pem 路径
- // pkcs12FilePath:apiclient_cert.p12 路径
- // 返回err
- func (q *Client) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath any) (err error) {
- if err = checkCertFilePathOrContent(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
- return err
- }
- config, err := q.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath)
- if err != nil {
- return
- }
- q.tlsHc.SetTLSConfig(config)
- return nil
- }
-
- // 添加QQ证书内容
- // certFileContent:apiclient_cert.pem 内容
- // keyFileContent:apiclient_key.pem 内容
- // pkcs12FileContent:apiclient_cert.p12 内容
- // 返回err
- func (q *Client) AddCertFileContent(certFileContent, keyFileContent, pkcs12FileContent []byte) (err error) {
- return q.AddCertFilePath(certFileContent, keyFileContent, pkcs12FileContent)
- }
-
- func checkCertFilePathOrContent(certFile, keyFile, pkcs12File any) error {
- if certFile == nil && keyFile == nil && pkcs12File == nil {
- return nil
- }
- if certFile != nil && keyFile != nil {
- files := map[string]any{"certFile": certFile, "keyFile": keyFile}
- for varName, v := range files {
- switch v := v.(type) {
- case string:
- if v == gopay.NULL {
- return fmt.Errorf("%s is empty", varName)
- }
- case []byte:
- if len(v) == 0 {
- return fmt.Errorf("%s is empty", varName)
- }
- default:
- return fmt.Errorf("%s type error", varName)
- }
- }
- return nil
- } else if pkcs12File != nil {
- switch pkcs12File := pkcs12File.(type) {
- case string:
- if pkcs12File == gopay.NULL {
- return errors.New("pkcs12File is empty")
- }
- case []byte:
- if len(pkcs12File) == 0 {
- return errors.New("pkcs12File is empty")
- }
- default:
- return errors.New("pkcs12File type error")
- }
- return nil
- } else {
- return errors.New("certFile keyFile must all nil or all not nil")
- }
- }
-
- // 生成请求XML的Body体
- func GenerateXml(bm gopay.BodyMap) (reqXml string) {
- bs, err := xml.Marshal(bm)
- if err != nil {
- return gopay.NULL
- }
- return string(bs)
- }
-
- // 获取QQ支付正式环境Sign值
- func GetReleaseSign(apiKey string, signType string, bm gopay.BodyMap) (sign string) {
- var h hash.Hash
- if signType == SignType_HMAC_SHA256 {
- h = hmac.New(sha256.New, []byte(apiKey))
- } else {
- h = md5.New()
- }
- h.Write([]byte(bm.EncodeWeChatSignParams(apiKey)))
- return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
- }
-
- func (q *Client) getReleaseSign(apiKey string, signType string, bm gopay.BodyMap) (sign string) {
- signParams := bm.EncodeWeChatSignParams(apiKey)
- if q.DebugSwitch == gopay.DebugOn {
- xlog.Debugf("QQ_Request_SignStr: %s", signParams)
- }
- var h hash.Hash
- if signType == SignType_HMAC_SHA256 {
- h = q.sha256Hash
- } else {
- h = q.md5Hash
- }
- q.mu.Lock()
- defer func() {
- h.Reset()
- q.mu.Unlock()
- }()
- h.Write([]byte(signParams))
- return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
- }
-
- func (q *Client) addCertConfig(certFile, keyFile, pkcs12File any) (tlsConfig *tls.Config, err error) {
- if certFile == nil && keyFile == nil && pkcs12File == nil {
- return nil, errors.New("cert parse failed")
- }
-
- var (
- certPem, keyPem []byte
- certificate tls.Certificate
- )
- if certFile != nil && keyFile != nil {
- if _, ok := certFile.([]byte); ok {
- certPem = certFile.([]byte)
- } else {
- certPem, err = os.ReadFile(certFile.(string))
- }
- if _, ok := keyFile.([]byte); ok {
- keyPem = keyFile.([]byte)
- } else {
- keyPem, err = os.ReadFile(keyFile.(string))
- }
- if err != nil {
- return nil, fmt.Errorf("os.ReadFile:%w", err)
- }
- } else if pkcs12File != nil {
- var pfxData []byte
- if _, ok := pkcs12File.([]byte); ok {
- pfxData = pkcs12File.([]byte)
- } else {
- if pfxData, err = os.ReadFile(pkcs12File.(string)); err != nil {
- return nil, fmt.Errorf("os.ReadFile:%w", err)
- }
- }
- blocks, err := pkcs12.ToPEM(pfxData, q.MchId)
- if err != nil {
- return nil, fmt.Errorf("pkcs12.ToPEM:%w", err)
- }
- for _, b := range blocks {
- keyPem = append(keyPem, pem.EncodeToMemory(b)...)
- }
- certPem = keyPem
- }
- if certPem != nil && keyPem != nil {
- if certificate, err = tls.X509KeyPair(certPem, keyPem); err != nil {
- return nil, fmt.Errorf("tls.LoadX509KeyPair:%w", err)
- }
- tlsConfig = &tls.Config{
- Certificates: []tls.Certificate{certificate},
- InsecureSkipVerify: true,
- }
- return tlsConfig, nil
- }
- return nil, errors.New("cert files must all nil or all not nil")
- }
|