Android ONE store支付

简介: 什么是ONE store应用内支付(IAP)一家商店应用内部支付(下称IAP)是一家商店使用的,支付服务,开发者销售手机应用程序的应用内部商品时,利用一个商店的验证和支付系统完成向用户支付费用,解决等价流程。一店服务(一店服务,OSS)替代开发的应用商品,OSS与一店总服务器连接执行支付工作,用于响应用户的应用内部商品购买请求。

ONE store支付:



详情:https://dev.onestore.co.kr/devpoc/reference/view/Apps


1、什么是ONE store应用内支付(IAP)


一家商店应用内部支付(下称IAP)是一家商店使用的,支付服务,开发者销售手机应用程序的应用内部商品时,利用一个商店的验证和支付系统完成向用户支付费用,解决等价流程。一店服务(一店服务,OSS)替代开发的应用商品,OSS与一店总服务器连接执行支付工作,用于响应用户的应用内部商品购买请求。


2、开发环境配置建议安卓应用程序程序适用的IAP SDK所需的开发环境如下:


Android 4.0及以上版本(API版本14以上)

Java SDK 1.6版本

Android studio 2.0及以上版本


3、事先准备


详情:https://dev.onestore.co.kr/devpoc/reference/view/Apps


3-1、配置应用ID

3-2、填写银行信息

3-3、应用内商品注册

3-3.1应用内商品个别注册

3-3.2应用内商品批量注册

3-4、配置认证密钥

3-5、下载示例应用

3-6、新增应用内支付库(Library)

3-7、设置 Android Manifest文档

3-8、安装ONE store应用


4、实现应用内支付


详情可通过VPN:https://dev.onestore.co.kr/devpoc/reference/view/IAP_v17_05_implementation_cn(已更新至v6版本文章最后有电梯)


使用SDK实现应用内支付


4-1、发起ONE store登录的请求


调用 launchLoginFlowAsync,请求登录于ONE store。

以参数传递的requestCode用于以后确认返回至onActivityResult的数据。


/*
 * PurchaseClient的 launchLoginFlowAsync API(登录)回调监听器
 */
PurchaseClient.LoginFlowListener mLoginFlowListener = new PurchaseClient.LoginFlowListener() {
    @Override
    public void onSuccess() {
        Log.d(TAG, "launchLoginFlowAsync onSuccess");
        // 开发者应自行编写登录成功后的方案。
    }
    @Override
    public void onError(IapResult result) {
        Log.e(TAG, "launchLoginFlowAsync onError, " + result.toString());
    }
    @Override
    public void onErrorRemoteException() {
        Log.e(TAG, "launchLoginFlowAsync onError, 无法连接ONE store服务");
    }
    @Override
    public void onErrorSecurityException() {
        Log.e(TAG, "launchLoginFlowAsync onError, 应用状态异常下请求支付");
    }
    @Override
    public void onErrorNeedUpdateException() {
        Log.e(TAG, "launchLoginFlowAsync onError, 需要更新ONE store客户端 ");
    }
};
int IAP_API_VERSION = 5;
int LOGIN_REQUEST_CODE = 2000; // 向onActivityResult 返回的 request code
mPurchaseClient.launchLoginFlowAsync(IAP_API_VERSION, "调用Activity".this, LOGIN_REQUEST_CODE, mLoginFlowListener)

4-2、应用内支付初始化与连接


使用应用内支付SDK时,应进行初始化,创建PurchaseClient对象并执行购买方法。首先在创建PurchaseClient对象时,输入当前Activity的Context信息和签名密钥值。创建对象后,执行connect连接。在此过程中,SDK中与应用内支付服务连接,启动为购买的各种参数设定的操作。


/*
 * PurchaseClient的 connect API 回调监听器
 * 返回绑定成功或失败以及是否要更新ONE store服务的结果。
 */
PurchaseClient.ServiceConnectionListener mServiceConnectionListener = new PurchaseClient.ServiceConnectionListener() {
    @Override
    public void onConnected() {
        Log.d(TAG, "Service connected");
    }
    @Override
    public void onDisconnected() {
        Log.d(TAG, "Service disconnected");
    }
    @Override
    public void onErrorNeedUpdateException() {
        Log.e(TAG, "connect onError, 需要更新ONE store客户端 ");
  PurchaseClient.launchUpdateOrInstallFlow(this);
    }
};
@Override
public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
    // PurchaseClient 初始化——将公钥作为参数传递,以验证context和Signature。
    mPurchaseClient = new PurchaseClient(this, AppSecurity.getPublicKey());
    // 请求绑定ONE store服务,以启动应用内支付。
    mPurchaseClient.connect(mServiceConnectionListener);
}


注意连接时未安装ONE store客户端或ONE store客户端版本不支持应用内支付 V17版本的情况,会调用 ServiceConnectionListener之onErrorNeedUpdateException()。出现该错误时,调用安装或更新ONE store客户端的方法,即PurchaseClient.launchUpdateOrInstallFlow。


退出Activity时,在 onDestroy方法中输入解除PurchaseClient的代码。


@Override
protected void onDestroy() {
    super.onDestroy();
    if (mPurchaseClient == null) {
        Log.d(TAG, "PurchaseClient is not initialized");
        return;
    }
    // 关闭应用时,使用PurchaseClient中断服务。
    mPurchaseClient.terminate();
}


4-3、查询是否支持


开发者在正式使用应用内支付方法之前,应先调用相应方法,确认能否启动应用内支付。

如果SDK方法是使用AIDL提供的API,以回调形式返回成功及失败的结果。

对失败的返回会提供使用SDK的开发者必须处理的三大错误(onErrorRemoteException、onErrorSecurityException、onErrorNeedUpdateException)和普通错误(onError)。向onError监听器返回的IapResult有返回码和对返回码进行说明的Enum,开发者应根据开发方案,处理相应错误。


/*
 * PurchaseClient的isBillingSupportedAsync (查询是否支持)回调监听器
 */
PurchaseClient.BillingSupportedListener mBillingSupportedListener = new PurchaseClient.BillingSupportedListener() {
    @Override
    public void onSuccess() {
        Log.d(TAG, "isBillingSupportedAsync onSuccess");
    }
    @Override
    public void onError(IapResult result) {
        Log.e(TAG, "isBillingSupportedAsync onError, " + result.toString());
    }
    @Override
    public void onErrorRemoteException() {
        Log.e(TAG, "isBillingSupportedAsync onError, 无法连接ONE store服务");
    }
    @Override
    public void onErrorSecurityException() {
        Log.e(TAG, "isBillingSupportedAsync onError, 应用状态异常下请求支付");
    }
    @Override
    public void onErrorNeedUpdateException() {
        Log.e(TAG, "isBillingSupportedAsync onError, 需要更新ONE store客户端");
    }
};
// ONE store应用内支付API版本
int IAP_API_VERSION = 5;
mPurchaseClient.isBillingSupportedAsync(IAP_API_VERSION, mBillingSupportedListener);

4-4、查询商品信息


开发者在 ArrayList输入采用queryProductAsync方法的参数中放入想要获取信息的应用内商品ID并调用,返回结果至已注册的监听器。

商品ID指开发者在开发者中心注册商品时自定义的商品ID。商品信息会以 ProductDetail形式返回至 onSuccess监听器。


/*
 * PurchaseClient的 queryProductsAsync API (商品信息查询)回调监听器
 */
PurchaseClient.QueryProductsListener mQueryProductsListener = new PurchaseClient.QueryProductsListener() {
    @Override
    public void onSuccess(List productDetails) {
        Log.d(TAG, "queryProductsAsync onSuccess, " + productDetails.toString());
    }
    @Override
    public void onErrorRemoteException() {
        Log.e(TAG, "queryProductsAsync onError, 无法连接ONE store服务 ");
    }
    @Override
    public void onErrorSecurityException() {
        Log.e(TAG, "queryProductsAsync onError, 应用状态异常下请求支付 ");
    }
    @Override
    public void onErrorNeedUpdateException() {
        Log.e(TAG, "queryProductsAsync onError, 需要更新ONE store客户端");
    }
    @Override
    public void onError(IapResult result) {
        Log.e(TAG, "queryProductsAsync onError, " + result.toString());
    }
};
int IAP_API_VERSION = 5;
String productType = IapEnum.ProductType.IN_APP.getType(); // "inapp"
ArrayList productCodes = new ArrayList<>();
productCodes.add("p5000");
productCodes.add("p10000");
mPurchaseClient.queryProductsAsync(IAP_API_VERSION, productCodes, productType, mQueryProductsListener);

4-5、发起购买请求


调用launchPurchaseFlowAsync方法执行购买。调用方法时,输入想要购买的应用内商品ID、商品名称、商品类别和开发者任意决定的launchPurchaseFlowAsync(不超过100byte),该值用于支付成功后确认数据的正确性和附加数据,并以参数传递的requestCode用于确认返回至onActivityResult的数据。

购买成功时结果返回至onSuccess监听器,以SDK的 PurchaseData规格返回。开发者基于收到的结果,再通过 developerPayload确认数据的正确性和附加数据,以签名信息来验证。

管理型商品,通过设置商品消耗处理为用户提供商品。

ONE store面向用户开展发送优惠券、 购物返现(cashback)等各种优惠推广活动。开发者发起购买请求时,可通过gameUserId、promotionApplicable参数,允许或控制用户参加推广活动。开发者选择应用的唯一标识符及是否参与活动并传递给ONE store,ONE store基于该值处理用户的活动优惠。


注意:gameUserId,protectionApplicable参数必须事先应用于ONE store经理的促销工作。一般说来,该值不应发送。

此外,gameUserId参数应当送到散列单一值,以便在事先发送价值信息时,没有隐私信息保护问题。


/*
* PurchaseClient的 launchPurchaseFlowAsync API (购买)回调监听器
 */
PurchaseClient.PurchaseFlowListener mPurchaseFlowListener = new PurchaseClient.PurchaseFlowListener() {
    @Override
    public void onSuccess(PurchaseData purchaseData) {
  Log.d(TAG, "launchPurchaseFlowAsync onSuccess, " + purchaseData.toString());
        // 购买成功后检查开发者payload。
        if (!isValidPayload(purchaseData.getDeveloperPayload())) {
            Log.d(TAG, "launchPurchaseFlowAsync onSuccess, Payload is not valid.");
            return;
        }
        // 购买成功后检查签名。
        boolean validPurchase = AppSecurity.isValidPurchase(purchaseData.getPurchaseData(), purchaseData.getSignature());
        if (validPurchase) {
            if (product5000.equals(purchaseData.getProductId())) {{
                // 管理型商品(inapp)购买成功后消耗。
                consumeItem(purchaseData);
            }
        } else {
            Log.d(TAG, "launchPurchaseFlowAsync onSuccess, Signature is not valid.");
            return;
        }
    }
    @Override
    public void onError(IapResult result) {
        Log.e(TAG, "launchPurchaseFlowAsync onError, " + result.toString());
    }
    @Override
    public void onErrorRemoteException() {
        Log.e(TAG, "launchPurchaseFlowAsync onError, 无法连接ONE store服务 ");
    }
    @Override
    public void onErrorSecurityException() {
        Log.e(TAG, "launchPurchaseFlowAsync onError, 应用状态异常下请求支付 ");
    }
    @Override
    public void onErrorNeedUpdateException() {
        Log.e(TAG, "launchPurchaseFlowAsync onError, 需要更新ONE store客户端 ");
    }
};
int IAP_API_VERSION = 5;
int PURCHASE_REQUEST_CODE = 1000; // 返回至onActivityResult的request code
String product5000 = "p5000"; // 请求购买的商品ID
String productName = ""; // ""时显示开发者中心注册的商品名称
String productType = IapEnum.ProductType.IN_APP.getType(); // "inapp"
String devPayload = AppSecurity.generatePayload();
String gameUserId = ""; // 默认 ""
boolean promotionApplicable = false;
mPurchaseClient.launchPurchaseFlowAsync(IAP_API_VERSION, "调用Activity".this, PURCHASE_REQUEST_CODE, product5000, productName, productType, devPayload, gameUserId, promotionApplicable, mPurchaseFlowListener);

支付成功时返回至监听器的Purchase信息参考“应用内支付参考 - getPurchaseIntent() 发起购买请求”。

支付结果会返回至调用launchPurchaseFlowAsync的Activity的onActivityResult,在这里须添加handlePurchaseData方法,以SDK处理购买结果。启动handlePurchaseData方法时,如果作为请求购买的参数输入的 PurchaseFlowListener为null的话,会返回false(失败)。成功或错误的处理结果会通过 PurchaseFlowListener来返回。


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.e(TAG, "onActivityResult resultCode " + resultCode);
    switch (requestCode) {
        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
                }
            } else {
                Log.e(TAG, "onActivityResult user canceled");
                // user canceled , do nothing..
            }
            break;
        default:
    }
}


4-6、商品消耗


如为管理型商品(inapp),未消耗已购商品时无法再次购买。用户购买商品后,其购买信息托管给ONE store,商品被消耗,ONE store立刻收回用户购买商品的权限。也就是说,如过购买了管理型商品而未消耗,可作为永久性商品,如购买后立刻消耗商品,可作为消耗型商品,如超过一定期限消耗已购商品,可作为限期型商品。要发起商品消耗请求时,将返回至launchPurchaseFlowAsync或queryPurchasesAsync的购买信息,作为 consumeAsync 方法的参数传递并调用。


/*
 * 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 onErrorRemoteException() {
        Log.e(TAG, "consumeAsync onError, 无法连接ONE store服务");
    }
    @Override
    public void onErrorSecurityException() {
        Log.e(TAG, "consumeAsync onError, 应用状态异常下请求支付");
    }
    @Override
    public void onErrorNeedUpdateException() {
        Log.e(TAG, "consumeAsync onError, 需要更新ONE store客户端 ");
    }
    @Override
    public void onError(IapResult result) {
        Log.e(TAG, "consumeAsync onError, " + result.toString());
    }
};
int IAP_API_VERSION = 5;
PurchaseData purchaseData; // 查询购买记录及请求购买后接到的PurchaseData
mPurchaseClient.consumeAsync(IAP_API_VERSION, purchaseData, mConsumeListener);

4-7、查询购买记录


调用queryPurchasesAsync方法来获取用户已购但未消耗的管理型商品(inapp)和用户订阅的包月自动支付商品(auto)。SDK会验证签名以确认购买信息数据伪造与否,如签名验证失败,会将“IapResult”内定义的 IapResult.IAP_ERROR_SIGNATURE_VERIFICATION值返回至onError监听器。出现错误表示购买信息数据有伪造的可能,有必要确认是否有abusing袭击。

开发者查询购买记录获得管理型商品(inapp),可通过设置商品消耗向用户提供商品。


/*
 * PurchaseClient的queryPurchasesAsync API (查询购买记录)回调监听器
 */
PurchaseClient.QueryPurchaseListener mQueryPurchaseListener = new PurchaseClient.QueryPurchaseListener() {
    @Override
    public void onSuccess(List purchaseDataList, String productType) {
  Log.d(TAG, "queryPurchasesAsync onSuccess, " + purchaseDataList.toString());
        if (IapEnum.ProductType.IN_APP.getType().equalsIgnoreCase(productType)) {
            // 如为查询购买记录后获取的管理型商品( inapp),先验证签名,成功后消耗商品。
        } else if (IapEnum.ProductType.AUTO.getType().equalsIgnoreCase(productType)) {
            // 如为查询购买记录后获取的包月自动支付商品( auto),先验证签名,成功后根据开发者应用处理需求编写方案。
        }
    }
    @Override
    public void onErrorRemoteException() {
        Log.e(TAG, "queryPurchasesAsync onError, 无法连接ONE store服务");
    }
    @Override
    public void onErrorSecurityException() {
        Log.e(TAG, "queryPurchasesAsync onError, 应用状态异常下请求支付");
    }
    @Override
    public void onErrorNeedUpdateException() {
        Log.e(TAG, "queryPurchasesAsync onError, 需要更新ONE store客户端 ");
    }
    @Override
    public void onError(IapResult result) {
        Log.e(TAG, "queryPurchasesAsync onError, " + result.toString());
    }
};
int IAP_API_VERSION = 5;
String productType = IapEnum.ProductType.IN_APP.getType(); // "inapp"
mPurchaseClient.queryPurchasesAsync(IAP_API_VERSION, productType, mQueryPurchaseListener);


4-8、移动端消耗失败,导致掉单


1、后台订单查询

image.png


2、在onestore后台点击consume进行手动消耗,然后自己给玩家进行手动补单就好

image.png


此版本为V5版本,onestore已更新至v6版本要接入最新版本的请自行前往:


ONE store支付官网文档


Google Pay支付


Mycard支付

相关文章
|
移动开发 Java 开发工具
Android客户端三步完成支付宝支付SDK接入
Android客户端三步完成支付宝支付SDK接入
2093 0
|
JavaScript Java 测试技术
Android MyCard支付
MyCard支付: 1、通过商务联系MyCard进行技术对接,获得最新MyCardPaySDK.jar和接入文档 2、导入MyCardPaySDK.jar 3、根据MyCard提供文档设置AndroidManifest.xml 4、根据自身需求确定是走SDK支付方式还是WebView支付方式
621 0
|
小程序 Android开发 iOS开发
微信小程序-虚拟支付:适用场景 / iPhone调试用支付成功,Android调用失败,提示“小程序支付能力已被限制” / “errMsg“.“requestPayment:fail banned”
微信小程序-虚拟支付:适用场景 / iPhone调试用支付成功,Android调用失败,提示“小程序支付能力已被限制” / “errMsg“.“requestPayment:fail banned”
537 0
|
Java 开发工具 Android开发
利用Android Studio在App中集成第三方支付
利用Android Studio在App中集成第三方支付
|
安全 算法 搜索推荐
android移动支付——银联支付
android移动支付——银联支付
|
XML 存储 前端开发
Android自定义控件(二)——支付宝支付成功动画
读律看书三九年,乌纱头上有青天,男儿欲画凌烟阁,第一功名不爱钱。
309 0
Android自定义控件(二)——支付宝支付成功动画
|
Java 开发工具 Android开发
Android 银联控件支付开发流程
项目中要用到支付功能,需要支付宝支付、微信支付、银联支付,所以打算总结一下,方便以后的查阅,也方便大家, 用到的地方避免再次被坑。 今天我们就主要介绍一下银联控件支付,其他支付也写了对应教程,并且给出了连接。
243 0
|
Java 开发工具 Android开发
Android 支付宝支付开发流程
项目中要用到支付功能,需要支付宝支付、微信支付、银联支付,所以打算总结一下,方便以后的查阅,也方便大家, 用到的地方避免再次被坑。 今天我们就主要介绍一下支付宝支付,其他支付也给出了对应的连接。
565 0
|
存储 移动开发 安全
Android微信支付和支付宝支付快速接入
创建应用并获取APPID 开发者中心中创建您的应用,会为您生成应用唯一标识(APPID),并且可以申请开通开放产品使用权限,通过APPID您的应用才能调用开放产品的接口能力。在“我的应用”中按下图方式查看APPID。
834 0
Android微信支付和支付宝支付快速接入
|
测试技术 API 数据安全/隐私保护
Android——实现人脸支付
功能实现 人脸支付 API初始化 人脸特征提取 返回支付结果 密码框输入支付 自定义密码输入框控件 初始化控件 密码匹配 尾言 效果展
375 0