react-native-iap v3

Hyo
dooboolab
Published in
3 min readJun 12, 2019

It has been more than a year now since I’ve been maintaining react-native-iap. I’ve had a great experience maintaining this module and I’ve understood the process of working as a community.

Today, I’d like to introduce you my failure in implementing react-native-iap and what’s been updated in version 3. What I’ve missed out when building this module was that I’ve made every methods as promises and callbacks. I’ve realized that it didn’t quite work this way. There were several issues related to this design.

The flow of the purchase has been renewed by the founding in issue #307. Therefore, I’ve decided to redesign the purchase flow not relying on the callback or promise. There are some reasons not to approach in this way.
1. There may be more than one responses when requesting a payment.
2. The purchase responses are asynchronous which means request that’s made beforehand may not complete at first.
3. The purchase may be pended and hard to track what has been done (example).
4. Billing flow should be more like an event handler rather than acallback pattern.

When I first realized this, I’ve quickly supported a workaround version starting from 2.4.0-beta release. PR #348 describes how I’ve solved issue without heavy approach. I’ve added addAdditionalSuccessPurchaseListenerIOS to handle next event after the failure which I know isn’t a perfect solution. This was just a quick workaround. Of course, this encountered several issues such as #423.

Below is a new purchase flow for react-native-iap in version 3.

Above diagram shows how you can handle multiple purchases in 3.0.0

Most likely, you’ll want to handle the store kit flow detailed here, which happens when a user successfully pays after solving a problem with his or her account — for example, when the credit card information has expired.

If you see the clip, you will understand better that you won’t get the next promise result when a user does not have the payment method for the first time. You’ll get failed callback and then get lost. This flow was a bit terrible for me because I couldn’t ever reproduce this in sandbox mode which should have supported all the test cases to the developers.

In react-native-iap@3.0.+, it is recommended to write codes like below.

  1. Subscribe the events
componentDidMount() {
try {
const result = await RNIap.initConnection();
console.log('result', result);
} catch (err) {
console.warn(err.code, err.message);
}
purchaseUpdateSubscription = purchaseUpdatedListener(
(purchase: ProductPurchase) => {
console.log('purchaseUpdatedListener', purchase);
this.setState({
receipt: purchase.transactionReceipt },
() => this.goNext()
);
});
purchaseErrorSubscription = purchaseErrorListener(
(error: PurchaseError) => {
console.log('purchaseErrorListener', error);
Alert.alert('purchase error', JSON.stringify(error));
});
}

2. Request purchase

requestPurchase = async(sku) => {
try {
RNIap.requestPurchase(sku);
} catch (err) {
console.warn(err.code, err.message);
}
}
requestSubscription = async(sku) => {
try {
RNIap.requestSubscription(sku);
} catch (err) {
Alert.alert(err.message);
}
}
render() {
...
onPress={() => this.requestPurchase(product.productId)}
...
}

Furthermore, there are more updates in react-native-iap v3 not regarding the purchase flow. You can check it out in PR #510.

Starting from react-native-iap@3.3.0, there has been great work contributed by @solidfox that safely completes the transaction of the purchases even in a severe disaster such as when your app crashed. Below diagram shows the enhanced purchase flow from 3.3.0.

Enhanced purchase flow in 3.3.0

Many thanks to all the contributors including issuers. Hope more people enjoy building better purchase flow together with us.

Enjoy!

--

--