精华内容
下载资源
问答
  • one store 6.7.2 安装包 apk, 韩国最大app市场. apk, 直接安装即可, one store 6.7.2
  • Android ONE store支付

    2020-12-09 22:20:43
    onestore支付、onestore支付、onestore支付!!!

    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<ProductDetail> 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<String> 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<PurchaseData> 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、后台订单查询
     

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

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

    ONE store支付官网文档

    Google Pay支付

    Mycard支付

    展开全文
  • ONE store平台配置

    千次阅读 2019-09-11 18:15:25
    前提:要使用onestore支付首先需要有onestore的账户密码 配置步骤 第一步:打开官网登录ONE store 第二步:点击app然后点击注册,创建应用 第三步:填写配置内容(app名称和包名) 第四步:填写配置详情...

    前提:要使用onestore支付首先需要有onestore的账户密码

    配置步骤

    onestore登录.png

    • 第二步:点击app然后点击注册,创建应用
      创建应用.png

    • 第三步:填写配置内容(app名称和包名)

    配置1.png

    • 第四步:填写配置详情

    配置详情.png
    配置详情1.png

    配置详情2.png

    配置详情3.png

    • 第五步:设置商品价格
      商品价格.png
    • 第六步:上传apk
      上传apk.png
      上传apk2.png
      上传详情.png
    • 第七步:应用内商品注册
      应用内商品注册.png
      应用内商品信息详情.png
    展开全文
  • 海外SDK接入1 onestore

    千次阅读 2020-03-07 14:42:55
    OneStore 准备工作! 1,官方文档:https://dev.onestore.co.kr/devpoc/reference/view/Tools 2,https://github.com/ONE-store/inapp-sdk-chi/wiki/Tools-Developer-Guide 3 demo:...

    OneStore

    准备工作!

    1,官方文档:https://dev.onestore.co.kr/devpoc/reference/view/Tools
    2,https://github.com/ONE-store/inapp-sdk-chi/wiki/Tools-Developer-Guide
    3 demo:https://github.com/ONE-store/iap_v5/tree/onestore_iap_sample
    4 需要有ONE store服务的设备以及 翻墙
    

    配置商品列表

    onestore 提供了两种商品类型:管理型和包月自动支付商品,
    管理型商品流程:购买->消耗->再次购买
    包月自动支付:购买(订阅)->退订
    可通过自定义消耗管理型商品来构建消耗型或者永久型商品
    

    购买流程

    1 客户端请求服务器获取商品信息以及自定义订单号
    2 客户端发起SDK支付
    3 支付完成,客户端将支付结果发送服务器做验证
    4 服务器验证成功,针对管理型商品服务器调用消耗接口,消耗商品	
    

    客户端配置

    cocos2dx引擎
    ndk-r11c

    build.gradle <project级别>

            classpath 'com.android.tools.build:gradle:3.2.0'
    
    

    gradle/wrapper/gradle-wrapper.properties

    distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
    
    

    buld.gradle <app级别>

        compileSdkVersion 28
        defaultConfig {
            applicationId APPLICATION_ID
            minSdkVersion 16
            targetSdkVersion 28
    		
    		externalNativeBuild{...}
    	}
    

    后台配置

    由管理人员完成
    需要提供参数:
    License Key: (公钥) (客户端/服务器)
    Client_ID:(服务器)
    Client_secret:(服务器)
    android jar:jar file(eg. iap_plugin_v17.01.00_20180206.jar)

    客户端接入

    官方提供SDK方式和直接实现服务器接口两种方式,这里采用SDK,
    客户端实现支付,登陆检测,以及检测漏单
    服务器实现支付结果验证,消耗,以及订阅/退订
    

    1 设置 Android Manifest文档

    <application ...... >
            <!-- One Store SDK begin -->
            <meta-data android:name="iap:api_version"
                       android:value="5" />
            <!-- (可选) 选择支付界面(UI):API V5支持弹窗式的支付界面。在iap:view_option里加入popup时,会显示弹窗式的支付画面。 -->
            <!-- <meta-data
                android:name="iap:view_option"
                android:value="popup | full" > -->
    
            <!-- One Store SDK end -->          
    

    2 导入jar包,直接放到app/libs下即可,没有此目录的话,自己建一个
    3 初始化
    在应用的Oncreate方法中调用执行初始化

    @Override
    public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
        // PurchaseClient 初始化——将公钥作为参数传递,以验证context和Signature。
        mPurchaseClient = new PurchaseClient(this, AppSecurity.getPublicKey());
     
        // 请求绑定ONE store服务,以启动应用内支付。
        mPurchaseClient.connect(mServiceConnectionListener);
    }
    

    3.2 退出时需要调用登出

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

    3.3 客户端检测是否可以支付

    // ONE store应用内支付API版本
    int IAP_API_VERSION = 5;
    mPurchaseClient.isBillingSupportedAsync(IAP_API_VERSION, mBillingSupportedListener);
    

    3.4 发起支付

    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, this, PURCHASE_REQUEST_CODE, product5000, productName, productType, devPayload, gameUserId, promotionApplicable, mPurchaseFlowListener);
    

    3.5 查询购买记录(检测是否有未消耗商品)

     
    int IAP_API_VERSION = 5;
    String productType = IapEnum.ProductType.IN_APP.getType(); // "inapp"
    mPurchaseClient.queryPurchasesAsync(IAP_API_VERSION, productType, mQueryPurchaseListener);
    

    3.6 ONE store登录的请求

    int IAP_API_VERSION = 5;
    int LOGIN_REQUEST_CODE = 2000; // 向onActivityResult 返回的 request code
     mPurchaseClient.launchLoginFlowAsync(IAP_API_VERSION, this, LOGIN_REQUEST_CODE, mLoginFlowListener)
    

    3.6.2 登陆结果

            switch (reqcode ){
                case SDKHelper.REQ_CODE_GOOGLE_LOGIN:
                    if (resultCode == mActivity.RESULT_OK) {
                        if (mPurchaseClient.handleLoginData(intent) == false) {
                            Log.e(TAG, "onActivityResult handleLoginData false ");
                        }
                    } else {
                        Log.e(TAG, "onActivityResult user canceled");
                    }
                    break;
                default:
            }
    

    服务器处理

    1 服务器验证,one store采用sha512公钥验证
    2 服务器消耗
    URI: https://{host}/v2/purchase/consume/{purchaseId}/{packageName}
    3 变更订阅状态
    URI: https://{host}/v2/purchase/manage-payment-status/{purchaseId}/{packageName}/{action}

    客户端代码

    APPactivity,java

    package org.cocos2dx.lua;
    
    import android.content.Intent;
    import android.os.Bundle;
    import org.cocos2dx.lib.Cocos2dxActivity;
    public class AppActivity extends Cocos2dxActivity{
        private SDKHelper mSDKHelper = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.setEnableVirtualButton(false);
            super.onCreate(savedInstanceState);
            // Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508
            if (!isTaskRoot()) {
                // Android launched another instance of the root activity into an existing task
                //  so just quietly finish and go away, dropping the user back into the activity
                //  at the top of the stack (ie: the last state of this task)
                // Don't need to finish it again since it's finished in super.onCreate .
                return;
            }
            // DO OTHER INITIALIZATION BELOW
            // 初始化渠道SDK
            this.initSDKHelper();
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            if (mSDKHelper != null){
                mSDKHelper.onStart();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
    
            if (mSDKHelper != null ){
                mSDKHelper.onDestroy();
            }
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (mSDKHelper != null ){
                mSDKHelper.onActivityResult(requestCode,resultCode,data);
            }
        }
    
        private void initSDKHelper(){
            mSDKHelper = new SDKHelper();
            mSDKHelper.initSDK(this);
        }
    }
    
    

    2 SDKHelper.java

    public class SDKHelper {
        private static String TAG = SDKHelper.class.getSimpleName();
    
        private static Cocos2dxActivity mActivity = null;
        private static OneStoreHelper mOneStoreHelper = null;
    
        public static final int REQ_CODE_ONE_STORE_LOGIN  = 1000;
        public static final int REQ_CODE_ONE_STORE_PURCHAS= 1001;
    
        public void initSDK(Cocos2dxActivity context)
        {
            mActivity = context;
            // one store pay
            mOneStoreHelper = new OneStoreHelper();
            mOneStoreHelper.initSDK(context);
        }
       
        public void onDestroy(){
            mOneStoreHelper.onDestroy();
        }
    
        public void onActivityResult(int reqcode, int resultCode, Intent intent){
            mOneStoreHelper.onActivityResult(reqcode,resultCode,intent);
        }
    
    
    
        public static void runOnGL(final int luaFunc, final String retData){
            if (luaFunc == -1 || luaFunc == 0) return;
    
            mActivity.runOnGLThread(new Runnable() {
                @Override
                public void run() {
                    Cocos2dxLuaJavaBridge.callLuaFunctionWithString(luaFunc,retData);
                    Cocos2dxLuaJavaBridge.releaseLuaFunction(luaFunc);
                }
            });
        }
        //  ------------------------------------------------------------
        //              lua 调用 android
        //  ------------------------------------------------------------
        public static int test(final int luaFunc){
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.i(TAG, "test----->");
                }
            });
            return 1;
        }
    
        // 返回SDK是否成功
        public static boolean checkSDKInit(){
            Log.d(TAG,"checkinit===");
    //        return false;
            return mOneStoreHelper.mInitResult && mOneStoreHelper.mBillingSupported;
        }
    
        public static void onLoginPayment(final String args ,final int luaFunc){
            Log.d(TAG,"onLoginPayment");
            JSONObject jsonObject = new JSONObject();
    
            if (checkSDKInit() == true) {
                try{
                    jsonObject.put("code",1);
                    jsonObject.put("error_msg","sdk unInit");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                runOnGL(luaFunc,jsonObject.toString());
                Log.d(TAG,"onLoginPayment  1111");
    
                return;
            };
            boolean ret = false;
            if (mOneStoreHelper.mInitResult == false){
                Log.d(TAG,"onLoginPayment 2222");
    
                mOneStoreHelper.initWithCallback(luaFunc);
            }else if(mOneStoreHelper.mBillingSupported == false){
                Log.d(TAG,"onLoginPayment 333");
    
                mOneStoreHelper.checkBillingSupportedAndLoadPurchases(luaFunc);
            }else {
                try{
                    jsonObject.put("code",0);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                Log.d(TAG,"onLoginPayment 4444");
    
                runOnGL(luaFunc,jsonObject.toString());
            }
    
        }
    
        public static void onPayment(final String args,final int luaFunc){
            mOneStoreHelper.onPayment(args,luaFunc);
        }
    
        public static void queryPurchases(final String args,final int luaFunc){
            mOneStoreHelper.queryPurchases(args,luaFunc);
        }
    }
    
    

    3 OneStoreHelper.java

    public class OneStoreHelper {
    
        private PurchaseClient mPurchaseClient = null;
        private Cocos2dxActivity mActivity = null;
    
        private final String mPublicKey = "#########......####";
        private final String TAG = getClass().getSimpleName();
        private static final int IAP_API_VERSION = 5;
    
        //购买回调
        private int mPurchaseCallbackFunc = -1;
        //初始化结果
        protected boolean mInitResult = false;
        // 是否支持支付
        protected boolean mBillingSupported = false;
    
        public void initSDK(Cocos2dxActivity context){
            mActivity = context;
            initWithCallback(-1);
        }
    
        public void initWithCallback(final int luaFunc){
            if (luaFunc != -1  ) mPurchaseCallbackFunc = luaFunc;
            mPurchaseClient = new PurchaseClient(mActivity,mPublicKey);
            mPurchaseClient.connect(mServiceConnectionListener);
        }
    
        public void onDestroy(){
            mInitResult = false;
            mBillingSupported = false;
            mPurchaseClient.terminate();
            mPurchaseClient = null;
        }
    
        public void onActivityResult(int reqcode, int resultCode, Intent intent){
    
            switch (reqcode ){
                case SDKHelper.REQ_CODE_ONE_STORE_PURCHAS:
                    if (resultCode == mActivity.RESULT_OK) {
                        if (mPurchaseClient.handlePurchaseData(intent) == false) {
                            Log.e(TAG, "onActivityResult handlePurchaseData false ");
                            // 没有支付监听 mPurchaseFlowListener
                        }
                    } else {
                        Log.e(TAG, "onActivityResult user canceled");
    
                        // user canceled , do nothing..
                    }
                    break;
                case SDKHelper.REQ_CODE_ONE_STORE_LOGIN:
    
                    /*
                     * launchLoginFlowAsync API 호출 시 전달받은 intent 데이터를 handleLoginData를 통하여 응답값을 파싱합니다.
                     * 파싱 이후 응답 결과를 launchLoginFlowAsync 호출 시 넘겨준 LoginFlowListener 를 통하여 전달합니다.
                     */
    
                    if (resultCode == mActivity.RESULT_OK) {
                        if (mPurchaseClient.handleLoginData(intent) == false) {
                            Log.e(TAG, "onActivityResult handleLoginData false ");
                            // listener is null
                        }
                    } else {
                        Log.e(TAG, "onActivityResult user canceled");
    
                        // user canceled , do nothing..
                    }
                    break;
    
                default:
    
            }
        }
    
        public void showOneStoreCallback(final String retData,final int retCode){
            String retStr = retData;
    
            if (retCode != 0){
                JSONObject jsonObject = new JSONObject();
                try {
                    jsonObject.put("code",retCode);
                    jsonObject.put("error_msg",retData);
    
                    retStr = jsonObject.toString();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
    
            SDKHelper.runOnGL(mPurchaseCallbackFunc,retStr);
            mPurchaseCallbackFunc = -1;
        }
    
        // 检查是否支持支付
        public void checkBillingSupportedAndLoadPurchases(final int luaFunc){
            Log.d(TAG, "checkBillingSupportedAndLoadPurchases()");
            if (luaFunc != -1  ) mPurchaseCallbackFunc = luaFunc;
            if (mPurchaseClient == null) {
                Log.d(TAG, "PurchaseClient is not initialized");
                showOneStoreCallback("mPurchaseClient == null",1);
                return;
            }
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mPurchaseClient.isBillingSupportedAsync(IAP_API_VERSION, mBillingSupportedListener);
                }
            });
        }
        // 提示更新OneStore客户端
        private void updateOrInstallOneStoreService(){
            Log.d(TAG,"updateOrInstallOneStoreService");
    
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    PurchaseClient.launchUpdateOrInstallFlow(mActivity);
                }
            });
        }
    
        //  -----------------------------------------------------------------------------
        //                      sdk 接口调用
        //  -----------------------------------------------------------------------------
    
        public void loadLoginFlow(final String args,final int luaFunc){
            if (luaFunc != -1  ) mPurchaseCallbackFunc = luaFunc;
    
            if (mPurchaseClient == null) {
                Log.d(TAG, "PurchaseClient is not initialized");
                showOneStoreCallback("mPurchaseClient == null",1);
                return;
            }
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
    //                AlertDialog
                    if (mPurchaseClient.launchLoginFlowAsync(IAP_API_VERSION, mActivity, SDKHelper.REQ_CODE_ONE_STORE_LOGIN, mLoginFlowListener) == false) {
                        // listener is null
                    }
    
                }
            });
    
    
        }
    
        public void queryPurchases(final String args,final int luaFunc){
            mPurchaseCallbackFunc = luaFunc;
            if (mBillingSupported == false){
                Log.d(TAG, "PurchaseClient is not initialized");
                showOneStoreCallback("mPurchaseClient == null",1);
                return;
            }
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    try {
                        JSONObject jsonObject = new JSONObject(args);
                        String productType = jsonObject.getString("product_type");
                        mPurchaseClient.queryPurchasesAsync(IAP_API_VERSION,productType,mQueryPurchaseListener);
    
                    } catch (JSONException e) {
                        e.printStackTrace();
                        showOneStoreCallback("failed",1);
                    }
                }
            });
    
        }
    
    
        public void onPayment(final String args,final int luaFunc){
            mPurchaseCallbackFunc = luaFunc;
            if (mBillingSupported == false){
                Log.d(TAG, "PurchaseClient is not initialized");
                showOneStoreCallback("mBillingSupported == false",1);
                return;
            }
            Log.d(TAG, "launchPurchaseFlowAsync  args  =  "+args);
    
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    try {
                        JSONObject jsonObject = new JSONObject(args);
    
                        String productId = jsonObject.getString("product_id");
                        String productType = jsonObject.getString("product_type");
                        String devPayload = jsonObject.getString("payload");
                        String productName = "";// 默认显示开发者中心商品名
                        String gameUserId = ""; // 默认 ""
                        boolean promotionApplicable = false;
                        Log.d(TAG, "launchPurchaseFlowAsync  devPayload  =  "+devPayload);
                        Log.d(TAG, "launchPurchaseFlowAsync  productType =  "+productType);
                        Log.d(TAG, "launchPurchaseFlowAsync  productId   =  "+productId);
    
                        mPurchaseClient.launchPurchaseFlowAsync(IAP_API_VERSION,mActivity,SDKHelper.REQ_CODE_ONE_STORE_PURCHAS,productId,productName, productType,devPayload,gameUserId,promotionApplicable,mPurchaseFlowListener);
    
                    }catch (Exception e){
                        e.printStackTrace();
                        showOneStoreCallback("failed",1);
                    }
                }
            });
        }
    
        // 登陆回调,返回绑定成功或者失败,或者提示是否更新OneStore服务
        PurchaseClient.ServiceConnectionListener mServiceConnectionListener = new PurchaseClient.ServiceConnectionListener() {
            @Override
            public void onConnected() {
                Log.d(TAG,"onConnected success");
                mInitResult = true;
                checkBillingSupportedAndLoadPurchases(-1);
            }
    
            @Override
            public void onDisconnected() {
                Log.d(TAG, "Service disconnected");
                mInitResult = false;
                showOneStoreCallback("Service disconnected",1);
    
            }
    
            @Override
            public void onErrorNeedUpdateException() {
                mInitResult = false;
                updateOrInstallOneStoreService();
            }
        };
        // 检测是否支持支付 回调
        PurchaseClient.BillingSupportedListener mBillingSupportedListener = new PurchaseClient.BillingSupportedListener() {
            @Override
            public void onSuccess() {
                Log.d(TAG, "isBillingSupportedAsync onSuccess");
                mBillingSupported = true;
                JSONObject jsonObject = new JSONObject();
                try {
                    jsonObject.put("code",0);
                    String retStr = jsonObject.toString();
    
                    showOneStoreCallback(retStr,0);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onError(IapResult iapResult) {
                mBillingSupported = false;
                Log.e(TAG, "isBillingSupportedAsync onError, " + iapResult.toString());
                showOneStoreCallback(iapResult.toString(),1);
                // 提示需要登陆,发起登陆One Store
                if (IapResult.RESULT_NEED_LOGIN == iapResult) {
                    loadLoginFlow("",-1);
                }
            }
    
            @Override
            public void onErrorRemoteException() {
                mBillingSupported = false;
                Log.e(TAG, "isBillingSupportedAsync onError, 无法连接ONE STORE服务");
                showOneStoreCallback("onErrorRemoteException",1);
            }
    
            @Override
            public void onErrorSecurityException() {
                mBillingSupported = false;
                Log.e(TAG, "isBillingSupportedAsync onError, 应用状态异常下请求支付");
                showOneStoreCallback("onErrorSecurityException",1);
    //            hideProgress();
    //            alert("비정상 앱에서 결제가 요청되었습니다");
            }
    
            @Override
            public void onErrorNeedUpdateException() {
                mBillingSupported = false;
                Log.e(TAG, "isBillingSupportedAsync onError, 需要更新ONE STORE客户端");
                showOneStoreCallback("onErrorNeedUpdateException",1);
    //            hideProgress();
                updateOrInstallOneStoreService();
            }
        };
    
        // 查询购买记录回调
        PurchaseClient.QueryPurchaseListener mQueryPurchaseListener = new PurchaseClient.QueryPurchaseListener() {
            @Override
            public void onSuccess(List<PurchaseData> purchaseDataList, String productType) {
    
                JSONObject jsonObject = new JSONObject();
                try {
                    ArrayList<String> payloads = new ArrayList<>();
                    JSONArray jsonArray = new JSONArray();
                    for (PurchaseData purchase : purchaseDataList) {
                        JSONObject jsonObject1 = new JSONObject();
                        jsonObject1.put("payload",purchase.getDeveloperPayload());
                        jsonObject1.put("purchaseData",purchase.getPurchaseData());
                        jsonObject1.put("product_id",purchase.getProductId());
                        jsonObject1.put("signature",purchase.getSignature());
                        jsonObject1.put("purchase_id",purchase.getPurchaseId());
    
    //                    boolean bVerify = verifyPurchase(purchase.getPurchaseData(),purchase.getSignature());
    //                    jsonObject1.put("verify",bVerify);
    
                        jsonArray.put(jsonObject1);
                    }
                    jsonObject.put("product_type",productType);
                    jsonObject.put("purchases",jsonArray);
                    jsonObject.put("code",0);
                    String retStr = jsonObject.toString();
                    showOneStoreCallback(retStr,0);
                } catch (JSONException e) {
                    e.printStackTrace();
                    showOneStoreCallback("failed",1);
                }
    
            }
    
            @Override
            public void onError(IapResult iapResult) {
                Log.e(TAG, "launchPurchaseFlowAsync onError, " + iapResult.toString());
                showOneStoreCallback(iapResult.toString(),1);
            }
    
            @Override
            public void onErrorRemoteException() {
                Log.e(TAG, "launchPurchaseFlowAsync onError, 无法连接ONE store服务 ");
                showOneStoreCallback("onErrorRemoteException",1);
            }
    
            @Override
            public void onErrorSecurityException() {
                Log.e(TAG, "launchPurchaseFlowAsync onError, 应用状态异常下请求支付 ");
                showOneStoreCallback("onErrorSecurityException",1);
            }
    
            @Override
            public void onErrorNeedUpdateException() {
                Log.e(TAG, "launchPurchaseFlowAsync onError, 需要更新ONE store客户端");
                showOneStoreCallback("onErrorNeedUpdateException",1);
            }
        };
    
        // 支付回调
        PurchaseClient.PurchaseFlowListener mPurchaseFlowListener = new PurchaseClient.PurchaseFlowListener() {
            @Override
            public void onSuccess(PurchaseData purchaseData) {
                Log.d(TAG, "launchPurchaseFlowAsync onSuccess, " + purchaseData.toString());
    //            boolean bVerify = verifyPurchase(purchaseData.getPurchaseData(),purchaseData.getSignature());
                JSONObject jsonObject = new JSONObject();
                try {
                    JSONArray jsonArray = new JSONArray();
                    JSONObject jsonObject1 = new JSONObject();
                    jsonObject1.put("payload",purchaseData.getDeveloperPayload());
                    jsonObject1.put("purchaseData",purchaseData.getPurchaseData());
                    jsonObject1.put("product_id",purchaseData.getProductId());
                    jsonObject1.put("signature",purchaseData.getSignature());
                    jsonObject1.put("purchase_id",purchaseData.getPurchaseId());
    //                jsonObject1.put("verify",bVerify);
                    jsonArray.put(jsonObject1);
    
                    jsonObject.put("purchases",jsonArray);
                    jsonObject.put("code",0);
                    String retStr = jsonObject.toString();
                    showOneStoreCallback(retStr,0);
                } catch (JSONException e) {
                    e.printStackTrace();
                    showOneStoreCallback("failed",1);
                }
    
            }
    
            @Override
            public void onError(IapResult iapResult) {
                Log.e(TAG, "launchPurchaseFlowAsync onError, " + iapResult.toString());
                showOneStoreCallback(iapResult.toString(),1);
            }
    
            @Override
            public void onErrorRemoteException() {
                Log.e(TAG, "launchPurchaseFlowAsync onError, 无法连接ONE store服务 ");
                showOneStoreCallback("onErrorRemoteException",1);
            }
    
            @Override
            public void onErrorSecurityException() {
                Log.e(TAG, "launchPurchaseFlowAsync onError, 应用状态异常下请求支付 ");
                showOneStoreCallback("onErrorSecurityException",1);
            }
    
            @Override
            public void onErrorNeedUpdateException() {
                Log.e(TAG, "launchPurchaseFlowAsync onError, 需要更新ONE store客户端");
                showOneStoreCallback("onErrorNeedUpdateException",1);
    
                updateOrInstallOneStoreService();
            }
        };
    
        PurchaseClient.LoginFlowListener mLoginFlowListener = new PurchaseClient.LoginFlowListener() {
            @Override
            public void onSuccess() {
                JSONObject jsonObject = new JSONObject();
                try {
                    jsonObject.put("code",0);
                    String retStr = jsonObject.toString();
                    showOneStoreCallback(retStr,0);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onError(IapResult iapResult) {
                Log.e(TAG, "LoginFlowListener onError, " + iapResult.toString());
                showOneStoreCallback(iapResult.toString(),1);
            }
    
            @Override
            public void onErrorRemoteException() {
                Log.e(TAG, "LoginFlowListener onError, 无法连接ONE store服务 ");
                showOneStoreCallback("onErrorRemoteException",1);
            }
    
            @Override
            public void onErrorSecurityException() {
                Log.e(TAG, "LoginFlowListener onError, 应用状态异常下请求支付 ");
                showOneStoreCallback("onErrorSecurityException",1);
            }
    
            @Override
            public void onErrorNeedUpdateException() {
                Log.e(TAG, "LoginFlowListener onError, 需要更新ONE store客户端");
                showOneStoreCallback("onErrorNeedUpdateException",1);
    
                updateOrInstallOneStoreService();
            }
        };
    
    }
    
    

    服务器代码

    1,verify php

        public function verifyRecharge($signedData,$signature,$publicKey = '')
        {   
            if (empty($publicKey)) {
                $publicKey = "-----BEGIN PUBLIC KEY-----\n" . chunk_split(ONE_STROE_PUBLICKEY, 64, "\n") ."-----END PUBLIC KEY-----";
            }
            $key = openssl_pkey_get_public($publicKey);
            if(!$key){
                echo "error  publicKey  无效!!! \n";
                return false;
            }
            $ret = openssl_verify($signedData, base64_decode($signature), $key,"SHA512");
            openssl_free_key($key);
            return $ret;
        }
        // 根据私钥 生成认证信息
        function getSign($content, $privateKey){
            $key = openssl_get_privatekey($privateKey);
            if (!$key) {
               return false;
            }
            openssl_sign($content, $signature, $key, "SHA512");
            openssl_free_key($key);
            $sign = base64_encode($signature);
            return $sign;
        }
    
    
        public function verifyTest()
        {
           	$publicKey = '';
            $signature = '';
            $signedData = '';
             $t = $this->verifyRecharge($signedData,$signature,$publicKey);
             echo "ret === $t";
        }
    
    

    2 oneStore.php

    <?php
    
    	namespace lib;
    	
    	const ONE_STORE_URL_SDKBOX = 'sbpp.onestore.co.kr';
    	const ONE_STORE_URL_DEV	= 'apis.onestore.co.kr';
    	const ONE_STORE_CLIENT_ID = '';
    	const ONE_STORE_SECRET = '';
    	const ONE_STORE_PACKAGE_NAME = '';
    
    	const EXPIRES_LIMIT = 600;
    	const ACCESS_TOKEN_KEY = 'access_token';
    
    	class OneStoreHelper 
    	{
    		public $access_token = null;
    		private $host = ONE_STORE_URL_SDKBOX;
    		private $packageName = ONE_STORE_PACKAGE_NAME;
    
    		function __construct()
    		{	
    			$this->checkExpires();
    		}
    
    		/*  查询购买商品详情
    			{
    			  "consumptionState": 0,   		已购商品消耗状态(0:未消耗,1:消耗)
    			  "developerPayload": "developerPayload",
    			  "purchaseState": 0,   		购买状态(0:完成购买,1:完成取消)
    			  "purchaseTime": 1345678900000	购买时间(ms)
    			}
    		 */
    		public function getPurchaseDetails($purchaseId)
    		{		
    			// echo "getPurchaseDetails   \n";
    			if (empty($purchaseId)) return [];
    			$url = "https://{$this->host}/v2/purchase/details/{$purchaseId}/{$this->packageName}";
    			// echo "url === $url  \n";
    			return $this->getPurchaseByUrl($url);
    		}
    		/*  查询购买商品详情
    			{
    			  "consumptionState": 0,   		已购商品消耗状态(0:未消耗,1:消耗)
    			  "developerPayload": "developerPayload",
    			  "purchaseState": 0,   		购买状态(0:完成购买,1:完成取消)
    			  "purchaseTime": 1345678900000	购买时间(ms)
    			}
    		 */
    		public function getPurchaseDetailsByProductId($purchaseId,$product_id)
    		{	
    			if (empty($purchaseId) || empty($product_id)) return [];
    			$url = "https://{$this->host}/v2/purchase/details-by-productid/{$purchaseId}/{$this->packageName}/{$product_id}";
    			return $this->getPurchaseByUrl($url);
    		}
    		/*  Desc: 基于购买ID,查询已购买的包月自动支付商品详情。
    			URI: https://{host}/v2/purchase/recurring-details/{purchaseId}/{packageName}
    			Method: GET
    			{
    			  "startTime": 1345678900000,
    			  "expiryTime": 1345678999999,
    			  "nextPaymentTime": 1345688000000,
    			  "autoRenewing": true,
    			  "price": 50000
    			  "developerPayload": "8ce0dc420c9dd244580a",
    			  "purchaseState": 0,
    			  "cancelReason": 1,
    			  "cancelledTime": 1345679000000
    			}
    		 */
    		public function getRecurringPurchaseDetails ($purchaseId)
    		{
    			if (empty($purchaseId)) return [];
    			$url = "https://{$this->host}/v2/purchase/recurring-details/{$purchaseId}/{$this->packageName}";
    			return $this->getPurchaseByUrl($url);
    		}
    		/*  Desc: 通过第一次购买的包月自动支付商品ID,查询相应商品的到期日及最后(最新)购买的详情
    			URI: https://{host}/v2/purchase/last-recurring-details/{purchaseId}/{packageName}
    			{
    			  "startTime": 1345678900000,
    			  "expiryTime": 1345678999999,
    			  "nextPaymentTime": 1345688000000,
    			  "autoRenewing": true,
    			  "cancelReason": 1,
    			  "cancelledTime": 1345679000000,
    			  "lastPurchaseId":"15081718460701027851"
    			}
    		 */
    		public function getLastRecurringPurchaseDetails ($purchaseId)
    		{
    			if (empty($purchaseId)) return [];
    			$url = "https://{$this->host}/v2/purchase/last-recurring-details/{$purchaseId}/{$this->packageName}";
    			return $this->getPurchaseByUrl($url);
    		}
    		/*  Desc: 变更自动支付状态(退订与停止退订)
    			POST
    			action: 状态变更类型,cancel(退订),reactivate(停止退订)(Data Size : 10)
    			{
    			  "responseCode": 0,
    			  "purchaseId" : "17103013155810111392"
    			}
    		 */
    		public function manageRecurringPaymentStatus($purchaseId,$action)
    		{
    			if (empty($purchaseId)) return [];
    			$url = "https://{$this->host}/v2/purchase/manage-payment-status/{$purchaseId}/{$this->packageName}/{$action}";
    			// echo "$url";
    			return $this->getPurchaseByUrl($url,true);
    		}
    		/*   查询购买取消记录。
    			额外参数
    			continuationKey				string
    			startTime  			起始时间 string
    			endTime				结束时间 string
    			maxResults			最大数量,默认100
    			{
    			  "continuationKey": "continuationKey",
    			  "voidedPurchaseList": [
    			    {
    			        "purchaseId" : "17103009124410111299",
    			        "purchaseTime" : 1345678900000,
    			        "voidedTime" : 1345678910000
    			    },
    			    ...
    			  ]
    			}
    		 */
    		public function getVoidedPurchases()
    		{
    			$url = "https://{$this->host}/v2/purchase/voided-purchases/{$this->packageName}";
    			$data = [
    
    			];
    			return $this->getPurchaseByUrl($url);
    		}
    		/* 	Desc: 将已购商品设为消耗的商品
    			Method: POST
    			{
    			  "consumptionState": 0,
    			  "purchaseId" : "17103013155810111392"
    			}
    		 */
    		public function consumePurchase($purchaseId)
    		{
    			if (empty($purchaseId)) return [];
    			$url = "https://{$this->host}/v2/purchase/consume/{$purchaseId}/{$this->packageName}";
    			// echo "$url";
    			return $this->getPurchaseByUrl($url,true);
    		}
    
    		private function checkExpires()
    		{		
    			$redis = _getRedis();
    			$this->access_token = $redis->get(ACCESS_TOKEN_KEY);
    			$expires_in = $redis->TTL(ACCESS_TOKEN_KEY);
    					
    			if (empty($this->access_token) || $expires_in < EXPIRES_LIMIT) {
    				// echo "checkExpires  expires_in == $expires_in  \n";
    				$this->getAccessTokens();
    			}
    		}
    
    		private function getAccessTokens()
    		{
    			$url="https://".$this->host."/v2/oauth/token";
    
    			$header = [
    				'Content-Type'=>'application/x-www-form-urlencoded',
    				'charset'=>'utf-8'
    			];
    			$data = [
    				'client_id' => ONE_STORE_CLIENT_ID,
    				'client_secret' => ONE_STORE_SECRET,
    				'grant_type'	=> 'client_credentials',
    			];
    
    			$retData = $this->doHttp($url,$data,$header,1);
    			$jsonData = json_decode($retData,true);
    			// echo $retData;
    			if (isset($jsonData['access_token'])) {
    				$redis = _getRedis();
    				$redis->set(ACCESS_TOKEN_KEY,$jsonData['access_token'],$jsonData['expires_in']);
    
    				$this->access_token = $jsonData['access_token'];
    			}
    
    		}
    
    		private function getPurchaseByUrl($url,$isPost = false)	
    		{
    			$this->checkExpires();
    			$header = [
    				'Content-Type :application/json',
    				'Authorization: Bearer '.$this->access_token
    			];
    
    			$retData = $this->doHttp($url,null,$header,$isPost ? 1:0);
    			return $retData;
    		}
    
    		private function doHttp($url,$data,$header,$httpType = 0)
    		{		
    
    			$ch = curl_init();
    			if ($httpType == 1) {
    				// post 
    				curl_setopt($ch, CURLOPT_POST, true);
    				if (!empty($data))curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    			}
    
    			// if(true){  //判断请求协议http或https
    			//      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
    			//      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);  // 从证书中检查SSL加密算法是否存在
    			//  }
    			curl_setopt($ch, CURLOPT_URL, $url);
    			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    			curl_setopt ( $ch, CURLOPT_TIMEOUT, 30 );
    			if (!empty($header)) {
    				curl_setopt($ch, CURLOPT_HTTPHEADER,$header);
    			}
    			$retData = curl_exec($ch);
    			if ($retData == false) {
    				$retData = curl_error($ch);
    			}
    			curl_close($ch);
    			return $retData;
    		}
    	}
    
    展开全文
  • OneStore_Android_接入

    万次阅读 2018-03-06 21:13:18
    OneStore 是海外韩国重要的一个支付SDK,网上的资料少的可怜,特意总结一下,防止下次踩坑 接入方法及代码 官方wiki : https://github.com/ONE-store/inapp-sdk-chi/wiki 官方后台地址 : ...

    OneStore

    是海外韩国重要的一个支付SDK,网上的资料少的可怜,特意总结一下,防止下次踩坑
    

    接入方法及代码

    官方wiki : https://github.com/ONE-store/inapp-sdk-chi/wiki
    官方后台地址 : https://dev.onestore.co.kr/icms-app/contents/contentlist?locale=en
    国内大神CSDN:http://blog.csdn.net/qq_31148061/article/details/72817996

    遇到的问题

    1、提示错误码 -3000 ONE store service is not installed 尚未安装合适的客户端版本
    需安装下载 OneStore_Service 服务,页面提示可获取下载链接
    PS:我安装的是ONE_store_service_v6.050_20180130_170736_release_vc84.apk

    2、错误码 2006 您的终端设备尚未注册开发者平台。请注册后使用。

    • 安装IAP Setting App,安装成功后,输入MDN 为01011112222, 点击Save

    • OneStore 后台应用->【In-App】->【Billing Test】-> 在 【Test Phone Number】中填入 【01011112222】,点击【add】即可

    OneStore 针对韩国以外的地区,模拟创建一个电话号码,方便海外测试。

    PS: 这个问题坑了我好久!!!!百度谷歌都搜不到资料,最后还是无意间在Onestore官网找到解决方法,坑爹啊!
    传送门 : https://dev.onestore.co.kr/devpoc/reference/view/Tools_IAP#download

    3、错误码 3124 由于未设定商品,无法测试。
    这是由于未修改 商品测试状态
    方法图示
    这里写图片描述

    展开全文
  • OneStore - NSUserDefaults的一个单一值代理,拥有简洁的API
  • OneStore Gradle和Maven Gradle dependencies { implementation ' net.sjava:appstore:1.1.0 ' } Maven < groupId>net.sjava</ groupId> < artifactId>appstore < version>1.1.0 用法 private void ...
  • 韩国ONE store平台支付集成(android)

    千次阅读 2020-03-07 11:25:37
    前端时间接入韩国Onestore平台的时候踩了一些坑,国内的文档又很少,记录一下,废话不多说。我们开始吧。 内容一览官方接入文档开始集成支付逻辑集成一、集成步骤二、集成代码三、集成问题 官方接入文档 官方文档有...
  • 语言:English 这是最好的智能手机Aliexpress商店,欧盟DHL送货无需关税 Aliexpress排名前一的商店最佳智能手机速卖通商店欧盟人员无需定制关税快速DHL送货仅23,8€29USD原始的小米,魅族,华为,One +和其他手机。
  • 前段时间也需要支持了韩国那边的应用内支付,给的文档上面讲了需要集成onestore支付。由于对韩国那边的应用内支付没有什么概念,所以就百度了一番。奈何,文档太少或者写的不是很清晰(难道能说是因为自己不太理解)...
  • Google Play支付: ...下面记录为个人摘录1、更新应用程序的依赖关系 将以下行添加到build.gradle您应用的文件的“依赖项”部分: dependencies {  … ...}2、连接到Google Play 在发出Google Play结算请求之前,您必须先...
  • 海外SDK之----------韩国支付onestore

    千次阅读 2019-08-14 14:41:28
    首先你运营给你一个文件 Onestore_iap_plugin.zip 你解压出来就是了,或者去onestore的官网去下载。接入代码和流程大致如下:           /* 这里只是一个成员变量的区分 */ ...
  • One-Piece-Store-源码

    2021-07-23 18:51:49
    One Piece store 是日本动漫 One Piece 产品的展示项目,由漫画家尾田荣一郎创作。 该应用程序作为传奇粉丝的电子商务销售产品目录,它是在Gama Academy xp38版本期间构建的一个简单的网络应用程序,仅供学习和非...
  • 定时任务出现异常 : org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'jyGroup.jyJob', because one already exists with this identification. 2018-07-19 09:36:48.002 INFO 6128 --- [pool-...
  • OneStore使用干净的API的NSUserDefaults的单一值代理。 使用OneStore…为每个NSUserDefaults值创建一个代理(一个OneStore对象)。 堆栈支持多个NSUserDefaults和名称空间。 OneStore使用干净的API的NSUserDefaults...
  • 基于VDI、RDSH、Workspace ONE、App Store技术的邮政企业云端门户平台构建.pdf
  • 参考:http://stackoverflow.com/questions/8881453/the-model-used-to-open-the-store-is-incompatible-with-the-one-used-to-create-the

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 148,219
精华内容 59,287
关键字:

onestore