Google支付从创建商品到支付成功踩过的坑
最近app需要上架到谷歌应用市场,必要条件是需要集成谷歌支付,于是开始一顿操作++++一堆怼脸型的bug解决过程,先从创建应用开始。
- 创建谷歌账号,并开通开发者权限,需要支付money,公司账号。
- 创建应用,应用提前准备好名称,图片等信息,开发人员需要打出一个release包,需要签名文件签名,注意版本号,测试阶段时,使用的版本号,不能高于谷歌平台上传的这个包。release包可以无内容,主要是包名和签名固定。
- 需要开发人员 准备谷歌的测试账号,实现不用支付即可完成支付流程。
- 创建应用-上传apk-提交内容详情内容-确定内容分级-选择发布范围,整个过程。创建过程中未截图保存内容,欢迎有遇到问题的朋友,评论区留言交流。
- 新版的谷歌支付已经废弃掉原有Google In-app Billing, 复制aidl文件到项目中的方式,目前使用 BillingClient 链接谷歌-查询产品-购买-消耗等一系列流程。
app内接入流程
1、添加依赖、添加权限。
implementation 'com.android.billingclient:billing:3.0.0'
<!--谷歌商店应用内购买结算需要的权限-->
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="com.farsitel.bazaar.permission.PAY_THROUGH_BAZAAR" />
2、创建连接。
public void init() {
mBillingClient = BillingClient.newBuilder(mActivityRef.get())
.setListener(mPurchasesUpdatedListener)
.enablePendingPurchases()
.build();
if (!mBillingClient.isReady()) {
mBillingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult != null) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
LogUtil.i(TAG, "onBillingSetupFinished==ok");
} else {
LogUtil.w(TAG, "onBillingSetupFinished--error==" + billingResult.getDebugMessage() + "====" + billingResult.getResponseCode());
}
} else {
LogUtil.w(TAG, "billingResult ==== null");
}
}
@Override
public void onBillingServiceDisconnected() {
LogUtil.w(TAG, "onBillingServiceDisconnected");
}
});
} else {
LogUtil.w(TAG, "mBillingClient.isReady() false");
}
}
3、购买
/**
* 购买
*/
public void recharge() {
if (mBillingClient.isReady()) {
List<String> skuList = new ArrayList<>();
skuList.add(mSku);//商品的id
skuList.add("gas");// 这个参数不能为空,值随便传
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
//querySkuDetailsAsync 查询方法,list集合中传入商品id,谷歌后台-》应用内商品-》具体商品
mBillingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(BillingResult billingResult,
List<SkuDetails> skuDetailsList) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
&& skuDetailsList != null) {
for (SkuDetails skuDetails : skuDetailsList) {
// skuDetails 对象信息
// {
// "skuDetailsToken":"AEuhp4K_N_DyvTtZXkguU4XHEfLN2y54NJwxl9B5XxyVk1cvJ7Vkh-cZHpKEApKj3-il",
// "productId":"f0908u_",
// "type":"inapp",
// "price":"US$1.34",
// "price_amount_micros":1339320,
// "price_currency_code":"USD",
// "title":"VIP (Funchat)",
// "description":"Become VIP chatting with girls you like"
// }
String sku = skuDetails.getSku();//商品id
if (mSku.equals(sku)) {
LogUtil.i(TAG, "sku can buy ");
LogUtil.i(TAG, skuDetails.toString());
//真正的购买方法
BillingFlowParams purchaseParams =
BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.build();
mBillingClient.launchBillingFlow(mActivityRef.get(), purchaseParams);
}
}
} else {
LogUtil.w(TAG, "goods search fail");
}
}
});
} else {
ToastUtil.toastShortMessage(mActivityRef.get().getString(R.string.google_connect_error));
}
}
4、购买回调接口,购买成功,调用消耗方法,不然会导致下次购买失败
/**
* 购买回调
*/
private PurchasesUpdatedListener mPurchasesUpdatedListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> list) {
String debugMessage = billingResult.getDebugMessage();
LogUtil.e(TAG, "--》" + debugMessage);
if (list != null && list.size() > 0) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
LogUtil.i(TAG, "购买成功,开始消耗商品");
for (Purchase purchase : list) {
mConsume = "2";
LogUtil.i(TAG, "PurchaseToken->" + purchase.getPurchaseToken());
consume(purchase.getPurchaseToken());
}
}
} else {
switch (billingResult.getResponseCode()) {
case BillingClient.BillingResponseCode.SERVICE_TIMEOUT: {//服务连接超时
mListener.onState(mActivityRef.get(), RechargeResult.failOf("-3"));
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED: {
mListener.onState(mActivityRef.get(), RechargeResult.failOf("-2"));
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.SERVICE_DISCONNECTED: {//服务未连接
mListener.onState(mActivityRef.get(), RechargeResult.failOf("-1"));
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.USER_CANCELED: {//取消
mListener.onState(mActivityRef.get(), RechargeResult.failOf("1"));
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE: {//服务不可用
mListener.onState(mActivityRef.get(), RechargeResult.failOf("2"));
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.BILLING_UNAVAILABLE: {//购买不可用
mListener.onState(mActivityRef.get(), RechargeResult.failOf("3"));
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.ITEM_UNAVAILABLE: {//商品不存在
mListener.onState(mActivityRef.get(), RechargeResult.failOf("4"));
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.DEVELOPER_ERROR: {//提供给 API 的无效参数
mListener.onState(mActivityRef.get(), RechargeResult.failOf("5"));
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.ERROR: {//错误
mListener.onState(mActivityRef.get(), RechargeResult.failOf("6"));
mActivityRef.get().finish();
break;
}
case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED: {//未消耗掉
mConsume = "1";
queryHistory();
break;
}
case BillingClient.BillingResponseCode.ITEM_NOT_OWNED: {//不可购买
mListener.onState(mActivityRef.get(), RechargeResult.failOf("8"));
mActivityRef.get().finish();
break;
}
}
}
}
};
5、消耗
/**
* 消耗
*/
private void consume(String purchaseToken) {
// 只有消费成功之后,才能真正到账,否则3天之后,会执行退款处理 测试阶段只有5分钟
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchaseToken)
.build();
mBillingClient.consumeAsync(consumeParams, new ConsumeResponseListener() {
@Override
public void onConsumeResponse(BillingResult billingResult, String s) {
Log.e(TAG, "onConsumeResponse code = " + billingResult.getResponseCode() + " , msg = " + billingResult.getDebugMessage() + " , purchaseToken = " + purchaseToken); // 消费成功 处理自己的流程,我选择先存入数据库
LogUtil.w(TAG, "-->" + s);
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
LogUtil.i(TAG,"consume success ");
}
}
});
//上传服务器验证
// uploadToServer(purchaseToken, mOrderID, mPayTest);
}
错误1:此版本的应用未配置为通过GooglePlay结算。有关详情,请访问帮助中心。
app内错误截图
出现问题原因
- 是打包的时候,versionCode的值比提交到google play后台的版本要高。
- 打包的时候,和google play后台上的包的签名不一致,APK与发布证书一起签署。(重要提示:使用“Google Play应用程序签名”时,只有直接从Google PlayStore下载才有效!
- 登录测试机已登录谷歌账号,并已添加到谷歌测试账号中,添加地址 https://play.google.com/apps/testing/包名
- 确认账号信息里可用于测试的Gmail账号里,已添加测试账号。
错误2:应用内无法查询商品id,无法吊起支付窗口
一定要等你的应用为**Published**状态之后,并且创建了应用内商品为已激活状态,在app里面才能查到商品id,执行支付等操作,否则怎么样都查不到
- 应用已经发布了,但是还是吊不起支付窗口
首先app需要安装google三件套,不知道怎么安装的,可以安装一个YouTube,进入app后会自动提示你需要安装google play,需要vpn,然后一定注意了,需要在权限设置里面,把google play的##允许应用在后台弹窗界面##这个权限打开,一定记得要打开
- 当一切准备就绪之后,报:目前还无法在您所在的国家/地区购买Google Play中的内容。这个因为在中国不允许。
网页登录你的google账户:在设置里面,把你的地址改成美国或其他支持的国家,然后清除app内google play的数据,重新进入,重新选择地区(刚才你修改的地区),选完之后会提示你切换到美国的商店,然后再添加付款信息(中国的卡就行,我用的是招商银行的信用卡),这样就万事大吉了,之后就可以正常支付了。
错误3:In-app billing API version 3 is not supported on this device.
该手机登录Google账号的问题,或者说是Google账号的归属地问题,如果之前是ok的,突然报这样的的问题,重启,重启,重启 !!!包括电脑。至于哪些地方不能使用,我没有足够的账号数据支撑。或许咱们能做的是在产品角度,给出相应提示,例如更换账号啥的。
错误4:signInResult:failed code=12501
先检查网络是否墙了
流程跑通,放鞭炮,现在回顾来看,其实还挺简单的,最最最前提的条件是,*成功,测试账号信息完善,会省80%的工作量。
本文地址:https://blog.csdn.net/lxm20819/article/details/107141822
上一篇: 刘询曾多次想换太子,最后为什么放弃了?
下一篇: Object-C,对象和方法