{"id":4566,"url":"https://github.com/idehub/react-native-billing","last_synced_at":"2025-08-04T01:32:38.418Z","repository":{"id":49763058,"uuid":"49832935","full_name":"idehub/react-native-billing","owner":"idehub","description":"React Native bridge to InApp Billing on Android.","archived":true,"fork":false,"pushed_at":"2020-09-04T18:20:35.000Z","size":343,"stargazers_count":628,"open_issues_count":1,"forks_count":116,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-07-19T10:45:47.649Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":false,"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/idehub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-01-17T19:53:47.000Z","updated_at":"2025-06-19T01:38:10.000Z","dependencies_parsed_at":"2022-08-30T09:41:56.559Z","dependency_job_id":null,"html_url":"https://github.com/idehub/react-native-billing","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/idehub/react-native-billing","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idehub%2Freact-native-billing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idehub%2Freact-native-billing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idehub%2Freact-native-billing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idehub%2Freact-native-billing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idehub","download_url":"https://codeload.github.com/idehub/react-native-billing/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idehub%2Freact-native-billing/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268636419,"owners_count":24282089,"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","status":"online","status_checked_at":"2025-08-03T02:00:12.545Z","response_time":2577,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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.457Z","updated_at":"2025-08-04T01:32:37.941Z","avatar_url":"https://github.com/idehub.png","language":"Java","funding_links":[],"categories":["Components","Java"],"sub_categories":["System"],"readme":"# InApp Billing for Android [![npm version](https://img.shields.io/npm/v/react-native-billing.svg)](https://www.npmjs.com/package/react-native-billing) [![Build Status](https://travis-ci.org/idehub/react-native-billing.svg?branch=master)](https://travis-ci.org/idehub/react-native-billing)\n\n**React Native Billing** is built to provide an easy interface to InApp Billing on **Android**, accomplished by wrapping [anjlab's InApp Billing library](https://github.com/anjlab/android-inapp-billing-v3).\n\n```js\nimport InAppBilling from \"react-native-billing\";\n\nasync purchase() {\n  try {\n    await InAppBilling.open();\n    const details = await InAppBilling.purchase(\"android.test.purchased\");\n    console.log(\"You purchased: \", details);\n  } catch (err) {\n    console.log(err);\n  } finally {\n    await InAppBilling.close();\n  }\n}\n\nasync checkSubscription() {\n    try {\n    await InAppBilling.open();\n    // If subscriptions/products are updated server-side you\n    // will have to update cache with loadOwnedPurchasesFromGoogle()\n    await InAppBilling.loadOwnedPurchasesFromGoogle();\n    const isSubscribed = await InAppBilling.isSubscribed(\"myapp.productId\")\n    console.log(\"Customer subscribed: \", isSubscribed);\n  } catch (err) {\n    console.log(err);\n  } finally {\n    await InAppBilling.close();\n  }\n}\n```\n\n## Installation and linking\n\n1.  `npm install --save react-native-billing` or `yarn add react-native-billing`\n2.  `react-native link react-native-billing`\n\nWith this, the `link`command will do most of the heavy lifting for native linking. **But**, you will still need add your Google Play license key to the `strings.xml` (step 5). If you are using a React Native version less than v0.18 you will also have to do step 4.3 (override `onActivityResult`).\n\n## Manual installation Android\n\n1.  `npm install --save react-native-billing`\n2.  Add the following in `android/setting.gradle`\n\n```gradle\n...\ninclude ':react-native-billing', ':app'\nproject(':react-native-billing').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-billing/android')\n```\n\n3.  And the following in `android/app/build.gradle`\n\n```gradle\n...\ndependencies {\n    ...\n    compile project(':react-native-billing')\n}\n```\n\n4.  Update MainActivity or MainApplication depending on React Native version.\n\n- React Native version \u003e= 0.29\n  Edit `MainApplication.java`.\n  1.  Add `import com.idehub.Billing.InAppBillingBridgePackage;`\n  2.  Register package:\n  ```java\n  @Override\n  protected List\u003cReactPackage\u003e getPackages() {\n    return Arrays.\u003cReactPackage\u003easList(\n      new MainReactPackage(),\n      // add package here\n      new InAppBillingBridgePackage()\n    );\n  }\n  ```\n- React Native version \u003c 0.29\n  Edit `MainActivity.java`. Step 4.3 is only required if you are using a lower React Native version than 18.0 and/or your `MainActivity` class does not inherit from `ReactActivity`.\n\n  1.  Add `import com.idehub.Billing.InAppBillingBridgePackage;`\n  2.  Register package in ReactInstanceManager: `.addPackage(new InAppBillingBridgePackage())`\n  3.  Override `onActivityResult`:\n\n  ```java\n  @Override\n  protected void onActivityResult(int requestCode, int resultCode, Intent data) {\n        mReactInstanceManager.onActivityResult(requestCode, resultCode, data);\n  }\n  ```\n\n  Larger example:\n\n  ```java\n  // Step 1; import package:\n  import com.idehub.Billing.InAppBillingBridgePackage;\n\n  public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {\n      ...\n\n      @Override\n      protected void onCreate(Bundle savedInstanceState) {\n          ...\n\n          mReactInstanceManager = ReactInstanceManager.builder()\n                  .setApplication(getApplication())\n                  .setBundleAssetName(\"index.android.bundle\")\n                  .setJSMainModuleName(\"index.android\")\n                  .addPackage(new MainReactPackage())\n                  // Step 2; register package\n                  .addPackage(new InAppBillingBridgePackage())\n                  .setUseDeveloperSupport(BuildConfig.DEBUG)\n                  .setInitialLifecycleState(LifecycleState.RESUMED)\n                  .build();\n\n          ...\n      }\n      // Step 3: For RN \u003c v0.18, override onActivityResult\n      @Override\n      protected void onActivityResult(int requestCode, int resultCode, Intent data) {\n          mReactInstanceManager.onActivityResult(requestCode, resultCode, data);\n      }\n      ...\n  ```\n\n5.  Add your Google Play license key as a line to your `android/app/src/main/res/values/strings.xml` with the name `RNB_GOOGLE_PLAY_LICENSE_KEY`. For example:\n\n```xml\n\u003cstring name=\"RNB_GOOGLE_PLAY_LICENSE_KEY\"\u003eYOUR_GOOGLE_PLAY_LICENSE_KEY_HERE\u003c/string\u003e\n```\n\nAlternatively, you can add your license key as a parameter when registering the `InAppBillingBridgePackage`, like so:\n\n```java\n.addPackage(new InAppBillingBridgePackage(\"YOUR_LICENSE_KEY\"))\n```\n\nor for React Native 29+\n\n```java\nnew InAppBillingBridgePackage(\"YOUR_LICENSE_KEY\")\n```\n\n## Testing with static responses\n\nIf you want to test with static responses, you can use reserved productids defined by Google. These are:\n\n- android.test.purchased\n- android.test.canceled\n- android.test.refunded\n- android.test.item_unavailable\n\nIf you want to test with these productids, you will have to use a `null` license key. This is because your actual license key will not validate when using these productids.\n\nIn order to do this send in `null` as parameter, along with your Activity-instance, when registering the package:\n`.addPackage(new InAppBillingBridgePackage(null, this))`\n\n[See the Google Play docs for more info on static responses](http://developer.android.com/google/play/billing/billing_testing.html#billing-testing-static).\n\nFor instance to purchase and consume the static `android.test.purchased` products, with async/await (you can chain the promise) :\n\n```js\n// To be sure the service is close before opening it\nasync pay() {\n  await InAppBilling.close();\n  try {\n    await InAppBilling.open();\n    if (!await InAppBilling.isPurchased(productId)) {\n      const details = await InAppBilling.purchase(productId);\n      console.log('You purchased: ', details);\n    }\n    const transactionStatus = await InAppBilling.getPurchaseTransactionDetails(productId);\n    console.log('Transaction Status', transactionStatus);\n    const productDetails = await InAppBilling.getProductDetails(productId);\n    console.log(productDetails);\n  } catch (err) {\n    console.log(err);\n  } finally {\n    await InAppBilling.consumePurchase(productId);\n    await InAppBilling.close();\n  }\n}\n```\n\n## Testing with your own In-app products\n\nTesting with static responses is limited, because you are only able to test the `purchase` function. Therefore, testing with real In-app products is recommended. But before that is possible, you need to do the following:\n\n- I will assume you've already created your Google Play Developer account and an application there.\n- Now you need to create an In-app product under your application at the Google Play Developer Console and activate it (press the button at the top right).\n- Assuming you have installed this module (InApp Billing), you can write the JS code as explained in the Javascript API section. I suggest you to use `getProductDetails` function to see if it's the product is retrieved.\n- When you're ready to test, you'll need to properly create a signed APK. You can follow this [guide](https://facebook.github.io/react-native/docs/signed-apk-android.html). (**Important**: You'll have to install the APK as described in the guide. Not in the way you'd normally debug an React Native app on Android).\n- When you have the APK, you need to upload it to Play Developer Console, either the Alpha or the Beta channel will be fine. Remember your app will need to have a proper `applicationId` (normally your package name) and `versionCode` set in `android/app/build.gradle`.\n- After uploading, you will have to publish it to the market. Don't worry, when publishing the APK to the Alpha or Beta channel the APK will not be available for general public. (**Important**: It might take several hours for Google to process the APK).\n- The final part is, you'll need to add testers for the channel you've published to. The web page will give you a signup URL (opt-in) after you've approved open testing. Visit this URL in the browser of your **testing device** (it must be a physical device, not a emulator) and signup, and download the app where it redirected.\n- Try to buy something with the device. The purchase will eventually be cancelled, but you can also do this manually through your Google Merchant wallet.\n\n**Important**: You can only test on a physical Android device, not from an emulator.\n\n## Handle Canceled Subscriptions\n\nCall `InAppBilling.getSubscriptionTransactionDetails(productId)` and check the `details.autoRenewing` flag. It will be set to `false` once subscription gets cancelled. Also notice, that you will need to call periodically `InAppBilling.loadOwnedPurchasesFromGoogle()` method in order to update purchase/subscription information from the Google-servers.\n\n## Javascript API\n\nAll methods return a `Promise`.\n\n### open()\n\n**Important:** Opens the service channel to Google Play. Must be called (once!) before any other billing methods can be called.\n\n```javascript\nInAppBilling.open().then(() =\u003e InAppBilling.purchase(\"android.test.purchased\"));\n```\n\n### close()\n\n**Important:** Must be called to close the service channel to Google Play, when you are done doing billing related work. Failure to close the service channel may degrade the performance of your app.\n\n```javascript\nInAppBilling.open()\n  .then(() =\u003e InAppBilling.purchase(\"android.test.purchased\"))\n  .then(details =\u003e {\n    console.log(\"You purchased: \", details);\n    return InAppBilling.close();\n  });\n```\n\n### loadOwnedPurchasesFromGoogle()\n\nRefreshes the internal purchases \u0026 subscriptions status cache.\n\n```javascript\nInAppBilling.loadOwnedPurchasesFromGoogle().then(...);\n```\n\n### purchase(productId)\n\n##### Parameter(s)\n\n- **productId (required):** String\n- **developerPayload:** String\n\n##### Returns:\n\n- **transactionDetails:** Object:\n  - **productId:** String\n  - **orderId:** String\n  - **purchaseToken:** String\n  - **purchaseTime:** String\n  - **purchaseState:** String (\"PurchasedSuccessfully\", \"Canceled\", \"Refunded\", \"SubscriptionExpired\")\n  - **receiptSignature:** String\n  - **receiptData:** String\n  - **autoRenewing** Boolean\n  - **developerPayload:** String\n\n```javascript\nInAppBilling.purchase(\"android.test.purchased\").then(details =\u003e {\n  console.log(details);\n});\n```\n\n### consumePurchase(productId)\n\n##### Parameter(s)\n\n- **productId (required):** String\n\n##### Returns:\n\n- **consumed:** Boolean (If consumed or not)\n\n```javascript\nInAppBilling.consumePurchase('your.inapp.productid').then(...);\n```\n\n### subscribe(productId)\n\n##### Parameter(s)\n\n- **productId (required):** String\n- **developerPayload:** String\n\n##### Returns:\n\n- **transactionDetails:** Object:\n  - **productId:** String\n  - **orderId:** String\n  - **purchaseToken:** String\n  - **purchaseTime:** String\n  - **purchaseState:** String (\"PurchasedSuccessfully\", \"Canceled\", \"Refunded\", \"SubscriptionExpired\")\n  - **receiptSignature:** String\n  - **receiptData:** String\n  - **autoRenewing** Boolean\n  - **developerPayload:** String\n\n```javascript\nInAppBilling.subscribe(\"your.inapp.productid\").then(details =\u003e {\n  console.log(details);\n});\n```\n\n### isSubscribed(productId)\n\n##### Parameter(s)\n\n- **productId (required):** String\n\n##### Returns:\n\n- **subscribed:** Boolean\n\n```javascript\nInAppBilling.isSubscribed('your.inapp.productid').then(...);\n```\n\n### updateSubscription(oldProductIds, productId)\n\n##### Parameter(s)\n\n- **oldProductIds (required)**: Array of String\n- **productId (required)**: String\n- **developerPayload:** String\n\n##### Returns:\n\n- **transactionDetails:** Object:\n  - **productId:** String\n  - **orderId:** String\n  - **purchaseToken:** String\n  - **purchaseTime:** String\n  - **purchaseState:** String (\"PurchasedSuccessfully\", \"Canceled\", \"Refunded\", \"SubscriptionExpired\")\n  - **receiptSignature:** String\n  - **receiptData:** String\n  - **autoRenewing** Boolean\n  - **developerPayload:** String\n\n```javascript\nInAppBilling.updateSubscription(['subscription.p1m', 'subscription.p3m'], 'subscription.p12m').then(...)\n```\n\n### isPurchased(productId)\n\n##### Parameter(s)\n\n- **productId (required):** String\n\n##### Returns:\n\n- **purchased:** Boolean\n\n```javascript\nInAppBilling.isPurchased('your.inapp.productid').then(...);\n```\n\n### isOneTimePurchaseSupported()\n\n##### Returns:\n\n- **oneTimePurchaseSupported:** Boolean\n\n```javascript\nInAppBilling.isOneTimePurchaseSupported().then(...);\n```\n\n### isValidTransactionDetails(productId)\n\nValidates if the transaction for the productId has a valid signature.\n\n##### Parameter(s)\n\n- **productId (required):** String\n\n##### Returns:\n\n- **isValid:** Boolean\n\n```javascript\nInAppBilling.isValidTransactionDetails(\"your.inapp.productid\").then(isValid =\u003e {\n  console.log(isValid);\n});\n```\n\n### listOwnedProducts()\n\n##### Returns:\n\n- **ownedProductIds:** Array of String\n\n```javascript\nInAppBilling.listOwnedProducts().then(...);\n```\n\n### listOwnedSubscriptions()\n\n##### Returns:\n\n- **ownedSubscriptionIds:** Array of String\n\n```javascript\nInAppBilling.listOwnedSubscriptions().then(...);\n```\n\n### getProductDetails(productId)\n\n**Important:** Use this to query managed products. Subscriptions require the use of `getSubscriptionDetails`.\n\n##### Parameter(s)\n\n- **productId (required):** String\n\n##### Returns:\n\n- **productDetails:** Object:\n  - **productId:** String\n  - **title:** String\n  - **description:** String\n  - **isSubscription:** Boolean\n  - **currency:** String\n  - **priceValue:** Double\n  - **priceText:** String\n\n```javascript\nInAppBilling.getProductDetails('your.inapp.productid').then(...);\n```\n\n### getProductDetailsArray(productIds)\n\n##### Parameter(s)\n\n- **productIds (required):** String-array\n\n##### Returns:\n\n- **productDetailsArray:** Array of the productDetails (same as above)\n\n```javascript\nInAppBilling.getProductDetailsArray(['your.inapp.productid', 'your.inapp.productid2']).then(...);\n```\n\n### getSubscriptionDetails(productId)\n\n##### Parameter(s)\n\n- **productId (required):** String\n\n##### Returns:\n\n- **productDetails:** Object:\n  - **productId:** String\n  - **title:** String\n  - **description:** String\n  - **isSubscription:** Boolean\n  - **currency:** String\n  - **priceValue:** Double\n  - **priceText:** String\n  - **subscriptionPeriod** String\n  - **subscriptionFreeTrialPeriod** String - Only if product has a free trial period\n  - **haveTrialPeriod** Boolean\n  - **introductoryPriceValue** Double\n  - **introductoryPriceText** String - Only if product has a introductory price\n  - **introductoryPricePeriod** String - Only if product has a introductory price\n  - **haveIntroductoryPeriod** Boolean\n  - **introductoryPriceCycles** Number\n\n```javascript\nInAppBilling.getSubscriptionDetails('your.inapp.productid').then(...);\n```\n\n### getSubscriptionDetailsArray(productIds)\n\n##### Parameter(s)\n\n- **productIds (required):** String-Array\n\n##### Returns:\n\n- **productDetailsArray:** Array of the productDetails (same as above)\n\n```javascript\nInAppBilling.getSubscriptionDetailsArray(['your.inapp.productid', 'your.inapp.productid2']).then(...);\n```\n\n### getPurchaseTransactionDetails(productId)\n\n##### Parameter(s)\n\n- **productId (required):** String\n\n##### Returns:\n\n- **transactionDetails:** Object:\n  - **productId:** String\n  - **orderId:** String\n  - **purchaseToken:** String\n  - **purchaseTime:** String\n  - **purchaseState:** String (\"PurchasedSuccessfully\", \"Canceled\", \"Refunded\", \"SubscriptionExpired\")\n  - **receiptSignature:** String\n  - **receiptData:** String\n  - **autoRenewing** Boolean\n  - **developerPayload:** String\n\n```javascript\nInAppBilling.getPurchaseTransactionDetails(\"your.inapp.productid\").then(\n  details =\u003e {\n    console.log(details);\n  }\n);\n```\n\n### getSubscriptionTransactionDetails(productId)\n\n##### Parameter(s)\n\n- **productId (required):** String\n\n##### Returns:\n\n- **transactionDetails:** Object:\n  - **productId:** String\n  - **orderId:** String\n  - **purchaseToken:** String\n  - **purchaseTime:** String\n  - **purchaseState:** String (\"PurchasedSuccessfully\", \"Canceled\", \"Refunded\", \"SubscriptionExpired\")\n  - **receiptSignature:** String\n  - **receiptData:** String\n  - **autoRenewing** Boolean\n  - **developerPayload:** String\n\n```javascript\nInAppBilling.getSubscriptionTransactionDetails(\"your.inapp.productid\").then(\n  details =\u003e {\n    console.log(details);\n  }\n);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidehub%2Freact-native-billing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidehub%2Freact-native-billing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidehub%2Freact-native-billing/lists"}