Giter Club home page Giter Club logo

react-native-in-app-utils's Introduction

react-native-in-app-utils

A react-native wrapper for handling in-app purchases in iOS.

Breaking Change

  • Due to a major breaking change in RN 0.40+, use version 5 or higher of this lib when installing from npm.

Notes

  • You need an Apple Developer account to use in-app purchases.

  • You have to set up your in-app purchases in iTunes Connect first. Follow steps 1-13 in this tutorial for an easy explanation.

  • You have to test your in-app purchases on a real device, in-app purchases will always fail on the Simulator.

Installation

  1. Install with react-native cli react-native install react-native-in-app-utils

  2. Whenever you want to use it within React code now you just have to do: var InAppUtils = require('NativeModules').InAppUtils; or for ES6:

import { NativeModules } from 'react-native'
const { InAppUtils } = NativeModules

API

Loading products

You have to load the products first to get the correctly internationalized name and price in the correct currency.

const identifiers = [
   'com.xyz.abc',
];
InAppUtils.loadProducts(identifiers, (error, products) => {
   console.log(products);
   //update store here.
});

Response: An array of product objects with the following fields:

Field Type Description
identifier string The product identifier
price number The price as a number
currencySymbol string The currency symbol, i.e. "$" or "SEK"
currencyCode string The currency code, i.e. "USD" of "SEK"
priceString string Localised string of price, i.e. "$1,234.00"
countryCode string Country code of the price, i.e. "GB" or "FR"
downloadable boolean Whether the purchase is downloadable
description string Description string
title string Title string

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 to determine what might be the issue(s).

Checking if payments are allowed

InAppUtils.canMakePayments((canMakePayments) => {
   if(!canMakePayments) {
      Alert.alert('Not Allowed', 'This device is not allowed to make purchases. Please check restrictions on device');
   }
})

NOTE: canMakePayments may return false because of country limitation or parental contol/restriction setup on the device.

Buy product

var productIdentifier = 'com.xyz.abc';
InAppUtils.purchaseProduct(productIdentifier, (error, response) => {
   // NOTE for v3.0: User can cancel the payment which will be available as error object here.
   if(response && response.productIdentifier) {
      Alert.alert('Purchase Successful', 'Your Transaction ID is ' + response.transactionIdentifier);
      //unlock store here.
   }
});

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.

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.

NOTE: purchaseProductForUser(productIdentifier, username, callback) is also available. https://stackoverflow.com/questions/29255568/is-there-any-way-to-know-purchase-made-by-which-itunes-account-ios/29280858#29280858

Response: A transaction object with the following fields:

Field Type Description
originalTransactionDate number The original transaction date (ms since epoch)
originalTransactionIdentifier string The original transaction identifier
transactionDate number The transaction date (ms since epoch)
transactionIdentifier string The transaction identifier
productIdentifier string The product identifier
transactionReceipt string The transaction receipt as a base64 encoded string

NOTE: originalTransactionDate and originalTransactionIdentifier are only available for subscriptions that were previously cancelled or expired.

Restore payments

InAppUtils.restorePurchases((error, response) => {
   if(error) {
      Alert.alert('itunes Error', 'Could not connect to itunes store.');
   } else {
      Alert.alert('Restore Successful', 'Successfully restores all your purchases.');
      
      if (response.length === 0) {
        Alert.alert('No Purchases', "We didn't find any purchases to restore.");
        return;
      }

      response.forEach((purchase) => {
        if (purchase.productIdentifier === 'com.xyz.abc') {
          // Handle purchased product.
        }
      });
   }
});

NOTE: restorePurchasesForUser(username, callback) is also available. https://stackoverflow.com/questions/29255568/is-there-any-way-to-know-purchase-made-by-which-itunes-account-ios/29280858#29280858

Response: An array of transaction objects with the following fields:

Field Type Description
originalTransactionDate number The original transaction date (ms since epoch)
originalTransactionIdentifier string The original transaction identifier
transactionDate number The transaction date (ms since epoch)
transactionIdentifier string The transaction identifier
productIdentifier string The product identifier
transactionReceipt string The transaction receipt as a base64 encoded string

Receipts

iTunes receipts are associated to the users iTunes account and can be retrieved without any product reference.

InAppUtils.receiptData((error, receiptData)=> {
  if(error) {
    Alert.alert('itunes Error', 'Receipt not found.');
  } else {
    //send to validation server
  }
});

Response: The receipt as a base64 encoded string.

Can make payments

Check if in-app purchases are enabled/disabled.

InAppUtils.canMakePayments((enabled) => {
  if(enabled) {
    Alert.alert('IAP enabled');
  } else {
    Alert.alert('IAP disabled');
  }
});

Response: The enabled boolean flag.

Testing

To 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.

  1. Set up a test account ("Sandbox Tester") in iTunes Connect. See the official documentation here.

  2. Run your app on an actual iOS device. To do so, first run the react-native server on the local network instead of localhost. Then connect your iDevice to your Mac via USB and select it from the list of available devices and simulators in the very top bar. (Next to the build and stop buttons)

  3. Open the app and buy something with your Sandbox Tester Apple Account!

Monthly Subscriptions

You can check if the receipt is still valid using iap-receipt-validator package

import iapReceiptValidator from 'iap-receipt-validator';

const password = 'b212549818ff42ecb65aa45c'; // Shared Secret from iTunes connect
const production = false; // use sandbox or production url for validation
const validateReceipt = iapReceiptValidator(password, production);

async validate(receiptData) {
    try {
        const validationData = await validateReceipt(receiptData);

        // check if Auto-Renewable Subscription is still valid
        // validationData['latest_receipt_info'][0].expires_date > today
    } catch(err) {
        console.log(err.valid, err.error, err.message)
    }
}

This 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

Free trial period for in-app-purchase

There is nothing to set up related to this library. Instead, If you want to set up a free trial period for in-app-purchase, you have to set it up at iTunes Connect > your app > your in-app-purchase > free trial period (say 3-days or any period you can find from the pulldown menu)

The flow we know at this point seems to be (auto-renewal case):

  1. FIRST, user have to 'purchase' no matter the free trial period is set or not.
  2. 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.
  3. 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.

react-native-in-app-utils's People

Contributors

adambutler avatar akshetpandey avatar andrewn avatar benadamstyles avatar bodysplash avatar bsy avatar cainaleaouk avatar cbrevik avatar chetstone avatar chirag04 avatar christiangenco avatar codler avatar denisizmaylov avatar gaafar avatar gnestor avatar grifotv avatar johan-dutoit avatar joshuapinter avatar kawashimaken avatar kesha-antonov avatar marcgreenstock avatar markburns avatar martnu avatar mxstbr avatar pennersr avatar philwilks avatar quarrant avatar ralfnieuwenhuizen avatar smkhalsa avatar superandrew213 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-in-app-utils's Issues

Hosted Content

How do I access the hosted content I uploaded to my in-app purchase?

Question about the linked tutorial

In the linked tutorial, on step 5 it's telling to add your view controller as below:

#import <StoreKit/StoreKit.h>

//put the name of your view controller in place of MyViewController
@interface MyViewController() <SKProductsRequestDelegate, SKPaymentTransactionObserver>

@end

@implementation MyViewController //the name of your view controller (same as above)
  //the code below will be added here
@end

What should I use instead of MyViewController?

I'm actually not sure if I need to complete the entire tutorial including setting product IDs in kRemoveAdsProductIdentifier etc. for your library to work. I'd appreciate if you could make this clear for me.

Thanks for your help.

mock test failed

Hello. How to test this module?

npm test ->

Cannot find module 'NativeModules'

my code

import {
	Platform,
	NativeModules,
} from 'react-native';
import { InAppUtils } from 'NativeModules';

Subscription

Hello, can someone post here working code example for subscription or tell me what is wrong with my code?
Thanks in advance.

I can get products from itunes connect, but I can't pay.

const products = [
'com.test.test.subscription',
'com.test.test.noncons',
];
InAppUtils.loadProducts(products, (error, productsReturned) => {
InAppUtils.purchaseProduct(products[0], (purchaseError, response) => {
if (response && response.productIdentifier) {
AlertIOS.alert('Purchase Successful', Your Transaction ID is ${response.transactionIdentifier});
this.setState({
productId
});
} else {
AlertIOS.alert(purchaseError.message);
}
});
});

I'm testing on real device.

Exception raised when restoring purchases

After making a purchase (as a sandbox user) when I try to restore my purchases it results in an exception being raised in InAppUtils.m -

2016-07-25 14:40:14.240 [info][tid:NSOperationQueue 0x17003a1e0 :: NSOperation 0x17424bdf0 (QOS: LEGACY)][RCTPerformanceLogger.m:41] Unbalanced calls start/end for tag 0
2016-07-25 14:40:16.617 CookAndCount[6892:2261038] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]'
*** First throw call stack:
(0x1856342d8 0x1973080e4 0x1855209c8 0x1855207f8 0x100213294 0x185514cdc 0x18a00ceb0 0x18a00c40c 0x18a00d6cc 0x1003d0fd4 0x1003d0f94 0x1003d5c28 0x1855eb7f8 0x1855e98a0 0x1855152d4 0x18ef6b6fc 0x18a112f40 0x1000e7e68 0x1979b2a08)
libc++abi.dylib: terminating with uncaught exception of type NSException

image

The state is shown here -

image

Purchase Meta Data and Generic Product Identifiers

Apple has a limit of 10,000 product identifiers per application. We are going to have more than 10,000 products in our app - thus this presents an obvious problem. Also, there is no API for creating these product identifiers and it's extremely tedious. We are looking at having generic product identifiers.

The problem with this is that when we would call InAppUtils.restorePurchases, we'd get no unique information back from Apple that we could use to figure out which actual product was purchased. Is there a way to pass up some specific metadata when we call purchaseProduct so that when we call InAppUtils.restorePurchases we can get that metadata back?

Question: Right flow of purchases

Hi, there!

I dont really understand right flow of purchases. My questions are:

  1. How to mark transaction finished? (At which step it occurs)
  2. If some error happens in application server that validates a purchases, how to complete transaction?

Now I have a flow like this:

  1. On application start calls InAppUtils.loadProducts..
  2. When user click on buy button calls InAppUtils.purchaseProduct..
  3. Then receipt sends on a server for validation

Using this library confuses the phone's Apple ID

When I buy a subscription, I'm being asked to enter my iTunes password to make the purchase. Everything goes well and I can buy the subscription. (Except that sometimes I have to enter my password successfully multiple times)

However, things begin to behave strangely on my phone. I'm being asked for my iTunes password all the time. As if something happened that desynchronized my iTunes account with my iPhone.

Has anybody else noticed this behaviour? Thanks!

Android Support

Any plans to add android support now that react native is out for android ?

Android Support ?

Hey guy,

First of all, thank you for you plugin ! Very good work !

Do you have planned to add a android support ? Because i want to have the same library to handle this part.. And added a new library it's very painful !

Thank ! :)

The products returns an empty Array [] ?

Hi,

Any resolution to this issue? I'm seeing the same thing....
The products returns an empty Array [].

RCT_EXPORT_METHOD(loadProducts:(NSArray *)productIdentifiers
callback:(RCTResponseSenderBlock)callback)
{
if([SKPaymentQueue canMakePayments]){
SKProductsRequest *productsRequest = [[SKProductsRequest alloc]
initWithProductIdentifiers:[NSSet setWithArray:productIdentifiers]];
productsRequest.delegate = self;
_callbacks[RCTKeyForInstance(productsRequest)] = callback;
[productsRequest start];
} else {
callback(@[@"not_available"]);
}
}

In this code, productIdentifiers is always nil value.
Why is productIdentifiers empty array []?

loadProducts only returns first subscription in group?

If I have subscription group:

com.mycompany.myapp.premium

and in that group has:

com.mycompany.myapp.premium.3months
com.mycompany.myapp.premium.1months

loadProducts only returns one of them

com.mycompany.myapp.premium.3months

Is this normal? If so, how can I list them both so the user has a choice to pick the subscription price/duration they are after?

It won't purchase... ever. Help please!

Hello everybody,

Here is my issue. I've done this:

var products = [
   'com.xyz.abc',
];
InAppUtils.loadProducts(products, (error, products) => {
   //update store here.
});

and also this:

var productIdentifier = 'com.xyz.abc';
InAppUtils.purchaseProduct(productIdentifier, (error, response) => {
   // NOTE for v3.0: User can cancel the payment which will be availble as error object here.
   if(response && response.productIdentifier) {
      AlertIOS.alert('Purchase Successful', 'Your Transaction ID is ' + response.transactionIdentifier);
      //unlock store here.
   }
});

The thing is that everything seems to go well but it never enters the piece of code where the store has to be unlocked.

When I tap on the icon of the inAPP purchase product, it opens the dialog to buy it. If I buy it, it does nothing. Not even an alert. It's like InAppUtils.purchaseProduct now would be working differently. It never callsback. All the management lays on the purchaseProduct method and it says the product has been purchased but not with the alert or alerts I'm trying to use.

Can anyone help? Thanks in advance!

Native module cannot be null

Hi,

After I run rnpm install react-native-in-app-utils I got this error.

screen shot 2016-11-12 at 1 50 37 pm

Log file:

: Native module cannot be null.
: Unhandled JS Exception: Native module cannot be null.
: Requiring module "191", which threw an exception.
: Unhandled JS Exception: Requiring module "191", which threw an exception.
: Module AppRegistry is not a registered callable module.
: Unhandled JS Exception: Module AppRegistry is not a registered callable module.

Any advice ?

Invalid Product Identifiers get ignored.

If you supply an invalid product identifier, it gets ignored. No error or warning is produced.

This is what the response object looks like when an invalid product identifier is passed:
screenshot 2016-08-04 16 06 28

I think we should populate the returned error object with the invalid product identifiers.

Originally discovered in #29

restore purchases doesn't work in iOS 10.2.1

restore purchases doesn't work in iOS 10.2.1
it always returns error - restore_failed
I've tried to debug in XCode, the full error message is 'Cannot connect to iTunes Store'

but it worked great with previous ios version (don't remember exactly which one)
it asked for itunes credentials and returned purchases.

in 10.2.1 it stops to ask itunes credentials and always returns this error.

Interrupted transaction fails

Apple's guidelines suggest testing an interrupted transaction. When following that procedure, the transaction does not complete. When the app starts up again and this component is loaded, it adds the transaction observer and StoreKit immediately tries to complete the transaction but at this point there is no callback so it fails with No callback registered for transaction with state purchased.

All is not lost however, because the user could attempt the purchase again and if she agrees to the purchase, StoreKit comes back with You've already purchased this item, would you like to restore it for free? But not too intuitive to have to agree to purchase first.

I guess a workaround would be to add a restore purchases button... I didn't think my app would need it because once the purchase is complete the user is able to register for an account and uses that to log in in the future. Guess it's needed for this edge case.

I wonder if there's a way this component could be modified to have an appropriate callback registered at startup?

How do I test receiptData() with existing paid app?

I have a paid app that I'm thinking about making free with in app purchases. If I make the switch I'll need to check if the user has already paid for the app and then enable the paid features. I think the receiptData() should do what I need but I'm not sure how to test it. I built the app and ran it using my development provisioning profile on my device and receiptData() just returns an error. So I built the app with a distribution provisioning profile and submitted it to the app store then downloaded the app using test flight but I'm still getting the same error. How do I get the receipt data from an existing app?

kudos

Thanks dude, this works good on testflight so far :)

invalid product error?

hi,

I can get product details via this code:

var products = [
            'com.emretekince.xxx',
        ];
        InAppUtils.loadProducts(products, (error, products) => {
           console.log(products) // it works
        });

        InAppUtils.purchaseProduct(products[0], (error, response) => {
            console.warn(error) // invalid_product error
            // NOTE for v3.0: User can cancel the payment which will be availble as error object here.
            if(response && response.productIdentifier) {
                AlertIOS.alert('Purchase Successful', 'Your Transaction ID is ' + response.transactionIdentifier);
                //unlock store here.
            }
        });

But I can't test buy product code. I have tested it with my device but I got same error.

invalid_product

Add promise support

Promises are much easier to work with instead of callbacks, and we can use inside async functions using await making programming easier

Handling auto renewing subscriptions

I'm able to purchase a subscription (marked as auto renewable in iTunes), get receipt data, and send to the server for validation. The server is able to validate the receipt fine and sees the original subscription, when it's valid, and when it expires.

Monthly auto renewable subscriptions are supposed to auto renew 5-6 times in Apple's sandbox but I always see the subscription expire after the first period (5 mins on sandbox for monthly renewable).

Here are Apple's notes around this area:
https://developer.apple.com/library/content/technotes/tn2387/_index.html

I see react-native-in-app-utils handling the callbacks, but it's not clear to me how the subscription renewal gets recognized and processed by the app/server.

Will react-native-in-app-utils handle this or is there some way of handling these that someone has figured out?

Better error/fail handling

Hey, awesome work here!

In my fork (branch stranger) I added this to get more information at failing time. Otherwise if the user cancel or something else happen, I can't hide HUDs or react in the UI in any way.

switch (transaction.error.code) {
    case SKErrorUnknown:
        callback(@[@"transaction_failed_unknown"]);
        break;
    case SKErrorClientInvalid:
        callback(@[@"transaction_failed_client_invalid"]);
        break;
    case SKErrorPaymentCancelled:
        callback(@[@"transaction_failed_payment_cancelled"]);
        break;
    case SKErrorPaymentInvalid:
        callback(@[@"transaction_failed_payment_invalid"]);
        break;
    case SKErrorPaymentNotAllowed:
        callback(@[@"transaction_failed_payment_not_allowed"]);
        break;
    case SKErrorStoreProductNotAvailable:
        callback(@[@"transaction_failed_store_product_not_available"]);
        break;
    case SKErrorCloudServicePermissionDenied:
        callback(@[@"transaction_failed_cloud_service_permission_denied"]);
        break;
    case SKErrorCloudServiceNetworkConnectionFailed:
        callback(@[@"transaction_failed_cloud_service_network_connection_failed"]);
        break;

    default:
        break;
}

Apple rejected my app because it isn't IPv6 compatible

Hi, after I implemented this library apple rejected my latest app.

This is the rejection message:

We discovered one or more bugs in your app when reviewed on iPad and iPhone running iOS 10.1.1 on Wi-Fi connected to an IPv6 network.

Specifically, we received an error message when we tapped on the “Purchase No Ads version” button.

We've attached screenshot(s) for your reference.

Next Steps

Please run your app on a device while connected to an IPv6 network (all apps must support IPv6) to identify the issue(s), then revise and resubmit your app for review.

If we misunderstood the intended behavior of your app, please reply to this message in Resolution Center to provide information on how these features were intended to work.

I fact I tested in a IPv6 network but everything is working fine.

Any advice about what could be wrong?

Thanks a lot

Add example

please add an example of use this package

Restore function works before purchase is made

Hi,

I used the exact code in the example for my restore button.
Unfortunately, when testing with my sandbox users, I am able to "restore" the purchase successfully before it has ever been bought. Any ideas?
My code is posted below.

EDIT: Also, logging response and response.productIdentifier appear to be undefined

onPress() {

  InAppUtils.restorePurchases((error, response)=> {
    if(error) {
        Alert.alert('iTunes Error', 'Could not connect to iTunes store.');
    } else {
        Alert.alert('Restore Successful', 'Successfully restored your purchase.');
        
        if (global.packs.indexOf('expansion') === -1){
                    global.packs = global.packs.concat('expansion')
        }
        AsyncStorage.setItem("expansion", "unlocked");

        this.setState({bought: true})

    }
})

}

Question: How to leave the sandbox mode?

The issue i have recently is that the inapp-billing-process always "thinks" i am in sandbox mode. It doesn't matter if i run the app on real device in debug mode or release-mode.
It always shows "Sandbox-Mode" when it asks for my apple-id and password.

I would expect to be in production-mode when running the app in release-mode on real-device (similar as it is to google play store). Or has it something to do with me having an Apple developer account with the same apple-id?

Even when i install the app per Testflight (ReleaseBuild) i am on the sandbox mode.

Any ideas? How will this lib differ between sandbox and production mode?

Free trial period for in-app-purchase

It might not be the responsibility of this library, however I wonder if anyone have implemented the free-trial period for in-app-purchase with this lib? (For example check if the free trial period is over, etc) Or, simply just set up the free-trail period in iTunes-connect and forget it, don't have to code anything in react native side?

My understanding is (auto-renewal case):
(1) FIRST, user have to 'purchase' not matter the free trial period is set or not.
(2) if the app is configured to have free trial period, THEN user can use the app in that free trial period without being charged
(3) when the free trial period is over, apple's system starts to auto renew user's purchase, user still can use the app, but now user will get charged from then on.

I'l appreciate any experiences if you have some to share. Thank you! :-)

Couldn't receive callback from postponed transaction.

Hello there,

Thanks for this useful plugin!

I found a react-native app couldn't receive the callback properly when itunes store postpones a transaction because of some reason like user verification, but It asks ths user to purchase an item again after verification. Because when itunes store postpones a transaction, It drops SKPaymentTransactionStateFailed first and the native module remove the callback at that time.

I tried to remove callback only when the user cancels the transaction. But I'm not sure It is proper way.

Thanks,

Question: loadProducts returning []

Hello!
I'm new to the in-app purchases, so I have a few questions, as the code below gives empty array.

  1. products array should contain the 'Product ID' of itunesconnect in-app-purchase, right?
  2. I should see the result of this function in 'simulator' right?
  3. Apple says Your first In-App Purchase must be submitted with a new app version. Select it from the app’s In-App Purchases section and click Submit.. So if I upload a new bundle to testflight, it should be ok? I don't really get this?
  4. what else can cause this to return []?

componentDidMount() {
var products = [
'videogroup1',
];
NativeModules.InAppUtils.loadProducts(products, (error, productsReturn ) => {
Alert.alert('in app products loaded: ' + productsReturn.length);
});
}

Asked for apple id password multiple time even after the transaction was successful.

Hi
The library work fine for enabling payments but it asks for the apple password again after the purchase has been completed. Sometimes the app ask me for password at the start up as well without invoking any payment function.
I think this is related to lifecycle of SKPaymentQueue.
http://stackoverflow.com/questions/4988663/skpaymentqueue-addtransactionobserver-asking-for-app-store-password-on-startup-a

Can someone look at it?

Check if in-app purchase has been made on start

Hi there,

I'm a bit lost on how to achieve the following workflow:

  • When opening my app, check if the currently logged in user (in App Store) has already purchased my in-app purchase by either checking a local storage item and if not present, checking existing receiptData using the InAppUtils.receiptData function.

  • Add Get Full App button for purchasing in-app premium content using the InAppUtils.loadProducts & InAppUtils.purchaseProduct functions.

  • Add Restore Purchase button for manually restoring previous in-app purchase using the InAppUtils.restorePurchases function.

I'm confused what the receiptData actually contains? Does it contain ALL receipts from ALL the apps from the logged-in user? Or just the receipts from my app?

If I would just use this as a check for the in-app purchase, it will always enable the premium content:

InAppUtils.receiptData((error, receiptData)=> {
  if(error) {
    AlertIOS.alert('itunes Error', 'Receipt not found.');
  } else {
    // enable premium content
  }
});

With the InAppUtils.restorePurchases function you CAN check if the current purchases contain your in-app purchase, but that requires logging in to your AppStore account everytime/most of the time, so not ideal for step 1 of my workflow.

So my question is, how should I validate the receiptData? I don't have a server for my app.
I found this module for validating receipts, but I can't get it working yet with rn-nodify.

Any help is appreciated.
Thanks!

`purchaseProduct` returns `invalid_product` unless you call `loadProducts` first.

You need to call loadProducts first and then call purchaseProduct either at a later time or in the callback for loadProducts.

At the very least the README should reflect this.

But, ideally, purchaseProduct should work without having to call loadProducts first.

Let me know your thoughts on this to make sure we're on the same page before I do a PR.

Question: Validating receipts

Thanks for this library Chirag! Just wondering what your suggestion is in regards to fetching the receiptData? I'm new to mobile apps and am not sure if fetching the receipt right after a transaction is the best approach? I've noticed receiptData change depending on when it's fetched.

Would be nice to add something in the documentation for this to help newbies like myself.

Thank you!

InAppUtils not a propery of NativeModules

Hi there,

Thanks for al your work on this library. I'm having a small problem which is that when I load NativeModules it does have the InAppUtils property so this returns undefined:

import { NativeModules } from 'react-native'
  const { InAppUtils } = NativeModules
...
  componentWillMount() {
    console.log(InAppUtils
}

I installed using both rnpm install --save react-native-in-app-utils and npm install --save react-native-in-app-utils; react-native-link. In both cases it looks like the libraries are linked properly in Xcode.

Any ideas how I can check that the library is installed properly?

Error in Loading products

Hi !

Following the readme I've installed the module with rnpm. The module seems to be installed, but when I try to loadProducts :

InAppUtils.loadProducts(products, (error, products) => {
   //update store here.
});

I find this error in the simulator :

_NativeModules2.default.loadProducts is not a function

Any idea how to fix this issue ? I'm using this configuration:

in package.json

"react-native": "0.39.2",
...
"react-native-in-app-utils": "4.0.0",

in index.js

import {
...
NativeModules,
} from 'react-native';
import { InAppUtils } from 'NativeModules'

Thanks a lot,

I keep getting invalid_product error

I created a item in iTunes Connect and the In-App Purchase Summary is as follows:

Reference Name: Glass
Product ID: com.singleglass.glass
Type: Non-Consumable
Apple ID: 1135803760

And then I tried to load products using

var products = [
   'com.singleglass.glass',
];
InAppUtils.loadProducts(products, (error, products) => {
   // invalid_product error here...
});

It does not work. I keep getting invalid_product errors here.

Is there something that I did wrong?

p.s: In-App Purchase Details is in Waiting for Screenshot status. But it seems that I cannot get the IAP to work before I can submit a screen shot right?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.