react-native-iap 12.4.9 → 12.4.10
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/ios/RNIapIos.swift +2 -7
- package/lib/commonjs/modules/ios.js +13 -2
- package/lib/commonjs/modules/ios.js.map +1 -1
- package/lib/module/modules/ios.js +13 -2
- package/lib/module/modules/ios.js.map +1 -1
- package/lib/typescript/modules/ios.d.ts +13 -2
- package/package.json +1 -1
- package/src/modules/ios.ts +13 -2
package/ios/RNIapIos.swift
CHANGED
|
@@ -601,15 +601,10 @@ class RNIapIos: RCTEventEmitter, SKRequestDelegate, SKPaymentTransactionObserver
|
|
|
601
601
|
}
|
|
602
602
|
|
|
603
603
|
periodNumberIOS = String(format: "%lu", numOfUnits)
|
|
604
|
-
|
|
604
|
+
|
|
605
|
+
if product.subscriptionPeriod != nil {
|
|
605
606
|
itemType = "subs"
|
|
606
607
|
}
|
|
607
|
-
// More reliable way of determining a subs on newer iOS versions
|
|
608
|
-
if #available(iOS 12.0, tvOS 12.0, *) {
|
|
609
|
-
if product.subscriptionGroupIdentifier != nil {
|
|
610
|
-
itemType = "subs"
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
608
|
|
|
614
609
|
// subscriptionPeriod = product.subscriptionPeriod ? [product.subscriptionPeriod stringValue] : @"";
|
|
615
610
|
// introductoryPrice = product.introductoryPrice != nil ? [NSString stringWithFormat:@"%@", product.introductoryPrice] : @"";
|
|
@@ -21,8 +21,19 @@ const {
|
|
|
21
21
|
const getPendingPurchasesIOS = async () => (0, _internal.getIosModule)().getPendingTransactions();
|
|
22
22
|
/**
|
|
23
23
|
* Get the current receipt base64 encoded in IOS.
|
|
24
|
-
*
|
|
25
|
-
|
|
24
|
+
* From: https://apphud.com/blog/app-store-receipt-validation#what-is-app-store-receipt
|
|
25
|
+
> Does a receipt always exist in the app?
|
|
26
|
+
> If a user downloaded the app from the App Store – yes. However, in sandbox if your app was installed via Xcode or Testflight, then there won't be a receipt until you make a purchase or restore.
|
|
27
|
+
*
|
|
28
|
+
## Usage
|
|
29
|
+
```tsx
|
|
30
|
+
import {useCallback} from 'react';
|
|
31
|
+
import {getReceiptIOS} from 'react-native-iap';
|
|
32
|
+
|
|
33
|
+
const receipt = useCallback(async () => await getReceiptIOS({forceRefresh: false}));
|
|
34
|
+
```
|
|
35
|
+
* @param {forceRefresh?:boolean} Requests the receipt from Bundle.main.appStoreReceiptURL. Based on the note above, looks like forceRefresh only makes sense when testing an app not downloaded from the Appstore.
|
|
36
|
+
* @returns {Promise<string>} The receipt data
|
|
26
37
|
*/
|
|
27
38
|
|
|
28
39
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["RNIapIos","NativeModules","getPendingPurchasesIOS","getIosModule","getPendingTransactions","getReceiptIOS","forceRefresh","isIosStorekit2","requestReceipt","Promise","reject","presentCodeRedemptionSheetIOS","presentCodeRedemptionSheet","getPromotedProductIOS","promotedProduct","buyPromotedProductIOS","buyPromotedProduct","fetchJsonOrThrow","url","receiptBody","response","fetch","method","headers","Accept","body","JSON","stringify","ok","Object","assign","Error","statusText","statusCode","status","json","TEST_RECEIPT","requestAgnosticReceiptValidationIos","testResponse","validateReceiptIos","isTest","clearTransactionIOS","clearTransaction","clearProductsIOS","clearProducts"],"sources":["ios.ts"],"sourcesContent":["import {NativeModules} from 'react-native';\nimport type {ResponseBody as ReceiptValidationResponse} from '@jeremybarbet/apple-api-types';\n\nimport {getIosModule, isIosStorekit2} from '../internal';\nconst {RNIapIos} = NativeModules;\nimport type {\n ProductIOS,\n ProductPurchase,\n Purchase,\n Sku,\n SubscriptionIOS,\n} from '../types';\nimport type {PaymentDiscount} from '../types/apple';\n\nimport type {NativeModuleProps} from './common';\n\ntype getItems = (skus: Sku[]) => Promise<ProductIOS[] | SubscriptionIOS[]>;\n\ntype getAvailableItems = (\n automaticallyFinishRestoredTransactions: boolean,\n) => Promise<Purchase[]>;\n\nexport type BuyProduct = (\n sku: Sku,\n andDangerouslyFinishTransactionAutomaticallyIOS: boolean,\n applicationUsername: string | undefined,\n quantity: number,\n withOffer: Record<keyof PaymentDiscount, string> | undefined,\n) => Promise<Purchase>;\n\ntype clearTransaction = () => Promise<void>;\ntype clearProducts = () => Promise<void>;\ntype promotedProduct = () => Promise<ProductIOS | null>;\ntype buyPromotedProduct = () => Promise<void>;\ntype requestReceipt = (refresh: boolean) => Promise<string>;\n\ntype finishTransaction = (transactionIdentifier: string) => Promise<boolean>;\n\ntype getPendingTransactions = () => Promise<ProductPurchase[]>;\ntype presentCodeRedemptionSheet = () => Promise<null>;\n\nexport interface IosModuleProps extends NativeModuleProps {\n getItems: getItems;\n getAvailableItems: getAvailableItems;\n buyProduct: BuyProduct;\n clearTransaction: clearTransaction;\n clearProducts: clearProducts;\n promotedProduct: promotedProduct;\n buyPromotedProduct: buyPromotedProduct;\n requestReceipt: requestReceipt;\n finishTransaction: finishTransaction;\n getPendingTransactions: getPendingTransactions;\n presentCodeRedemptionSheet: presentCodeRedemptionSheet;\n disable: () => Promise<null>;\n}\n\n/**\n * Get the current receipt base64 encoded in IOS.\n * @param {forceRefresh?:boolean}\n * @returns {Promise<ProductPurchase[]>}\n */\nexport const getPendingPurchasesIOS = async (): Promise<ProductPurchase[]> =>\n getIosModule().getPendingTransactions();\n\n/**\n * Get the current receipt base64 encoded in IOS.\n * @param {forceRefresh?:boolean}
|
|
1
|
+
{"version":3,"names":["RNIapIos","NativeModules","getPendingPurchasesIOS","getIosModule","getPendingTransactions","getReceiptIOS","forceRefresh","isIosStorekit2","requestReceipt","Promise","reject","presentCodeRedemptionSheetIOS","presentCodeRedemptionSheet","getPromotedProductIOS","promotedProduct","buyPromotedProductIOS","buyPromotedProduct","fetchJsonOrThrow","url","receiptBody","response","fetch","method","headers","Accept","body","JSON","stringify","ok","Object","assign","Error","statusText","statusCode","status","json","TEST_RECEIPT","requestAgnosticReceiptValidationIos","testResponse","validateReceiptIos","isTest","clearTransactionIOS","clearTransaction","clearProductsIOS","clearProducts"],"sources":["ios.ts"],"sourcesContent":["import {NativeModules} from 'react-native';\nimport type {ResponseBody as ReceiptValidationResponse} from '@jeremybarbet/apple-api-types';\n\nimport {getIosModule, isIosStorekit2} from '../internal';\nconst {RNIapIos} = NativeModules;\nimport type {\n ProductIOS,\n ProductPurchase,\n Purchase,\n Sku,\n SubscriptionIOS,\n} from '../types';\nimport type {PaymentDiscount} from '../types/apple';\n\nimport type {NativeModuleProps} from './common';\n\ntype getItems = (skus: Sku[]) => Promise<ProductIOS[] | SubscriptionIOS[]>;\n\ntype getAvailableItems = (\n automaticallyFinishRestoredTransactions: boolean,\n) => Promise<Purchase[]>;\n\nexport type BuyProduct = (\n sku: Sku,\n andDangerouslyFinishTransactionAutomaticallyIOS: boolean,\n applicationUsername: string | undefined,\n quantity: number,\n withOffer: Record<keyof PaymentDiscount, string> | undefined,\n) => Promise<Purchase>;\n\ntype clearTransaction = () => Promise<void>;\ntype clearProducts = () => Promise<void>;\ntype promotedProduct = () => Promise<ProductIOS | null>;\ntype buyPromotedProduct = () => Promise<void>;\ntype requestReceipt = (refresh: boolean) => Promise<string>;\n\ntype finishTransaction = (transactionIdentifier: string) => Promise<boolean>;\n\ntype getPendingTransactions = () => Promise<ProductPurchase[]>;\ntype presentCodeRedemptionSheet = () => Promise<null>;\n\nexport interface IosModuleProps extends NativeModuleProps {\n getItems: getItems;\n getAvailableItems: getAvailableItems;\n buyProduct: BuyProduct;\n clearTransaction: clearTransaction;\n clearProducts: clearProducts;\n promotedProduct: promotedProduct;\n buyPromotedProduct: buyPromotedProduct;\n requestReceipt: requestReceipt;\n finishTransaction: finishTransaction;\n getPendingTransactions: getPendingTransactions;\n presentCodeRedemptionSheet: presentCodeRedemptionSheet;\n disable: () => Promise<null>;\n}\n\n/**\n * Get the current receipt base64 encoded in IOS.\n * @param {forceRefresh?:boolean}\n * @returns {Promise<ProductPurchase[]>}\n */\nexport const getPendingPurchasesIOS = async (): Promise<ProductPurchase[]> =>\n getIosModule().getPendingTransactions();\n\n/**\n * Get the current receipt base64 encoded in IOS.\n * From: https://apphud.com/blog/app-store-receipt-validation#what-is-app-store-receipt\n > Does a receipt always exist in the app?\n > If a user downloaded the app from the App Store – yes. However, in sandbox if your app was installed via Xcode or Testflight, then there won't be a receipt until you make a purchase or restore.\n * \n ## Usage \n ```tsx\nimport {useCallback} from 'react';\nimport {getReceiptIOS} from 'react-native-iap';\n\nconst receipt = useCallback(async () => await getReceiptIOS({forceRefresh: false}));\n```\n * @param {forceRefresh?:boolean} Requests the receipt from Bundle.main.appStoreReceiptURL. Based on the note above, looks like forceRefresh only makes sense when testing an app not downloaded from the Appstore.\n * @returns {Promise<string>} The receipt data\n */\nexport const getReceiptIOS = async ({\n forceRefresh,\n}: {\n forceRefresh?: boolean;\n}): Promise<string> => {\n if (!isIosStorekit2()) {\n return RNIapIos.requestReceipt(forceRefresh ?? false);\n } else {\n return Promise.reject('Only available on Sk1');\n }\n};\n/**\n * Launches a modal to register the redeem offer code in IOS.\n * @returns {Promise<null>}\n */\nexport const presentCodeRedemptionSheetIOS = async (): Promise<null> =>\n getIosModule().presentCodeRedemptionSheet();\n\n/**\n * Should Add Store Payment (iOS only)\n * Indicates the the App Store purchase should continue from the app instead of the App Store.\n * @returns {Promise<Product | null>} promoted product\n */\nexport const getPromotedProductIOS = (): Promise<ProductIOS | null> => {\n if (!isIosStorekit2()) {\n return RNIapIos.promotedProduct();\n } else {\n return Promise.reject('Only available on Sk1');\n }\n};\n\n/**\n * Buy the currently selected promoted product (iOS only)\n * Initiates the payment process for a promoted product. Should only be called in response to the `iap-promoted-product` event.\n * @returns {Promise<void>}\n */\nexport const buyPromotedProductIOS = (): Promise<void> =>\n getIosModule().buyPromotedProduct();\n\nconst fetchJsonOrThrow = async (\n url: string,\n receiptBody: Record<string, unknown>,\n): Promise<ReceiptValidationResponse | false> => {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(receiptBody),\n });\n\n if (!response.ok) {\n throw Object.assign(new Error(response.statusText), {\n statusCode: response.status,\n });\n }\n\n return response.json();\n};\n\nconst TEST_RECEIPT = 21007;\nconst requestAgnosticReceiptValidationIos = async (\n receiptBody: Record<string, unknown>,\n): Promise<ReceiptValidationResponse | false> => {\n const response = await fetchJsonOrThrow(\n 'https://buy.itunes.apple.com/verifyReceipt',\n receiptBody,\n );\n\n // Best practice is to check for test receipt and check sandbox instead\n // https://developer.apple.com/documentation/appstorereceipts/verifyreceipt\n if (response && response.status === TEST_RECEIPT) {\n const testResponse = await fetchJsonOrThrow(\n 'https://sandbox.itunes.apple.com/verifyReceipt',\n receiptBody,\n );\n\n return testResponse;\n }\n\n return response;\n};\n\n/**\n * Validate receipt for iOS.\n * @param {object} receiptBody the receipt body to send to apple server.\n * @param {boolean} isTest whether this is in test environment which is sandbox.\n * @returns {Promise<Apple.ReceiptValidationResponse | false>}\n */\nexport const validateReceiptIos = async ({\n receiptBody,\n isTest,\n}: {\n receiptBody: Record<string, unknown>;\n isTest?: boolean;\n}): Promise<ReceiptValidationResponse | false> => {\n if (isTest == null) {\n return await requestAgnosticReceiptValidationIos(receiptBody);\n }\n\n const url = isTest\n ? 'https://sandbox.itunes.apple.com/verifyReceipt'\n : 'https://buy.itunes.apple.com/verifyReceipt';\n\n const response = await fetchJsonOrThrow(url, receiptBody);\n\n return response;\n};\n\n/**\n * Clear Transaction (iOS only)\n * Finish remaining transactions. Related to issue #257 and #801\n * link : https://github.com/dooboolab/react-native-iap/issues/257\n * https://github.com/dooboolab/react-native-iap/issues/801\n * @returns {Promise<void>}\n */\nexport const clearTransactionIOS = (): Promise<void> =>\n getIosModule().clearTransaction();\n\n/**\n * Clear valid Products (iOS only)\n * Remove all products which are validated by Apple server.\n * @returns {void}\n */\nexport const clearProductsIOS = (): Promise<void> =>\n getIosModule().clearProducts();\n"],"mappings":"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"}
|
|
@@ -12,8 +12,19 @@ const {
|
|
|
12
12
|
export const getPendingPurchasesIOS = async () => getIosModule().getPendingTransactions();
|
|
13
13
|
/**
|
|
14
14
|
* Get the current receipt base64 encoded in IOS.
|
|
15
|
-
*
|
|
16
|
-
|
|
15
|
+
* From: https://apphud.com/blog/app-store-receipt-validation#what-is-app-store-receipt
|
|
16
|
+
> Does a receipt always exist in the app?
|
|
17
|
+
> If a user downloaded the app from the App Store – yes. However, in sandbox if your app was installed via Xcode or Testflight, then there won't be a receipt until you make a purchase or restore.
|
|
18
|
+
*
|
|
19
|
+
## Usage
|
|
20
|
+
```tsx
|
|
21
|
+
import {useCallback} from 'react';
|
|
22
|
+
import {getReceiptIOS} from 'react-native-iap';
|
|
23
|
+
|
|
24
|
+
const receipt = useCallback(async () => await getReceiptIOS({forceRefresh: false}));
|
|
25
|
+
```
|
|
26
|
+
* @param {forceRefresh?:boolean} Requests the receipt from Bundle.main.appStoreReceiptURL. Based on the note above, looks like forceRefresh only makes sense when testing an app not downloaded from the Appstore.
|
|
27
|
+
* @returns {Promise<string>} The receipt data
|
|
17
28
|
*/
|
|
18
29
|
|
|
19
30
|
export const getReceiptIOS = async _ref => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","getIosModule","isIosStorekit2","RNIapIos","getPendingPurchasesIOS","getPendingTransactions","getReceiptIOS","forceRefresh","requestReceipt","Promise","reject","presentCodeRedemptionSheetIOS","presentCodeRedemptionSheet","getPromotedProductIOS","promotedProduct","buyPromotedProductIOS","buyPromotedProduct","fetchJsonOrThrow","url","receiptBody","response","fetch","method","headers","Accept","body","JSON","stringify","ok","Object","assign","Error","statusText","statusCode","status","json","TEST_RECEIPT","requestAgnosticReceiptValidationIos","testResponse","validateReceiptIos","isTest","clearTransactionIOS","clearTransaction","clearProductsIOS","clearProducts"],"sources":["ios.ts"],"sourcesContent":["import {NativeModules} from 'react-native';\nimport type {ResponseBody as ReceiptValidationResponse} from '@jeremybarbet/apple-api-types';\n\nimport {getIosModule, isIosStorekit2} from '../internal';\nconst {RNIapIos} = NativeModules;\nimport type {\n ProductIOS,\n ProductPurchase,\n Purchase,\n Sku,\n SubscriptionIOS,\n} from '../types';\nimport type {PaymentDiscount} from '../types/apple';\n\nimport type {NativeModuleProps} from './common';\n\ntype getItems = (skus: Sku[]) => Promise<ProductIOS[] | SubscriptionIOS[]>;\n\ntype getAvailableItems = (\n automaticallyFinishRestoredTransactions: boolean,\n) => Promise<Purchase[]>;\n\nexport type BuyProduct = (\n sku: Sku,\n andDangerouslyFinishTransactionAutomaticallyIOS: boolean,\n applicationUsername: string | undefined,\n quantity: number,\n withOffer: Record<keyof PaymentDiscount, string> | undefined,\n) => Promise<Purchase>;\n\ntype clearTransaction = () => Promise<void>;\ntype clearProducts = () => Promise<void>;\ntype promotedProduct = () => Promise<ProductIOS | null>;\ntype buyPromotedProduct = () => Promise<void>;\ntype requestReceipt = (refresh: boolean) => Promise<string>;\n\ntype finishTransaction = (transactionIdentifier: string) => Promise<boolean>;\n\ntype getPendingTransactions = () => Promise<ProductPurchase[]>;\ntype presentCodeRedemptionSheet = () => Promise<null>;\n\nexport interface IosModuleProps extends NativeModuleProps {\n getItems: getItems;\n getAvailableItems: getAvailableItems;\n buyProduct: BuyProduct;\n clearTransaction: clearTransaction;\n clearProducts: clearProducts;\n promotedProduct: promotedProduct;\n buyPromotedProduct: buyPromotedProduct;\n requestReceipt: requestReceipt;\n finishTransaction: finishTransaction;\n getPendingTransactions: getPendingTransactions;\n presentCodeRedemptionSheet: presentCodeRedemptionSheet;\n disable: () => Promise<null>;\n}\n\n/**\n * Get the current receipt base64 encoded in IOS.\n * @param {forceRefresh?:boolean}\n * @returns {Promise<ProductPurchase[]>}\n */\nexport const getPendingPurchasesIOS = async (): Promise<ProductPurchase[]> =>\n getIosModule().getPendingTransactions();\n\n/**\n * Get the current receipt base64 encoded in IOS.\n * @param {forceRefresh?:boolean}
|
|
1
|
+
{"version":3,"names":["NativeModules","getIosModule","isIosStorekit2","RNIapIos","getPendingPurchasesIOS","getPendingTransactions","getReceiptIOS","forceRefresh","requestReceipt","Promise","reject","presentCodeRedemptionSheetIOS","presentCodeRedemptionSheet","getPromotedProductIOS","promotedProduct","buyPromotedProductIOS","buyPromotedProduct","fetchJsonOrThrow","url","receiptBody","response","fetch","method","headers","Accept","body","JSON","stringify","ok","Object","assign","Error","statusText","statusCode","status","json","TEST_RECEIPT","requestAgnosticReceiptValidationIos","testResponse","validateReceiptIos","isTest","clearTransactionIOS","clearTransaction","clearProductsIOS","clearProducts"],"sources":["ios.ts"],"sourcesContent":["import {NativeModules} from 'react-native';\nimport type {ResponseBody as ReceiptValidationResponse} from '@jeremybarbet/apple-api-types';\n\nimport {getIosModule, isIosStorekit2} from '../internal';\nconst {RNIapIos} = NativeModules;\nimport type {\n ProductIOS,\n ProductPurchase,\n Purchase,\n Sku,\n SubscriptionIOS,\n} from '../types';\nimport type {PaymentDiscount} from '../types/apple';\n\nimport type {NativeModuleProps} from './common';\n\ntype getItems = (skus: Sku[]) => Promise<ProductIOS[] | SubscriptionIOS[]>;\n\ntype getAvailableItems = (\n automaticallyFinishRestoredTransactions: boolean,\n) => Promise<Purchase[]>;\n\nexport type BuyProduct = (\n sku: Sku,\n andDangerouslyFinishTransactionAutomaticallyIOS: boolean,\n applicationUsername: string | undefined,\n quantity: number,\n withOffer: Record<keyof PaymentDiscount, string> | undefined,\n) => Promise<Purchase>;\n\ntype clearTransaction = () => Promise<void>;\ntype clearProducts = () => Promise<void>;\ntype promotedProduct = () => Promise<ProductIOS | null>;\ntype buyPromotedProduct = () => Promise<void>;\ntype requestReceipt = (refresh: boolean) => Promise<string>;\n\ntype finishTransaction = (transactionIdentifier: string) => Promise<boolean>;\n\ntype getPendingTransactions = () => Promise<ProductPurchase[]>;\ntype presentCodeRedemptionSheet = () => Promise<null>;\n\nexport interface IosModuleProps extends NativeModuleProps {\n getItems: getItems;\n getAvailableItems: getAvailableItems;\n buyProduct: BuyProduct;\n clearTransaction: clearTransaction;\n clearProducts: clearProducts;\n promotedProduct: promotedProduct;\n buyPromotedProduct: buyPromotedProduct;\n requestReceipt: requestReceipt;\n finishTransaction: finishTransaction;\n getPendingTransactions: getPendingTransactions;\n presentCodeRedemptionSheet: presentCodeRedemptionSheet;\n disable: () => Promise<null>;\n}\n\n/**\n * Get the current receipt base64 encoded in IOS.\n * @param {forceRefresh?:boolean}\n * @returns {Promise<ProductPurchase[]>}\n */\nexport const getPendingPurchasesIOS = async (): Promise<ProductPurchase[]> =>\n getIosModule().getPendingTransactions();\n\n/**\n * Get the current receipt base64 encoded in IOS.\n * From: https://apphud.com/blog/app-store-receipt-validation#what-is-app-store-receipt\n > Does a receipt always exist in the app?\n > If a user downloaded the app from the App Store – yes. However, in sandbox if your app was installed via Xcode or Testflight, then there won't be a receipt until you make a purchase or restore.\n * \n ## Usage \n ```tsx\nimport {useCallback} from 'react';\nimport {getReceiptIOS} from 'react-native-iap';\n\nconst receipt = useCallback(async () => await getReceiptIOS({forceRefresh: false}));\n```\n * @param {forceRefresh?:boolean} Requests the receipt from Bundle.main.appStoreReceiptURL. Based on the note above, looks like forceRefresh only makes sense when testing an app not downloaded from the Appstore.\n * @returns {Promise<string>} The receipt data\n */\nexport const getReceiptIOS = async ({\n forceRefresh,\n}: {\n forceRefresh?: boolean;\n}): Promise<string> => {\n if (!isIosStorekit2()) {\n return RNIapIos.requestReceipt(forceRefresh ?? false);\n } else {\n return Promise.reject('Only available on Sk1');\n }\n};\n/**\n * Launches a modal to register the redeem offer code in IOS.\n * @returns {Promise<null>}\n */\nexport const presentCodeRedemptionSheetIOS = async (): Promise<null> =>\n getIosModule().presentCodeRedemptionSheet();\n\n/**\n * Should Add Store Payment (iOS only)\n * Indicates the the App Store purchase should continue from the app instead of the App Store.\n * @returns {Promise<Product | null>} promoted product\n */\nexport const getPromotedProductIOS = (): Promise<ProductIOS | null> => {\n if (!isIosStorekit2()) {\n return RNIapIos.promotedProduct();\n } else {\n return Promise.reject('Only available on Sk1');\n }\n};\n\n/**\n * Buy the currently selected promoted product (iOS only)\n * Initiates the payment process for a promoted product. Should only be called in response to the `iap-promoted-product` event.\n * @returns {Promise<void>}\n */\nexport const buyPromotedProductIOS = (): Promise<void> =>\n getIosModule().buyPromotedProduct();\n\nconst fetchJsonOrThrow = async (\n url: string,\n receiptBody: Record<string, unknown>,\n): Promise<ReceiptValidationResponse | false> => {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(receiptBody),\n });\n\n if (!response.ok) {\n throw Object.assign(new Error(response.statusText), {\n statusCode: response.status,\n });\n }\n\n return response.json();\n};\n\nconst TEST_RECEIPT = 21007;\nconst requestAgnosticReceiptValidationIos = async (\n receiptBody: Record<string, unknown>,\n): Promise<ReceiptValidationResponse | false> => {\n const response = await fetchJsonOrThrow(\n 'https://buy.itunes.apple.com/verifyReceipt',\n receiptBody,\n );\n\n // Best practice is to check for test receipt and check sandbox instead\n // https://developer.apple.com/documentation/appstorereceipts/verifyreceipt\n if (response && response.status === TEST_RECEIPT) {\n const testResponse = await fetchJsonOrThrow(\n 'https://sandbox.itunes.apple.com/verifyReceipt',\n receiptBody,\n );\n\n return testResponse;\n }\n\n return response;\n};\n\n/**\n * Validate receipt for iOS.\n * @param {object} receiptBody the receipt body to send to apple server.\n * @param {boolean} isTest whether this is in test environment which is sandbox.\n * @returns {Promise<Apple.ReceiptValidationResponse | false>}\n */\nexport const validateReceiptIos = async ({\n receiptBody,\n isTest,\n}: {\n receiptBody: Record<string, unknown>;\n isTest?: boolean;\n}): Promise<ReceiptValidationResponse | false> => {\n if (isTest == null) {\n return await requestAgnosticReceiptValidationIos(receiptBody);\n }\n\n const url = isTest\n ? 'https://sandbox.itunes.apple.com/verifyReceipt'\n : 'https://buy.itunes.apple.com/verifyReceipt';\n\n const response = await fetchJsonOrThrow(url, receiptBody);\n\n return response;\n};\n\n/**\n * Clear Transaction (iOS only)\n * Finish remaining transactions. Related to issue #257 and #801\n * link : https://github.com/dooboolab/react-native-iap/issues/257\n * https://github.com/dooboolab/react-native-iap/issues/801\n * @returns {Promise<void>}\n */\nexport const clearTransactionIOS = (): Promise<void> =>\n getIosModule().clearTransaction();\n\n/**\n * Clear valid Products (iOS only)\n * Remove all products which are validated by Apple server.\n * @returns {void}\n */\nexport const clearProductsIOS = (): Promise<void> =>\n getIosModule().clearProducts();\n"],"mappings":"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"}
|
|
@@ -35,8 +35,19 @@ export interface IosModuleProps extends NativeModuleProps {
|
|
|
35
35
|
export declare const getPendingPurchasesIOS: () => Promise<ProductPurchase[]>;
|
|
36
36
|
/**
|
|
37
37
|
* Get the current receipt base64 encoded in IOS.
|
|
38
|
-
*
|
|
39
|
-
|
|
38
|
+
* From: https://apphud.com/blog/app-store-receipt-validation#what-is-app-store-receipt
|
|
39
|
+
> Does a receipt always exist in the app?
|
|
40
|
+
> If a user downloaded the app from the App Store – yes. However, in sandbox if your app was installed via Xcode or Testflight, then there won't be a receipt until you make a purchase or restore.
|
|
41
|
+
*
|
|
42
|
+
## Usage
|
|
43
|
+
```tsx
|
|
44
|
+
import {useCallback} from 'react';
|
|
45
|
+
import {getReceiptIOS} from 'react-native-iap';
|
|
46
|
+
|
|
47
|
+
const receipt = useCallback(async () => await getReceiptIOS({forceRefresh: false}));
|
|
48
|
+
```
|
|
49
|
+
* @param {forceRefresh?:boolean} Requests the receipt from Bundle.main.appStoreReceiptURL. Based on the note above, looks like forceRefresh only makes sense when testing an app not downloaded from the Appstore.
|
|
50
|
+
* @returns {Promise<string>} The receipt data
|
|
40
51
|
*/
|
|
41
52
|
export declare const getReceiptIOS: ({ forceRefresh, }: {
|
|
42
53
|
forceRefresh?: boolean | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-iap",
|
|
3
|
-
"version": "12.4.
|
|
3
|
+
"version": "12.4.10",
|
|
4
4
|
"description": "React Native In App Purchase Module.",
|
|
5
5
|
"repository": "https://github.com/dooboolab/react-native-iap",
|
|
6
6
|
"author": "dooboolab <support@dooboolab.com> (https://github.com/dooboolab)",
|
package/src/modules/ios.ts
CHANGED
|
@@ -64,8 +64,19 @@ export const getPendingPurchasesIOS = async (): Promise<ProductPurchase[]> =>
|
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Get the current receipt base64 encoded in IOS.
|
|
67
|
-
*
|
|
68
|
-
|
|
67
|
+
* From: https://apphud.com/blog/app-store-receipt-validation#what-is-app-store-receipt
|
|
68
|
+
> Does a receipt always exist in the app?
|
|
69
|
+
> If a user downloaded the app from the App Store – yes. However, in sandbox if your app was installed via Xcode or Testflight, then there won't be a receipt until you make a purchase or restore.
|
|
70
|
+
*
|
|
71
|
+
## Usage
|
|
72
|
+
```tsx
|
|
73
|
+
import {useCallback} from 'react';
|
|
74
|
+
import {getReceiptIOS} from 'react-native-iap';
|
|
75
|
+
|
|
76
|
+
const receipt = useCallback(async () => await getReceiptIOS({forceRefresh: false}));
|
|
77
|
+
```
|
|
78
|
+
* @param {forceRefresh?:boolean} Requests the receipt from Bundle.main.appStoreReceiptURL. Based on the note above, looks like forceRefresh only makes sense when testing an app not downloaded from the Appstore.
|
|
79
|
+
* @returns {Promise<string>} The receipt data
|
|
69
80
|
*/
|
|
70
81
|
export const getReceiptIOS = async ({
|
|
71
82
|
forceRefresh,
|