All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 6m36s
添加苹果IAP通知处理功能,包括解析和验证JWS签名、处理交易状态变更 新增订单号字段用于关联订单处理 实现交易记录的创建和更新逻辑 处理订阅状态的变更和过期时间计算
79 lines
2.4 KiB
Go
79 lines
2.4 KiB
Go
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
|
|
})
|
|
}
|