Let the store take PRO back, and finish every purchase
This commit is contained in:
+18
-1
@@ -50,6 +50,11 @@ const grant = async () => {
|
||||
await AsyncStorage.setItem(CACHE_KEY, '1').catch(() => {});
|
||||
};
|
||||
|
||||
const revoke = async () => {
|
||||
set({ owned: false, error: null });
|
||||
await AsyncStorage.removeItem(CACHE_KEY).catch(() => {});
|
||||
};
|
||||
|
||||
// Play hands the purchase to the listener. Grant it, then finalise: an Android
|
||||
// purchase left unacknowledged for three days is automatically refunded.
|
||||
// ponytail: the grant is client-side. Server-side verification of
|
||||
@@ -80,7 +85,19 @@ export async function initProUnlock() {
|
||||
]);
|
||||
const listed = (Array.isArray(products) ? products : []).find((p) => p.id === PRO_SKU);
|
||||
set({ price: listed?.displayPrice ?? null });
|
||||
if (purchases.some((p) => p.productId === PRO_SKU)) await grant();
|
||||
const bought = purchases.find((p) => p.productId === PRO_SKU);
|
||||
if (bought) {
|
||||
await grant();
|
||||
// A purchase Play never got from us finalised (the app was killed between
|
||||
// the two) is refunded automatically after three days. Harmless to repeat.
|
||||
await finishTransaction({ purchase: bought as never, isConsumable: false }).catch(() => {});
|
||||
} else if (listed) {
|
||||
// The store is the authority: a refunded purchase is no longer in the
|
||||
// list, so the cache must not outlive it. Only when the query ANSWERED and
|
||||
// the product is still on sale — an offline or broken query also returns
|
||||
// nothing, and that must never revoke a paying user.
|
||||
await revoke();
|
||||
}
|
||||
} catch (e) {
|
||||
set({ error: e instanceof Error ? e.message : 'Store unavailable' });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user