feat(appleIAP): 实现苹果应用内购买通知处理逻辑
Build docker and publish / build (20.15.1) (push) Successful in 6m36s
Build docker and publish / build (20.15.1) (push) Successful in 6m36s
添加苹果IAP通知处理功能,包括解析和验证JWS签名、处理交易状态变更 新增订单号字段用于关联订单处理 实现交易记录的创建和更新逻辑 处理订阅状态的变更和过期时间计算
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
package notify
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
iapmodel "github.com/perfect-panel/server/internal/model/iap/apple"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
iapapple "github.com/perfect-panel/server/pkg/iap/apple"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AppleIAPNotifyLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAppleIAPNotifyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AppleIAPNotifyLogic {
|
||||
return &AppleIAPNotifyLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AppleIAPNotifyLogic) Handle(signedPayload string) error {
|
||||
txPayload, _, err := iapapple.VerifyNotificationSignedPayload(signedPayload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return l.svcCtx.DB.Transaction(func(db *gorm.DB) error {
|
||||
var existing *iapmodel.Transaction
|
||||
existing, _ = iapmodel.NewModel(l.svcCtx.DB, l.svcCtx.Redis).FindByOriginalId(l.ctx, txPayload.OriginalTransactionId)
|
||||
if existing == nil || existing.Id == 0 {
|
||||
rec := &iapmodel.Transaction{
|
||||
UserId: 0,
|
||||
OriginalTransactionId: txPayload.OriginalTransactionId,
|
||||
TransactionId: txPayload.TransactionId,
|
||||
ProductId: txPayload.ProductId,
|
||||
PurchaseAt: txPayload.PurchaseDate,
|
||||
RevocationAt: txPayload.RevocationDate,
|
||||
JWSHash: "",
|
||||
}
|
||||
if e := db.Model(&iapmodel.Transaction{}).Create(rec).Error; e != nil {
|
||||
return e
|
||||
}
|
||||
} else {
|
||||
if txPayload.RevocationDate != nil {
|
||||
if e := db.Model(&iapmodel.Transaction{}).
|
||||
Where("original_transaction_id = ?", txPayload.OriginalTransactionId).
|
||||
Update("revocation_at", txPayload.RevocationDate).Error; e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
}
|
||||
pm, _ := iapapple.ParseProductMap(l.svcCtx.Config.Site.CustomData)
|
||||
m := pm.Items[txPayload.ProductId]
|
||||
token := "iap:" + txPayload.OriginalTransactionId
|
||||
sub, e := l.svcCtx.UserModel.FindOneSubscribeByToken(l.ctx, token)
|
||||
if e == nil && sub != nil && sub.Id != 0 {
|
||||
if txPayload.RevocationDate != nil {
|
||||
sub.Status = 3
|
||||
t := *txPayload.RevocationDate
|
||||
sub.FinishedAt = &t
|
||||
sub.ExpireTime = t
|
||||
} else if m.DurationDays > 0 {
|
||||
exp := iapapple.CalcExpire(txPayload.PurchaseDate, m.DurationDays)
|
||||
sub.ExpireTime = exp
|
||||
sub.Status = 1
|
||||
}
|
||||
if e := l.svcCtx.UserModel.UpdateSubscribe(l.ctx, sub, db); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user