Android Billing 4.0.0的实现导致React Native In App Purchase (RNIAP)停止工作。

huangapple go评论143阅读模式
英文:

implementation of android billing 4.0.0 causes React Native In App Purchase (RNIAP) to stop working

问题

我正在尝试在我的Android React Native应用中实现Android Billing 4.0.0。

我已经尝试将以下行添加到我的build.gradle(app)中:

implementation 'com.android.billingclient:billing:4.0.0' 

然而,当我包含上述行时,我的React Native In App Purchase(RNIAP)停止工作。

在我的JS代码中,我有以下行(如果需要,您可以查看完整文件):

const products = await RNIap.getProducts(itemSkus);

然而,当我添加此行时,RNIap.getProducts的await从不返回任何内容,并且不执行此行之后的代码。这一行似乎卡住了。

当我删除上述行时,RNIap.getProducts正常工作并显示内购项目。但是,如果我删除上述行,Google Play控制台会显示“请升级到4或更高版本的计费库以发布此应用”,因此我无法上传新应用。

我知道这不是模拟器问题,因为我已经使用上述行发布了应用程序,而在现场环境中仍然未返回IAP。

我已经在我的AndroidManifest.xml中包含了以下内容:

<uses-permission android:name="com.android.vending.BILLING" />

在iOS上一切都正常工作。

以下是我的代码:

(注意:出于安全原因,我已更改了包名称和内购名称)

iap.js

// 这里是您的JavaScript代码,我不会对其进行翻译。

package.json

// 这里是您的package.json文件,我不会对其进行翻译。

希望有人遇到过类似的问题并能帮助我找到解决方案。

谢谢,Andrew


<details>
<summary>英文:</summary>

I am trying to implement Android Billing 4.0.0 on my Android React Native app.

I have tried implementing the below line  into my build.gradle (app):

implementation 'com.android.billingclient:billing:4.0.0'


However, my React Native In App Purchase (RNIAP) has stopped working when I include the above line.

On my JS code I  have the following line  (you can see the full file below if needed):

const products = await RNIap.getProducts(itemSkus);


However, when I add this line the RNIap.getProducts await never returns anything and the code following this line is not executed.  This line seems to get stuck.

When I remove the  above line, the RNIap.getProducts works and displays the In App Purchase. However, if i remove  the above line, Google Play  Console displays &#39;please upgrade to billing library version 4 or newer to publish this app&#39; - and therefore i can&#39;t upload the new app.

I know it&#39;s not an emulator issue as I have published the app with the above line and in the live environment the IAP is still not returned.

I have included the below in my AndroidManifest.xml

    &lt;uses-permission android:name=&quot;com.android.vending.BILLING&quot; /&gt;

Everything works correctly on iOS.

Below is my code:

(Note: i have changed the package name &amp; in-app purchase name for security reasons) 

iap.js

import React, { Component } from "react";
import {
View,
Text,
StyleSheet,
Platform,
PixelRatio,
} from "react-native";
import {Header,Left,Right,Icon,Content,Grid,Row,Col,Container,H1,Button,Footer} from 'native-base';
import LinearGradient from 'react-native-linear-gradient';

//Redux imports
import { connect } from "react-redux";
import { toggle } from '../../Reducers/toggle';

//In-app Purchase import
import * as RNIap from 'react-native-iap';

const itemSkus = Platform.select({
ios: [
'example.for_stackoverflow.ios',
],
android: [
'example.for_stackoverflow.android',
],
});

class Iap extends Component {
constructor(props) {
console.log(itemSkus);
super(props);

this.state = {
  productList: [],
  receipt: &#39;&#39;,
  availableItemsMessage: &#39;&#39;,
};

}

state = {
toggle: this.props.toggle.togglePremium || false,
};

handleChange = ( toggle ) => {
this.setState({ toggle });
};

async componentDidMount() {
try {
const result = await RNIap.initConnection();
console.log('result', result);
} catch (err) {
console.warn(err.code, err.message);
}
this.getItems();
}

//after purcahse to to the finish transaction page.
goToNext = () => {
this.props.navigation.navigate('Logout', {
receipt: this.state.receipt,
});
}

getItems = async() => {
try {
console.log(itemSkus + ' check itemSkus');
const products = await RNIap.getProducts(itemSkus);
//const subscriptions = await RNIap.getSubscriptions(itemSkus);
// const products = await RNIap.getSubscriptions(itemSkus);
console.log(products + 'check Products');
this.setState({ productList: products });
} catch (err) {
console.log(err.message + ' err.message');
console.warn(err.code, err.message);
}
}

buyItem = async(sku) => {
//console.info('buyItem: ' + sku);
// const purchase = await RNIap.buyProduct(sku);
// const products = await RNIap.buySubscription(sku);
// const purchase = await RNIap.buyProductWithoutFinishTransaction(sku);
try {
const purchase: any = await RNIap.buyProduct(sku);
this.setState({ receipt: purchase.transactionReceipt }, () => this.goToNext());
} catch (err) {
//console.warn(err.code, err.message);
const subscription = RNIap.addAdditionalSuccessPurchaseListenerIOS(async (purchase) => {
this.setState({ receipt: purchase.transactionReceipt }, () => this.goToNext());
subscription.remove();
});
}
}

getPurchases = async() => {
try {
console.log('get hit, and when??');
const purchases = await RNIap.getAvailablePurchases();
let restoredTitles = '';
let coins = CoinStore.getCount();
purchases.forEach(purchase => {
if (purchase.productId == '4dot6OVER01') {
this.setState({ togglePremium: true });
restoredTitles += 'Premium Version';
}
else if (purchase.productId == 'android.test.purchased') {
console.log(purchase.productId);
this.setState({ togglePremium: true });
restoredTitles += 'Premium Version';
}
})
Alert.alert('Restore Successful', 'You successfully restored the following purchases: ' + restoredTitles);
} catch(err) {
//console.warn(err); // standardized err.code and err.message available
Alert.alert(err.message);
}
}

static navigationOptions = {
  drawerIcon : ({tintColor}) =&gt; (
    &lt;Icon name=&quot;ios-star-outline&quot; style={{fontSize: 24, color: tintColor}} /&gt;
  )
}

getPrice = (priceString) =&gt; {
  const price = JSON.parse(priceString);
  //return (&lt;H1 style={styles.textHeaderNumber}&gt;${price}&lt;/H1&gt;)
  return(&lt;Text style={styles.buttonTextBackWhite}&gt;${price}&lt;/Text&gt;)
}

getTitle = (titleString) =&gt; {

  const title = JSON.parse(titleString);
  return(&lt;Row&gt;&lt;H1 style={styles.textHeader}&gt;{title}&lt;/H1&gt;&lt;/Row&gt;)
}

getDescription = (descString) =&gt; {

  const desc = JSON.parse(descString);
  return(&lt;Row&gt;&lt;Text style={styles.textDesc}&gt;{desc}&lt;/Text&gt;&lt;/Row&gt;)
}

render() {
  const purchase = this.props.toggle.togglePremium;
  const { productList, receipt, availableItemsMessage } = this.state;
  console.log(productList + &#39; check productList&#39;);
  const receipt100 = receipt.substring(0, 100);
    return (

            &lt;Col size={1}&gt;



                  &lt;Row&gt;&lt;Text style={styles.textHeader}&gt;Cricket Over Counter Premium&lt;/Text&gt;&lt;/Row&gt;
                  &lt;Row&gt;&lt;Text style={styles.textDesc}&gt;Cricket Umpire Over and Ball Counter upgrade to premium to allow all features for the entire innings!&lt;/Text&gt;&lt;/Row&gt;


              {

                productList.map((product, i) =&gt; {
                  console.log(product + &#39; check product.&#39;);
                  return (
                    &lt;Row key={i} style={{
                      flexDirection: &#39;column&#39;, alignItems: &#39;center&#39;,
                    }}&gt;

                      &lt;Button rounded large warning style={styles.largeButtonGreen}
                          onPress={() =&gt; this.buyItem(product.productId)} &gt;
                          {this.getPrice(JSON.stringify(product.price))}
                        &lt;/Button&gt;
                    &lt;/Row&gt;
              );
          })
        }


            &lt;/Col&gt;
    );
}

}

const mapStateToProps = state => ({
toggle: state.toggle,
});

export default connect(mapStateToProps)(Iap);



package.json


{
"name": "ExampleForStackOverflow",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"@invertase/react-native-apple-authentication": "^2.1.2",
"@react-native-async-storage/async-storage": "^1.13.4",
"@react-native-firebase/app": "^10.8.0",
"@react-native-firebase/auth": "^10.8.0",
"@react-native-firebase/firestore": "^10.8.0",
"@react-native-google-signin/google-signin": "^7.0.0-alpha.3",
"@react-native-picker/picker": "^1.16.7",
"@react-navigation/drawer": "^5.12.3",
"@react-navigation/native": "^5.9.2",
"native-base": "^2.15.2",
"react": "16.13.1",
"react-compose": "^2.0.0",
"react-native": "0.63.5",
"react-native-animatable": "^1.3.3",
"react-native-apple-authentication": "^2.0.0",
"react-native-cli": "^2.0.1",
"react-native-dotenv": "^3.3.1",
"react-native-draggable-flatlist": "^3.0.7",
"react-native-elements": "^3.2.0",
"react-native-gesture-handler": "^1.10.1",
"react-native-haptic-feedback": "^1.11.0",
"react-native-iap": "^5.2.14",
"react-native-keep-awake": "^4.0.0",
"react-native-linear-gradient": "^2.5.6",
"react-native-reanimated": "^1.13.4",
"react-native-restart": "0.0.24",
"react-native-safe-area-context": "^3.1.9",
"react-native-safe-area-view": "^1.1.1",
"react-native-screens": "^2.17.1",
"react-native-scroll-into-view": "^2.0.2",
"react-native-splash-screen": "^3.2.0",
"react-native-swipe-list-view": "^3.2.9",
"react-native-swipeable-item": "^2.0.2",
"react-native-switch": "^2.0.0",
"react-native-vector-icons": "^8.0.0",
"react-native-webview": "^11.2.3",
"react-navigation": "^4.4.3",
"react-navigation-drawer": "^2.6.0",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"redux-devtools-extension": "^2.13.8",
"redux-logger": "^3.0.6",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.3.0",
"tcomb-form-native": "^0.6.20"
},
"devDependencies": {
"@babel/core": "^7.8.4",
"@babel/runtime": "^7.8.4",
"@react-native-community/eslint-config": "^1.1.0",
"babel-jest": "^25.1.0",
"eslint": "^6.5.1",
"jest": "^25.1.0",
"metro-react-native-babel-preset": "^0.59.0",
"react-test-renderer": "16.13.1"
},
"jest": {
"preset": "react-native"
}
}



Hopefully someone has  experienced a  similar issue and  can  help me with  a  solution.

Thanks,
Andrew






</details>


# 答案1
**得分**: 1

我找到了问题。

我使用的是"react-native 0.63.5"。我安装了"react-native-iap 5.2.14",但它不支持Android Billing Library 4.0.0。

因为我使用的React Native版本低于0.65,所以我必须将我的"react-native-iap"包升级到v7.5.6(这是支持React Native版本小于0.65和Android Billing Library 4.0.0的最新版本)。

所以,对于可能遇到这个问题的任何人:

RN < 0.65 - 请升级到"react-native-iap 7.5.6"。方法是在您的package.json文件中更新"react-native-iap"的版本,然后运行npm install。

RN >= 0.65 - 尝试通过在package.json文件中更新"react-native-iap"的版本并运行npm install来升级到最新稳定版本的"react-native-iap"。

<details>
<summary>英文:</summary>

I figured out the issue.

I am on &quot;react-native 0.63.5. I had react-native-iap 5.2.14 installed - which doesn&#39;t support Android Billing Library 4.0.0.

Because i&#39;m on a React Native versions less than 0.65, i have to update my react-native-iap package to v7.5.6 (as thats the newest version that supports react native &lt;0.65 AND android billing library 4.0.0.

So for anyone that might come across this issue:

RN &lt; 0.65 - upgrade to react-native-iap 7.5.6. do this by updating react-native-iap version on your package.json file and running npm install

RN &gt;= 0.65 - try updating to the latest stable version of react-native-iap by updating react-native-iap version on your package.json file and running npm install

</details>



huangapple
  • 本文由 发表于 2023年3月12日 11:13:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75710868.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定