private async disableReplacedSubscription()

in ClassyTaxiServer/src/play-billing/PurchasesManager.ts [171:222]


  private async disableReplacedSubscription(packageName: string, sku: string, purchaseToken: string): Promise<void> {
    console.log('Disabling purchase token = ', purchaseToken);
    // STEP 1: Lookup the purchase record in Firestore
    const purchaseRecordDoc = await this.purchasesDbRef.doc(purchaseToken).get();

    if (purchaseRecordDoc.exists) {
      // Purchase record found in Firestore. Check if it has been disabled.
      if (purchaseRecordDoc.data().replacedByAnotherPurchase) {
        // The old purchase has been. We don't need to take further action
        return;
      } else {
        // STEP 2a: Old purchase found in cache, so we disable it
        await purchaseRecordDoc.ref.update({ replacedByAnotherPurchase: true, userId: REPLACED_PURCHASE_USERID_PLACEHOLDER });
        return;
      }
    } else {
      // Purchase record not found in Firestore. We'll try to fetch purchase detail from Play Developer API to backfill the missing cache
      const apiResponse = await new Promise((resolve, reject) => {
        this.playDeveloperApiClient.purchases.subscriptions.get({
          packageName: packageName,
          subscriptionId: sku,
          token: purchaseToken
        }, async (err, result) => {
          if (err) {
            console.warn('Error fetching purchase data from Play Developer API to backfilled missing purchase record in Firestore. ', err.message);
            // We only log an warning to console log as there is chance that backfilling is impossible.
            // For example: after a subscription upgrade, the new token has linkedPurchaseToken to be the token before upgrade.
            // We can't tell the sku of the purchase before upgrade from the old token itself, so we can't query Play Developer API
            // to backfill our cache.
            resolve(null);
          } else {
            resolve(result.data);
          }
        })
      })

      if (apiResponse) {
        // STEP 2b. Parse the response from Google Play Developer API and store the purchase detail
        const now = Date.now();
        const subscriptionPurchase = SubscriptionPurchaseImpl.fromApiResponse(apiResponse, packageName, purchaseToken, sku, now);
        subscriptionPurchase.replacedByAnotherPurchase = true; // Mark the purchase as already being replaced by other purchase.
        subscriptionPurchase.userId = REPLACED_PURCHASE_USERID_PLACEHOLDER;
        const firestoreObject = subscriptionPurchase.toFirestoreObject();
        await purchaseRecordDoc.ref.set(firestoreObject);

        // STEP 3. If this purchase has also replaced another purchase, repeating from STEP 1 with the older token
        if (subscriptionPurchase.linkedPurchaseToken) {
          await this.disableReplacedSubscription(packageName, sku, subscriptionPurchase.linkedPurchaseToken);
        }
      }
    }
  }