async handleSubscription()

in in_app_purchases/step_10/firebase-backend/functions/src/google-play.purchase-handler.ts [88:156]


    async handleSubscription(
        userId: string | null,
        productData: ProductData,
        token: string,
    ): Promise<boolean> {
      try {
        // Verify the purchase with Google
        const response = await this.androidPublisher.purchases.subscriptions
            .get(
                {
                  packageName: ANDROID_PACKAGE_ID,
                  subscriptionId: productData.productId,
                  token,
                },
            );
        // Make sure an order id exists
        if (!response.data.orderId) {
          console.error("Could not handle purchase without order id");
          return false;
        }
        // If a subscription suffix is present (..#) extract the orderId.
        let orderId = response.data.orderId;
        const orderIdMatch = /^(.+)?[.]{2}[0-9]+$/g.exec(orderId);
        if (orderIdMatch) {
          orderId = orderIdMatch[1];
        }
        console.log({
          rawOrderId: response.data.orderId,
          newOrderId: orderId,
        });
        // Construct purchase data for db updates
        const purchaseData: Omit<SubscriptionPurchase, "userId"> = {
          type: "SUBSCRIPTION",
          iapSource: "google_play",
          orderId: orderId,
          productId: productData.productId,
          purchaseDate: firestore.Timestamp.fromMillis(parseInt(response.data.startTimeMillis ?? "0", 10)),
          expiryDate: firestore.Timestamp.fromMillis(parseInt(response.data.expiryTimeMillis ?? "0", 10)),
          status: [
            "PENDING", // Payment pending
            "ACTIVE", // Payment received
            "ACTIVE", // Free trial
            "PENDING", // Pending deferred upgrade/downgrade
            "EXPIRED", // Expired or cancelled
          ][response.data.paymentState ?? 4] as SubscriptionStatus,
        };
        try {
          if (userId) {
            // If we know the userId,
            // update the existing purchase or create it if it does not exist.
            await this.iapRepository
                .createOrUpdatePurchase({
                  ...purchaseData,
                  userId,
                } as Purchase);
          } else {
            // If we do not know the user id, a previous entry must already
            // exist, and thus we'll only update it.
            await this.iapRepository.updatePurchase(purchaseData);
          }
        } catch (e) {
          console.log("Could not create or update purchase", {orderId, productId: productData.productId});
        }
        return true;
      } catch (e) {
        console.error(e);
        return false;
      }
    }