Unverified Commit 6b02d963 authored by Andrei Mihu's avatar Andrei Mihu Committed by GitHub
Browse files

Improve extraction of product info from Apple in-app purchases and subscriptions. (#912)

parent cc80b3d6
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -63,11 +63,6 @@ func ValidatePurchasesApple(ctx context.Context, logger *zap.Logger, db *sql.DB,
		return nil, status.Error(codes.FailedPrecondition, fmt.Sprintf("Invalid Receipt. Status: %d", validation.Status))
	}

	if validation.LatestReceipt != "" {
		// Receipt is for a subscription, ValidateSubscriptionApple should be used instead.
		return nil, status.Error(codes.FailedPrecondition, "Subscription Receipt. Use the appropriate function instead.")
	}

	env := api.StoreEnvironment_PRODUCTION
	if validation.Environment == iap.AppleSandboxEnvironment {
		env = api.StoreEnvironment_SANDBOX
@@ -75,6 +70,10 @@ func ValidatePurchasesApple(ctx context.Context, logger *zap.Logger, db *sql.DB,

	storagePurchases := make([]*storagePurchase, 0, len(validation.Receipt.InApp))
	for _, purchase := range validation.Receipt.InApp {
		if purchase.ExpiresDateMs != "" {
			continue
		}

		purchaseTime, err := strconv.ParseInt(purchase.PurchaseDateMs, 10, 64)
		if err != nil {
			return nil, err
@@ -91,6 +90,11 @@ func ValidatePurchasesApple(ctx context.Context, logger *zap.Logger, db *sql.DB,
		})
	}

	if len(storagePurchases) == 0 && len(validation.Receipt.InApp) > 0 {
		// All purchases in this receipt are subscriptions.
		return nil, status.Error(codes.FailedPrecondition, "Subscription Receipt. Use the appropriate function instead.")
	}

	if !persist {
		// Skip storing the receipts
		validatedPurchases := make([]*api.ValidatedPurchase, 0, len(storagePurchases))
+18 −10
Original line number Diff line number Diff line
@@ -248,24 +248,32 @@ func ValidateSubscriptionApple(ctx context.Context, logger *zap.Logger, db *sql.
		return nil, status.Error(codes.FailedPrecondition, fmt.Sprintf("Invalid Receipt. Status: %d", validation.Status))
	}

	if validation.LatestReceipt == "" {
		// Receipt is for a purchase, ValidatePurchaseApple should be used instead.
		return nil, status.Error(codes.FailedPrecondition, "Purchase Receipt. Use the appropriate function instead.")
	}

	env := api.StoreEnvironment_PRODUCTION
	if validation.Environment == iap.AppleSandboxEnvironment {
		env = api.StoreEnvironment_SANDBOX
	}

	latestSubReceiptInfo := validation.LatestReceiptInfo[0]
	var found bool
	var receiptInfo iap.ValidateReceiptAppleResponseLatestReceiptInfo
	for _, latestReceiptInfo := range validation.LatestReceiptInfo {
		if latestReceiptInfo.ExpiresDateMs == "" {
			// Not a subscription, skip.
			continue
		}
		receiptInfo = latestReceiptInfo
		found = true
	}
	if !found {
		// Receipt is for a purchase (or otherwise has no subscriptions for any reason) so ValidatePurchaseApple should be used instead.
		return nil, status.Error(codes.FailedPrecondition, "Purchase Receipt. Use the appropriate function instead.")
	}

	purchaseTime, err := strconv.ParseInt(latestSubReceiptInfo.OriginalPurchaseDateMs, 10, 64)
	purchaseTime, err := strconv.ParseInt(receiptInfo.OriginalPurchaseDateMs, 10, 64)
	if err != nil {
		return nil, err
	}

	expireTimeInt, err := strconv.ParseInt(latestSubReceiptInfo.ExpiresDateMs, 10, 64)
	expireTimeInt, err := strconv.ParseInt(receiptInfo.ExpiresDateMs, 10, 64)
	if err != nil {
		return nil, err
	}
@@ -280,8 +288,8 @@ func ValidateSubscriptionApple(ctx context.Context, logger *zap.Logger, db *sql.
	storageSub := &storageSubscription{
		userID:                userID,
		store:                 api.StoreProvider_APPLE_APP_STORE,
		productId:             latestSubReceiptInfo.ProductId,
		originalTransactionId: latestSubReceiptInfo.OriginalTransactionId,
		productId:             receiptInfo.ProductId,
		originalTransactionId: receiptInfo.OriginalTransactionId,
		purchaseTime:          parseMillisecondUnixTimestamp(purchaseTime),
		environment:           env,
		expireTime:            expireTime,