Skip to main content

In-App Purchase (IAP) Flow

Flow Overview

These diagrams outline the different parts of the process for handling Apple In-App Purchases.

1. Initial Purchase Flow (Client-Side - DEPRECATED)

2. Apple Server Notifications & Subscription Update

3. Transaction History Fetching

Process Description

  1. Initial Purchase (Client-Side Triggered): Note: This flow relying on the client sending the final transaction is considered deprecated. The preferred method relies on Apple Server-to-Server notifications (see Point 2).

    • User initiates a purchase in the mobile app for a VipPackage.
    • The app calls the backend's createFirstOrder endpoint (handled by InAppPurchaseService).
    • An Order record is created with status = PENDING, payment_method = IAP, and a unique iap_order_id (UUID). This iap_order_id is returned to the app.
    • The app uses the product ID (iap_product_id) to proceed with the Apple purchase flow, providing the iap_order_id as the appAccountToken.
    • Upon successful Apple payment, the app receives transaction details.
    • The app sends these transaction details back to the backend's /callback endpoint (from mobile).
    • InAppPurchaseService::callback calls processClientCallbackNotification.
    • processClientCallbackNotification calls updateOrder to find the pending Order (using iap_order_id from the transaction's appAccountToken) and updates its status to COMPLETED, storing payment details (payment_reference_id, paid_amount, paid_currency, etc.). It also calculates potential free trial days.
    • The OrderObserver (triggered by the Order update) calls VipSubscriptionService to create/activate the VipSubscription. (See VIP Subscriptions Flow for details on subscription creation/activation logic).
  2. Server-to-Server Notifications (Apple Triggered):

    • Apple sends notifications (callbacks) to the backend endpoint for various subscription events (e.g., SUBSCRIBED, DID_RENEW, EXPIRED, DID_FAIL_TO_RENEW, REFUND, DID_CHANGE_RENEWAL_PREF, PRICE_INCREASE).
    • The callback endpoint receives the signed payload and dispatches ProcessIapCallbackJob.
    • The job calls InAppPurchaseService::callback (with $from_mobile = false).
    • InAppPurchaseService first logs the raw callback data using createCallbackLog.
    • It then calls processServerCallbackNotification, parsing the signed transaction and notification data.
    • Based on the notificationType and subtype, it routes to specific handling methods:
      • subscriptibe: Handles initial buys or resubscriptions. It might update an existing pending order or create a new completed order if the subscription originated outside the app flow (e.g., managed directly in the App Store). Calls VipSubscriptionService::renewVipSubscription.
      • renewSubscription: Handles successful renewals. Creates a new Order record for the renewal transaction using createRenewOrder and calls VipSubscriptionService::renewVipSubscription.
      • expireSubscription: Handles expirations or renewal failures. Calls VipSubscriptionService::processExpireVipSubscription.
      • refundSubscription: Handles refunds. Calls VipSubscriptionService::refundVipSubscription.
      • Other methods (upgradeSubscription, downgradeSubscription, handlePriceIncreaseNotification): Handle specific lifecycle events, often interacting with VipSubscriptionService.
    • Note: The core logic for creating, updating, and managing the state of the VipSubscription record itself (e.g., setting dates, status, history) resides within the VipSubscriptionService, as detailed in the VIP Subscriptions Flow.
  3. Fetching Transaction History:

    • The getHistories method allows fetching notification/transaction history from Apple's API for a given date range.
    • It uses a JWT token for authentication with Apple's API.
    • It handles pagination (paginationToken, hasMore) using the loop method if necessary to retrieve all records.
    • It parses the signed payloads (signedPayload, signedTransactionInfo) from the history response.
    • It can return raw transaction data, associated order IDs, user IDs, etc.

Key Models & Services

  • InAppPurchaseService: Core service handling all interactions with Apple's IAP system (callbacks, history, transaction parsing).
  • Order: Represents the purchase transaction, linking the User and VipPackage, storing payment status and IAP details (iap_order_id, payment_reference_id).
  • VipPackage: Defines the product being purchased, including its iap_product_id.
  • VipSubscription: Represents the user's access grant, managed based on order completion and IAP notifications.
  • VipSubscriptionService: Handles the business logic for creating, renewing, expiring, and refunding VipSubscription records based on triggers from InAppPurchaseService or OrderObserver.
  • CallbackLog: Stores raw data received from Apple's server-to-server notifications for auditing and debugging.
  • User: The customer account making the purchase.
  • ProcessIapCallbackJob: A queued job to process incoming Apple server notifications asynchronously.
  • OrderObserver: Listens for Order model events (specifically updates) to trigger VipSubscriptionService actions upon order completion.