Android三方支付:Google Play支付、MyCard支付、ONE store支付

Google Play支付:

详情可通过VPN:https://developer.android.com/google/play/billing/billing_library_overview#java

下面记录为个人摘录

1、更新应用程序的依赖关系

将以下行添加到build.gradle您应用的文件的“依赖项”部分:

dependencies {

    ...

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

}

2、连接到Google Play

在发出Google Play结算请求之前,您必须先通过以下步骤建立与Google Play的连接:

调用newBuilder() 以创建的实例。 BillingClient 您还必须调用 setListener(),将传递给引用, PurchasesUpdatedListener 以接收有关您的应用发起的购买以及Google Play商店发起的购买的更新。

建立与Google Play的连接。设置过程是异步的,BillingClientStateListener 一旦客户端的设置完成并且可以发出进一步的请求,您就必须实现A 来接收回调。

覆盖 onBillingServiceDisconnected() 回调方法,并实施您自己的重试策略,以在客户端断开连接的情况下处理与Google Play的连接丢失。例如,BillingClient如果Google Play商店服务在后台更新,则可能会失去其连接。 在发出进一步的请求之前,BillingClient必须调用 startConnection()方法重新启动连接。

private BillingClient billingClient;

...

billingClient = BillingClient.newBuilder(activity).setListener(this).build();

billingClient.startConnection(new BillingClientStateListener() {

    @Override

    public void onBillingSetupFinished(BillingResult billingResult) {

        if (billingResult.getResponseCode() ==  BillingResponseCode.OK) {

            // The BillingClient is ready. You can query purchases here.

        }

    }

    @Override

    public void onBillingServiceDisconnected() {

        // Try to restart the connection on the next request to

        // Google Play by calling the startConnection() method.

    }

});

注意:强烈建议您实施自己的连接重试策略并覆盖该 onBillingServiceDisconnected() 方法。BillingClient执行任何方法时,请确保维护连接。

3、查询应用内商品详细信息

您在配置应用内商品时创建的唯一商品ID用于异步查询Google Play的应用内商品详细信息。要在Google Play中查询应用内商品详情,请致电 querySkuDetailsAsync()。调用此方法时,传递一个实例,SkuDetailsParams 该实例 指定产品ID字符串列表和一个SkuType。该SkuType可以是SkuType.INAPP一次性产品或SkuType.SUBS订阅费。

注意:要查询产品详细信息,您的应用将使用您在Google Play控制台中配置产品时定义的产品ID。有关更多信息,请参阅 添加一次性产品特定功能 或添加订阅特定功能。

要处理异步操作的结果,还必须指定一个实现该SkuDetailsResponseListener 接口的侦听 器。然后onSkuDetailsResponse() ,您可以重写 以在查询结束时通知侦听器,如以下示例代码所示:

List<String> skuList = new ArrayList<> ();

skuList.add("premium_upgrade");

skuList.add("gas");

SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();

params.setSkusList(skuList).setType(SkuType.INAPP);

billingClient.querySkuDetailsAsync(params.build(),

    new SkuDetailsResponseListener() {

        @Override

        public void onSkuDetailsResponse(BillingResult billingResult,

                List<SkuDetails> skuDetailsList) {

            // Process the result.

        }

    });

注意:premium_upgrade产品ID代表用户可以购买一次但无限期使用的新游戏车。可以无限期使用的一次性产品称为非消耗品。气体产品ID代表气体,用户可以多次购买该气体。非无限使用的一次性产品称为消耗品。要处理临时资源的消耗,请参阅指示一次性产品已消耗。

您的应用应通过将其与APK捆绑在一起或从您自己的安全后端服务器中查询来维护自己的产品ID列表。

调用 getResponseCode() 以检索响应代码。如果请求成功,则响应代码为BillingResponse.OK。有关Google Play其他可能的响应代码的列表,请参见 BillingClient.BillingResponse。

如果发生错误,您可以 getDebugMessage() 用来查看相关的错误消息。

该谷歌Play结算库存储查询结果中List的 SkuDetails 对象。然后,您可以SkuDetails 在列表中的每个对象上调用各种方法,以查看有关应用内商品的相关信息,例如其价格或说明。要查看可用的产品详细信息,请参阅SkuDetails类中的方法列表。

以下示例显示了如何使用SkuDetails上一个代码段返回的对象来检索应用内商品的价格:

if (result.getResponseCode() == BillingResponse.OK && skuDetailsList != null) {

   for (SkuDetails skuDetails : skuDetailsList) {

       String sku = skuDetails.getSku();

       String price = skuDetails.getPrice();

       if ("premium_upgrade".equals(sku)) {

           premiumUpgradePrice = price;

       } else if ("gas".equals(sku)) {

           gasPrice = price;

       }

   }

}

4、允许购买应用内商品

某些Android手机可能具有较旧版本的Google Play商店应用,该版本不支持某些产品类型,例如订阅。因此,在您的应用进入计费流程之前,请致电 isFeatureSupported() 以检查设备是否支持您要销售的产品。有关产品类型的列表,请参见 BillingClient.FeatureType。

要从您的应用发出购买请求,请launchBillingFlow()从UI线程调用 方法。将引用传递给BillingFlowParams 包含相关数据的 对象以完成购买,例如商品的商品ID(skuId)和商品类型(SkuType.INAPP针对一次性商品或SkuType.SUBS订阅商品)。要获取的实例 BillingFlowParams ,请使用 BillingFlowParams.Builder 类:

// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().

BillingFlowParams flowParams = BillingFlowParams.newBuilder()

        .setSkuDetails(skuDetails)

        .build();

int responseCode = billingClient.launchBillingFlow(flowParams);

当您调用该 launchBillingFlow() 方法时,系统会显示Google Play购买屏幕。

该 launchBillingFlow() 方法返回中列出的几个响应代码之一 BillingClient.BillingResponse。Google Play调用将 onPurchasesUpdated() 购买操作的结果传递给实现该PurchasesUpdatedListener接口的侦听 器的方法。使用setListener()前面在“ 连接到Google Play”部分中演示的方法指定了侦听器 。

您必须实现该 onPurchasesUpdated() 方法以处理可能的响应代码。以下代码段显示了如何覆盖该 onPurchasesUpdated() 方法:

@Override

void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {

    if (billingResult.getResponseCode() == BillingResponse.OK

            && purchases != null) {

        for (Purchase purchase : purchases) {

            handlePurchase(purchase);

        }

    } else if (billingResult.getResponseCode() == BillingResponse.USER_CANCELED) {

        // Handle an error caused by a user cancelling the purchase flow.

    } else {

        // Handle any other error codes.

    }

}

成功购买会产生一个Google Play成功屏幕。

成功的购买还会生成购买令牌,该令牌是代表用户及其所购买的应用内商品的产品ID的唯一标识符。您的应用程序可以将购买令牌存储在本地,或者理想情况下,可以将其传递到安全的后端服务器,该服务器可以用来验证购买并防止欺诈。购买令牌对于每次一次性产品购买都是唯一的。但是,由于订阅是一次性购买的,并且会在常规结算周期自动更新,因此订阅的购买令牌在每个结算周期都保持不变。

还通过电子邮件向用户发送包含订单ID或交易唯一ID的交易收据。用户会收到一封电子邮件,其中包含每次一次性产品购买以及首次订阅购买和随后定期自动续订的唯一订单ID。您可以使用订单ID在Google Play控制台中管理退款。有关更多详细信息,请参阅 查看和退款您的应用程序的订单和订阅。

注意:代表订购重复性的订单号有一个附加整数,代表该订购的特定重复性。例如,初始订阅订单ID可能 GPA.1234-5678-9012-34567与后续订购ID分别为GPA.1234-5678-9012-34567..0(第一次重复orderID), GPA.1234-5678-9012-34567..1(第二次重复orderID)等等。

注意:如果用户在购买应用内商品时(例如在免费试用订阅期间)没有欠款,则订单ID为$ 0。例如,当用户取消订阅时,订阅将保持有效,直到计费期结束。如果用户决定重新注册,则其帐户中会保留一些贷方。在这种情况下,将创建一个新的购买令牌,为$ 0创建一个订单ID,并在信用用完后续订。

5、确认购买(消费掉才算真正的完结该订单)

如果您使用的是Google Play结算库2.0版或更高版本,则必须在三天内确认所有购买。未正确确认购买会导致这些购买被退款。

Google Play支持从应用内(应用内)或应用外(应用外)购买产品。为了使Google Play无论用户在哪里购买产品,都能够确保一致的购买体验,您必须SUCCESS在授予用户权利后尽快确认所有通过Google Play计费库收到状态的购买。如果您在三天内不确认购买,则用户会自动收到退款,Google Play会撤消购买。对于待处理的交易,购买PENDING状态为3天的窗口不适用。相反,它在购买移至该SUCCESS状态时开始。

您可以使用以下方法之一确认购买:

对于易耗品,请使用 consumeAsync()客户端API中的。

对于未消费的产品,请使用 acknowledgePurchase()客户端API中的。

acknowledge()服务器API中也提供了一种新方法。

对于订阅,您必须确认任何包含新购买令牌的购买。这意味着需要确认所有初始购买,计划变更和重新注册,但您无需确认后续续订。要确定采购是否需要确认,您可以检查采购中的确认字段。

该Purchase对象包括isAcknowledged() 指示是否已经确认购买的 方法。此外,服务器端API包括用于确认布尔值 Product.purchases.get()和Product.subscriptions.get()。在确认购买之前,请使用以下方法确定是否已确认购买。

此示例显示如何确认订阅购买:

BillingClient client = ...

AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ...

void handlePurchase(Purchase purchase) {

    if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {

        // Grant entitlement to the user.

        ...

        // Acknowledge the purchase if it hasn't already been acknowledged.

        if (!purchase.isAcknowledged()) {

            AcknowledgePurchaseParams acknowledgePurchaseParams =

                AcknowledgePurchaseParams.newBuilder()

                    .setPurchaseToken(purchase.getPurchaseToken())

                    .build();

            client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);

        }

    }

}


ONE store支付:

详情可通过VPN:https://dev.onestore.co.kr/devpoc/reference/view/IAP_v17_cn

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

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

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

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

Java SDK 1.6版本

Android studio 2.0及以上版本

3、事先准备

详情可通过VPN:https://dev.onestore.co.kr/devpoc/reference/view/IAP_v17_04_preparation_cn

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

使用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);

MyCard支付:

1、通过商务联系MyCard进行技术对接,获得最新MyCardPaySDK.jar和接入文档

2、导入MyCardPaySDK.jar

3、根据MyCard提供文档设置AndroidManifest.xml

4、根据自身需求确定是走SDK支付方式还是WebView支付方式

4-1、SDK支付方式

        MyCardSDK sdk = new MyCardSDK(activity);

        //flag   true代表测试环境,false代表正式环境

        sdk.StartPayActivityForResult(flag, bean.getAuthCode());

        // 通过onActivityResult接收SDK結果

        if (requestCode == Config.Payment_RequestCode) {

            if( resultCode == -1)

            {

                JSONObject js = null;

                try {

                    js = new JSONObject(data.getStringExtra(Config.PaySDK_Result));

                    MLog.e(data.getStringExtra(Config.PaySDK_Result));

                    if (js.optInt("returnCode") == 1 && js.optInt("payResult") == 3) {

                        String orderNo = js.getString("facTradeSeq");

                        //进行你的操作

                    }

                } catch (JSONException e) {

                    e.printStackTrace();

                } catch (Exception e){

                }

            }else{

            }

        }

4-2、WEB支付方式

测试环境链接(http://test.mycard*)、正式环境链接(https://www.mycard*)不搞混乱就好,后面拼接字段需要注意

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345