in typescript/src/services/google-play-v2.ts [36:147]
export async function fetchGoogleSubscriptionV2(
purchaseToken: string,
packageName: string,
): Promise<GoogleSubscription> {
try {
const client = await initialiseAndroidPublisherClient();
const purchase = await client.purchases.subscriptionsv2.get({
packageName,
token: purchaseToken,
});
// A subscription purchase refers to one or many underlying products ("line items".) However, by convention (and by
// constraining/controling the UX within the app), we will always assume that a subscription purchase refers to exactly
// one product.
if (purchase.data.lineItems?.length != 1) {
throw Error(
'The subscription purchase must refer to exactly one product',
);
}
const product = purchase.data.lineItems[0];
const startTime = purchase.data.startTime ?? null;
const expiryTime = product.expiryTime;
if (!expiryTime) {
throw Error('The subscription purchase does not have an expiry time');
}
const userCancellationTime =
purchase.data.canceledStateContext?.userInitiatedCancellation
?.cancelTime ?? null;
const autoRenewing = product.autoRenewingPlan?.autoRenewEnabled ?? false;
const testPurchase = purchase.data.testPurchase ? true : false;
const productId = product.productId;
if (!productId) {
throw Error('The product does not have an ID');
}
const basePlanId = product.offerDetails?.basePlanId;
if (!basePlanId) {
throw Error('Unable to determine the base plan for the product');
}
const subscription = await client.monetization.subscriptions.get({
packageName,
productId,
});
const basePlan = subscription.data.basePlans?.find(
(x) => x.basePlanId == basePlanId,
);
if (!basePlan) {
throw Error('Unable to determine the base plan for the product');
}
const billingPeriodDuration =
basePlan.autoRenewingBasePlanType?.billingPeriodDuration ??
basePlan.prepaidBasePlanType?.billingPeriodDuration;
if (!billingPeriodDuration) {
throw Error(
'Unable to determine a billing period duration for the base plan',
);
}
const offerId = product.offerDetails?.offerId ?? null;
const latestOrderId = purchase.data.latestOrderId;
if (!latestOrderId) {
throw Error(
'An order ID is expected to be associated with the purchase, but was not present',
);
}
const obfuscatedExternalAccountId =
purchase.data.externalAccountIdentifiers?.obfuscatedExternalAccountId ??
undefined;
return {
startTime: parseNullableDate(startTime),
expiryTime: new Date(expiryTime),
userCancellationTime: parseNullableDate(userCancellationTime),
autoRenewing,
// Map the product_id for test Feast purchases for easy identification downstream
productId: mapAndroidProductId(productId, packageName, testPurchase),
billingPeriodDuration,
freeTrial: isFreeTrial(offerId, latestOrderId),
testPurchase,
obfuscatedExternalAccountId,
rawResponse: purchase.data,
};
} catch (error: any) {
if (error?.status == 400 || error?.status == 404 || error?.status == 410) {
console.error(
`fetchGoogleSubscriptionV2 error: invalid purchase token; subscription not found; or no such package name (status = ${error.status})`,
error,
);
} else {
console.error(`fetchGoogleSubscriptionV2 error:`, error);
}
throw error;
}
}