expo-iap 2.2.0 → 2.2.1
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/build/ExpoIap.types.d.ts.map +1 -1
- package/build/ExpoIap.types.js.map +1 -1
- package/build/index.d.ts +2 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +12 -10
- package/build/index.js.map +1 -1
- package/build/useIap.d.ts.map +1 -1
- package/build/useIap.js +2 -1
- package/build/useIap.js.map +1 -1
- package/iap.md +399 -93
- package/package.json +1 -1
- package/src/ExpoIap.types.ts +1 -1
- package/src/index.ts +11 -36
- package/src/useIap.ts +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoIap.types.d.ts","sourceRoot":"","sources":["../src/ExpoIap.types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,2BAA2B,EAC3B,+BAA+B,EAC/B,0BAA0B,EAC3B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,uBAAuB,EACvB,2BAA2B,EAC3B,sBAAsB,EACvB,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,WAAW,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAGF,MAAM,MAAM,WAAW,GAAG;IAAC,QAAQ,EAAE,KAAK,CAAA;CAAC,CAAC;AAC5C,MAAM,MAAM,eAAe,GAAG;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAC,CAAC;AAEpD,oBAAY,WAAW;IACrB,aAAa,UAAU;IACvB,YAAY,SAAS;CACtB;AAGD,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAGF,MAAM,MAAM,OAAO,GACf,CAAC,cAAc,GAAG,eAAe,CAAC,GAClC,CAAC,UAAU,GAAG,WAAW,CAAC,CAAC;AAG/B,MAAM,MAAM,eAAe,GACvB,CAAC,sBAAsB,GAAG,eAAe,CAAC,GAC1C,CAAC,kBAAkB,GAAG,WAAW,CAAC,CAAC;AAGvC,MAAM,MAAM,oBAAoB,GAC5B,CAAC,sBAAsB,GAAG,eAAe,GAAG;
|
|
1
|
+
{"version":3,"file":"ExpoIap.types.d.ts","sourceRoot":"","sources":["../src/ExpoIap.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoIap.types.js","sourceRoot":"","sources":["../src/ExpoIap.types.ts"],"names":[],"mappings":"AAqCA,MAAM,CAAN,IAAY,WAGX;AAHD,WAAY,WAAW;IACrB,sCAAuB,CAAA;IACvB,oCAAqB,CAAA;AACvB,CAAC,EAHW,WAAW,KAAX,WAAW,QAGtB;AAgDD,MAAM,CAAN,IAAY,SAkBX;AAlBD,WAAY,SAAS;IACnB,oCAAuB,CAAA;IACvB,kDAAqC,CAAA;IACrC,0CAA6B,CAAA;IAC7B,sDAAyC,CAAA;IACzC,8CAAiC,CAAA;IACjC,gDAAmC,CAAA;IACnC,gDAAmC,CAAA;IACnC,kDAAqC,CAAA;IACrC,oEAAuD,CAAA;IACvD,8CAAiC,CAAA;IACjC,wCAA2B,CAAA;IAC3B,gDAAmC,CAAA;IACnC,oDAAuC,CAAA;IACvC,wFAA2E,CAAA;IAC3E,sDAAyC,CAAA;IACzC,4CAA+B,CAAA;IAC/B,wDAA2C,CAAA;AAC7C,CAAC,EAlBW,SAAS,KAAT,SAAS,QAkBpB;AAED,MAAM,OAAO,aAAa;IAEf;IACA;IACA;IACA;IACA;IACA;IANT,YACS,IAAY,EACZ,OAAe,EACf,YAAqB,EACrB,YAAqB,EACrB,IAAgB,EAChB,SAAkB;QALlB,SAAI,GAAJ,IAAI,CAAQ;QACZ,YAAO,GAAP,OAAO,CAAQ;QACf,iBAAY,GAAZ,YAAY,CAAS;QACrB,iBAAY,GAAZ,YAAY,CAAS;QACrB,SAAI,GAAJ,IAAI,CAAY;QAChB,cAAS,GAAT,SAAS,CAAS;QAEzB,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF","sourcesContent":["import {\n ProductAndroid,\n ProductPurchaseAndroid,\n RequestPurchaseAndroidProps,\n RequestSubscriptionAndroidProps,\n SubscriptionProductAndroid,\n} from './types/ExpoIapAndroid.types';\nimport {\n ProductIos,\n ProductPurchaseIos,\n RequestPurchaseIosProps,\n RequestSubscriptionIosProps,\n SubscriptionProductIos,\n} from './types/ExpoIapIos.types';\n\nexport type ChangeEventPayload = {\n value: string;\n};\n\n/**\n * Base product type with common properties shared between iOS and Android\n */\nexport type ProductBase = {\n id: string;\n title: string;\n description: string;\n type: ProductType;\n displayName?: string;\n displayPrice?: string;\n price?: number;\n currency?: string;\n};\n\n// Define literal platform types for better type discrimination\nexport type IosPlatform = {platform: 'ios'};\nexport type AndroidPlatform = {platform: 'android'};\n\nexport enum ProductType {\n InAppPurchase = 'inapp',\n Subscription = 'subs',\n}\n\n// Common base purchase type\nexport type PurchaseBase = {\n id: string;\n transactionId?: string;\n transactionDate: number;\n transactionReceipt: string;\n purchaseToken?: string;\n};\n\n// Union type for platform-specific product types with proper discriminators\nexport type Product =\n | (ProductAndroid & AndroidPlatform)\n | (ProductIos & IosPlatform);\n\n// Union type for platform-specific purchase types with proper discriminators\nexport type ProductPurchase =\n | (ProductPurchaseAndroid & AndroidPlatform)\n | (ProductPurchaseIos & IosPlatform);\n\n// Union type for platform-specific subscription purchase types with proper discriminators\nexport type SubscriptionPurchase =\n | (ProductPurchaseAndroid & AndroidPlatform & {
|
|
1
|
+
{"version":3,"file":"ExpoIap.types.js","sourceRoot":"","sources":["../src/ExpoIap.types.ts"],"names":[],"mappings":"AAqCA,MAAM,CAAN,IAAY,WAGX;AAHD,WAAY,WAAW;IACrB,sCAAuB,CAAA;IACvB,oCAAqB,CAAA;AACvB,CAAC,EAHW,WAAW,KAAX,WAAW,QAGtB;AAgDD,MAAM,CAAN,IAAY,SAkBX;AAlBD,WAAY,SAAS;IACnB,oCAAuB,CAAA;IACvB,kDAAqC,CAAA;IACrC,0CAA6B,CAAA;IAC7B,sDAAyC,CAAA;IACzC,8CAAiC,CAAA;IACjC,gDAAmC,CAAA;IACnC,gDAAmC,CAAA;IACnC,kDAAqC,CAAA;IACrC,oEAAuD,CAAA;IACvD,8CAAiC,CAAA;IACjC,wCAA2B,CAAA;IAC3B,gDAAmC,CAAA;IACnC,oDAAuC,CAAA;IACvC,wFAA2E,CAAA;IAC3E,sDAAyC,CAAA;IACzC,4CAA+B,CAAA;IAC/B,wDAA2C,CAAA;AAC7C,CAAC,EAlBW,SAAS,KAAT,SAAS,QAkBpB;AAED,MAAM,OAAO,aAAa;IAEf;IACA;IACA;IACA;IACA;IACA;IANT,YACS,IAAY,EACZ,OAAe,EACf,YAAqB,EACrB,YAAqB,EACrB,IAAgB,EAChB,SAAkB;QALlB,SAAI,GAAJ,IAAI,CAAQ;QACZ,YAAO,GAAP,OAAO,CAAQ;QACf,iBAAY,GAAZ,YAAY,CAAS;QACrB,iBAAY,GAAZ,YAAY,CAAS;QACrB,SAAI,GAAJ,IAAI,CAAY;QAChB,cAAS,GAAT,SAAS,CAAS;QAEzB,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF","sourcesContent":["import {\n ProductAndroid,\n ProductPurchaseAndroid,\n RequestPurchaseAndroidProps,\n RequestSubscriptionAndroidProps,\n SubscriptionProductAndroid,\n} from './types/ExpoIapAndroid.types';\nimport {\n ProductIos,\n ProductPurchaseIos,\n RequestPurchaseIosProps,\n RequestSubscriptionIosProps,\n SubscriptionProductIos,\n} from './types/ExpoIapIos.types';\n\nexport type ChangeEventPayload = {\n value: string;\n};\n\n/**\n * Base product type with common properties shared between iOS and Android\n */\nexport type ProductBase = {\n id: string;\n title: string;\n description: string;\n type: ProductType;\n displayName?: string;\n displayPrice?: string;\n price?: number;\n currency?: string;\n};\n\n// Define literal platform types for better type discrimination\nexport type IosPlatform = {platform: 'ios'};\nexport type AndroidPlatform = {platform: 'android'};\n\nexport enum ProductType {\n InAppPurchase = 'inapp',\n Subscription = 'subs',\n}\n\n// Common base purchase type\nexport type PurchaseBase = {\n id: string;\n transactionId?: string;\n transactionDate: number;\n transactionReceipt: string;\n purchaseToken?: string;\n};\n\n// Union type for platform-specific product types with proper discriminators\nexport type Product =\n | (ProductAndroid & AndroidPlatform)\n | (ProductIos & IosPlatform);\n\n// Union type for platform-specific purchase types with proper discriminators\nexport type ProductPurchase =\n | (ProductPurchaseAndroid & AndroidPlatform)\n | (ProductPurchaseIos & IosPlatform);\n\n// Union type for platform-specific subscription purchase types with proper discriminators\nexport type SubscriptionPurchase =\n | (ProductPurchaseAndroid & AndroidPlatform & {autoRenewingAndroid: boolean})\n | (ProductPurchaseIos & IosPlatform);\n\nexport type Purchase = ProductPurchase | SubscriptionPurchase;\n\nexport type RequestPurchaseProps =\n | RequestPurchaseIosProps\n | RequestPurchaseAndroidProps;\n\nexport type SubscriptionProduct =\n | (SubscriptionProductAndroid & AndroidPlatform)\n | (SubscriptionProductIos & IosPlatform);\n\nexport type RequestSubscriptionProps =\n | RequestSubscriptionAndroidProps\n | RequestSubscriptionIosProps;\n\nexport type PurchaseResult = {\n responseCode?: number;\n debugMessage?: string;\n code?: string;\n message?: string;\n purchaseToken?: string;\n};\n\nexport enum ErrorCode {\n E_UNKNOWN = 'E_UNKNOWN',\n E_USER_CANCELLED = 'E_USER_CANCELLED',\n E_USER_ERROR = 'E_USER_ERROR',\n E_ITEM_UNAVAILABLE = 'E_ITEM_UNAVAILABLE',\n E_REMOTE_ERROR = 'E_REMOTE_ERROR',\n E_NETWORK_ERROR = 'E_NETWORK_ERROR',\n E_SERVICE_ERROR = 'E_SERVICE_ERROR',\n E_RECEIPT_FAILED = 'E_RECEIPT_FAILED',\n E_RECEIPT_FINISHED_FAILED = 'E_RECEIPT_FINISHED_FAILED',\n E_NOT_PREPARED = 'E_NOT_PREPARED',\n E_NOT_ENDED = 'E_NOT_ENDED',\n E_ALREADY_OWNED = 'E_ALREADY_OWNED',\n E_DEVELOPER_ERROR = 'E_DEVELOPER_ERROR',\n E_BILLING_RESPONSE_JSON_PARSE_ERROR = 'E_BILLING_RESPONSE_JSON_PARSE_ERROR',\n E_DEFERRED_PAYMENT = 'E_DEFERRED_PAYMENT',\n E_INTERRUPTED = 'E_INTERRUPTED',\n E_IAP_NOT_AVAILABLE = 'E_IAP_NOT_AVAILABLE',\n}\n\nexport class PurchaseError implements Error {\n constructor(\n public name: string,\n public message: string,\n public responseCode?: number,\n public debugMessage?: string,\n public code?: ErrorCode,\n public productId?: string,\n ) {\n this.name = '[expo-iap]: PurchaseError';\n this.message = message;\n this.responseCode = responseCode;\n this.debugMessage = debugMessage;\n this.code = code;\n this.productId = productId;\n }\n}\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare enum IapEvent {
|
|
|
10
10
|
PurchaseError = "purchase-error",
|
|
11
11
|
TransactionIapUpdated = "iap-transaction-updated"
|
|
12
12
|
}
|
|
13
|
-
export declare function setValueAsync(value: string):
|
|
13
|
+
export declare function setValueAsync(value: string): any;
|
|
14
14
|
export declare const emitter: EventEmitter;
|
|
15
15
|
export declare const purchaseUpdatedListener: (listener: (event: Purchase) => void) => import("expo-modules-core").Subscription;
|
|
16
16
|
export declare const purchaseErrorListener: (listener: (error: PurchaseError) => void) => import("expo-modules-core").Subscription;
|
|
@@ -28,10 +28,9 @@ export declare const getAvailablePurchases: ({ alsoPublishToEventListener, onlyI
|
|
|
28
28
|
}) => Promise<ProductPurchase[]>;
|
|
29
29
|
export declare const requestPurchase: (request: RequestPurchaseIosProps | RequestPurchaseAndroidProps) => Promise<ProductPurchase | ProductPurchase[] | void>;
|
|
30
30
|
export declare const requestSubscription: (request: RequestSubscriptionProps) => Promise<SubscriptionPurchase | SubscriptionPurchase[] | null | void>;
|
|
31
|
-
export declare const finishTransaction: ({ purchase, isConsumable,
|
|
31
|
+
export declare const finishTransaction: ({ purchase, isConsumable, }: {
|
|
32
32
|
purchase: Purchase;
|
|
33
33
|
isConsumable?: boolean;
|
|
34
|
-
developerPayloadAndroid?: string;
|
|
35
34
|
}) => Promise<PurchaseResult | boolean>;
|
|
36
35
|
export * from './useIap';
|
|
37
36
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EACL,OAAO,EACP,eAAe,EAEf,QAAQ,EACR,aAAa,EACb,cAAc,EACd,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,2BAA2B,EAE5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEL,uBAAuB,EAExB,MAAM,0BAA0B,CAAC;AAOlC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAG9B,eAAO,MAAM,EAAE,KAAmB,CAAC;AAEnC,oBAAY,QAAQ;IAClB,eAAe,qBAAqB;IACpC,aAAa,mBAAmB;IAChC,qBAAqB,4BAA4B;CAClD;AAED,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EACL,OAAO,EACP,eAAe,EAEf,QAAQ,EACR,aAAa,EACb,cAAc,EACd,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,2BAA2B,EAE5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEL,uBAAuB,EAExB,MAAM,0BAA0B,CAAC;AAOlC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAG9B,eAAO,MAAM,EAAE,KAAmB,CAAC;AAEnC,oBAAY,QAAQ;IAClB,eAAe,qBAAqB;IACpC,aAAa,mBAAmB;IAChC,qBAAqB,4BAA4B;CAClD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,OAE1C;AAED,eAAO,MAAM,OAAO,cAEnB,CAAC;AAEF,eAAO,MAAM,uBAAuB,aACxB,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,6CAOpC,CAAC;AAEF,eAAO,MAAM,qBAAqB,aACtB,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,6CAGzC,CAAC;AAEF,wBAAgB,cAAc,QAE7B;AAED,eAAO,MAAM,WAAW,SAAgB,MAAM,EAAE,KAAG,QAAQ,OAAO,EAAE,CAuBnE,CAAC;AAEF,eAAO,MAAM,gBAAgB,SACrB,MAAM,EAAE,KACb,QAAQ,mBAAmB,EAAE,CAkC/B,CAAC;AAEF,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAEtD;AAED,eAAO,MAAM,kBAAkB,6DAG5B;IACD,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,KAAQ,QAAQ,eAAe,EAAE,CAmB7B,CAAC;AAEN,eAAO,MAAM,qBAAqB,6DAG/B;IACD,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,KAAQ,QAAQ,eAAe,EAAE,CAkB7B,CAAC;AAiBN,eAAO,MAAM,eAAe,YACjB,uBAAuB,GAAG,2BAA2B,KAC7D,QAAQ,eAAe,GAAG,eAAe,EAAE,GAAG,IAAI,CAuChD,CAAC;AAEN,eAAO,MAAM,mBAAmB,YACrB,wBAAwB,KAChC,QAAQ,oBAAoB,GAAG,oBAAoB,EAAE,GAAG,IAAI,GAAG,IAAI,CAwCjE,CAAC;AAEN,eAAO,MAAM,iBAAiB,gCAG3B;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,KAAG,QAAQ,cAAc,GAAG,OAAO,CA2BnC,CAAC;AAEF,cAAc,UAAU,CAAC"}
|
package/build/index.js
CHANGED
|
@@ -16,10 +16,10 @@ export var IapEvent;
|
|
|
16
16
|
IapEvent["PurchaseError"] = "purchase-error";
|
|
17
17
|
IapEvent["TransactionIapUpdated"] = "iap-transaction-updated";
|
|
18
18
|
})(IapEvent || (IapEvent = {}));
|
|
19
|
-
export
|
|
20
|
-
return
|
|
19
|
+
export function setValueAsync(value) {
|
|
20
|
+
return ExpoIapModule.setValueAsync(value);
|
|
21
21
|
}
|
|
22
|
-
export const emitter = new EventEmitter(ExpoIapModule
|
|
22
|
+
export const emitter = new EventEmitter(ExpoIapModule || NativeModulesProxy.ExpoIap);
|
|
23
23
|
export const purchaseUpdatedListener = (listener) => {
|
|
24
24
|
const emitterSubscription = emitter.addListener(IapEvent.PurchaseUpdated, listener);
|
|
25
25
|
return emitterSubscription;
|
|
@@ -164,7 +164,7 @@ export const requestSubscription = (request) => (Platform.select({
|
|
|
164
164
|
});
|
|
165
165
|
},
|
|
166
166
|
}) || (() => Promise.resolve(null)))();
|
|
167
|
-
export const finishTransaction = ({ purchase, isConsumable,
|
|
167
|
+
export const finishTransaction = ({ purchase, isConsumable, }) => {
|
|
168
168
|
return (Platform.select({
|
|
169
169
|
ios: async () => {
|
|
170
170
|
const transactionId = purchase.transactionId;
|
|
@@ -175,13 +175,15 @@ export const finishTransaction = ({ purchase, isConsumable, developerPayloadAndr
|
|
|
175
175
|
return Promise.resolve(true);
|
|
176
176
|
},
|
|
177
177
|
android: async () => {
|
|
178
|
-
if (purchase?.purchaseToken) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return ExpoIapModule.consumeProduct(purchase.purchaseToken
|
|
178
|
+
if (!purchase?.purchaseToken) {
|
|
179
|
+
return Promise.reject(new Error('purchaseToken is required to finish transaction'));
|
|
180
|
+
}
|
|
181
|
+
if (isConsumable) {
|
|
182
|
+
return ExpoIapModule.consumeProduct(purchase.purchaseToken);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
return ExpoIapModule.acknowledgePurchase(purchase.purchaseToken);
|
|
183
186
|
}
|
|
184
|
-
return Promise.reject(new Error('purchase is not suitable to be purchased'));
|
|
185
187
|
},
|
|
186
188
|
}) || (() => Promise.reject(new Error('Unsupported Platform'))))();
|
|
187
189
|
};
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,wCAAwC;AACxC,OAAO,EAAC,kBAAkB,EAAE,YAAY,EAAC,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAC;AACtC,OAAO,EAGL,WAAW,GAOZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAU5C,OAAO,EAAC,YAAY,EAAE,wBAAwB,EAAC,MAAM,eAAe,CAAC;AACrE,OAAO,EACL,gBAAgB,EAChB,4BAA4B,GAC7B,MAAM,mBAAmB,CAAC;AAE3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAE9B,iCAAiC;AACjC,MAAM,CAAC,MAAM,EAAE,GAAG,aAAa,CAAC,EAAE,CAAC;AAEnC,MAAM,CAAN,IAAY,QAIX;AAJD,WAAY,QAAQ;IAClB,gDAAoC,CAAA;IACpC,4CAAgC,CAAA;IAChC,6DAAiD,CAAA;AACnD,CAAC,EAJW,QAAQ,KAAR,QAAQ,QAInB;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAa;IAC/C,OAAO,MAAM,aAAa,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,YAAY,CACrC,aAAa,IAAI,kBAAkB,CAAC,OAAO,CAC5C,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,QAAmC,EACnC,EAAE;IACF,MAAM,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAC7C,QAAQ,CAAC,eAAe,EACxB,QAAQ,CACT,CAAC;IACF,OAAO,mBAAmB,CAAC;AAC7B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,QAAwC,EACxC,EAAE;IACF,OAAO,OAAO,CAAC,WAAW,CAAgB,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;AAC9E,CAAC,CAAC;AAEF,MAAM,UAAU,cAAc;IAC5B,OAAO,aAAa,CAAC,cAAc,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,IAAc,EAAsB,EAAE;IACtE,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAClB,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,QAAQ,CAAC,MAAM,CAAC;QACrB,GAAG,EAAE,KAAK,IAAI,EAAE;YACd,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACjD,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC5B,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAa,EAAE,EAAE,CAAC,YAAY,CAAU,IAAI,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,cAAc,CACjD,WAAW,CAAC,aAAa,EACzB,IAAI,CACL,CAAC;YACF,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAgB,EAAE,EAAE,CAC1C,gBAAgB,CAAU,OAAO,CAAC,CACnC,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;KACjE,CAAC,EAAE,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EACnC,IAAc,EACkB,EAAE;IAClC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAClB,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,QAAQ,CAAC,MAAM,CAAC;QACrB,GAAG,EAAE,KAAK,IAAI,EAAE;YACd,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAEpD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAa,EAAE,EAAE;gBACvC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC;oBAAE,OAAO,KAAK,CAAC;gBAClD,OAAO,CACL,OAAO,IAAI,KAAK,QAAQ;oBACxB,IAAI,KAAK,IAAI;oBACb,IAAI,IAAI,IAAI;oBACZ,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ;oBAC3B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CACvB,CAAC;YACJ,CAAC,CAA0B,CAAC;QAC9B,CAAC;QACD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAElE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAa,EAAE,EAAE;gBACvC,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC;oBAAE,OAAO,KAAK,CAAC;gBACtD,OAAO,CACL,OAAO,IAAI,KAAK,QAAQ;oBACxB,IAAI,KAAK,IAAI;oBACb,IAAI,IAAI,IAAI;oBACZ,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ;oBAC3B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CACvB,CAAC;YACJ,CAAC,CAA0B,CAAC;QAC9B,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;KACjE,CAAC,EAAE,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,OAAO,aAAa,CAAC,aAAa,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EACjC,0BAA0B,GAAG,KAAK,EAClC,sBAAsB,GAAG,KAAK,MAI5B,EAAE,EAA8B,EAAE,CACpC,CACE,QAAQ,CAAC,MAAM,CAAC;IACd,GAAG,EAAE,KAAK,IAAI,EAAE;QACd,OAAO,aAAa,CAAC,iBAAiB,CACpC,0BAA0B,EAC1B,sBAAsB,CACvB,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,KAAK,IAAI,EAAE;QAClB,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,wBAAwB,CAC3D,WAAW,CAAC,aAAa,CAC1B,CAAC;QAEF,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,wBAAwB,CAChE,WAAW,CAAC,YAAY,CACzB,CAAC;QAEF,OAAO,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACxC,CAAC;CACF,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAClC,EAAE,CAAC;AAEN,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,EACpC,0BAA0B,GAAG,KAAK,EAClC,sBAAsB,GAAG,IAAI,MAI3B,EAAE,EAA8B,EAAE,CACpC,CACE,QAAQ,CAAC,MAAM,CAAC;IACd,GAAG,EAAE,GAAG,EAAE,CACR,aAAa,CAAC,iBAAiB,CAC7B,0BAA0B,EAC1B,sBAAsB,CACvB;IACH,OAAO,EAAE,KAAK,IAAI,EAAE;QAClB,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,uBAAuB,CAC1D,WAAW,CAAC,aAAa,CAC1B,CAAC;QAEF,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,uBAAuB,CAC/D,WAAW,CAAC,YAAY,CACzB,CAAC;QAEF,OAAO,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACxC,CAAC;CACF,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAClC,EAAE,CAAC;AAEN,MAAM,gBAAgB,GAAG,CACvB,KAAkC,EACiB,EAAE;IACrD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE;KACtC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,OAA8D,EACT,EAAE,CACvD,CACE,QAAQ,CAAC,MAAM,CAAC;IACd,GAAG,EAAE,KAAK,IAAI,EAAE;QACd,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,EAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAC,GAAG,OAAO,CAAC;QAE5D,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAE1C,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,UAAU,CAC7C,GAAG,EACH,eAAe,EACf,QAAQ,IAAI,CAAC,CAAC,EACd,KAAK,CACN,CAAC;QAEF,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,EAAE,KAAK,IAAI,EAAE;QAClB,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,EACJ,IAAI,EACJ,0BAA0B,EAC1B,0BAA0B,EAC1B,mBAAmB,GACpB,GAAG,OAAO,CAAC;QAEZ,OAAO,aAAa,CAAC,aAAa,CAAC;YACjC,IAAI,EAAE,WAAW,CAAC,aAAa;YAC/B,MAAM,EAAE,IAAI;YACZ,aAAa,EAAE,SAAS;YACxB,eAAe,EAAE,CAAC,CAAC;YACnB,mBAAmB,EAAE,0BAA0B;YAC/C,mBAAmB,EAAE,0BAA0B;YAC/C,aAAa,EAAE,EAAE;YACjB,mBAAmB,EAAE,mBAAmB,IAAI,KAAK;SAClD,CAAC,CAAC;IACL,CAAC;CACF,CAAC,IAAI,OAAO,CAAC,OAAO,CACtB,EAAE,CAAC;AAEN,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,OAAiC,EACqC,EAAE,CACxE,CACE,QAAQ,CAAC,MAAM,CAAC;IACd,GAAG,EAAE,KAAK,IAAI,EAAE;QACd,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,EAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAC,GAC/C,OAAsC,CAAC;QAEzC,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAE1C,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,UAAU,CAC7C,GAAG,EACH,eAAe,EACf,QAAQ,IAAI,CAAC,CAAC,EACd,KAAK,CACN,CAAC;QAEF,OAAO,OAAO,CAAC,OAAO,CAAC,QAAgC,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,EAAE,KAAK,IAAI,EAAE;QAClB,MAAM,EACJ,IAAI,EACJ,mBAAmB,EACnB,0BAA0B,EAC1B,0BAA0B,EAC1B,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,GACrB,GAAG,OAA0C,CAAC;QAE/C,OAAO,aAAa,CAAC,aAAa,CAAC;YACjC,IAAI,EAAE,WAAW,CAAC,YAAY;YAC9B,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;YAC5B,aAAa,EAAE,oBAAoB;YACnC,eAAe,EAAE,sBAAsB;YACvC,mBAAmB,EAAE,0BAA0B;YAC/C,mBAAmB,EAAE,0BAA0B;YAC/C,aAAa,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC;YAC5D,mBAAmB,EAAE,mBAAmB,IAAI,KAAK;SAClD,CAAC,CAAC;IACL,CAAC;CACF,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CACpC,EAAE,CAAC;AAEN,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,EAChC,QAAQ,EACR,YAAY,EACZ,uBAAuB,GAKxB,EAAqC,EAAE;IACtC,OAAO,CACL,QAAQ,CAAC,MAAM,CAAC;QACd,GAAG,EAAE,KAAK,IAAI,EAAE;YACd,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC;YAE7C,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAC9D,CAAC;YACJ,CAAC;YACD,MAAM,aAAa,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;YACrD,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,QAAQ,EAAE,aAAa,EAAE,CAAC;gBAC5B,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CAAC,0CAA0C,CAAC,CACtD,CAAC;gBACJ,CAAC;gBAED,OAAO,aAAa,CAAC,cAAc,CACjC,QAAQ,CAAC,aAAa,EACtB,uBAAuB,CACxB,CAAC;YACJ,CAAC;YACD,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CAAC,0CAA0C,CAAC,CACtD,CAAC;QACJ,CAAC;KACF,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAChE,EAAE,CAAC;AACN,CAAC,CAAC;AAEF,cAAc,UAAU,CAAC","sourcesContent":["// Import the native module. On web, it will be resolved to ExpoIap.web.ts\n// and on native platforms to ExpoIap.ts\nimport {NativeModulesProxy, EventEmitter} from 'expo-modules-core';\nimport {Platform} from 'react-native';\nimport {\n Product,\n ProductPurchase,\n ProductType,\n Purchase,\n PurchaseError,\n PurchaseResult,\n RequestSubscriptionProps,\n SubscriptionProduct,\n SubscriptionPurchase,\n} from './ExpoIap.types';\nimport ExpoIapModule from './ExpoIapModule';\nimport {\n RequestPurchaseAndroidProps,\n RequestSubscriptionAndroidProps,\n} from './types/ExpoIapAndroid.types';\nimport {\n PaymentDiscount,\n RequestPurchaseIosProps,\n RequestSubscriptionIosProps,\n} from './types/ExpoIapIos.types';\nimport {isProductIos, isSubscriptionProductIos} from './modules/ios';\nimport {\n isProductAndroid,\n isSubscriptionProductAndroid,\n} from './modules/android';\n\nexport * from './modules/android';\nexport * from './modules/ios';\n\n// Get the native constant value.\nexport const PI = ExpoIapModule.PI;\n\nexport enum IapEvent {\n PurchaseUpdated = 'purchase-updated',\n PurchaseError = 'purchase-error',\n TransactionIapUpdated = 'iap-transaction-updated',\n}\n\nexport async function setValueAsync(value: string) {\n return await ExpoIapModule.setValueAsync(value);\n}\n\nexport const emitter = new EventEmitter(\n ExpoIapModule ?? NativeModulesProxy.ExpoIap,\n);\n\nexport const purchaseUpdatedListener = (\n listener: (event: Purchase) => void,\n) => {\n const emitterSubscription = emitter.addListener(\n IapEvent.PurchaseUpdated,\n listener,\n );\n return emitterSubscription;\n};\n\nexport const purchaseErrorListener = (\n listener: (error: PurchaseError) => void,\n) => {\n return emitter.addListener<PurchaseError>(IapEvent.PurchaseError, listener);\n};\n\nexport function initConnection() {\n return ExpoIapModule.initConnection();\n}\n\nexport const getProducts = async (skus: string[]): Promise<Product[]> => {\n console.log('getProducts', skus);\n if (!skus?.length) {\n return Promise.reject(new Error('\"skus\" is required'));\n }\n\n return Platform.select({\n ios: async () => {\n const items = await ExpoIapModule.getItems(skus);\n console.log('items', items);\n return items.filter((item: unknown) => isProductIos<Product>(item));\n },\n android: async () => {\n const products = await ExpoIapModule.getItemsByType(\n ProductType.InAppPurchase,\n skus,\n );\n return products.filter((product: unknown) =>\n isProductAndroid<Product>(product),\n );\n },\n default: () => Promise.reject(new Error('Unsupported Platform')),\n })();\n};\n\nexport const getSubscriptions = async (\n skus: string[],\n): Promise<SubscriptionProduct[]> => {\n if (!skus?.length) {\n return Promise.reject(new Error('\"skus\" is required'));\n }\n\n return Platform.select({\n ios: async () => {\n const rawItems = await ExpoIapModule.getItems(skus);\n\n return rawItems.filter((item: unknown) => {\n if (!isSubscriptionProductIos(item)) return false;\n return (\n typeof item === 'object' &&\n item !== null &&\n 'id' in item &&\n typeof item.id === 'string' &&\n skus.includes(item.id)\n );\n }) as SubscriptionProduct[];\n },\n android: async () => {\n const rawItems = await ExpoIapModule.getItemsByType('subs', skus);\n\n return rawItems.filter((item: unknown) => {\n if (!isSubscriptionProductAndroid(item)) return false;\n return (\n typeof item === 'object' &&\n item !== null &&\n 'id' in item &&\n typeof item.id === 'string' &&\n skus.includes(item.id)\n );\n }) as SubscriptionProduct[];\n },\n default: () => Promise.reject(new Error('Unsupported Platform')),\n })();\n};\n\nexport async function endConnection(): Promise<boolean> {\n return ExpoIapModule.endConnection();\n}\n\nexport const getPurchaseHistory = ({\n alsoPublishToEventListener = false,\n onlyIncludeActiveItems = false,\n}: {\n alsoPublishToEventListener?: boolean;\n onlyIncludeActiveItems?: boolean;\n} = {}): Promise<ProductPurchase[]> =>\n (\n Platform.select({\n ios: async () => {\n return ExpoIapModule.getAvailableItems(\n alsoPublishToEventListener,\n onlyIncludeActiveItems,\n );\n },\n android: async () => {\n const products = await ExpoIapModule.getPurchaseHistoryByType(\n ProductType.InAppPurchase,\n );\n\n const subscriptions = await ExpoIapModule.getPurchaseHistoryByType(\n ProductType.Subscription,\n );\n\n return products.concat(subscriptions);\n },\n }) || (() => Promise.resolve([]))\n )();\n\nexport const getAvailablePurchases = ({\n alsoPublishToEventListener = false,\n onlyIncludeActiveItems = true,\n}: {\n alsoPublishToEventListener?: boolean;\n onlyIncludeActiveItems?: boolean;\n} = {}): Promise<ProductPurchase[]> =>\n (\n Platform.select({\n ios: () =>\n ExpoIapModule.getAvailableItems(\n alsoPublishToEventListener,\n onlyIncludeActiveItems,\n ),\n android: async () => {\n const products = await ExpoIapModule.getAvailableItemsByType(\n ProductType.InAppPurchase,\n );\n\n const subscriptions = await ExpoIapModule.getAvailableItemsByType(\n ProductType.Subscription,\n );\n\n return products.concat(subscriptions);\n },\n }) || (() => Promise.resolve([]))\n )();\n\nconst offerToRecordIos = (\n offer: PaymentDiscount | undefined,\n): Record<keyof PaymentDiscount, string> | undefined => {\n if (!offer) {\n return undefined;\n }\n return {\n identifier: offer.identifier,\n keyIdentifier: offer.keyIdentifier,\n nonce: offer.nonce,\n signature: offer.signature,\n timestamp: offer.timestamp.toString(),\n };\n};\n\nexport const requestPurchase = (\n request: RequestPurchaseIosProps | RequestPurchaseAndroidProps,\n): Promise<ProductPurchase | ProductPurchase[] | void> =>\n (\n Platform.select({\n ios: async () => {\n if (!('sku' in request)) {\n throw new Error('sku is required for iOS purchase');\n }\n\n const {sku, appAccountToken, quantity, withOffer} = request;\n\n const offer = offerToRecordIos(withOffer);\n\n const purchase = await ExpoIapModule.buyProduct(\n sku,\n appAccountToken,\n quantity ?? -1,\n offer,\n );\n\n return Promise.resolve(purchase);\n },\n android: async () => {\n if (!('skus' in request) || !request.skus.length) {\n throw new Error('skus is required for Android purchase');\n }\n\n const {\n skus,\n obfuscatedAccountIdAndroid,\n obfuscatedProfileIdAndroid,\n isOfferPersonalized,\n } = request;\n\n return ExpoIapModule.buyItemByType({\n type: ProductType.InAppPurchase,\n skuArr: skus,\n purchaseToken: undefined,\n replacementMode: -1,\n obfuscatedAccountId: obfuscatedAccountIdAndroid,\n obfuscatedProfileId: obfuscatedProfileIdAndroid,\n offerTokenArr: [],\n isOfferPersonalized: isOfferPersonalized ?? false,\n });\n },\n }) || Promise.resolve\n )();\n\nexport const requestSubscription = (\n request: RequestSubscriptionProps,\n): Promise<SubscriptionPurchase | SubscriptionPurchase[] | null | void> =>\n (\n Platform.select({\n ios: async () => {\n if (!('sku' in request)) {\n throw new Error('sku is required for iOS subscriptions');\n }\n\n const {sku, appAccountToken, quantity, withOffer} =\n request as RequestSubscriptionIosProps;\n\n const offer = offerToRecordIos(withOffer);\n\n const purchase = await ExpoIapModule.buyProduct(\n sku,\n appAccountToken,\n quantity ?? -1,\n offer,\n );\n\n return Promise.resolve(purchase as SubscriptionPurchase);\n },\n android: async () => {\n const {\n skus,\n isOfferPersonalized,\n obfuscatedAccountIdAndroid,\n obfuscatedProfileIdAndroid,\n subscriptionOffers,\n replacementModeAndroid,\n purchaseTokenAndroid,\n } = request as RequestSubscriptionAndroidProps;\n\n return ExpoIapModule.buyItemByType({\n type: ProductType.Subscription,\n skuArr: skus.map((so) => so),\n purchaseToken: purchaseTokenAndroid,\n replacementMode: replacementModeAndroid,\n obfuscatedAccountId: obfuscatedAccountIdAndroid,\n obfuscatedProfileId: obfuscatedProfileIdAndroid,\n offerTokenArr: subscriptionOffers.map((so) => so.offerToken),\n isOfferPersonalized: isOfferPersonalized ?? false,\n });\n },\n }) || (() => Promise.resolve(null))\n )();\n\nexport const finishTransaction = ({\n purchase,\n isConsumable,\n developerPayloadAndroid,\n}: {\n purchase: Purchase;\n isConsumable?: boolean;\n developerPayloadAndroid?: string;\n}): Promise<PurchaseResult | boolean> => {\n return (\n Platform.select({\n ios: async () => {\n const transactionId = purchase.transactionId;\n\n if (!transactionId) {\n return Promise.reject(\n new Error('transactionId required to finish iOS transaction'),\n );\n }\n await ExpoIapModule.finishTransaction(transactionId);\n return Promise.resolve(true);\n },\n android: async () => {\n if (purchase?.purchaseToken) {\n if (!isConsumable) {\n return Promise.reject(\n new Error('purchase is not suitable to be purchased'),\n );\n }\n\n return ExpoIapModule.consumeProduct(\n purchase.purchaseToken,\n developerPayloadAndroid,\n );\n }\n return Promise.reject(\n new Error('purchase is not suitable to be purchased'),\n );\n },\n }) || (() => Promise.reject(new Error('Unsupported Platform')))\n )();\n};\n\nexport * from './useIap';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Import the native module. On web, it will be resolved to ExpoIap.web.ts\n// and on native platforms to ExpoIap.ts\nimport {NativeModulesProxy, EventEmitter} from 'expo-modules-core';\nimport {Platform} from 'react-native';\nimport {\n Product,\n ProductPurchase,\n ProductType,\n Purchase,\n PurchaseError,\n PurchaseResult,\n RequestSubscriptionProps,\n SubscriptionProduct,\n SubscriptionPurchase,\n} from './ExpoIap.types';\nimport ExpoIapModule from './ExpoIapModule';\nimport {\n RequestPurchaseAndroidProps,\n RequestSubscriptionAndroidProps,\n} from './types/ExpoIapAndroid.types';\nimport {\n PaymentDiscount,\n RequestPurchaseIosProps,\n RequestSubscriptionIosProps,\n} from './types/ExpoIapIos.types';\nimport {isProductIos, isSubscriptionProductIos} from './modules/ios';\nimport {\n isProductAndroid,\n isSubscriptionProductAndroid,\n} from './modules/android';\n\nexport * from './modules/android';\nexport * from './modules/ios';\n\n// Get the native constant value.\nexport const PI = ExpoIapModule.PI;\n\nexport enum IapEvent {\n PurchaseUpdated = 'purchase-updated',\n PurchaseError = 'purchase-error',\n TransactionIapUpdated = 'iap-transaction-updated',\n}\n\nexport function setValueAsync(value: string) {\n return ExpoIapModule.setValueAsync(value);\n}\n\nexport const emitter = new EventEmitter(\n ExpoIapModule || NativeModulesProxy.ExpoIap,\n);\n\nexport const purchaseUpdatedListener = (\n listener: (event: Purchase) => void,\n) => {\n const emitterSubscription = emitter.addListener(\n IapEvent.PurchaseUpdated,\n listener,\n );\n return emitterSubscription;\n};\n\nexport const purchaseErrorListener = (\n listener: (error: PurchaseError) => void,\n) => {\n return emitter.addListener<PurchaseError>(IapEvent.PurchaseError, listener);\n};\n\nexport function initConnection() {\n return ExpoIapModule.initConnection();\n}\n\nexport const getProducts = async (skus: string[]): Promise<Product[]> => {\n console.log('getProducts', skus);\n if (!skus?.length) {\n return Promise.reject(new Error('\"skus\" is required'));\n }\n\n return Platform.select({\n ios: async () => {\n const items = await ExpoIapModule.getItems(skus);\n console.log('items', items);\n return items.filter((item: unknown) => isProductIos<Product>(item));\n },\n android: async () => {\n const products = await ExpoIapModule.getItemsByType(\n ProductType.InAppPurchase,\n skus,\n );\n return products.filter((product: unknown) =>\n isProductAndroid<Product>(product),\n );\n },\n default: () => Promise.reject(new Error('Unsupported Platform')),\n })();\n};\n\nexport const getSubscriptions = async (\n skus: string[],\n): Promise<SubscriptionProduct[]> => {\n if (!skus?.length) {\n return Promise.reject(new Error('\"skus\" is required'));\n }\n\n return Platform.select({\n ios: async () => {\n const rawItems = await ExpoIapModule.getItems(skus);\n return rawItems.filter((item: unknown) => {\n if (!isSubscriptionProductIos(item)) return false;\n return (\n typeof item === 'object' &&\n item !== null &&\n 'id' in item &&\n typeof item.id === 'string' &&\n skus.includes(item.id)\n );\n }) as SubscriptionProduct[];\n },\n android: async () => {\n const rawItems = await ExpoIapModule.getItemsByType('subs', skus);\n return rawItems.filter((item: unknown) => {\n if (!isSubscriptionProductAndroid(item)) return false;\n return (\n typeof item === 'object' &&\n item !== null &&\n 'id' in item &&\n typeof item.id === 'string' &&\n skus.includes(item.id)\n );\n }) as SubscriptionProduct[];\n },\n default: () => Promise.reject(new Error('Unsupported Platform')),\n })();\n};\n\nexport async function endConnection(): Promise<boolean> {\n return ExpoIapModule.endConnection();\n}\n\nexport const getPurchaseHistory = ({\n alsoPublishToEventListener = false,\n onlyIncludeActiveItems = false,\n}: {\n alsoPublishToEventListener?: boolean;\n onlyIncludeActiveItems?: boolean;\n} = {}): Promise<ProductPurchase[]> =>\n (\n Platform.select({\n ios: async () => {\n return ExpoIapModule.getAvailableItems(\n alsoPublishToEventListener,\n onlyIncludeActiveItems,\n );\n },\n android: async () => {\n const products = await ExpoIapModule.getPurchaseHistoryByType(\n ProductType.InAppPurchase,\n );\n const subscriptions = await ExpoIapModule.getPurchaseHistoryByType(\n ProductType.Subscription,\n );\n return products.concat(subscriptions);\n },\n }) || (() => Promise.resolve([]))\n )();\n\nexport const getAvailablePurchases = ({\n alsoPublishToEventListener = false,\n onlyIncludeActiveItems = true,\n}: {\n alsoPublishToEventListener?: boolean;\n onlyIncludeActiveItems?: boolean;\n} = {}): Promise<ProductPurchase[]> =>\n (\n Platform.select({\n ios: () =>\n ExpoIapModule.getAvailableItems(\n alsoPublishToEventListener,\n onlyIncludeActiveItems,\n ),\n android: async () => {\n const products = await ExpoIapModule.getAvailableItemsByType(\n ProductType.InAppPurchase,\n );\n const subscriptions = await ExpoIapModule.getAvailableItemsByType(\n ProductType.Subscription,\n );\n return products.concat(subscriptions);\n },\n }) || (() => Promise.resolve([]))\n )();\n\nconst offerToRecordIos = (\n offer: PaymentDiscount | undefined,\n): Record<keyof PaymentDiscount, string> | undefined => {\n if (!offer) {\n return undefined;\n }\n return {\n identifier: offer.identifier,\n keyIdentifier: offer.keyIdentifier,\n nonce: offer.nonce,\n signature: offer.signature,\n timestamp: offer.timestamp.toString(),\n };\n};\n\nexport const requestPurchase = (\n request: RequestPurchaseIosProps | RequestPurchaseAndroidProps,\n): Promise<ProductPurchase | ProductPurchase[] | void> =>\n (\n Platform.select({\n ios: async () => {\n if (!('sku' in request)) {\n throw new Error('sku is required for iOS purchase');\n }\n const {sku, appAccountToken, quantity, withOffer} = request;\n const offer = offerToRecordIos(withOffer);\n const purchase = await ExpoIapModule.buyProduct(\n sku,\n appAccountToken,\n quantity ?? -1,\n offer,\n );\n return Promise.resolve(purchase);\n },\n android: async () => {\n if (!('skus' in request) || !request.skus.length) {\n throw new Error('skus is required for Android purchase');\n }\n const {\n skus,\n obfuscatedAccountIdAndroid,\n obfuscatedProfileIdAndroid,\n isOfferPersonalized,\n } = request;\n return ExpoIapModule.buyItemByType({\n type: ProductType.InAppPurchase,\n skuArr: skus,\n purchaseToken: undefined,\n replacementMode: -1,\n obfuscatedAccountId: obfuscatedAccountIdAndroid,\n obfuscatedProfileId: obfuscatedProfileIdAndroid,\n offerTokenArr: [],\n isOfferPersonalized: isOfferPersonalized ?? false,\n });\n },\n }) || Promise.resolve\n )();\n\nexport const requestSubscription = (\n request: RequestSubscriptionProps,\n): Promise<SubscriptionPurchase | SubscriptionPurchase[] | null | void> =>\n (\n Platform.select({\n ios: async () => {\n if (!('sku' in request)) {\n throw new Error('sku is required for iOS subscriptions');\n }\n const {sku, appAccountToken, quantity, withOffer} =\n request as RequestSubscriptionIosProps;\n const offer = offerToRecordIos(withOffer);\n const purchase = await ExpoIapModule.buyProduct(\n sku,\n appAccountToken,\n quantity ?? -1,\n offer,\n );\n return Promise.resolve(purchase as SubscriptionPurchase);\n },\n android: async () => {\n const {\n skus,\n isOfferPersonalized,\n obfuscatedAccountIdAndroid,\n obfuscatedProfileIdAndroid,\n subscriptionOffers,\n replacementModeAndroid,\n purchaseTokenAndroid,\n } = request as RequestSubscriptionAndroidProps;\n return ExpoIapModule.buyItemByType({\n type: ProductType.Subscription,\n skuArr: skus.map((so) => so),\n purchaseToken: purchaseTokenAndroid,\n replacementMode: replacementModeAndroid,\n obfuscatedAccountId: obfuscatedAccountIdAndroid,\n obfuscatedProfileId: obfuscatedProfileIdAndroid,\n offerTokenArr: subscriptionOffers.map((so) => so.offerToken),\n isOfferPersonalized: isOfferPersonalized ?? false,\n });\n },\n }) || (() => Promise.resolve(null))\n )();\n\nexport const finishTransaction = ({\n purchase,\n isConsumable,\n}: {\n purchase: Purchase;\n isConsumable?: boolean;\n}): Promise<PurchaseResult | boolean> => {\n return (\n Platform.select({\n ios: async () => {\n const transactionId = purchase.transactionId;\n if (!transactionId) {\n return Promise.reject(\n new Error('transactionId required to finish iOS transaction'),\n );\n }\n await ExpoIapModule.finishTransaction(transactionId);\n return Promise.resolve(true);\n },\n android: async () => {\n if (!purchase?.purchaseToken) {\n return Promise.reject(\n new Error('purchaseToken is required to finish transaction'),\n );\n }\n if (isConsumable) {\n return ExpoIapModule.consumeProduct(purchase.purchaseToken);\n } else {\n return ExpoIapModule.acknowledgePurchase(purchase.purchaseToken);\n }\n },\n }) || (() => Promise.reject(new Error('Unsupported Platform')))\n )();\n};\n\nexport * from './useIap';\n"]}
|
package/build/useIap.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIap.d.ts","sourceRoot":"","sources":["../src/useIap.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,OAAO,EACP,eAAe,EACf,QAAQ,EACR,aAAa,EACb,cAAc,EACd,mBAAmB,EAEpB,MAAM,iBAAiB,CAAC;AAIzB,KAAK,UAAU,GAAG;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,mBAAmB,EAAE,eAAe,EAAE,CAAC;IACvC,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,iBAAiB,EAAE,eAAe,EAAE,CAAC;IACrC,kBAAkB,EAAE,eAAe,EAAE,CAAC;IACtC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,oBAAoB,CAAC,EAAE,aAAa,CAAC;IACrC,iBAAiB,EAAE,CAAC,EAClB,QAAQ,EACR,YAAY,EACZ,uBAAuB,GACxB,EAAE;QACD,QAAQ,EAAE,QAAQ,CAAC;QACnB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,uBAAuB,CAAC,EAAE,MAAM,CAAC;KAClC,KAAK,OAAO,CAAC,MAAM,GAAG,OAAO,GAAG,cAAc,GAAG,IAAI,CAAC,CAAC;IACxD,qBAAqB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,oBAAoB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD,CAAC;AAMF,wBAAgB,MAAM,IAAI,UAAU,
|
|
1
|
+
{"version":3,"file":"useIap.d.ts","sourceRoot":"","sources":["../src/useIap.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,OAAO,EACP,eAAe,EACf,QAAQ,EACR,aAAa,EACb,cAAc,EACd,mBAAmB,EAEpB,MAAM,iBAAiB,CAAC;AAIzB,KAAK,UAAU,GAAG;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,mBAAmB,EAAE,eAAe,EAAE,CAAC;IACvC,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,iBAAiB,EAAE,eAAe,EAAE,CAAC;IACrC,kBAAkB,EAAE,eAAe,EAAE,CAAC;IACtC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,oBAAoB,CAAC,EAAE,aAAa,CAAC;IACrC,iBAAiB,EAAE,CAAC,EAClB,QAAQ,EACR,YAAY,EACZ,uBAAuB,GACxB,EAAE;QACD,QAAQ,EAAE,QAAQ,CAAC;QACnB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,uBAAuB,CAAC,EAAE,MAAM,CAAC;KAClC,KAAK,OAAO,CAAC,MAAM,GAAG,OAAO,GAAG,cAAc,GAAG,IAAI,CAAC,CAAC;IACxD,qBAAqB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,oBAAoB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD,CAAC;AAMF,wBAAgB,MAAM,IAAI,UAAU,CAqInC"}
|
package/build/useIap.js
CHANGED
|
@@ -39,7 +39,8 @@ export function useIAP() {
|
|
|
39
39
|
if (purchase.id === currentPurchase?.id) {
|
|
40
40
|
setCurrentPurchase(undefined);
|
|
41
41
|
}
|
|
42
|
-
if (purchase.id === currentPurchaseError?.productId) {
|
|
42
|
+
if (purchase.id === currentPurchaseError?.productId) {
|
|
43
|
+
// Note that PurchaseError still uses productId
|
|
43
44
|
setCurrentPurchaseError(undefined);
|
|
44
45
|
}
|
|
45
46
|
}
|
package/build/useIap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIap.js","sourceRoot":"","sources":["../src/useIap.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,WAAW,EACX,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,IAAI,CAAC;AACZ,OAAO,EAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AAqCvD,IAAI,0BAAwC,CAAC;AAC7C,IAAI,yBAAuC,CAAC;AAC5C,IAAI,4BAA0C,CAAC;AAE/C,MAAM,UAAU,MAAM;IACpB,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC3D,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAY,EAAE,CAAC,CAAC;IACxD,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAE5D,EAAE,CAAC,CAAC;IACN,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAwB,EAAE,CAAC,CAAC;IAC9E,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CACxD,EAAE,CACH,CAAC;IACF,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAAG,QAAQ,CAE1D,EAAE,CAAC,CAAC;IACN,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,EAAmB,CAAC;IAC1E,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,GACnD,QAAQ,EAAiB,CAAC;IAE5B,MAAM,eAAe,GAAG,WAAW,CAAC,KAAK,EAAE,IAAc,EAAiB,EAAE;QAC1E,WAAW,CAAC,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IACvC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,oBAAoB,GAAG,WAAW,CACtC,KAAK,EAAE,IAAc,EAAiB,EAAE;QACtC,gBAAgB,CAAC,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,CAAC,EACD,EAAE,CACH,CAAC;IAEF,MAAM,yBAAyB,GAAG,WAAW,CAAC,KAAK,IAAmB,EAAE;QACtE,qBAAqB,CAAC,MAAM,qBAAqB,EAAE,CAAC,CAAC;IACvD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,wBAAwB,GAAG,WAAW,CAAC,KAAK,IAAmB,EAAE;QACrE,oBAAoB,CAAC,MAAM,kBAAkB,EAAE,CAAC,CAAC;IACnD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,iBAAiB,GAAG,WAAW,CACnC,KAAK,EAAE,EACL,QAAQ,EACR,YAAY,EACZ,uBAAuB,GAKxB,EAAqD,EAAE;QACtD,IAAI,CAAC;YACH,OAAO,MAAM,iBAAiB,CAAC;gBAC7B,QAAQ;gBACR,YAAY;gBACZ,uBAAuB;aACxB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,IAAI,QAAQ,CAAC,EAAE,KAAK,eAAe,EAAE,EAAE,EAAE,CAAC;gBACxC,kBAAkB,CAAC,SAAS,CAAC,CAAC;YAChC,CAAC;YAED,IAAI,QAAQ,CAAC,EAAE,KAAK,oBAAoB,EAAE,SAAS,EAAE,CAAC
|
|
1
|
+
{"version":3,"file":"useIap.js","sourceRoot":"","sources":["../src/useIap.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n endConnection,\n initConnection,\n purchaseErrorListener,\n purchaseUpdatedListener,\n transactionUpdatedIos,\n getProducts,\n getAvailablePurchases,\n getPurchaseHistory,\n getSubscriptions,\n} from './';\nimport {useCallback, useEffect, useState} from 'react';\nimport {\n Product,\n ProductPurchase,\n Purchase,\n PurchaseError,\n PurchaseResult,\n SubscriptionProduct,\n SubscriptionPurchase,\n} from './ExpoIap.types';\nimport {TransactionEvent} from './modules/ios';\nimport {Subscription} from 'expo-modules-core';\n\ntype IAP_STATUS = {\n connected: boolean;\n products: Product[];\n promotedProductsIOS: ProductPurchase[];\n subscriptions: SubscriptionProduct[];\n purchaseHistories: ProductPurchase[];\n availablePurchases: ProductPurchase[];\n currentPurchase?: ProductPurchase;\n currentPurchaseError?: PurchaseError;\n finishTransaction: ({\n purchase,\n isConsumable,\n developerPayloadAndroid,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n developerPayloadAndroid?: string;\n }) => Promise<string | boolean | PurchaseResult | void>;\n getAvailablePurchases: () => Promise<void>;\n getPurchaseHistories: () => Promise<void>;\n getProducts: (skus: string[]) => Promise<void>;\n getSubscriptions: (skus: string[]) => Promise<void>;\n};\n\nlet purchaseUpdateSubscription: Subscription;\nlet purchaseErrorSubscription: Subscription;\nlet promotedProductsSubscription: Subscription;\n\nexport function useIAP(): IAP_STATUS {\n const [connected, setConnected] = useState<boolean>(false);\n const [products, setProducts] = useState<Product[]>([]);\n const [promotedProductsIOS, setPromotedProductsIOS] = useState<\n ProductPurchase[]\n >([]);\n const [subscriptions, setSubscriptions] = useState<SubscriptionProduct[]>([]);\n const [purchaseHistories, setPurchaseHistories] = useState<ProductPurchase[]>(\n [],\n );\n const [availablePurchases, setAvailablePurchases] = useState<\n ProductPurchase[]\n >([]);\n const [currentPurchase, setCurrentPurchase] = useState<ProductPurchase>();\n const [currentPurchaseError, setCurrentPurchaseError] =\n useState<PurchaseError>();\n\n const requestProducts = useCallback(async (skus: string[]): Promise<void> => {\n setProducts(await getProducts(skus));\n }, []);\n\n const requestSubscriptions = useCallback(\n async (skus: string[]): Promise<void> => {\n setSubscriptions(await getSubscriptions(skus));\n },\n [],\n );\n\n const requestAvailablePurchases = useCallback(async (): Promise<void> => {\n setAvailablePurchases(await getAvailablePurchases());\n }, []);\n\n const requestPurchaseHistories = useCallback(async (): Promise<void> => {\n setPurchaseHistories(await getPurchaseHistory());\n }, []);\n\n const finishTransaction = useCallback(\n async ({\n purchase,\n isConsumable,\n developerPayloadAndroid,\n }: {\n purchase: ProductPurchase;\n isConsumable?: boolean;\n developerPayloadAndroid?: string;\n }): Promise<string | boolean | PurchaseResult | void> => {\n try {\n return await finishTransaction({\n purchase,\n isConsumable,\n developerPayloadAndroid,\n });\n } catch (err) {\n throw err;\n } finally {\n if (purchase.id === currentPurchase?.id) {\n setCurrentPurchase(undefined);\n }\n\n if (purchase.id === currentPurchaseError?.productId) {\n // Note that PurchaseError still uses productId\n setCurrentPurchaseError(undefined);\n }\n }\n },\n [\n currentPurchase?.id,\n currentPurchaseError?.productId,\n setCurrentPurchase,\n setCurrentPurchaseError,\n ],\n );\n\n const initIapWithSubscriptions = useCallback(async (): Promise<void> => {\n const result = await initConnection();\n\n setConnected(result);\n\n if (result) {\n purchaseUpdateSubscription = purchaseUpdatedListener(\n async (purchase: Purchase | SubscriptionPurchase) => {\n setCurrentPurchaseError(undefined);\n setCurrentPurchase(purchase);\n },\n );\n\n purchaseErrorSubscription = purchaseErrorListener(\n (error: PurchaseError) => {\n setCurrentPurchase(undefined);\n setCurrentPurchaseError(error);\n },\n );\n\n promotedProductsSubscription = transactionUpdatedIos(\n (event: TransactionEvent) => {\n setPromotedProductsIOS((prevProducts) =>\n event.transaction\n ? [...prevProducts, event.transaction]\n : prevProducts,\n );\n },\n );\n }\n }, []);\n\n useEffect(() => {\n initIapWithSubscriptions();\n\n return (): void => {\n if (purchaseUpdateSubscription) purchaseUpdateSubscription.remove();\n if (purchaseErrorSubscription) purchaseErrorSubscription.remove();\n if (promotedProductsSubscription) promotedProductsSubscription.remove();\n\n endConnection();\n setConnected(false);\n };\n }, [initIapWithSubscriptions]);\n\n return {\n connected,\n products,\n promotedProductsIOS,\n subscriptions,\n purchaseHistories,\n finishTransaction,\n availablePurchases,\n currentPurchase,\n currentPurchaseError,\n getProducts: requestProducts,\n getSubscriptions: requestSubscriptions,\n getAvailablePurchases: requestAvailablePurchases,\n getPurchaseHistories: requestPurchaseHistories,\n };\n}\n"]}
|
package/iap.md
CHANGED
|
@@ -1,14 +1,44 @@
|
|
|
1
1
|
# Expo IAP Documentation
|
|
2
2
|
|
|
3
|
+
> **Key Feature**: `expo-iap` works seamlessly with Expo's managed workflow—no bare setup or native code required! This is a major improvement over `react-native-iap`, making it ideal for small teams using Expo SDK.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`expo-iap` is an Expo module for handling in-app purchases (IAP) on iOS (StoreKit 2) and Android (Google Play Billing). It supports consumables, non-consumables, and subscriptions. While it’s functional in managed workflows, it’s still under active development—test thoroughly before deploying to production. For a fully stable alternative, consider RevenueCat.
|
|
8
|
+
|
|
3
9
|
## Installation in Managed Expo Projects
|
|
4
10
|
|
|
5
|
-
For [managed](https://docs.expo.dev/archive/managed-vs-bare/) Expo projects,
|
|
11
|
+
For [managed](https://docs.expo.dev/archive/managed-vs-bare/) Expo projects, add `expo-iap` and configure it via the Expo config plugin. It’s compatible with Expo SDK 51+ (check the [API documentation](#api-documentation) for official inclusion). If no documentation is available, it’s awaiting a future SDK release.
|
|
12
|
+
|
|
13
|
+
### Steps
|
|
14
|
+
|
|
15
|
+
1. **Add the Package**
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install expo-iap
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
2. **Configure with Expo Config Plugin** Add `'expo-iap'` to the `plugins` array in your `app.json` or `app.config.js`:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"expo": {
|
|
26
|
+
"plugins": ["expo-iap"]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This automatically configures Android BILLING permissions and iOS setup.
|
|
32
|
+
|
|
33
|
+
3. **Run Your App** Use `expo run:android` or `expo run:ios` to build and test.
|
|
34
|
+
|
|
35
|
+
> **Example**: See a working sample at [example/App.tsx](https://github.com/hyochan/expo-iap/blob/main/example/App.tsx).
|
|
6
36
|
|
|
7
37
|
## Installation in Bare React Native Projects
|
|
8
38
|
|
|
9
|
-
For bare
|
|
39
|
+
For bare projects, ensure the [`expo` package is installed and configured](https://docs.expo.dev/bare/installing-expo-modules/).
|
|
10
40
|
|
|
11
|
-
### Add the Package
|
|
41
|
+
### Add the Package
|
|
12
42
|
|
|
13
43
|
```bash
|
|
14
44
|
npm install expo-iap
|
|
@@ -16,7 +46,7 @@ npm install expo-iap
|
|
|
16
46
|
|
|
17
47
|
### Configure for iOS
|
|
18
48
|
|
|
19
|
-
Run `npx pod-install
|
|
49
|
+
Run `npx pod-install`. Set `deploymentTarget` to `15.0` or higher (StoreKit 2 requirement):
|
|
20
50
|
|
|
21
51
|
```json
|
|
22
52
|
"ios": {
|
|
@@ -26,7 +56,7 @@ Run `npx pod-install` after installing the npm package. Since `expo-iap` uses `S
|
|
|
26
56
|
|
|
27
57
|
### Configure for Android
|
|
28
58
|
|
|
29
|
-
No additional configuration is
|
|
59
|
+
No additional configuration is needed—Google Play Billing is handled internally.
|
|
30
60
|
|
|
31
61
|
### Configure with Expo Config Plugin
|
|
32
62
|
|
|
@@ -35,9 +65,7 @@ Add 'expo-iap' to the plugins array in your app.json or app.config.js file:
|
|
|
35
65
|
```json
|
|
36
66
|
{
|
|
37
67
|
"expo": {
|
|
38
|
-
"plugins": [
|
|
39
|
-
"expo-iap"
|
|
40
|
-
]
|
|
68
|
+
"plugins": ["expo-iap"]
|
|
41
69
|
}
|
|
42
70
|
}
|
|
43
71
|
```
|
|
@@ -50,128 +78,406 @@ This plugin automatically sets up the necessary Android configuration, including
|
|
|
50
78
|
|
|
51
79
|
### Consumable
|
|
52
80
|
|
|
53
|
-
- **Description**: Items that are
|
|
54
|
-
- **Behavior**: Requires
|
|
55
|
-
- **Platforms**: Supported on
|
|
81
|
+
- **Description**: Items that are consumed after purchase and can be repurchased (e.g., in-game currency, boosts).
|
|
82
|
+
- **Behavior**: Requires acknowledgment to enable repurchasing.
|
|
83
|
+
- **Platforms**: Supported on Android and iOS.
|
|
56
84
|
|
|
57
85
|
### Non-Consumable
|
|
58
86
|
|
|
59
|
-
- **Description**: One-time purchases
|
|
60
|
-
- **Behavior**: Supports restoration
|
|
61
|
-
- **Platforms**: Supported on
|
|
87
|
+
- **Description**: One-time purchases owned permanently (e.g., ad removal, premium features).
|
|
88
|
+
- **Behavior**: Supports restoration; cannot be repurchased.
|
|
89
|
+
- **Platforms**: Supported on Android and iOS.
|
|
62
90
|
|
|
63
91
|
### Subscription
|
|
64
92
|
|
|
65
|
-
- **Description**: Recurring purchases for ongoing access
|
|
66
|
-
- **Behavior**: Includes auto-renewing options and
|
|
67
|
-
- **Platforms**: Supported on
|
|
93
|
+
- **Description**: Recurring purchases for ongoing access (e.g., monthly memberships).
|
|
94
|
+
- **Behavior**: Includes auto-renewing options and restoration.
|
|
95
|
+
- **Platforms**: Supported on Android and iOS.
|
|
68
96
|
|
|
69
97
|
## Product Type
|
|
70
98
|
|
|
71
|
-
This section outlines the properties of products supported by `expo-iap
|
|
72
|
-
|
|
73
|
-
### Common Product Types
|
|
99
|
+
This section outlines the properties of products supported by `expo-iap`.
|
|
74
100
|
|
|
75
|
-
|
|
101
|
+
### Common Product Types (`BaseProduct`)
|
|
76
102
|
|
|
77
|
-
| Property | Type | Description
|
|
78
|
-
| -------------- | ------------- |
|
|
79
|
-
| `id` | `string` | Unique
|
|
80
|
-
| `title` | `string` |
|
|
81
|
-
| `description` | `string` |
|
|
82
|
-
| `type` | `ProductType` |
|
|
83
|
-
| `displayName` | `string?` |
|
|
84
|
-
| `displayPrice` | `string?` |
|
|
85
|
-
| `price` | `number?` |
|
|
86
|
-
| `currency` | `string?` | Currency code (optional)
|
|
103
|
+
| Property | Type | Description |
|
|
104
|
+
| -------------- | ------------- | -------------------------- |
|
|
105
|
+
| `id` | `string` | Unique product identifier |
|
|
106
|
+
| `title` | `string` | Product title |
|
|
107
|
+
| `description` | `string` | Product description |
|
|
108
|
+
| `type` | `ProductType` | `inapp` or `subs` |
|
|
109
|
+
| `displayName` | `string?` | UI display name (optional) |
|
|
110
|
+
| `displayPrice` | `string?` | Formatted price (optional) |
|
|
111
|
+
| `price` | `number?` | Price value (optional) |
|
|
112
|
+
| `currency` | `string?` | Currency code (optional) |
|
|
87
113
|
|
|
88
114
|
### Android-Only Product Types
|
|
89
115
|
|
|
90
116
|
- **`ProductAndroid`**
|
|
91
|
-
|
|
92
|
-
- `
|
|
93
|
-
- `oneTimePurchaseOfferDetails?: OneTimePurchaseOfferDetails`: Details for one-time purchases (e.g., price, currency).
|
|
117
|
+
- `name: string`: Product name (replaces `displayName` on Android).
|
|
118
|
+
- `oneTimePurchaseOfferDetails?: OneTimePurchaseOfferDetails`: One-time purchase details.
|
|
94
119
|
- `subscriptionOfferDetails?: SubscriptionOfferDetail[]`: Subscription offer details.
|
|
95
|
-
|
|
96
120
|
- **`SubscriptionProductAndroid`**
|
|
97
|
-
- `subscriptionOfferDetails: SubscriptionOfferAndroid[]`: Subscription-specific offers
|
|
121
|
+
- `subscriptionOfferDetails: SubscriptionOfferAndroid[]`: Subscription-specific offers.
|
|
98
122
|
|
|
99
123
|
### iOS-Only Product Types
|
|
100
124
|
|
|
101
125
|
- **`ProductIos`**
|
|
102
|
-
|
|
103
|
-
- `
|
|
104
|
-
- `
|
|
105
|
-
- `
|
|
106
|
-
- `subscription: SubscriptionInfo`: Subscription details (e.g., introductory offers, group ID).
|
|
107
|
-
|
|
126
|
+
- `displayPrice: string`: Formatted price.
|
|
127
|
+
- `isFamilyShareable: boolean`: Family sharing support.
|
|
128
|
+
- `jsonRepresentation: string`: StoreKit 2 JSON data.
|
|
129
|
+
- `subscription: SubscriptionInfo`: Subscription details.
|
|
108
130
|
- **`SubscriptionProductIos`**
|
|
109
|
-
- `discounts?: Discount[]`: Discount details
|
|
110
|
-
- `introductoryPrice?: string`: Introductory pricing
|
|
131
|
+
- `discounts?: Discount[]`: Discount details.
|
|
132
|
+
- `introductoryPrice?: string`: Introductory pricing info.
|
|
111
133
|
|
|
112
134
|
## Purchase Type
|
|
113
135
|
|
|
114
|
-
This section describes
|
|
115
|
-
|
|
116
|
-
### Common Purchase Types
|
|
136
|
+
This section describes purchase properties in `expo-iap`.
|
|
117
137
|
|
|
118
|
-
|
|
138
|
+
### Common Purchase Types (`ProductPurchase`)
|
|
119
139
|
|
|
120
|
-
| Property | Type | Description
|
|
121
|
-
| -------------------- | --------- |
|
|
122
|
-
| `id` | `string` |
|
|
123
|
-
| `transactionId` | `string?` |
|
|
124
|
-
| `transactionDate` | `number` |
|
|
125
|
-
| `transactionReceipt` | `string` |
|
|
126
|
-
| `purchaseToken` | `string?` | Purchase token (optional)
|
|
140
|
+
| Property | Type | Description |
|
|
141
|
+
| -------------------- | --------- | ------------------------- |
|
|
142
|
+
| `id` | `string` | Purchased product ID |
|
|
143
|
+
| `transactionId` | `string?` | Transaction ID (optional) |
|
|
144
|
+
| `transactionDate` | `number` | Unix timestamp |
|
|
145
|
+
| `transactionReceipt` | `string` | Receipt data |
|
|
146
|
+
| `purchaseToken` | `string?` | Purchase token (optional) |
|
|
127
147
|
|
|
128
148
|
### Android-Only Purchase Types
|
|
129
149
|
|
|
130
|
-
- **`ProductPurchase`
|
|
131
|
-
|
|
132
|
-
- `ids?: string[]`: List of purchased product IDs.
|
|
133
|
-
- `dataAndroid?: string`: Payment data.
|
|
134
|
-
- `signatureAndroid?: string`: Signature data.
|
|
135
|
-
- `autoRenewingAndroid?: boolean`: Auto-renewal status.
|
|
136
|
-
- `purchaseStateAndroid?: PurchaseStateAndroid`: Purchase state (e.g., PURCHASED, PENDING).
|
|
137
|
-
|
|
138
|
-
- **`SubscriptionPurchase` (Android Extensions)**
|
|
139
|
-
- `autoRenewingAndroid?: boolean`: Subscription auto-renewal status.
|
|
150
|
+
- **`ProductPurchase`**: Adds `ids`, `dataAndroid`, `signatureAndroid`, `purchaseStateAndroid`.
|
|
151
|
+
- **`SubscriptionPurchase`**: Includes `autoRenewingAndroid`.
|
|
140
152
|
|
|
141
153
|
### iOS-Only Purchase Types
|
|
142
154
|
|
|
143
|
-
- **`ProductPurchase`
|
|
144
|
-
|
|
145
|
-
- `quantityIos?: number`: Purchase quantity.
|
|
146
|
-
- `originalTransactionDateIos?: number`: Original transaction date.
|
|
147
|
-
- `originalTransactionIdentifierIos?: string`: Original transaction ID.
|
|
148
|
-
- `verificationResultIos?: string`: Verification result.
|
|
149
|
-
- `appAccountToken?: string`: App account token.
|
|
150
|
-
- `expirationDateIos?: number`: Expiration date for subscriptions.
|
|
151
|
-
- `webOrderLineItemIdIos?: number`: Web order line item ID.
|
|
152
|
-
- `environmentIos?: string`: App Store environment.
|
|
153
|
-
- `storefrontCountryCodeIos?: string`: App Store storefront country code.
|
|
154
|
-
- `appBundleIdIos?: string`: App bundle ID.
|
|
155
|
-
- `productTypeIos?: string`: Product type (e.g., "autoRenewable").
|
|
156
|
-
- `subscriptionGroupIdIos?: string`: Subscription group ID.
|
|
157
|
-
- `isUpgradedIos?: boolean`: Whether the subscription was upgraded.
|
|
158
|
-
- `ownershipTypeIos?: string`: Ownership type (e.g., individual, family sharing).
|
|
159
|
-
- `reasonIos?: string`: Transaction reason.
|
|
160
|
-
- `transactionReasonIos?: string`: Detailed transaction reason.
|
|
161
|
-
- `revocationDateIos?: number`: Date of revocation if refunded.
|
|
162
|
-
- `revocationReasonIos?: string`: Reason for revocation.
|
|
163
|
-
|
|
164
|
-
- **`SubscriptionPurchase` (iOS Extensions)**
|
|
165
|
-
- All the iOS-specific fields from `ProductPurchase`
|
|
166
|
-
- Automatic subscription-specific handling based on product type
|
|
155
|
+
- **`ProductPurchase`**: Adds fields like `quantityIos`, `expirationDateIos`, `subscriptionGroupIdIos`.
|
|
156
|
+
- **`SubscriptionPurchase`**: Extends with subscription-specific handling.
|
|
167
157
|
|
|
168
158
|
## Implementation Notes
|
|
169
159
|
|
|
170
160
|
### Platform-Uniform Purchase Handling
|
|
171
161
|
|
|
172
|
-
|
|
162
|
+
Transactions are mapped directly to `Purchase` or `SubscriptionPurchase` with platform-specific fields (e.g., `expirationDateIos`, `purchaseStateAndroid`).
|
|
163
|
+
|
|
164
|
+
### Status
|
|
165
|
+
|
|
166
|
+
This module is under development—expect occasional bugs (e.g., Android acknowledgment issues). Test thoroughly and consider contributing fixes!
|
|
167
|
+
|
|
168
|
+
> **Sample Code**: See [example/App.tsx](https://github.com/hyochan/expo-iap/blob/main/example/App.tsx).
|
|
169
|
+
|
|
170
|
+
## Implementation
|
|
171
|
+
|
|
172
|
+
Below is a simple example of fetching products and making a purchase with `expo-iap` in a managed workflow:
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
import {useEffect, useState} from 'react';
|
|
176
|
+
import {Button, Text, View} from 'react-native';
|
|
177
|
+
import {
|
|
178
|
+
initConnection,
|
|
179
|
+
endConnection,
|
|
180
|
+
getProducts,
|
|
181
|
+
requestPurchase,
|
|
182
|
+
purchaseUpdatedListener,
|
|
183
|
+
finishTransaction,
|
|
184
|
+
} from 'expo-iap';
|
|
185
|
+
|
|
186
|
+
export default function SimpleIAP() {
|
|
187
|
+
const [isConnected, setIsConnected] = useState(false);
|
|
188
|
+
const [product, setProduct] = useState(null);
|
|
189
|
+
|
|
190
|
+
// Initialize IAP and fetch products
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
const setupIAP = async () => {
|
|
193
|
+
if (await initConnection()) {
|
|
194
|
+
setIsConnected(true);
|
|
195
|
+
const products = await getProducts(['my.consumable.item']); // Replace with your product SKU
|
|
196
|
+
if (products.length > 0) setProduct(products[0]);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
setupIAP();
|
|
200
|
+
|
|
201
|
+
// Handle purchase updates
|
|
202
|
+
const purchaseListener = purchaseUpdatedListener(async (purchase) => {
|
|
203
|
+
if (purchase.transactionReceipt) {
|
|
204
|
+
await finishTransaction({purchase, isConsumable: true});
|
|
205
|
+
alert('Purchase completed!');
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
return () => {
|
|
210
|
+
purchaseListener.remove();
|
|
211
|
+
endConnection();
|
|
212
|
+
};
|
|
213
|
+
}, []);
|
|
214
|
+
|
|
215
|
+
// Trigger a purchase
|
|
216
|
+
const buyItem = async () => {
|
|
217
|
+
if (!product) return;
|
|
218
|
+
await requestPurchase({skus: [product.id]});
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
return (
|
|
222
|
+
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
|
|
223
|
+
<Text>{isConnected ? 'Connected' : 'Connecting...'}</Text>
|
|
224
|
+
{product ? (
|
|
225
|
+
<>
|
|
226
|
+
<Text>{`${product.title} - ${product.displayPrice}`}</Text>
|
|
227
|
+
<Button title="Buy Now" onPress={buyItem} />
|
|
228
|
+
</>
|
|
229
|
+
) : (
|
|
230
|
+
<Text>Loading product...</Text>
|
|
231
|
+
)}
|
|
232
|
+
</View>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
```
|
|
173
236
|
|
|
174
|
-
|
|
175
|
-
|
|
237
|
+
## Using useIAP Hook
|
|
238
|
+
|
|
239
|
+
The `useIAP` hook simplifies managing in-app purchases with `expo-iap`. Below is an example that fetches products and subscriptions, and allows purchasing them, styled similarly to the `expo-iap` example app. It assumes you’ve implemented the custom `useIAP` hook in your project.
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
import {useEffect, useState} from 'react';
|
|
243
|
+
import {
|
|
244
|
+
SafeAreaView,
|
|
245
|
+
ScrollView,
|
|
246
|
+
StyleSheet,
|
|
247
|
+
Text,
|
|
248
|
+
View,
|
|
249
|
+
Pressable,
|
|
250
|
+
Button,
|
|
251
|
+
InteractionManager,
|
|
252
|
+
Alert,
|
|
253
|
+
} from 'react-native';
|
|
254
|
+
import {useIap} from 'expo-iap';
|
|
255
|
+
import type {
|
|
256
|
+
PurchaseError,
|
|
257
|
+
ProductPurchase,
|
|
258
|
+
SubscriptionProduct,
|
|
259
|
+
} from 'expo-iap';
|
|
260
|
+
import {RequestSubscriptionAndroidProps} from './types/ExpoIapAndroid.types'; // Adjust path as needed
|
|
261
|
+
|
|
262
|
+
// Define SKUs
|
|
263
|
+
const productSkus = [
|
|
264
|
+
'cpk.points.1000',
|
|
265
|
+
'cpk.points.5000',
|
|
266
|
+
'cpk.points.10000',
|
|
267
|
+
'cpk.points.30000',
|
|
268
|
+
];
|
|
269
|
+
|
|
270
|
+
const subscriptionSkus = [
|
|
271
|
+
'cpk.membership.monthly.bronze',
|
|
272
|
+
'cpk.membership.monthly.silver',
|
|
273
|
+
];
|
|
274
|
+
|
|
275
|
+
// Define operations
|
|
276
|
+
const operations = [
|
|
277
|
+
'initConnection',
|
|
278
|
+
'getProducts',
|
|
279
|
+
'getSubscriptions',
|
|
280
|
+
'endConnection',
|
|
281
|
+
];
|
|
282
|
+
type Operation = (typeof operations)[number];
|
|
283
|
+
|
|
284
|
+
export default function IAPWithHook() {
|
|
285
|
+
const {
|
|
286
|
+
connected,
|
|
287
|
+
products,
|
|
288
|
+
subscriptions,
|
|
289
|
+
currentPurchase,
|
|
290
|
+
currentPurchaseError,
|
|
291
|
+
getProducts,
|
|
292
|
+
getSubscriptions,
|
|
293
|
+
finishTransaction,
|
|
294
|
+
requestPurchase,
|
|
295
|
+
requestSubscription,
|
|
296
|
+
} = useIAP();
|
|
297
|
+
|
|
298
|
+
const [isConnected, setIsConnected] = useState(connected);
|
|
299
|
+
|
|
300
|
+
// Handle operations
|
|
301
|
+
const handleOperation = async (operation: Operation) => {
|
|
302
|
+
switch (operation) {
|
|
303
|
+
case 'initConnection':
|
|
304
|
+
setIsConnected(true); // Connection is handled by useIAP hook
|
|
305
|
+
break;
|
|
306
|
+
case 'endConnection':
|
|
307
|
+
setIsConnected(false); // Cleanup is handled by useIAP hook
|
|
308
|
+
break;
|
|
309
|
+
case 'getProducts':
|
|
310
|
+
try {
|
|
311
|
+
await getProducts(productSkus);
|
|
312
|
+
} catch (error) {
|
|
313
|
+
console.error('Error fetching products:', error);
|
|
314
|
+
}
|
|
315
|
+
break;
|
|
316
|
+
case 'getSubscriptions':
|
|
317
|
+
try {
|
|
318
|
+
await getSubscriptions(subscriptionSkus);
|
|
319
|
+
} catch (error) {
|
|
320
|
+
console.error('Error fetching subscriptions:', error);
|
|
321
|
+
}
|
|
322
|
+
break;
|
|
323
|
+
default:
|
|
324
|
+
console.log('Unknown operation');
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
// Handle purchase updates and errors
|
|
329
|
+
useEffect(() => {
|
|
330
|
+
if (currentPurchase?.transactionReceipt) {
|
|
331
|
+
InteractionManager.runAfterInteractions(async () => {
|
|
332
|
+
try {
|
|
333
|
+
await finishTransaction({
|
|
334
|
+
purchase: currentPurchase,
|
|
335
|
+
isConsumable: true,
|
|
336
|
+
});
|
|
337
|
+
Alert.alert('Purchase updated', JSON.stringify(currentPurchase));
|
|
338
|
+
} catch (error) {
|
|
339
|
+
console.error('Error finishing transaction:', error);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (currentPurchaseError) {
|
|
345
|
+
InteractionManager.runAfterInteractions(() => {
|
|
346
|
+
Alert.alert('Purchase error', JSON.stringify(currentPurchaseError));
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}, [currentPurchase, currentPurchaseError, finishTransaction]);
|
|
350
|
+
|
|
351
|
+
return (
|
|
352
|
+
<SafeAreaView style={styles.container}>
|
|
353
|
+
<Text style={styles.title}>Expo IAP with useIAP Hook</Text>
|
|
354
|
+
<View style={styles.buttons}>
|
|
355
|
+
<ScrollView contentContainerStyle={styles.buttonsWrapper} horizontal>
|
|
356
|
+
{operations.map((operation) => (
|
|
357
|
+
<Pressable
|
|
358
|
+
key={operation}
|
|
359
|
+
onPress={() => handleOperation(operation)}
|
|
360
|
+
>
|
|
361
|
+
<View style={styles.buttonView}>
|
|
362
|
+
<Text>{operation}</Text>
|
|
363
|
+
</View>
|
|
364
|
+
</Pressable>
|
|
365
|
+
))}
|
|
366
|
+
</ScrollView>
|
|
367
|
+
</View>
|
|
368
|
+
<View style={styles.content}>
|
|
369
|
+
{!isConnected ? (
|
|
370
|
+
<Text>Not connected</Text>
|
|
371
|
+
) : (
|
|
372
|
+
<View style={{gap: 12}}>
|
|
373
|
+
<Text style={{fontSize: 20}}>Products</Text>
|
|
374
|
+
{products.map((item) => {
|
|
375
|
+
if (item.platform === 'android') {
|
|
376
|
+
return (
|
|
377
|
+
<View key={item.title} style={{gap: 12}}>
|
|
378
|
+
<Text>
|
|
379
|
+
{item.title} -{' '}
|
|
380
|
+
{item.oneTimePurchaseOfferDetails?.formattedPrice}
|
|
381
|
+
</Text>
|
|
382
|
+
<Button
|
|
383
|
+
title="Buy"
|
|
384
|
+
onPress={() => requestPurchase({skus: [item.id]})}
|
|
385
|
+
/>
|
|
386
|
+
</View>
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
if (item.platform === 'ios') {
|
|
390
|
+
return (
|
|
391
|
+
<View key={item.id} style={{gap: 12}}>
|
|
392
|
+
<Text>
|
|
393
|
+
{item.title} - {item.displayPrice}
|
|
394
|
+
</Text>
|
|
395
|
+
<Button
|
|
396
|
+
title="Buy"
|
|
397
|
+
onPress={() => requestPurchase({sku: item.id})}
|
|
398
|
+
/>
|
|
399
|
+
</View>
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
})}
|
|
403
|
+
|
|
404
|
+
<Text style={{fontSize: 20}}>Subscriptions</Text>
|
|
405
|
+
{subscriptions.map((item) => {
|
|
406
|
+
if (item.platform === 'android') {
|
|
407
|
+
return item.subscriptionOfferDetails?.map((offer) => (
|
|
408
|
+
<View key={offer.offerId} style={{gap: 12}}>
|
|
409
|
+
<Text>
|
|
410
|
+
{item.title} -{' '}
|
|
411
|
+
{offer.pricingPhases.pricingPhaseList
|
|
412
|
+
.map((ppl) => ppl.billingPeriod)
|
|
413
|
+
.join(',')}
|
|
414
|
+
</Text>
|
|
415
|
+
<Button
|
|
416
|
+
title="Subscribe"
|
|
417
|
+
onPress={() =>
|
|
418
|
+
requestSubscription({
|
|
419
|
+
skus: [item.id],
|
|
420
|
+
...(offer.offerToken && {
|
|
421
|
+
subscriptionOffers: [
|
|
422
|
+
{sku: item.id, offerToken: offer.offerToken},
|
|
423
|
+
],
|
|
424
|
+
}),
|
|
425
|
+
} as RequestSubscriptionAndroidProps)
|
|
426
|
+
}
|
|
427
|
+
/>
|
|
428
|
+
</View>
|
|
429
|
+
));
|
|
430
|
+
}
|
|
431
|
+
if (item.platform === 'ios') {
|
|
432
|
+
return (
|
|
433
|
+
<View key={item.id} style={{gap: 12}}>
|
|
434
|
+
<Text>
|
|
435
|
+
{item.displayName} - {item.displayPrice}
|
|
436
|
+
</Text>
|
|
437
|
+
<Button
|
|
438
|
+
title="Subscribe"
|
|
439
|
+
onPress={() => requestSubscription({sku: item.id})}
|
|
440
|
+
/>
|
|
441
|
+
</View>
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
})}
|
|
445
|
+
</View>
|
|
446
|
+
)}
|
|
447
|
+
</View>
|
|
448
|
+
</SafeAreaView>
|
|
449
|
+
);
|
|
450
|
+
}
|
|
176
451
|
|
|
177
|
-
|
|
452
|
+
const styles = StyleSheet.create({
|
|
453
|
+
container: {
|
|
454
|
+
flex: 1,
|
|
455
|
+
backgroundColor: '#fff',
|
|
456
|
+
alignItems: 'center',
|
|
457
|
+
},
|
|
458
|
+
title: {
|
|
459
|
+
marginTop: 24,
|
|
460
|
+
fontSize: 20,
|
|
461
|
+
fontWeight: 'bold',
|
|
462
|
+
},
|
|
463
|
+
buttons: {
|
|
464
|
+
height: 90,
|
|
465
|
+
},
|
|
466
|
+
buttonsWrapper: {
|
|
467
|
+
padding: 24,
|
|
468
|
+
gap: 8,
|
|
469
|
+
},
|
|
470
|
+
buttonView: {
|
|
471
|
+
borderRadius: 8,
|
|
472
|
+
borderWidth: 1,
|
|
473
|
+
borderColor: '#000',
|
|
474
|
+
padding: 8,
|
|
475
|
+
},
|
|
476
|
+
content: {
|
|
477
|
+
flex: 1,
|
|
478
|
+
alignSelf: 'stretch',
|
|
479
|
+
padding: 24,
|
|
480
|
+
gap: 12,
|
|
481
|
+
},
|
|
482
|
+
});
|
|
483
|
+
```
|
package/package.json
CHANGED
package/src/ExpoIap.types.ts
CHANGED
|
@@ -61,7 +61,7 @@ export type ProductPurchase =
|
|
|
61
61
|
|
|
62
62
|
// Union type for platform-specific subscription purchase types with proper discriminators
|
|
63
63
|
export type SubscriptionPurchase =
|
|
64
|
-
| (ProductPurchaseAndroid & AndroidPlatform & {
|
|
64
|
+
| (ProductPurchaseAndroid & AndroidPlatform & {autoRenewingAndroid: boolean})
|
|
65
65
|
| (ProductPurchaseIos & IosPlatform);
|
|
66
66
|
|
|
67
67
|
export type Purchase = ProductPurchase | SubscriptionPurchase;
|
package/src/index.ts
CHANGED
|
@@ -41,12 +41,12 @@ export enum IapEvent {
|
|
|
41
41
|
TransactionIapUpdated = 'iap-transaction-updated',
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export
|
|
45
|
-
return
|
|
44
|
+
export function setValueAsync(value: string) {
|
|
45
|
+
return ExpoIapModule.setValueAsync(value);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export const emitter = new EventEmitter(
|
|
49
|
-
ExpoIapModule
|
|
49
|
+
ExpoIapModule || NativeModulesProxy.ExpoIap,
|
|
50
50
|
);
|
|
51
51
|
|
|
52
52
|
export const purchaseUpdatedListener = (
|
|
@@ -104,7 +104,6 @@ export const getSubscriptions = async (
|
|
|
104
104
|
return Platform.select({
|
|
105
105
|
ios: async () => {
|
|
106
106
|
const rawItems = await ExpoIapModule.getItems(skus);
|
|
107
|
-
|
|
108
107
|
return rawItems.filter((item: unknown) => {
|
|
109
108
|
if (!isSubscriptionProductIos(item)) return false;
|
|
110
109
|
return (
|
|
@@ -118,7 +117,6 @@ export const getSubscriptions = async (
|
|
|
118
117
|
},
|
|
119
118
|
android: async () => {
|
|
120
119
|
const rawItems = await ExpoIapModule.getItemsByType('subs', skus);
|
|
121
|
-
|
|
122
120
|
return rawItems.filter((item: unknown) => {
|
|
123
121
|
if (!isSubscriptionProductAndroid(item)) return false;
|
|
124
122
|
return (
|
|
@@ -157,11 +155,9 @@ export const getPurchaseHistory = ({
|
|
|
157
155
|
const products = await ExpoIapModule.getPurchaseHistoryByType(
|
|
158
156
|
ProductType.InAppPurchase,
|
|
159
157
|
);
|
|
160
|
-
|
|
161
158
|
const subscriptions = await ExpoIapModule.getPurchaseHistoryByType(
|
|
162
159
|
ProductType.Subscription,
|
|
163
160
|
);
|
|
164
|
-
|
|
165
161
|
return products.concat(subscriptions);
|
|
166
162
|
},
|
|
167
163
|
}) || (() => Promise.resolve([]))
|
|
@@ -185,11 +181,9 @@ export const getAvailablePurchases = ({
|
|
|
185
181
|
const products = await ExpoIapModule.getAvailableItemsByType(
|
|
186
182
|
ProductType.InAppPurchase,
|
|
187
183
|
);
|
|
188
|
-
|
|
189
184
|
const subscriptions = await ExpoIapModule.getAvailableItemsByType(
|
|
190
185
|
ProductType.Subscription,
|
|
191
186
|
);
|
|
192
|
-
|
|
193
187
|
return products.concat(subscriptions);
|
|
194
188
|
},
|
|
195
189
|
}) || (() => Promise.resolve([]))
|
|
@@ -219,32 +213,26 @@ export const requestPurchase = (
|
|
|
219
213
|
if (!('sku' in request)) {
|
|
220
214
|
throw new Error('sku is required for iOS purchase');
|
|
221
215
|
}
|
|
222
|
-
|
|
223
216
|
const {sku, appAccountToken, quantity, withOffer} = request;
|
|
224
|
-
|
|
225
217
|
const offer = offerToRecordIos(withOffer);
|
|
226
|
-
|
|
227
218
|
const purchase = await ExpoIapModule.buyProduct(
|
|
228
219
|
sku,
|
|
229
220
|
appAccountToken,
|
|
230
221
|
quantity ?? -1,
|
|
231
222
|
offer,
|
|
232
223
|
);
|
|
233
|
-
|
|
234
224
|
return Promise.resolve(purchase);
|
|
235
225
|
},
|
|
236
226
|
android: async () => {
|
|
237
227
|
if (!('skus' in request) || !request.skus.length) {
|
|
238
228
|
throw new Error('skus is required for Android purchase');
|
|
239
229
|
}
|
|
240
|
-
|
|
241
230
|
const {
|
|
242
231
|
skus,
|
|
243
232
|
obfuscatedAccountIdAndroid,
|
|
244
233
|
obfuscatedProfileIdAndroid,
|
|
245
234
|
isOfferPersonalized,
|
|
246
235
|
} = request;
|
|
247
|
-
|
|
248
236
|
return ExpoIapModule.buyItemByType({
|
|
249
237
|
type: ProductType.InAppPurchase,
|
|
250
238
|
skuArr: skus,
|
|
@@ -268,19 +256,15 @@ export const requestSubscription = (
|
|
|
268
256
|
if (!('sku' in request)) {
|
|
269
257
|
throw new Error('sku is required for iOS subscriptions');
|
|
270
258
|
}
|
|
271
|
-
|
|
272
259
|
const {sku, appAccountToken, quantity, withOffer} =
|
|
273
260
|
request as RequestSubscriptionIosProps;
|
|
274
|
-
|
|
275
261
|
const offer = offerToRecordIos(withOffer);
|
|
276
|
-
|
|
277
262
|
const purchase = await ExpoIapModule.buyProduct(
|
|
278
263
|
sku,
|
|
279
264
|
appAccountToken,
|
|
280
265
|
quantity ?? -1,
|
|
281
266
|
offer,
|
|
282
267
|
);
|
|
283
|
-
|
|
284
268
|
return Promise.resolve(purchase as SubscriptionPurchase);
|
|
285
269
|
},
|
|
286
270
|
android: async () => {
|
|
@@ -293,7 +277,6 @@ export const requestSubscription = (
|
|
|
293
277
|
replacementModeAndroid,
|
|
294
278
|
purchaseTokenAndroid,
|
|
295
279
|
} = request as RequestSubscriptionAndroidProps;
|
|
296
|
-
|
|
297
280
|
return ExpoIapModule.buyItemByType({
|
|
298
281
|
type: ProductType.Subscription,
|
|
299
282
|
skuArr: skus.map((so) => so),
|
|
@@ -311,17 +294,14 @@ export const requestSubscription = (
|
|
|
311
294
|
export const finishTransaction = ({
|
|
312
295
|
purchase,
|
|
313
296
|
isConsumable,
|
|
314
|
-
developerPayloadAndroid,
|
|
315
297
|
}: {
|
|
316
298
|
purchase: Purchase;
|
|
317
299
|
isConsumable?: boolean;
|
|
318
|
-
developerPayloadAndroid?: string;
|
|
319
300
|
}): Promise<PurchaseResult | boolean> => {
|
|
320
301
|
return (
|
|
321
302
|
Platform.select({
|
|
322
303
|
ios: async () => {
|
|
323
304
|
const transactionId = purchase.transactionId;
|
|
324
|
-
|
|
325
305
|
if (!transactionId) {
|
|
326
306
|
return Promise.reject(
|
|
327
307
|
new Error('transactionId required to finish iOS transaction'),
|
|
@@ -331,21 +311,16 @@ export const finishTransaction = ({
|
|
|
331
311
|
return Promise.resolve(true);
|
|
332
312
|
},
|
|
333
313
|
android: async () => {
|
|
334
|
-
if (purchase?.purchaseToken) {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
new Error('purchase is not suitable to be purchased'),
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
return ExpoIapModule.consumeProduct(
|
|
342
|
-
purchase.purchaseToken,
|
|
343
|
-
developerPayloadAndroid,
|
|
314
|
+
if (!purchase?.purchaseToken) {
|
|
315
|
+
return Promise.reject(
|
|
316
|
+
new Error('purchaseToken is required to finish transaction'),
|
|
344
317
|
);
|
|
345
318
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
319
|
+
if (isConsumable) {
|
|
320
|
+
return ExpoIapModule.consumeProduct(purchase.purchaseToken);
|
|
321
|
+
} else {
|
|
322
|
+
return ExpoIapModule.acknowledgePurchase(purchase.purchaseToken);
|
|
323
|
+
}
|
|
349
324
|
},
|
|
350
325
|
}) || (() => Promise.reject(new Error('Unsupported Platform')))
|
|
351
326
|
)();
|
package/src/useIap.ts
CHANGED
|
@@ -109,7 +109,8 @@ export function useIAP(): IAP_STATUS {
|
|
|
109
109
|
setCurrentPurchase(undefined);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
if (purchase.id === currentPurchaseError?.productId) {
|
|
112
|
+
if (purchase.id === currentPurchaseError?.productId) {
|
|
113
|
+
// Note that PurchaseError still uses productId
|
|
113
114
|
setCurrentPurchaseError(undefined);
|
|
114
115
|
}
|
|
115
116
|
}
|