diff --git a/plugins/alipay_redpack/internal/alipay_redpack.go b/plugins/alipay_redpack/internal/alipay_redpack.go index d8e7c5f..6522d8f 100644 --- a/plugins/alipay_redpack/internal/alipay_redpack.go +++ b/plugins/alipay_redpack/internal/alipay_redpack.go @@ -83,7 +83,7 @@ func (s *AlipayCpnService) Notify(_ context.Context, request *proto.NotifyReques } n := notifyReq(request) - b, err := Verify(n, c.Npk) + b, err := Verify(n, c.PukPath) if err != nil { return nil, err } diff --git a/plugins/alipay_redpack/internal/alipay_redpack_test.go b/plugins/alipay_redpack/internal/alipay_redpack_test.go index 2c0862c..59360f5 100644 --- a/plugins/alipay_redpack/internal/alipay_redpack_test.go +++ b/plugins/alipay_redpack/internal/alipay_redpack_test.go @@ -15,7 +15,7 @@ func config() []byte { c := &Config{ AppId: "2021004100663111", Prk: "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDbA+YuMp4JUVj6rjzgwGKNXWkEMGX/rinqkfyBZ6B6p8EKz8zgA+ypiJLOixD3GyKnUnAzx4waNRZHfdEu+l57kJFtd/ipfwtJ28aTi7TqtqEpqD+UPY4ourt2CuyCFxWsonS6dczqtTvfAVArTdbGJYY+kNNVR3WiXgGUhkUu8N7vEowU00RUQGNdSVMUs4FX+HlU3RnEoRc/xUhPiaLf0Bm/g9wG96kwyg/TZvkNU7PpMVRdXeLrVORn0qThs3VA4dqondF+O12iC1TK4TKYGzFYczGAUsfuurtDyCc2GMoE+hH2FR8U7amQOVuYZFkutTdqaqukWpFQOr8wLeMzAgMBAAECggEAD715/3v3y6ejA3EeQvDQpGRANeLckcGMlaUkRpCSAf6oawSALuFZUt3T3zAzae7zUJ8mHTKMKR4DmeO68utfevXq3bkvj87nmslGvjfeKrgxYPMMjrTV0KuK6XLjiH3sOtn6FaR9s6iOwvovLs2LT/ZGbZyu84QNOjwTVP9JXZQkBgMItdKf+U3H2Cjp7U/qXBt8/9yzVFklp1g1883DAty0lzmT27dJimGVGaPQ8vNxo81+ZUEJAn6GUTk0K/GwJfhPTU8hh8G90n2LTyskoMjGxQe9lXfCcS9DmWawEQL4WTctPrDYlnS/cjCVMS0KXIFuxRNf6qaMYDeywC8BgQKBgQDyf40dvmw34Rrb46+NLayQ9W5CJI/dYeRajpCjoOomq5QYhbXzUCpVfbtByeGMsg3zN58NNsZGhl5SU0GdEdoOlxCk+2Hey2yQYF4ugQm/dTd68Jgqi3yujigAbNYa1ZhL9t3FqouPY1dGiaxl+DFYdSMIrsVFXh2NbrPyqTk5IQKBgQDnNaH7LCcIUqg9H8Tsls+8GLzP2HwF3hdll8asEsF3K3HX6/Zlp4VnnEcIkAxLRL/L0o5akXrmA18ZwfoSguTPXV9va3G2GgIiJHgcytmGtQVvbpFKuPnCXKz+avxnfO0flJqyYEuHr/40jsGbMkk0Kr52/n3ivXZbBUlT+tkt0wKBgB0qLgSnxEgsMJjFl3V5SsncWrhlwU+02Evz3X1wevjPpe4VFr7+ozjI+F5/MztCpt7bj6t9LPeKbYmlLb0ASqN6k6vj9+9ds97hWDJrnoqCRHvqt8JWKFauDi2O6WksyzZHqIB/dG14WyTGpg9VfEnRPLdsnZksKo26BLZol9NBAoGBAMz7oMNljqlzVtLyMo2q2zuhFuySusoc79NTL4FpE3rK2qCbA5V2YvDL/bIau7uTlRNodmrXZgU84fidIE9/Gsq5tp26vVK8Vj3c5Vxpf1dNcCct+MQtoMjvjzP0uBgsCrKf9lLEytHed1ozYnRsrbgBWWF4GTWH0cG6uxsoX5mfAoGAfYXKZdyRU+Su4y4EnDLMXd320ar7PaeuY8aZU7V6UQEsaOj6H3O8JMEOuBrOVEhAP2EkAC8ayargSXTSOkN97pg88agKDwA6jh4N6TKAK8XMft81YPPliVwZMsAUqihSKQBnKZ7ssHHLGWWWp5vfkyb7Y7dIkZcPzB0X3q/jL58=", - Npk: "", + PukPath: "", MchCertPath: "/Users/lsxd/code/php/yxxt/market/config/alipaycash/appCertPublicKey_2021004100663111.crt", RootCertPath: "/Users/lsxd/code/php/yxxt/market/config/alipaycash/alipayRootCert.crt", } diff --git a/plugins/alipay_redpack/internal/transform.go b/plugins/alipay_redpack/internal/transform.go index 86ca936..64b0c07 100644 --- a/plugins/alipay_redpack/internal/transform.go +++ b/plugins/alipay_redpack/internal/transform.go @@ -15,7 +15,7 @@ type Config struct { AppId string `json:"app_id"` BaseUri string `json:"base_uri"` Prk string `json:"prk"` // 私钥 - Npk string `json:"npk"` // 回调公钥 + PukPath string `json:"npk"` // 验签公钥 MchCertPath string `json:"mch_cert_path"` RootCertPath string `json:"root_cert_path"` @@ -37,7 +37,7 @@ func (c *Config) paramReq(req po.Req, method string) (*po.Param, error) { if err := req.Validate(); err != nil { return nil, err } - cert, err := alipay.GetCert(c.MchCertPath, c.RootCertPath, c.AppId) + cert, err := alipay.GetCert(c.MchCertPath, c.RootCertPath, c.PukPath, c.AppId) if err != nil { return nil, err } diff --git a/utils/alipay/cert.go b/utils/alipay/cert.go index da8e5c8..7186def 100644 --- a/utils/alipay/cert.go +++ b/utils/alipay/cert.go @@ -8,6 +8,7 @@ import ( type CertConfig struct { MchCertSN string RootCertSN string + PublicKey string } type manager struct { @@ -36,7 +37,7 @@ func init() { instance.CertConfigs = make(map[string]*CertConfig) } -func GetCert(mchCertPath, rootCertPath, appId string) (*CertConfig, error) { +func GetCert(mchCertPath, rootCertPath, PublicKeyPath, appId string) (*CertConfig, error) { if mchCertPath == "" || rootCertPath == "" || appId == "" { return nil, fmt.Errorf("mchCertPath or rootCertPath or appId is empty") } @@ -44,17 +45,22 @@ func GetCert(mchCertPath, rootCertPath, appId string) (*CertConfig, error) { if c != nil { return nil, fmt.Errorf("appId %s already exists", appId) } - mchCertSN, err := GetMchCertSN(mchCertPath) + mchCertSN, err := getMchCertSN(mchCertPath) if err != nil { return nil, fmt.Errorf("get mchCertSN error: %v", err) } - rootCertSN, err := GetRootCertSN(rootCertPath) + rootCertSN, err := getRootCertSN(rootCertPath) if err != nil { return nil, fmt.Errorf("get rootCertSN error: %v", err) } + publicKey, err := getPublicKey(PublicKeyPath) + if err != nil { + return nil, fmt.Errorf("get publicKey error: %v", err) + } c = &CertConfig{ MchCertSN: mchCertSN, RootCertSN: rootCertSN, + PublicKey: publicKey, } setCertConfig(appId, c) return c, nil diff --git a/utils/alipay/cert_test.go b/utils/alipay/cert_test.go index 4feacb3..9c73ae5 100644 --- a/utils/alipay/cert_test.go +++ b/utils/alipay/cert_test.go @@ -5,7 +5,7 @@ import ( ) func TestCertSN(t *testing.T) { - ms, err := GetMchCertSN("/Users/lsxd/code/php/yxxt/market/config/alipaycash/appCertPublicKey_2021004100663111.crt") + ms, err := getMchCertSN("/Users/lsxd/code/php/yxxt/market/config/alipaycash/appCertPublicKey_2021004100663111.crt") if err != nil { t.Error(err) } else { @@ -13,7 +13,7 @@ func TestCertSN(t *testing.T) { //78a57140055b8e7853b1576bcf763361 t.Logf("merchantCertSN:%s", ms) } - rs, err := GetRootCertSN("/Users/lsxd/code/php/yxxt/market/config/alipaycash/alipayRootCert.crt") + rs, err := getRootCertSN("/Users/lsxd/code/php/yxxt/market/config/alipaycash/alipayRootCert.crt") if err != nil { t.Error(err) } else { @@ -24,7 +24,7 @@ func TestCertSN(t *testing.T) { } func TestMchCertSN(t *testing.T) { - s, err := GetMchCertSN("/Users/lsxd/code/php/yxxt/market/config/alipaycash/appCertPublicKey_2021004100663111.crt") + s, err := getMchCertSN("/Users/lsxd/code/php/yxxt/market/config/alipaycash/appCertPublicKey_2021004100663111.crt") if err != nil { t.Error(err) } else { @@ -34,10 +34,20 @@ func TestMchCertSN(t *testing.T) { } func TestRootCertSN(t *testing.T) { - s, err := GetRootCertSN("/Users/lsxd/code/php/yxxt/market/config/alipaycash/alipayRootCert.crt") + s, err := getRootCertSN("/Users/lsxd/code/php/yxxt/market/config/alipaycash/alipayRootCert.crt") if err != nil { t.Error(err) } else { t.Log(s) } } + +func TestPublicKey(t *testing.T) { + s, err := getPublicKey("/Users/lsxd/code/php/yxxt/market/config/alipaycash/alipayCertPublicKey_RSA2.crt") + if err != nil { + t.Error(err) + } else { + //78a57140055b8e7853b1576bcf763361 + t.Log(s) + } +} diff --git a/utils/alipay/mch_cert.go b/utils/alipay/mch_cert.go index 280bc99..26e2e10 100644 --- a/utils/alipay/mch_cert.go +++ b/utils/alipay/mch_cert.go @@ -6,8 +6,8 @@ import ( "log" ) -// GetMchCertSN 提取证书序列号 -func GetMchCertSN(certPath string) (string, error) { +// getMchCertSN 提取证书序列号 +func getMchCertSN(certPath string) (string, error) { certData, err := ioutil.ReadFile(certPath) if err != nil { log.Fatalf("Failed to read the cert file: %s", err) diff --git a/utils/alipay/public_key.go b/utils/alipay/public_key.go new file mode 100644 index 0000000..4c1f591 --- /dev/null +++ b/utils/alipay/public_key.go @@ -0,0 +1,51 @@ +package alipay + +import ( + "crypto/x509" + "encoding/pem" + "fmt" + "io/ioutil" + "strings" +) + +// 从证书文件中提取公钥 +func getPublicKey(certPath string) (string, error) { + // 读取证书文件内容 + certData, err := ioutil.ReadFile(certPath) + if err != nil { + return "", fmt.Errorf("failed to read certificate file: %w", err) + } + + // 解码 PEM 编码的证书 + block, _ := pem.Decode(certData) + if block == nil { + return "", fmt.Errorf("failed to decode PEM block") + } + + // 解析证书 + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return "", fmt.Errorf("failed to parse certificate: %w", err) + } + + // 获取公钥 + pubKey := cert.PublicKey + + // 转换公钥为 PEM 格式 + pubKeyBytes, err := x509.MarshalPKIXPublicKey(pubKey) + if err != nil { + return "", fmt.Errorf("failed to marshal public key: %w", err) + } + + // 创建 PEM 块 + pemBlock := &pem.Block{ + Type: "PUBLIC KEY", + Bytes: pubKeyBytes, + } + + // 编码为 PEM 格式字符串 + pemBytes := pem.EncodeToMemory(pemBlock) + publicKey := strings.TrimSpace(string(pemBytes)) + + return publicKey, nil +} diff --git a/utils/alipay/root_cert.go b/utils/alipay/root_cert.go index 3ce0457..08755cb 100644 --- a/utils/alipay/root_cert.go +++ b/utils/alipay/root_cert.go @@ -7,8 +7,8 @@ import ( "strings" ) -// GetRootCertSN 计算证书的序列号并返回最终字符串 -func GetRootCertSN(certPath string) (string, error) { +// getRootCertSN 计算证书的序列号并返回最终字符串 +func getRootCertSN(certPath string) (string, error) { certData, err := ioutil.ReadFile(certPath) if err != nil { return "", fmt.Errorf("failed to read certificate file: %v", err)