From d8f5628bb1d1cb6942e20a28af778be4f9157e91 Mon Sep 17 00:00:00 2001 From: shanshanzhong Date: Tue, 16 Dec 2025 19:28:03 -0800 Subject: [PATCH] =?UTF-8?q?feat(iap/apple):=20=E6=B7=BB=E5=8A=A0=E5=AF=B9a?= =?UTF-8?q?ppAccountToken=E7=9A=84=E6=94=AF=E6=8C=81=E4=BB=A5=E5=85=B3?= =?UTF-8?q?=E8=81=94=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 解析JWS中的appAccountToken字段并添加到TransactionPayload结构体 在恢复逻辑中尝试使用appAccountToken关联现有订单 --- internal/logic/public/iap/apple/restoreLogic.go | 16 ++++++++++++++++ pkg/iap/apple/jws.go | 3 +++ pkg/iap/apple/types.go | 1 + 3 files changed, 20 insertions(+) diff --git a/internal/logic/public/iap/apple/restoreLogic.go b/internal/logic/public/iap/apple/restoreLogic.go index fa4aaa1..9364667 100644 --- a/internal/logic/public/iap/apple/restoreLogic.go +++ b/internal/logic/public/iap/apple/restoreLogic.go @@ -132,6 +132,22 @@ SIRDAVLcWemp0fMlnfDE4EHmqcD58arEJWsr3aWEhc4BHocOUIGjko0cVWGchrFa if err := tx.Model(&iapmodel.Transaction{}).Create(iapTx).Error; err != nil { return err } + + // Try to link with existing order if possible (Best Effort) + // Strategy 1: appAccountToken (from JWS) -> OrderNo (UUID) + if txp.AppAccountToken != "" { + // appAccountToken is usually a UUID string + // Try to find order by parsing UUID or matching direct orderNo (if we stored it as uuid) + // Since our orderNo is string, we can try to search it. + // However, AppAccountToken is strictly UUID format. If our orderNo is not UUID, we might need a mapping. + // Assuming orderNo -> UUID conversion was consistent on client side. + // Here we just try to update if we find an unpaid order with this ID (if orderNo was used as appAccountToken) + _ = l.svcCtx.OrderModel.UpdateOrderStatus(l.ctx, txp.AppAccountToken, 2, tx) + } + + // Strategy 2: If we had a way to pass orderNo in restore request (optional field in future), we could use it here. + // But for now, we only rely on appAccountToken or just skip order linking. + exp := iapapple.CalcExpire(txp.PurchaseDate, m.DurationDays) userSub := user.Subscribe{ UserId: u.Id, diff --git a/pkg/iap/apple/jws.go b/pkg/iap/apple/jws.go index 18aaf41..0c024e6 100644 --- a/pkg/iap/apple/jws.go +++ b/pkg/iap/apple/jws.go @@ -71,6 +71,9 @@ func ParseTransactionJWS(jws string) (*TransactionPayload, error) { t := time.UnixMilli(int64(v)) resp.RevocationDate = &t } + if v, ok := raw["appAccountToken"].(string); ok { + resp.AppAccountToken = v + } return &resp, nil } diff --git a/pkg/iap/apple/types.go b/pkg/iap/apple/types.go index ffdd807..05dd61d 100644 --- a/pkg/iap/apple/types.go +++ b/pkg/iap/apple/types.go @@ -9,5 +9,6 @@ type TransactionPayload struct { OriginalTransactionId string `json:"originalTransactionId"` PurchaseDate time.Time `json:"purchaseDate"` RevocationDate *time.Time`json:"revocationDate"` + AppAccountToken string `json:"appAccountToken"` }