package transferv3 import ( "crypto" "crypto/rsa" "crypto/sha256" "encoding/base64" "fmt" "strings" ) // BuildSignMessage 构建请求签名串(文档:请求方法\n请求URL路径\n时间戳\n随机串\n请求报文主体\n) func BuildSignMessage(method, urlPath, timestamp, nonce, body string) string { return method + "\n" + urlPath + "\n" + timestamp + "\n" + nonce + "\n" + body + "\n" } // Sign 使用商户私钥 SHA256withRSA 签名,返回 Base64 func Sign(signMessage string, privateKey *rsa.PrivateKey) (string, error) { h := sha256.Sum256([]byte(signMessage)) sig, err := rsa.SignPKCS1v15(nil, privateKey, crypto.SHA256, h[:]) if err != nil { return "", fmt.Errorf("rsa sign: %w", err) } return base64.StdEncoding.EncodeToString(sig), nil } // BuildAuthorization 构建 Authorization 头(文档格式) func BuildAuthorization(mchID, nonce, signature, timestamp, serialNo string) string { return fmt.Sprintf(`WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",signature="%s",timestamp="%s",serial_no="%s"`, mchID, nonce, signature, timestamp, serialNo) } // BuildVerifyMessage 构建回调验签串(文档:时间戳\n随机串\n请求报文主体\n) func BuildVerifyMessage(timestamp, nonce, body string) string { return timestamp + "\n" + nonce + "\n" + body + "\n" } // VerifySignature 使用平台公钥验证回调签名(Wechatpay-Signature 为 Base64) func VerifySignature(timestamp, nonce, body, signatureBase64 string, publicKey *rsa.PublicKey) bool { msg := BuildVerifyMessage(timestamp, nonce, body) sig, err := base64.StdEncoding.DecodeString(strings.TrimSpace(signatureBase64)) if err != nil { return false } h := sha256.Sum256([]byte(msg)) err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, h[:], sig) return err == nil }