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);
}
}
}
}