go语言接入苹果支付v2版本通知
一、配置,在https://appstoreconnect.apple.com/中配置服务器url
二、测试是否能接收到苹果沙盒环境发送的通知
1、根据配置,生成访问苹果服务器需要的jwt令牌
func main() {
// 替换为你的密钥文件路径、秘钥ID、Issuer ID 和 Bundle ID
privateKeyPath := "你的苹果证书"
keyID := "你的keyID "
issuerID := "你的issuerID "
bundleID := "你的bundleID "
// 读取私钥文件
privateKeyBytes, err := ioutil.ReadFile(privateKeyPath)
if err != nil {
fmt.Println("Failed to read private key file:", err)
return
}
// 解析PKCS#8格式的私钥
block, _ := pem.Decode(privateKeyBytes)
if block == nil {
fmt.Println("Failed to decode PEM block containing the key")
return
}
privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
fmt.Println("Failed to parse private key:", err)
return
}
// 类型断言为 ECDSA 私钥(Apple使用的签名算法)
signingKey, ok := privateKey.(*ecdsa.PrivateKey)
if !ok {
fmt.Println("Private key is not an ECDSA private key")
return
}
// 构建 JWT 的标头和负载
token := jwt.NewWithClaims(jwt.SigningMethodES256, jwt.MapClaims{
"iss": issuerID,
"aud": "appstoreconnect-v1",
"iat": time.Now().Unix(),
"exp": time.Now().Add(time.Hour).Unix(), // 到期时间为当前时间加1小时
"nonce": "6edffe66-b482-11eb-8529-0242ac130003",
"bid": bundleID,
})
token.Header["kid"] = keyID
// 生成 JWT
tokenString, err := token.SignedString(signingKey)
if err != nil {
fmt.Println("Failed to sign token:", err)
return
}
fmt.Println("JWT Token:", tokenString)
}
其中苹果证书、keyID 、issuerID、bundleID 在https://appstoreconnect.apple.com/中申请。
上述代码输出为
JWT Token: eyJhbGciOiJFUzI1NiIsImtpZCI6IlA2TjVYUTdEOFQiLCJ0eXAiOiJKV1QifQ.eyJhdW
QiOiJhcHBzdG9yZWNvbm5lY3QtdjEiLCJiaWQiOiJjb20udGVuZGEuc2VjdXJpdHkiLCJleHAiOjE3MD
cwMjI3MjcsImlhdCI6MTcwNzAxOTEyNywiaXNzIjoiNjlhNmRlODItOTFmNi00N2UzLWUwNTMtNWI4Yz
djMTFhNGQxIiwibm9uY2UiOiI2ZWRmZmU2Ni1iNDgyLTExZWItODUyOS0wMjQyYWMxMzAwMDMifQ.hUq
CM_XF6jnyQIOrc6ldUeTPYy3Ihkw6dIwASc78GVIZkI1YBAAGhABW41WbjZ5CzLzWg6MmRxImiUdFVrI
62g
获取到token后调用https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/test进行请求,苹果服务器沙盒环境就会发送通知
三、解析苹果通知
1.接入三方包
go get “github.com/go-pay/gopay/apple”
func (s basicService) ApplePayServerNotify(ctx context.Context, req api.ApplePayCallBackReq) (response api.ApplePayCallBackRes) {
//DecodeSignedPayload 解析SignedPayload数据
payload, err := apple.DecodeSignedPayload(req.SignedPayload)
if err != nil {
mylog.WithContext(ctx).Error(err.Error())
response.Status = FAIL
return response
}
// 解析订阅数据(可能没有)
renewalInfo, err := payload.DecodeRenewalInfo()
if err != nil {
mylog.WithContext(ctx).Sugar().Error(err)
}
// 解析交易数据(可能没有)
transactionInfo, err := payload.DecodeTransactionInfo()
if err != nil {
mylog.WithContext(ctx).Sugar().Error(err)
}
mylog.WithContext(ctx).Sugar().Debugf("data.transactionInfo: %+v", transactionInfo)
bs2, _ := json.Marshal(transactionInfo)
mylog.WithContext(ctx).Sugar().Debugf(string(bs2))
response.Status = FAIL
switch payload.NotificationType {
case "CONSUMPTION_REQUEST": //app内发起退款的回调通知
response.Status = s.ApplePayRequestNotify(ctx, transactionInfo)
case "REFUND": //退款成功
response.Status = s.ApplePayRefundNotify(ctx, transactionInfo)
case "REFUND_DECLINED": //退款失败
response.Status = s.ApplePayRefundFailNotify(ctx, transactionInfo)
}
return
}
2.苹果通知类型
https://learnku.com/articles/84461