expo-iap 3.1.7 → 3.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +92 -0
- package/android/src/main/java/expo/modules/iap/ExpoIapHelper.kt +69 -2
- package/android/src/main/java/expo/modules/iap/ExpoIapModule.kt +62 -4
- package/build/index.d.ts +32 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +40 -15
- package/build/index.js.map +1 -1
- package/build/modules/android.d.ts +68 -0
- package/build/modules/android.d.ts.map +1 -1
- package/build/modules/android.js +74 -0
- package/build/modules/android.js.map +1 -1
- package/build/modules/ios.d.ts +23 -0
- package/build/modules/ios.d.ts.map +1 -1
- package/build/modules/ios.js +34 -3
- package/build/modules/ios.js.map +1 -1
- package/build/types.d.ts +116 -13
- package/build/types.d.ts.map +1 -1
- package/build/types.js.map +1 -1
- package/build/useIAP.d.ts +8 -0
- package/build/useIAP.d.ts.map +1 -1
- package/build/useIAP.js +11 -1
- package/build/useIAP.js.map +1 -1
- package/bun.lockb +0 -0
- package/coverage/clover.xml +258 -234
- package/coverage/coverage-final.json +3 -3
- package/coverage/lcov-report/index.html +27 -27
- package/coverage/lcov-report/src/helpers/index.html +1 -1
- package/coverage/lcov-report/src/helpers/subscription.ts.html +1 -1
- package/coverage/lcov-report/src/index.html +19 -19
- package/coverage/lcov-report/src/index.ts.html +136 -31
- package/coverage/lcov-report/src/modules/android.ts.html +257 -8
- package/coverage/lcov-report/src/modules/index.html +23 -23
- package/coverage/lcov-report/src/modules/ios.ts.html +137 -11
- package/coverage/lcov-report/src/utils/debug.ts.html +1 -1
- package/coverage/lcov-report/src/utils/errorMapping.ts.html +1 -1
- package/coverage/lcov-report/src/utils/index.html +1 -1
- package/coverage/lcov.info +473 -429
- package/ios/ExpoIapHelper.swift +4 -0
- package/ios/ExpoIapModule.swift +34 -2
- package/openiap-versions.json +3 -3
- package/package.json +1 -1
- package/plugin/build/withIAP.d.ts +26 -0
- package/plugin/build/withIAP.js +67 -3
- package/plugin/build/withLocalOpenIAP.d.ts +2 -0
- package/plugin/build/withLocalOpenIAP.js +7 -0
- package/plugin/src/withIAP.ts +141 -3
- package/plugin/src/withLocalOpenIAP.ts +14 -4
- package/plugin/tsconfig.tsbuildinfo +1 -1
- package/src/index.ts +49 -14
- package/src/modules/android.ts +83 -0
- package/src/modules/ios.ts +45 -3
- package/src/types.ts +124 -13
- package/src/useIAP.ts +26 -1
package/src/modules/ios.ts
CHANGED
|
@@ -6,6 +6,8 @@ import ExpoIapModule from '../ExpoIapModule';
|
|
|
6
6
|
|
|
7
7
|
// Types
|
|
8
8
|
import type {
|
|
9
|
+
ExternalPurchaseLinkResultIOS,
|
|
10
|
+
ExternalPurchaseNoticeResultIOS,
|
|
9
11
|
MutationField,
|
|
10
12
|
ProductIOS,
|
|
11
13
|
Purchase,
|
|
@@ -49,7 +51,7 @@ export function isProductIOS<T extends {platform?: string}>(
|
|
|
49
51
|
* @platform iOS
|
|
50
52
|
*/
|
|
51
53
|
export const syncIOS: MutationField<'syncIOS'> = async () => {
|
|
52
|
-
return
|
|
54
|
+
return !!(await ExpoIapModule.syncIOS());
|
|
53
55
|
};
|
|
54
56
|
|
|
55
57
|
/**
|
|
@@ -264,7 +266,7 @@ export const validateReceiptIOS =
|
|
|
264
266
|
export const presentCodeRedemptionSheetIOS: MutationField<
|
|
265
267
|
'presentCodeRedemptionSheetIOS'
|
|
266
268
|
> = async () => {
|
|
267
|
-
return
|
|
269
|
+
return !!(await ExpoIapModule.presentCodeRedemptionSheetIOS());
|
|
268
270
|
};
|
|
269
271
|
|
|
270
272
|
/**
|
|
@@ -342,7 +344,7 @@ export const getPendingTransactionsIOS: QueryField<
|
|
|
342
344
|
export const clearTransactionIOS: MutationField<
|
|
343
345
|
'clearTransactionIOS'
|
|
344
346
|
> = async () => {
|
|
345
|
-
return
|
|
347
|
+
return !!(await ExpoIapModule.clearTransactionIOS());
|
|
346
348
|
};
|
|
347
349
|
|
|
348
350
|
/**
|
|
@@ -354,4 +356,44 @@ export const clearTransactionIOS: MutationField<
|
|
|
354
356
|
export const deepLinkToSubscriptionsIOS = (): Promise<void> =>
|
|
355
357
|
Linking.openURL('https://apps.apple.com/account/subscriptions');
|
|
356
358
|
|
|
359
|
+
/**
|
|
360
|
+
* Check if the device can present an external purchase notice sheet (iOS 18.2+).
|
|
361
|
+
*
|
|
362
|
+
* @returns Promise resolving to true if the notice sheet can be presented
|
|
363
|
+
* @platform iOS
|
|
364
|
+
*/
|
|
365
|
+
export const canPresentExternalPurchaseNoticeIOS: QueryField<
|
|
366
|
+
'canPresentExternalPurchaseNoticeIOS'
|
|
367
|
+
> = async () => {
|
|
368
|
+
return !!(await ExpoIapModule.canPresentExternalPurchaseNoticeIOS());
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Present an external purchase notice sheet to inform users about external purchases (iOS 18.2+).
|
|
373
|
+
* This must be called before opening an external purchase link.
|
|
374
|
+
*
|
|
375
|
+
* @returns Promise resolving to the result with action and error if any
|
|
376
|
+
* @platform iOS
|
|
377
|
+
*/
|
|
378
|
+
export const presentExternalPurchaseNoticeSheetIOS: MutationField<
|
|
379
|
+
'presentExternalPurchaseNoticeSheetIOS'
|
|
380
|
+
> = async () => {
|
|
381
|
+
const result = await ExpoIapModule.presentExternalPurchaseNoticeSheetIOS();
|
|
382
|
+
return result as ExternalPurchaseNoticeResultIOS;
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Present an external purchase link to redirect users to your website (iOS 16.0+).
|
|
387
|
+
*
|
|
388
|
+
* @param url - The external purchase URL to open
|
|
389
|
+
* @returns Promise resolving to the result with success status and error if any
|
|
390
|
+
* @platform iOS
|
|
391
|
+
*/
|
|
392
|
+
export const presentExternalPurchaseLinkIOS: MutationField<
|
|
393
|
+
'presentExternalPurchaseLinkIOS'
|
|
394
|
+
> = async (url: string) => {
|
|
395
|
+
const result = await ExpoIapModule.presentExternalPurchaseLinkIOS(url);
|
|
396
|
+
return result as ExternalPurchaseLinkResultIOS;
|
|
397
|
+
};
|
|
398
|
+
|
|
357
399
|
// iOS-specific APIs only; cross-platform wrappers live in src/index.ts
|
package/src/types.ts
CHANGED
|
@@ -5,17 +5,33 @@
|
|
|
5
5
|
|
|
6
6
|
export interface ActiveSubscription {
|
|
7
7
|
autoRenewingAndroid?: (boolean | null);
|
|
8
|
+
basePlanIdAndroid?: (string | null);
|
|
9
|
+
/**
|
|
10
|
+
* The current plan identifier. This is:
|
|
11
|
+
* - On Android: the basePlanId (e.g., "premium", "premium-year")
|
|
12
|
+
* - On iOS: the productId (e.g., "com.example.premium_monthly", "com.example.premium_yearly")
|
|
13
|
+
* This provides a unified way to identify which specific plan/tier the user is subscribed to.
|
|
14
|
+
*/
|
|
15
|
+
currentPlanId?: (string | null);
|
|
8
16
|
daysUntilExpirationIOS?: (number | null);
|
|
9
17
|
environmentIOS?: (string | null);
|
|
10
18
|
expirationDateIOS?: (number | null);
|
|
11
19
|
isActive: boolean;
|
|
12
20
|
productId: string;
|
|
13
21
|
purchaseToken?: (string | null);
|
|
22
|
+
/** Required for subscription upgrade/downgrade on Android */
|
|
23
|
+
purchaseTokenAndroid?: (string | null);
|
|
14
24
|
transactionDate: number;
|
|
15
25
|
transactionId: string;
|
|
16
26
|
willExpireSoon?: (boolean | null);
|
|
17
27
|
}
|
|
18
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Alternative billing mode for Android
|
|
31
|
+
* Controls which billing system is used
|
|
32
|
+
*/
|
|
33
|
+
export type AlternativeBillingModeAndroid = 'none' | 'user-choice' | 'alternative-only';
|
|
34
|
+
|
|
19
35
|
export interface AndroidSubscriptionOfferInput {
|
|
20
36
|
/** Offer token */
|
|
21
37
|
offerToken: string;
|
|
@@ -126,21 +142,67 @@ export enum ErrorCode {
|
|
|
126
142
|
UserError = 'user-error'
|
|
127
143
|
}
|
|
128
144
|
|
|
145
|
+
/** Result of presenting an external purchase link (iOS 18.2+) */
|
|
146
|
+
export interface ExternalPurchaseLinkResultIOS {
|
|
147
|
+
/** Optional error message if the presentation failed */
|
|
148
|
+
error?: (string | null);
|
|
149
|
+
/** Whether the user completed the external purchase flow */
|
|
150
|
+
success: boolean;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** User actions on external purchase notice sheet (iOS 18.2+) */
|
|
154
|
+
export type ExternalPurchaseNoticeAction = 'continue' | 'dismissed';
|
|
155
|
+
|
|
156
|
+
/** Result of presenting external purchase notice sheet (iOS 18.2+) */
|
|
157
|
+
export interface ExternalPurchaseNoticeResultIOS {
|
|
158
|
+
/** Optional error message if the presentation failed */
|
|
159
|
+
error?: (string | null);
|
|
160
|
+
/** Notice result indicating user action */
|
|
161
|
+
result: ExternalPurchaseNoticeAction;
|
|
162
|
+
}
|
|
163
|
+
|
|
129
164
|
export type FetchProductsResult = Product[] | ProductSubscription[] | null;
|
|
130
165
|
|
|
131
|
-
export type IapEvent = 'purchase-updated' | 'purchase-error' | 'promoted-product-ios';
|
|
166
|
+
export type IapEvent = 'purchase-updated' | 'purchase-error' | 'promoted-product-ios' | 'user-choice-billing-android';
|
|
132
167
|
|
|
133
168
|
export type IapPlatform = 'ios' | 'android';
|
|
134
169
|
|
|
170
|
+
/** Connection initialization configuration */
|
|
171
|
+
export interface InitConnectionConfig {
|
|
172
|
+
/**
|
|
173
|
+
* Alternative billing mode for Android
|
|
174
|
+
* If not specified, defaults to NONE (standard Google Play billing)
|
|
175
|
+
*/
|
|
176
|
+
alternativeBillingModeAndroid?: (AlternativeBillingModeAndroid | null);
|
|
177
|
+
}
|
|
178
|
+
|
|
135
179
|
export interface Mutation {
|
|
136
180
|
/** Acknowledge a non-consumable purchase or subscription */
|
|
137
181
|
acknowledgePurchaseAndroid: Promise<boolean>;
|
|
138
182
|
/** Initiate a refund request for a product (iOS 15+) */
|
|
139
183
|
beginRefundRequestIOS?: Promise<(string | null)>;
|
|
184
|
+
/**
|
|
185
|
+
* Check if alternative billing is available for this user/device
|
|
186
|
+
* Step 1 of alternative billing flow
|
|
187
|
+
*
|
|
188
|
+
* Returns true if available, false otherwise
|
|
189
|
+
* Throws OpenIapError.NotPrepared if billing client not ready
|
|
190
|
+
*/
|
|
191
|
+
checkAlternativeBillingAvailabilityAndroid: Promise<boolean>;
|
|
140
192
|
/** Clear pending transactions from the StoreKit payment queue */
|
|
141
193
|
clearTransactionIOS: Promise<boolean>;
|
|
142
194
|
/** Consume a purchase token so it can be repurchased */
|
|
143
195
|
consumePurchaseAndroid: Promise<boolean>;
|
|
196
|
+
/**
|
|
197
|
+
* Create external transaction token for Google Play reporting
|
|
198
|
+
* Step 3 of alternative billing flow
|
|
199
|
+
* Must be called AFTER successful payment in your payment system
|
|
200
|
+
* Token must be reported to Google Play backend within 24 hours
|
|
201
|
+
*
|
|
202
|
+
* Returns token string, or null if creation failed
|
|
203
|
+
* Throws OpenIapError.NotPrepared if billing client not ready
|
|
204
|
+
*/
|
|
205
|
+
createAlternativeBillingTokenAndroid?: Promise<(string | null)>;
|
|
144
206
|
/** Open the native subscription management surface */
|
|
145
207
|
deepLinkToSubscriptions: Promise<void>;
|
|
146
208
|
/** Close the platform billing connection */
|
|
@@ -151,12 +213,25 @@ export interface Mutation {
|
|
|
151
213
|
initConnection: Promise<boolean>;
|
|
152
214
|
/** Present the App Store code redemption sheet */
|
|
153
215
|
presentCodeRedemptionSheetIOS: Promise<boolean>;
|
|
216
|
+
/** Present external purchase custom link with StoreKit UI (iOS 18.2+) */
|
|
217
|
+
presentExternalPurchaseLinkIOS: Promise<ExternalPurchaseLinkResultIOS>;
|
|
218
|
+
/** Present external purchase notice sheet (iOS 18.2+) */
|
|
219
|
+
presentExternalPurchaseNoticeSheetIOS: Promise<ExternalPurchaseNoticeResultIOS>;
|
|
154
220
|
/** Initiate a purchase flow; rely on events for final state */
|
|
155
221
|
requestPurchase?: Promise<(Purchase | Purchase[] | null)>;
|
|
156
222
|
/** Purchase the promoted product surfaced by the App Store */
|
|
157
223
|
requestPurchaseOnPromotedProductIOS: Promise<boolean>;
|
|
158
224
|
/** Restore completed purchases across platforms */
|
|
159
225
|
restorePurchases: Promise<void>;
|
|
226
|
+
/**
|
|
227
|
+
* Show alternative billing information dialog to user
|
|
228
|
+
* Step 2 of alternative billing flow
|
|
229
|
+
* Must be called BEFORE processing payment in your payment system
|
|
230
|
+
*
|
|
231
|
+
* Returns true if user accepted, false if user canceled
|
|
232
|
+
* Throws OpenIapError.NotPrepared if billing client not ready
|
|
233
|
+
*/
|
|
234
|
+
showAlternativeBillingDialogAndroid: Promise<boolean>;
|
|
160
235
|
/** Open subscription management UI and return changed purchases (iOS 15+) */
|
|
161
236
|
showManageSubscriptionsIOS: Promise<PurchaseIOS[]>;
|
|
162
237
|
/** Force a StoreKit sync for transactions (iOS 15+) */
|
|
@@ -181,16 +256,24 @@ export interface MutationFinishTransactionArgs {
|
|
|
181
256
|
}
|
|
182
257
|
|
|
183
258
|
|
|
259
|
+
export type MutationInitConnectionArgs = (InitConnectionConfig | null) | undefined;
|
|
260
|
+
|
|
261
|
+
export type MutationPresentExternalPurchaseLinkIosArgs = string;
|
|
262
|
+
|
|
184
263
|
export type MutationRequestPurchaseArgs =
|
|
185
264
|
| {
|
|
186
265
|
/** Per-platform purchase request props */
|
|
187
266
|
request: RequestPurchasePropsByPlatforms;
|
|
188
267
|
type: 'in-app';
|
|
268
|
+
/** Use alternative billing (Google Play alternative billing, Apple external purchase link) */
|
|
269
|
+
useAlternativeBilling?: boolean | null;
|
|
189
270
|
}
|
|
190
271
|
| {
|
|
191
272
|
/** Per-platform subscription request props */
|
|
192
273
|
request: RequestSubscriptionPropsByPlatforms;
|
|
193
274
|
type: 'subs';
|
|
275
|
+
/** Use alternative billing (Google Play alternative billing, Apple external purchase link) */
|
|
276
|
+
useAlternativeBilling?: boolean | null;
|
|
194
277
|
};
|
|
195
278
|
|
|
196
279
|
|
|
@@ -333,6 +416,7 @@ export type Purchase = PurchaseAndroid | PurchaseIOS;
|
|
|
333
416
|
|
|
334
417
|
export interface PurchaseAndroid extends PurchaseCommon {
|
|
335
418
|
autoRenewingAndroid?: (boolean | null);
|
|
419
|
+
currentPlanId?: (string | null);
|
|
336
420
|
dataAndroid?: (string | null);
|
|
337
421
|
developerPayloadAndroid?: (string | null);
|
|
338
422
|
id: string;
|
|
@@ -353,6 +437,13 @@ export interface PurchaseAndroid extends PurchaseCommon {
|
|
|
353
437
|
}
|
|
354
438
|
|
|
355
439
|
export interface PurchaseCommon {
|
|
440
|
+
/**
|
|
441
|
+
* The current plan identifier. This is:
|
|
442
|
+
* - On Android: the basePlanId (e.g., "premium", "premium-year")
|
|
443
|
+
* - On iOS: the productId (e.g., "com.example.premium_monthly", "com.example.premium_yearly")
|
|
444
|
+
* This provides a unified way to identify which specific plan/tier the user is subscribed to.
|
|
445
|
+
*/
|
|
446
|
+
currentPlanId?: (string | null);
|
|
356
447
|
id: string;
|
|
357
448
|
ids?: (string[] | null);
|
|
358
449
|
isAutoRenewing: boolean;
|
|
@@ -377,6 +468,7 @@ export interface PurchaseIOS extends PurchaseCommon {
|
|
|
377
468
|
countryCodeIOS?: (string | null);
|
|
378
469
|
currencyCodeIOS?: (string | null);
|
|
379
470
|
currencySymbolIOS?: (string | null);
|
|
471
|
+
currentPlanId?: (string | null);
|
|
380
472
|
environmentIOS?: (string | null);
|
|
381
473
|
expirationDateIOS?: (number | null);
|
|
382
474
|
id: string;
|
|
@@ -405,17 +497,7 @@ export interface PurchaseIOS extends PurchaseCommon {
|
|
|
405
497
|
webOrderLineItemIdIOS?: (string | null);
|
|
406
498
|
}
|
|
407
499
|
|
|
408
|
-
export
|
|
409
|
-
id: string;
|
|
410
|
-
ids?: (string[] | null);
|
|
411
|
-
isAutoRenewing: boolean;
|
|
412
|
-
platform: IapPlatform;
|
|
413
|
-
productId: string;
|
|
414
|
-
purchaseState: PurchaseState;
|
|
415
|
-
purchaseToken?: (string | null);
|
|
416
|
-
quantity: number;
|
|
417
|
-
transactionDate: number;
|
|
418
|
-
}
|
|
500
|
+
export type PurchaseInput = Purchase;
|
|
419
501
|
|
|
420
502
|
export interface PurchaseOfferIOS {
|
|
421
503
|
id: string;
|
|
@@ -433,6 +515,8 @@ export interface PurchaseOptions {
|
|
|
433
515
|
export type PurchaseState = 'pending' | 'purchased' | 'failed' | 'restored' | 'deferred' | 'unknown';
|
|
434
516
|
|
|
435
517
|
export interface Query {
|
|
518
|
+
/** Check if external purchase notice sheet can be presented (iOS 18.2+) */
|
|
519
|
+
canPresentExternalPurchaseNoticeIOS: Promise<boolean>;
|
|
436
520
|
/** Get current StoreKit 2 entitlements (iOS 15+) */
|
|
437
521
|
currentEntitlementIOS?: Promise<(PurchaseIOS | null)>;
|
|
438
522
|
/** Retrieve products or subscriptions from the store */
|
|
@@ -584,11 +668,15 @@ export type RequestPurchaseProps =
|
|
|
584
668
|
/** Per-platform purchase request props */
|
|
585
669
|
request: RequestPurchasePropsByPlatforms;
|
|
586
670
|
type: 'in-app';
|
|
671
|
+
/** Use alternative billing (Google Play alternative billing, Apple external purchase link) */
|
|
672
|
+
useAlternativeBilling?: boolean | null;
|
|
587
673
|
}
|
|
588
674
|
| {
|
|
589
675
|
/** Per-platform subscription request props */
|
|
590
676
|
request: RequestSubscriptionPropsByPlatforms;
|
|
591
677
|
type: 'subs';
|
|
678
|
+
/** Use alternative billing (Google Play alternative billing, Apple external purchase link) */
|
|
679
|
+
useAlternativeBilling?: boolean | null;
|
|
592
680
|
};
|
|
593
681
|
|
|
594
682
|
export interface RequestPurchasePropsByPlatforms {
|
|
@@ -639,6 +727,11 @@ export interface Subscription {
|
|
|
639
727
|
purchaseError: PurchaseError;
|
|
640
728
|
/** Fires when a purchase completes successfully or a pending purchase resolves */
|
|
641
729
|
purchaseUpdated: Purchase;
|
|
730
|
+
/**
|
|
731
|
+
* Fires when a user selects alternative billing in the User Choice Billing dialog (Android only)
|
|
732
|
+
* Only triggered when the user selects alternative billing instead of Google Play billing
|
|
733
|
+
*/
|
|
734
|
+
userChoiceBillingAndroid: UserChoiceBillingDetails;
|
|
642
735
|
}
|
|
643
736
|
|
|
644
737
|
|
|
@@ -673,10 +766,22 @@ export interface SubscriptionStatusIOS {
|
|
|
673
766
|
state: string;
|
|
674
767
|
}
|
|
675
768
|
|
|
769
|
+
/**
|
|
770
|
+
* User Choice Billing event details (Android)
|
|
771
|
+
* Fired when a user selects alternative billing in the User Choice Billing dialog
|
|
772
|
+
*/
|
|
773
|
+
export interface UserChoiceBillingDetails {
|
|
774
|
+
/** Token that must be reported to Google Play within 24 hours */
|
|
775
|
+
externalTransactionToken: string;
|
|
776
|
+
/** List of product IDs selected by the user */
|
|
777
|
+
products: string[];
|
|
778
|
+
}
|
|
779
|
+
|
|
676
780
|
export type VoidResult = void;
|
|
677
781
|
|
|
678
782
|
// -- Query helper types (auto-generated)
|
|
679
783
|
export type QueryArgsMap = {
|
|
784
|
+
canPresentExternalPurchaseNoticeIOS: never;
|
|
680
785
|
currentEntitlementIOS: QueryCurrentEntitlementIosArgs;
|
|
681
786
|
fetchProducts: QueryFetchProductsArgs;
|
|
682
787
|
getActiveSubscriptions: QueryGetActiveSubscriptionsArgs;
|
|
@@ -712,16 +817,21 @@ export type QueryFieldMap = {
|
|
|
712
817
|
export type MutationArgsMap = {
|
|
713
818
|
acknowledgePurchaseAndroid: MutationAcknowledgePurchaseAndroidArgs;
|
|
714
819
|
beginRefundRequestIOS: MutationBeginRefundRequestIosArgs;
|
|
820
|
+
checkAlternativeBillingAvailabilityAndroid: never;
|
|
715
821
|
clearTransactionIOS: never;
|
|
716
822
|
consumePurchaseAndroid: MutationConsumePurchaseAndroidArgs;
|
|
823
|
+
createAlternativeBillingTokenAndroid: never;
|
|
717
824
|
deepLinkToSubscriptions: MutationDeepLinkToSubscriptionsArgs;
|
|
718
825
|
endConnection: never;
|
|
719
826
|
finishTransaction: MutationFinishTransactionArgs;
|
|
720
|
-
initConnection:
|
|
827
|
+
initConnection: MutationInitConnectionArgs;
|
|
721
828
|
presentCodeRedemptionSheetIOS: never;
|
|
829
|
+
presentExternalPurchaseLinkIOS: MutationPresentExternalPurchaseLinkIosArgs;
|
|
830
|
+
presentExternalPurchaseNoticeSheetIOS: never;
|
|
722
831
|
requestPurchase: MutationRequestPurchaseArgs;
|
|
723
832
|
requestPurchaseOnPromotedProductIOS: never;
|
|
724
833
|
restorePurchases: never;
|
|
834
|
+
showAlternativeBillingDialogAndroid: never;
|
|
725
835
|
showManageSubscriptionsIOS: never;
|
|
726
836
|
syncIOS: never;
|
|
727
837
|
validateReceipt: MutationValidateReceiptArgs;
|
|
@@ -744,6 +854,7 @@ export type SubscriptionArgsMap = {
|
|
|
744
854
|
promotedProductIOS: never;
|
|
745
855
|
purchaseError: never;
|
|
746
856
|
purchaseUpdated: never;
|
|
857
|
+
userChoiceBillingAndroid: never;
|
|
747
858
|
};
|
|
748
859
|
|
|
749
860
|
export type SubscriptionField<K extends keyof Subscription> =
|
package/src/useIAP.ts
CHANGED
|
@@ -26,6 +26,11 @@ import {
|
|
|
26
26
|
requestPurchaseOnPromotedProductIOS,
|
|
27
27
|
syncIOS,
|
|
28
28
|
} from './modules/ios';
|
|
29
|
+
import {
|
|
30
|
+
checkAlternativeBillingAvailabilityAndroid,
|
|
31
|
+
showAlternativeBillingDialogAndroid,
|
|
32
|
+
createAlternativeBillingTokenAndroid,
|
|
33
|
+
} from './modules/android';
|
|
29
34
|
|
|
30
35
|
// Types
|
|
31
36
|
import type {
|
|
@@ -80,12 +85,22 @@ type UseIap = {
|
|
|
80
85
|
requestPurchaseOnPromotedProductIOS: () => Promise<boolean>;
|
|
81
86
|
getActiveSubscriptions: (subscriptionIds?: string[]) => Promise<void>;
|
|
82
87
|
hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise<boolean>;
|
|
88
|
+
checkAlternativeBillingAvailabilityAndroid: () => Promise<boolean>;
|
|
89
|
+
showAlternativeBillingDialogAndroid: () => Promise<boolean>;
|
|
90
|
+
createAlternativeBillingTokenAndroid: (
|
|
91
|
+
sku?: string,
|
|
92
|
+
) => Promise<string | null>;
|
|
83
93
|
};
|
|
84
94
|
|
|
85
95
|
export interface UseIAPOptions {
|
|
86
96
|
onPurchaseSuccess?: (purchase: Purchase) => void;
|
|
87
97
|
onPurchaseError?: (error: PurchaseError) => void;
|
|
88
98
|
onPromotedProductIOS?: (product: Product) => void;
|
|
99
|
+
/**
|
|
100
|
+
* Alternative billing mode for Android
|
|
101
|
+
* If not specified, defaults to NONE (standard Google Play billing)
|
|
102
|
+
*/
|
|
103
|
+
alternativeBillingModeAndroid?: 'none' | 'user-choice' | 'alternative-only';
|
|
89
104
|
}
|
|
90
105
|
|
|
91
106
|
/**
|
|
@@ -419,7 +434,13 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
419
434
|
}
|
|
420
435
|
|
|
421
436
|
// NOW call initConnection after listeners are ready
|
|
422
|
-
const
|
|
437
|
+
const config = optionsRef.current?.alternativeBillingModeAndroid
|
|
438
|
+
? {
|
|
439
|
+
alternativeBillingModeAndroid:
|
|
440
|
+
optionsRef.current.alternativeBillingModeAndroid,
|
|
441
|
+
}
|
|
442
|
+
: undefined;
|
|
443
|
+
const result = await initConnection(config);
|
|
423
444
|
setConnected(result);
|
|
424
445
|
if (!result) {
|
|
425
446
|
// If connection failed, clean up listeners
|
|
@@ -466,5 +487,9 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
466
487
|
requestPurchaseOnPromotedProductIOS,
|
|
467
488
|
getActiveSubscriptions: getActiveSubscriptionsInternal,
|
|
468
489
|
hasActiveSubscriptions: hasActiveSubscriptionsInternal,
|
|
490
|
+
// Alternative billing methods (Android only)
|
|
491
|
+
checkAlternativeBillingAvailabilityAndroid,
|
|
492
|
+
showAlternativeBillingDialogAndroid,
|
|
493
|
+
createAlternativeBillingTokenAndroid,
|
|
469
494
|
};
|
|
470
495
|
}
|