Skip to content

Commit e5aacfd

Browse files
authored
feat(enh): only include obfuscatedProfileIdAndroid for new purchase (#3039)
Check if the subscription is `upgrade` and filter `obfuscatedProfileIdAndroid` field which is done in hyodotdev/openiap-google#13. ```kt val isUpgrade = !androidRequest.purchaseTokenAndroid.isNullOrEmpty() obfuscatedProfileIdAndroid = if (isUpgrade) null else androidRequest.obfuscatedProfileIdAndroid, ``` > Exact line: https://github.com/hyodotdev/openiap-google/blob/c7af9f04fbdeb42721315185d0e4ed3d8a056cfb/openiap/src/main/java/dev/hyo/openiap/OpenIapModule.kt#L309-L313 Add tests and example codes related to this. Resolve #3032 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Plan-change UI with upgrade/downgrade controls, current plan, expiry, auto-renew, and transaction display; added yearly subscription option. * **Documentation** * Simplified example links and note blocks for Purchase/Subscription/Available-Purchases/Offer-Code guides. * Updated API docs and guides to show useIAP invoked with onPurchaseSuccess/onPurchaseError callbacks (removing currentPurchase/currentPurchaseError examples). * **Tests** * Expanded subscription tests covering Android flows, ownership states, retries, connection transitions, modals, and logging. * **Chores** * Bumped a dependency patch version. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 5c00b99 commit e5aacfd

File tree

14 files changed

+1881
-1005
lines changed

14 files changed

+1881
-1005
lines changed

docs/docs/api/methods/listeners.md

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -379,19 +379,14 @@ For simpler usage, consider using the `useIAP` hook which automatically manages
379379
import {useIAP} from 'react-native-iap';
380380

381381
export default function StoreComponent() {
382-
const {currentPurchase, currentPurchaseError} = useIAP();
383-
384-
useEffect(() => {
385-
if (currentPurchase) {
386-
handlePurchaseUpdate(currentPurchase);
387-
}
388-
}, [currentPurchase]);
389-
390-
useEffect(() => {
391-
if (currentPurchaseError) {
392-
handlePurchaseError(currentPurchaseError);
393-
}
394-
}, [currentPurchaseError]);
382+
const {/* other props */} = useIAP({
383+
onPurchaseSuccess: async (purchase) => {
384+
await handlePurchaseUpdate(purchase);
385+
},
386+
onPurchaseError: (error) => {
387+
handlePurchaseError(error);
388+
},
389+
});
395390

396391
// Rest of component
397392
}

docs/docs/api/use-iap.md

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ import {useIAP} from 'react-native-iap';
2323
The `useIAP` hook follows React Hooks conventions and differs from calling functions directly from `react-native-iap` (index exports):
2424

2525
- **Automatic connection**: Automatically calls `initConnection` on mount and `endConnection` on unmount.
26-
- **Void-returning methods**: Methods like `fetchProducts`, `requestPurchase`, `getAvailablePurchases`, etc. return `Promise<void>` in the hook. They do not resolve to data. Instead, they update internal state exposed by the hook: `products`, `subscriptions`, `availablePurchases`, `currentPurchase`, etc.
27-
- **Don’t await for data**: When using the hook, do not write `const x = await fetchProducts(...)`. Call the method, then read the corresponding state from the hook.
28-
- **Prefer callbacks over `currentPurchase`**: `currentPurchase` was historically useful for debugging and migration, but for new code you should rely on `onPurchaseSuccess` and `onPurchaseError` options passed to `useIAP`.
26+
- **Void-returning methods**: Methods like `fetchProducts`, `requestPurchase`, `getAvailablePurchases`, etc. return `Promise<void>` in the hook. They do not resolve to data. Instead, they update internal state exposed by the hook: `products`, `subscriptions`, `availablePurchases`, etc.
27+
- **Don't await for data**: When using the hook, do not write `const x = await fetchProducts(...)`. Call the method, then read the corresponding state from the hook.
2928

3029
## Basic Usage
3130

@@ -35,8 +34,6 @@ const {
3534
products,
3635
subscriptions,
3736
availablePurchases,
38-
currentPurchase, // Debugging/migration friendly; prefer callbacks
39-
currentPurchaseError, // Debugging/migration friendly; prefer callbacks
4037
fetchProducts,
4138
requestPurchase,
4239
validateReceipt,
@@ -144,19 +141,6 @@ interface UseIAPOptions {
144141
));
145142
```
146143

147-
#### currentPurchase
148-
149-
- **Type**: `Purchase | null`
150-
- **Description**: Last purchase event captured by the hook. This value is primarily helpful for debugging and migration. For production flows, prefer handling purchase results via `onPurchaseSuccess` and errors via `onPurchaseError` passed to `useIAP`.
151-
- **Example (debug logging only)**:
152-
153-
```tsx
154-
useEffect(() => {
155-
if (currentPurchase) {
156-
console.log('Debug purchase event:', currentPurchase.id);
157-
}
158-
}, [currentPurchase]);
159-
```
160144

161145
#### currentPurchaseError
162146

@@ -235,7 +219,7 @@ interface UseIAPOptions {
235219
```tsx
236220
const buyProduct = async (productId: string) => {
237221
try {
238-
// In hook: returns void. Listen via callbacks or `currentPurchase`.
222+
// In hook: returns void. Listen via callbacks.
239223
await requestPurchase({
240224
request: {
241225
ios: {sku: productId},

docs/docs/examples/available-purchases.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import AdFitTopFixed from "@site/src/uis/AdFitTopFixed";
1010

1111
<AdFitTopFixed />
1212

13-
This example shows how to list and restore previously purchased items (non‑consumables and active subscriptions) using `getAvailablePurchases()` and `getActiveSubscriptions()`.
13+
This guide demonstrates how to list and restore previously purchased items (non‑consumables and active subscriptions) using `getAvailablePurchases()` and `getActiveSubscriptions()`.
1414

15-
View the full example source:
16-
17-
- GitHub: https://github.com/hyochan/react-native-iap/blob/main/example/app/available-purchases.tsx
15+
:::note
16+
The complete working example can be found at [example/screens/AvailablePurchases.tsx](https://github.com/hyochan/react-native-iap/blob/main/example/screens/AvailablePurchases.tsx). Note that the example code was heavily vibe-coded with Claude and is quite verbose/messy for demonstration purposes - use it as a reference only.
17+
:::
1818

1919
## Restore Flow
2020

docs/docs/examples/offer-code.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import AdFitTopFixed from "@site/src/uis/AdFitTopFixed";
1010

1111
<AdFitTopFixed />
1212

13-
Redeem App Store offer/promo codes using the native iOS sheet. This is useful for subscription promotional codes and requires a real iOS device.
13+
This guide demonstrates how to redeem App Store offer/promo codes using the native iOS sheet. This is useful for subscription promotional codes and requires a real iOS device.
1414

15-
View the full example source:
16-
17-
- GitHub: https://github.com/hyochan/react-native-iap/blob/main/example/app/offer-code.tsx
15+
:::note
16+
The complete working example can be found at [example/screens/OfferCode.tsx](https://github.com/hyochan/react-native-iap/blob/main/example/screens/OfferCode.tsx). Note that the example code was heavily vibe-coded with Claude and is quite verbose/messy for demonstration purposes - use it as a reference only.
17+
:::
1818

1919
## Usage
2020

docs/docs/examples/purchase-flow.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import AdFitTopFixed from "@site/src/uis/AdFitTopFixed";
1010

1111
<AdFitTopFixed />
1212

13-
This example walks through a clean purchase flow using react-native-iap with the `useIAP` hook and the new platform‑specific request shape. It mirrors the working sample in `example/app/purchase-flow.tsx`.
13+
This guide demonstrates a clean purchase flow using react-native-iap with the `useIAP` hook and the new platform‑specific request shape.
1414

15-
View the full example source:
16-
17-
- GitHub: [example/app/purchase-flow.tsx](https://github.com/hyochan/react-native-iap/blob/main/example/app/purchase-flow.tsx)
15+
:::note
16+
The complete working example can be found at [example/screens/PurchaseFlow.tsx](https://github.com/hyochan/react-native-iap/blob/main/example/screens/PurchaseFlow.tsx). Note that the example code was heavily vibe-coded with Claude and is quite verbose/messy for demonstration purposes - use it as a reference only.
17+
:::
1818

1919
## Flow Overview
2020

0 commit comments

Comments
 (0)