前端时间接入韩国Onestore平台的时候踩了一些坑,国内的文档又很少,记录一下,废话不多说。我们开始吧。
官方文档有中英韩三种语言,可移步官方接入文档
开始集成1】目前的新版本是V5,直接放V5的jar包。从gizub下载OneStore在应用程序中购买SDK
2】清单文件添加
//(必需)添加API版本:它需要显式声明IAPV 5<Meta-data androID:name="iap:API_version" androID:value="5" />//(可选)指定支付屏幕UI:API版本5支持d出格式中的支付屏幕UI。如果在下面的iap:vIEw_选项中输入d出值,则支付窗口将d出。如果没有设置值,默认情况下它将被视为全屏(AndroID:value=“Full”)。<Meta-data androID:name="iap:vIEw_option" androID:value="popup | full" >
支付逻辑集成一、集成步骤1】初始化API并绑定One Store服务
2】绑定成功,检查是否支持onestore支付,如果支持,继续
3】检查未完成的订单(掉单的情况处理),如果有执行验单,消单逻辑(如果是游戏,也可放到进入游戏后进行)
4】验单:玩家请求支付,支付成功后将有效数据发给服务器进行验证(本地也可进行验证,详见代码)
5】消单:服务器验证成功,告知客户端,客户端进行消单,服务器发送奖励
初始化,绑定
//需要引入的头文件 import com.onestore.iap.API.IapEnum; import com.onestore.iap.API.IapResult; import com.onestore.iap.API.ProductDetail; import com.onestore.iap.API.PurchaseClIEnt; import com.onestore.iap.API.PurchaseData; // onestore 渠道参数配置 private static final int IAP_API_VERSION = 5; private static final int COIN_PER_GAME = 5; private static final int PURCHASE_REQUEST_CODE = 1000; private static final int LOGIN_REQUEST_CODE = 2000; private static final String PRODUCT_TYPE = IapEnum.ProductType.IN_APP.getType(); // "inapp" //此处在你的初始化方法中执行{ // PurchaseClIEnt 初始化——将公钥作为参数传递,以验证context和Signature。 mpurchaseClIEnt = new PurchaseClIEnt(this, mpublicKey); // 请求绑定ONE store服务,以启动应用内支付。 mpurchaseClIEnt.connect(mServiceConnectionListener);}/* * PurchaseClIEnt的 connect API 回调监听器 * 返回绑定成功或失败以及是否要更新ONE store服务的结果。 */ PurchaseClIEnt.ServiceConnectionListener mServiceConnectionListener = new PurchaseClIEnt.ServiceConnectionListener() { @OverrIDe public voID onConnected() { Log.d(TAG, "Service connected"); checkBillingSupportedAndLoadPurchases(); } @OverrIDe public voID ondisconnected() { Log.d(TAG, "Service disconnected"); } @OverrIDe public voID one rrorNeedUpdateException() { Log.e(TAG, "connect one rror, 需要更新ONE store客户端 "); updateOrInstallOnestoreService(); } };
检查是否支持
private voID checkBillingSupportedAndLoadPurchases() { Log.d(TAG, "checkBillingSupportedAndLoadPurchases()"); if (mpurchaseClIEnt == null) { Log.d(TAG, "PurchaseClIEnt is not initialized"); return; } // 方法名字中以postfix加上“Async”,UI线程中为保证安全执行,创建线程处理 this.runOnUiThread(new Runnable() { @OverrIDe public voID run() { // 先执行 查询是否支持应用内支付 mpurchaseClIEnt.isBillingSupportedAsync(IAP_API_VERSION, mBillingSupportedListener); } }); } /* * PurchaseClIEnt的isBillingSupportedAsync (查询是否支持)回调监听器 */ PurchaseClIEnt.BillingSupportedListener mBillingSupportedListener = new PurchaseClIEnt.BillingSupportedListener() { @OverrIDe public voID onSuccess() { Log.d(TAG, "isBillingSupportedAsync onSuccess"); isBillingSupported = true; //检查掉单的情况 // queryPurchase(IapEnum.ProductType.IN_APP); } @OverrIDe public voID one rror(IapResult result) { Log.e(TAG, "isBillingSupportedAsync one rror, " + result.toString()); if (IapResult.RESulT_NEED_LOGIN == result) { loadLoginFlow(); } } @OverrIDe public voID one rrorremoteexception() { Log.e(TAG, "isBillingSupportedAsync one rror, 无法连接ONE store服务"); } @OverrIDe public voID one rrorSecurityException() { Log.e(TAG, "isBillingSupportedAsync one rror, 应用状态异常下请求支付"); } @OverrIDe public voID one rrorNeedUpdateException() { Log.e(TAG, "isBillingSupportedAsync one rror, 需要更新ONE store客户端"); updateOrInstallOnestoreService(); } };
发起支付
String devPayload = AppSecurity.generatePayload();//参数大多数在开头部分说明了,单独说明第9个参数false:是否支持onestore 促销活动mpurchaseClIEnt.launchPurchaseFlowAsync(IAP_API_VERSION, this, PURCHASE_REQUEST_CODE, goods_ID, goods_name, PRODUCT_TYPE, devPayload_, role_ID, false, mpurchaseFlowListener); /* * PurchaseClIEnt的 launchPurchaseFlowAsync API (购买)回调监听器 */ PurchaseClIEnt.PurchaseFlowListener mpurchaseFlowListener = new PurchaseClIEnt.PurchaseFlowListener() { @OverrIDe public voID onSuccess(PurchaseData purchaseData) { String logStr = "pay success, purchaseData: " + purchaseData.toString(); reportErrorToServer(Code_PayResult, logStr); // 购买成功后客户端检查开发者payload。 // if (!isValIDPayload(purchaseData.getDeveloperPayload())) { // Log.d(TAG, "launchPurchaseFlowAsync onSuccess, Payload is not valID."); // return; // } // 购买成功后客户端检查签名。 // boolean valIDPurchase = AppSecurity.verifyPurchase(purchaseData.getPurchaseData(), purchaseData.getSignature(), mpublicKey); // if (valIDPurchase) { // 管理型商品(inapp)购买成功后消耗。 verifyPurchasetoServerAndConsumeItem(purchaseData); // } else { // Log.d(TAG, "launchPurchaseFlowAsync onSuccess, Signature is not valID."); // return; // } } @OverrIDe public voID one rror(IapResult result) { if(result == IapResult.RESulT_NEED_LOGIN ) { //需要登陆onestore loadLoginFlow(); } else if(result == IapResult.RESulT_ITEM_UNAVAILABLE){ LogD("purchase Failed , item unavailable"); } else if(result == IapResult.RESulT_ITEM_ALREADY_OWNED){ LogD("purchase Failed , item ALREADY_OWNED"); //掉单了 queryPurchase(IapEnum.ProductType.IN_APP); } else{ } } @OverrIDe public voID one rrorremoteexception() { Log.e(TAG, "queryPurchasesAsync one rror, 无法连接ONE store服务"); } @OverrIDe public voID one rrorSecurityException() { Log.e(TAG, "queryPurchasesAsync one rror, 应用状态异常下请求支付"); } @OverrIDe public voID one rrorNeedUpdateException() { Log.e(TAG, "queryPurchasesAsync one rror, 需要更新ONE store客户端 "); updateOrInstallOnestoreService(); } };
服务器验单(略) + 客户端消单
private voID verifyPurchasetoServerAndConsumeItem(final PurchaseData purchaseData) { if (mpurchaseClIEnt == null) { Log.d(TAG, "PurchaseClIEnt is not initialized"); return; } ...... //服务器验单成功,执行消耗 mpurchaseClIEnt.consumeAsync(IAP_API_VERSION, purchaseData, mConsumeListener);} /* * PurchaseClIEnt的 consumeAsync API (商品消耗)回调监听器 */ PurchaseClIEnt.ConsumeListener mConsumeListener = new PurchaseClIEnt.ConsumeListener() { @OverrIDe public voID onSuccess(PurchaseData purchaseData) { Log.d(TAG, "consumeAsync onSuccess, " + purchaseData.toString()); // 商品消耗成功后,按各开发者编写的购买成功方案进行。 } @OverrIDe public voID one rrorremoteexception() { Log.e(TAG, "consumeAsync one rror, 无法连接ONE store服务"); } @OverrIDe public voID one rrorSecurityException() { Log.e(TAG, "consumeAsync one rror, 应用状态异常下请求支付"); } @OverrIDe public voID one rrorNeedUpdateException() { Log.e(TAG, "consumeAsync one rror, 需要更新ONE store客户端 "); updateOrInstallOnestoreService(); } @OverrIDe public voID one rror(IapResult result) { Log.e(TAG, "consumeAsync one rror, " + result.toString()); } };
其他代码里用到的方法
//未登陆onestore调用 private voID loadLoginFlow() { if (mpurchaseClIEnt == null) { Log.d(TAG, "PurchaseClIEnt is not initialized"); return; } mActivity.runOnUiThread(new Runnable() { @OverrIDe public voID run() { if (mpurchaseClIEnt.launchLoginFlowAsync(IAP_API_VERSION, mActivity, LOGIN_REQUEST_CODE, mLoginFlowListener) == false) { // Listener is null } } }); } //查询订单 private voID queryPurchase(final IapEnum.ProductType productType) { Log.d(TAG, "queryPurchase() :: productType - " + productType.getType()); if (mpurchaseClIEnt == null) { Log.d(TAG, "PurchaseClIEnt is not initialized"); return; } this.runOnUiThread(new Runnable() { @OverrIDe public voID run() { mpurchaseClIEnt.queryPurchasesAsync(IAP_API_VERSION, PRODUCT_TYPE, mqueryPurchaseListener); } }); } /* * PurchaseClIEnt的queryPurchasesAsync API (查询购买记录)回调监听器 */ PurchaseClIEnt.queryPurchaseListener mqueryPurchaseListener = new PurchaseClIEnt.queryPurchaseListener() { @OverrIDe public voID onSuccess(List<PurchaseData> purchaseDataList, String productType) { Log.d(TAG, "queryPurchasesAsync onSuccess, " + purchaseDataList.toString()); if (IapEnum.ProductType.IN_APP.getType().equalsIgnoreCase(productType)) { onl oadPurchaseInApp(purchaseDataList); } else if (IapEnum.ProductType.auto.getType().equalsIgnoreCase(productType)) { // 如为查询购买记录后获取的包月自动支付商品( auto),先验证签名,成功后根据开发者应用处理需求编写方案。 } } @OverrIDe public voID one rrorremoteexception() { Log.e(TAG, "queryPurchasesAsync one rror, 无法连接ONE store服务"); } @OverrIDe public voID one rrorSecurityException() { Log.e(TAG, "queryPurchasesAsync one rror, 应用状态异常下请求支付"); } @OverrIDe public voID one rrorNeedUpdateException() { Log.e(TAG, "queryPurchasesAsync one rror, 需要更新ONE store客户端 "); updateOrInstallOnestoreService(); } @OverrIDe public voID one rror(IapResult result) { Log.e(TAG, "queryPurchasesAsync one rror, " + result.toString()); } }; //掉单消耗 private voID onl oadPurchaseInApp(List<PurchaseData> purchaseDataList) { for (PurchaseData purchase : purchaseDataList) { ...... verifyPurchasetoServerAndConsumeItem(purchase); } } //商店更新 private voID updateOrInstallOnestoreService() { PurchaseClIEnt.launchUpdateOrInstallFlow(mActivity); }
onActivityResult
@OverrIDe public voID onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); LogD("onActivityResult: " + requestCode + " resultCode: " + resultCode); switch (requestCode) { case LOGIN_REQUEST_CODE: if (resultCode == Activity.RESulT_OK) { if (mpurchaseClIEnt.handleLoginData(data) == false) { Log.e(TAG, "onActivityResult handleLoginData false "); // Listener is null } } else { Log.e(TAG, "onActivityResult user canceled"); } break; case PURCHASE_REQUEST_CODE: /* * 调用 launchPurchaseFlowAsync API 时收到的intent数据通过handlePurchaseData解析返回值。 * 解析后返回结果通过调用 launchPurchaseFlowAsync 时的 PurchaseFlowListener 返回。 */ if (resultCode == Activity.RESulT_OK) { if (mpurchaseClIEnt.handlePurchaseData(data) == false) { Log.e(TAG, "onActivityResult handlePurchaseData false "); // Listener is null reportErrorToServer(Code_CommonLog, "Listener is null"); } } else { Log.e(TAG, "onActivityResult user canceled"); reportErrorToServer(Code_CommonLog, "onActivityResult user canceled"); // user canceled , do nothing.. } break; default: } }
AppSecurity,这个是案例里有的一个类,可以拿来用。
官方案例
三、集成问题1、无法拉起支付
1.1】手机必须安装最新版本的Onestore客户端,否则无法支付,自备梯子去拿,分享目前最新版连接
提取码:w0nu
1.2】手机需要翻墙,并且能够进入onestore客户端(可在初始化回调里面查看错误码知晓)
1.3】手机必须支持onestore支付(可在查询是否支持的回调里面查看错误码知晓)
1.4】查看支付回调错误码,常见的错误类型详见代码示例
1.5】查询购买记录,并且进行消费(主要是针对管理型商品(inapp))。注意:如果不进行消费是不能进行购买请求的1
2、 掉单的问题
如果代码逻辑正常,这种情况一般发生在玩家支付过程中网络中断、强退应用等情况。出现这种情况会导致2.1】玩家支付成功,但是没有收到相应的奖励。–未完成验单
2.2】玩家支付成功,没收到奖励,并且还不能继续购买这个商品。–未消单
俗称掉单。掉单了,如果无法处理,我们就只能补单。
为了减少补单的情况发生(总会有掉单),我们需要进行一些规避的方法。在应用启动后或者在发生无法继续购买商品时,重新查询当前是否存在未消耗的商品,如果存在,继续执行验单和消单逻辑,
3、极端 *** 作的情况
3.1】新版本中无法传递透传字段(可以试下payload传递是否可行)
我们项目内商品的分类比较特殊,如果玩家连续多次点击多个不同的商品,会导致错单的情况(订单号跟商品无法匹配),这就需要特殊处理,各位大佬一般用不着,本文不再赘述。
此内容参考https://blog.csdn.net/Silencemuyi/article/details/90708000,写的也很详细,想必也是被坑的厉害。 ↩︎
以上是内存溢出为你收集整理的韩国ONE store平台支付集成(android)全部内容,希望文章能够帮你解决韩国ONE store平台支付集成(android)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)