{"id":4563,"url":"https://github.com/chirag04/react-native-in-app-utils","last_synced_at":"2025-04-14T20:53:09.000Z","repository":{"id":33680476,"uuid":"37333226","full_name":"chirag04/react-native-in-app-utils","owner":"chirag04","description":"A react-native wrapper for handling in-app payments","archived":false,"fork":false,"pushed_at":"2021-06-09T16:30:45.000Z","size":90,"stargazers_count":891,"open_issues_count":83,"forks_count":183,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-04-07T14:09:22.601Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chirag04.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-06-12T16:44:13.000Z","updated_at":"2025-04-03T17:56:22.000Z","dependencies_parsed_at":"2022-07-14T14:47:22.840Z","dependency_job_id":null,"html_url":"https://github.com/chirag04/react-native-in-app-utils","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chirag04%2Freact-native-in-app-utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chirag04%2Freact-native-in-app-utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chirag04%2Freact-native-in-app-utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chirag04%2Freact-native-in-app-utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chirag04","download_url":"https://codeload.github.com/chirag04/react-native-in-app-utils/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248961047,"owners_count":21189990,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-01-05T20:17:16.370Z","updated_at":"2025-04-14T20:53:08.971Z","avatar_url":"https://github.com/chirag04.png","language":"Objective-C","funding_links":[],"categories":["Components"],"sub_categories":["System"],"readme":"# `react-native-in-app-utils`\n\nA react-native wrapper for handling in-app purchases in iOS.\n\n## Breaking Change\n\n- Due to a major breaking change in RN 0.40+, use version 5 or higher of this lib when installing from npm.\n\n## Notes\n\n- You need an Apple Developer account to use in-app purchases.\n\n- You have to set up your in-app purchases in iTunes Connect first. Follow steps 1-13 in this [tutorial](http://stackoverflow.com/questions/19556336/how-do-you-add-an-in-app-purchase-to-an-ios-application) for an easy explanation.\n\n- You have to test your in-app purchases on a real device, in-app purchases will always fail on the Simulator.\n\n## Installation\n\n1. Install with react-native cli `react-native install react-native-in-app-utils`\n\n2. Whenever you want to use it within React code now you just have to do: `var InAppUtils = require('NativeModules').InAppUtils;`\n   or for ES6:\n\n```\nimport { NativeModules } from 'react-native'\nconst { InAppUtils } = NativeModules\n```\n\n\n## API\n\n### Loading products\n\nYou have to load the products first to get the correctly internationalized name and price in the correct currency.\n\n```javascript\nconst identifiers = [\n   'com.xyz.abc',\n];\nInAppUtils.loadProducts(identifiers, (error, products) =\u003e {\n   console.log(products);\n   //update store here.\n});\n```\n\n**Response:** An array of product objects with the following fields:\n\n| Field          | Type    | Description                                 |\n| -------------- | ------- | ------------------------------------------- |\n| identifier     | string  | The product identifier                      |\n| price          | number  | The price as a number                       |\n| currencySymbol | string  | The currency symbol, i.e. \"$\" or \"SEK\"      |\n| currencyCode   | string  | The currency code, i.e. \"USD\" of \"SEK\"      |\n| priceString    | string  | Localised string of price, i.e. \"$1,234.00\" |\n| countryCode    | string  | Country code of the price, i.e. \"GB\" or \"FR\"|\n| downloadable   | boolean | Whether the purchase is downloadable        |\n| description    | string  | Description string                          |\n| title          | string  | Title string                                |\n\n**Troubleshooting:** If you do not get back your product(s) then there's a good chance that something in your iTunes Connect or Xcode is not properly configured. Take a look at this [StackOverflow Answer](http://stackoverflow.com/a/11707704/293280) to determine what might be the issue(s).\n\n### Checking if payments are allowed\n\n```javascript\nInAppUtils.canMakePayments((canMakePayments) =\u003e {\n   if(!canMakePayments) {\n      Alert.alert('Not Allowed', 'This device is not allowed to make purchases. Please check restrictions on device');\n   }\n})\n```\n\n**NOTE:** canMakePayments may return false because of country limitation or parental contol/restriction setup on the device.\n\n### Buy product\n\n```javascript\nvar productIdentifier = 'com.xyz.abc';\nInAppUtils.purchaseProduct(productIdentifier, (error, response) =\u003e {\n   // NOTE for v3.0: User can cancel the payment which will be available as error object here.\n   if(response \u0026\u0026 response.productIdentifier) {\n      Alert.alert('Purchase Successful', 'Your Transaction ID is ' + response.transactionIdentifier);\n      //unlock store here.\n   }\n});\n```\n\n**NOTE:** Call `loadProducts` prior to calling `purchaseProduct`, otherwise this will return `invalid_product`. If you're calling them right after each other, you will need to call `purchaseProduct` inside of the `loadProducts` callback to ensure it has had a chance to complete its call.\n\n**NOTE:** Call `canMakePurchases` prior to calling `purchaseProduct` to ensure that the user is allowed to make a purchase. It is generally a good idea to inform the user that they are not allowed to make purchases from their account and what they can do about it instead of a cryptic error message from iTunes.\n\n**NOTE:** `purchaseProductForUser(productIdentifier, username, callback)` is also available.\nhttps://stackoverflow.com/questions/29255568/is-there-any-way-to-know-purchase-made-by-which-itunes-account-ios/29280858#29280858\n\n**Response:** A transaction object with the following fields:\n\n| Field                 | Type   | Description                                        |\n| --------------------- | ------ | -------------------------------------------------- |\n| originalTransactionDate        | number | The original transaction date (ms since epoch)     |\n| originalTransactionIdentifier  | string | The original transaction identifier                |\n| transactionDate       | number | The transaction date (ms since epoch)              |\n| transactionIdentifier | string | The transaction identifier                         |\n| productIdentifier     | string | The product identifier                             |\n| transactionReceipt    | string | The transaction receipt as a base64 encoded string |\n\n**NOTE:**  `originalTransactionDate` and `originalTransactionIdentifier` are only available for subscriptions that were previously cancelled or expired.\n\n### Restore payments\n\n```javascript\nInAppUtils.restorePurchases((error, response) =\u003e {\n   if(error) {\n      Alert.alert('itunes Error', 'Could not connect to itunes store.');\n   } else {\n      Alert.alert('Restore Successful', 'Successfully restores all your purchases.');\n      \n      if (response.length === 0) {\n        Alert.alert('No Purchases', \"We didn't find any purchases to restore.\");\n        return;\n      }\n\n      response.forEach((purchase) =\u003e {\n        if (purchase.productIdentifier === 'com.xyz.abc') {\n          // Handle purchased product.\n        }\n      });\n   }\n});\n```\n\n**NOTE:** `restorePurchasesForUser(username, callback)` is also available.\nhttps://stackoverflow.com/questions/29255568/is-there-any-way-to-know-purchase-made-by-which-itunes-account-ios/29280858#29280858\n\n**Response:** An array of transaction objects with the following fields:\n\n| Field                          | Type   | Description                                        |\n| ------------------------------ | ------ | -------------------------------------------------- |\n| originalTransactionDate        | number | The original transaction date (ms since epoch)     |\n| originalTransactionIdentifier  | string | The original transaction identifier                |\n| transactionDate                | number | The transaction date (ms since epoch)              |\n| transactionIdentifier          | string | The transaction identifier                         |\n| productIdentifier              | string | The product identifier                             |\n| transactionReceipt             | string | The transaction receipt as a base64 encoded string |\n\n\n### Receipts\n\niTunes receipts are associated to the users iTunes account and can be retrieved without any product reference.\n\n```javascript\nInAppUtils.receiptData((error, receiptData)=\u003e {\n  if(error) {\n    Alert.alert('itunes Error', 'Receipt not found.');\n  } else {\n    //send to validation server\n  }\n});\n```\n\n**Response:** The receipt as a base64 encoded string.\n\n### Can make payments\n\nCheck if in-app purchases are enabled/disabled.\n\n```javascript\nInAppUtils.canMakePayments((enabled) =\u003e {\n  if(enabled) {\n    Alert.alert('IAP enabled');\n  } else {\n    Alert.alert('IAP disabled');\n  }\n});\n```\n\n**Response:** The enabled boolean flag.\n\n\n## Testing\n\nTo test your in-app purchases, you have to *run the app on an actual device*. Using the iOS Simulator, they will always fail as the simulator cannot connect to the iTunes Store. However, you can do certain tasks like using `loadProducts` without the need to run on a real device.\n\n1. Set up a test account (\"Sandbox Tester\") in iTunes Connect. See the official documentation [here](https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/SettingUpUserAccounts.html#//apple_ref/doc/uid/TP40011225-CH25-SW9).\n\n2. Run your app on an actual iOS device. To do so, first [run the react-native server on the local network](https://facebook.github.io/react-native/docs/runningondevice.html) instead of localhost. Then connect your iDevice to your Mac via USB and [select it from the list of available devices and simulators](https://i.imgur.com/6ifsu8Q.jpg) in the very top bar. (Next to the build and stop buttons)\n\n3. Open the app and buy something with your Sandbox Tester Apple Account!\n\n## Monthly Subscriptions\n\nYou can check if the receipt is still valid using [iap-receipt-validator](https://github.com/sibelius/iap-receipt-validator) package\n\n```jsx\nimport iapReceiptValidator from 'iap-receipt-validator';\n\nconst password = 'b212549818ff42ecb65aa45c'; // Shared Secret from iTunes connect\nconst production = false; // use sandbox or production url for validation\nconst validateReceipt = iapReceiptValidator(password, production);\n\nasync validate(receiptData) {\n    try {\n        const validationData = await validateReceipt(receiptData);\n\n        // check if Auto-Renewable Subscription is still valid\n        // validationData['latest_receipt_info'][0].expires_date \u003e today\n    } catch(err) {\n        console.log(err.valid, err.error, err.message)\n    }\n}\n```\n\nThis works on both react native and backend server, you should setup a cron job that run everyday to check if the receipt is still valid\n\n## Free trial period for in-app-purchase\nThere is nothing to set up related to this library.\nInstead, If you want to set up a free trial period for in-app-purchase, you have to set it up at\niTunes Connect \u003e your app \u003e your in-app-purchase \u003e free trial period (say 3-days or any period you can find from the pulldown menu)\n\nThe flow we know at this point seems to be (auto-renewal case):\n1. FIRST, user have to 'purchase' no matter the free trial period is set or not.\n2. If the app is configured to have a free trial period, THEN user can use the app in that free trial period without being charged.\n3. When the free trial period is over, Apple's system will start to auto-renew user's purchase, therefore user can continue to use the app, but user will be charged from that point on.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchirag04%2Freact-native-in-app-utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchirag04%2Freact-native-in-app-utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchirag04%2Freact-native-in-app-utils/lists"}