android amazon 支付接入

流程:

申请 Amazon 开发者帐号 ---> 在 amazon 控制台添加应用 ---> 添加应用内商品(消费类商品,授权类商品,订阅类商品)---> 导出 JSON 文件 --->集成 Amazon 支付 ---> 将导出的 JSON 文件 copy 到 /mnt/sdcard/目录下---> 沙河模式下测试支付 ---> 上传发布

注意:亚马逊目前使用 V1 签名;2.targetSdkVersion 版本必须小于等于29

SDK运行模式一共三种

①:SANDBOX 沙河模式,用于测试,与 Amazon App Tester 测试工具交互

②:PRODUCTION 提交到亚马逊应用商店才可测试

③:UNKNOWN 尚未通过调用verifyLicense()初始化SDK。
 

步骤一:集成亚马逊内购SDK

    implementation 'com.amazon.device:amazon-appstore-sdk:3.0.4'

步骤二:在 AndroidManifest.xml 文件中添加 ResponseReceiver 配置,如果应用 targetSdkVersion 设置的是 31 或更高版本,必须显式地将 android:exported 设置 ResponseReceiver android:exported 设置为true

<receiver android:name="com.amazon.device.iap.ResponseReceiver" android:exported="true"
            android:permission="com.amazon.inapp.purchasing.Permission.NOTIFY" >
            <intent-filter>
                <action
                    android:name="com.amazon.inapp.purchasing.NOTIFY" />
            </intent-filter>
 </receiver>

步骤三:实现并注册PurchasingListener (onCreate 生命周期方法中调用)

 purchasingListener = new PurchasingListener() {
            /**
             * 确定当前登录用户的UserId和marketplace。
             * @param response
             */
            @Override
            public void onUserDataResponse(final UserDataResponse response) {
                Log.d(LOG_TAG, "onUserDataResponse: requestId (" + response.getRequestId()
                        + ") userIdRequestStatus: "
                        + response.getRequestStatus()
                        + ")");
                //当前用户相关信息(用户ID和市场
                final UserDataResponse.RequestStatus status = response.getRequestStatus();
                switch (status) {
                    case SUCCESSFUL:
                        Log.d(LOG_TAG, "onUserDataResponse: get user id " + response.getUserData().getUserId()
                                + ", marketplace "
                                + response.getUserData().getMarketplace());
                        currentUserId = response.getUserData().getUserId();
                        currentMarketplace = response.getUserData().getMarketplace();
                        break;

                    case FAILED:
                        Log.d(LOG_TAG, "onUserDataResponse FAILED failed, status code is " + status);
                    case NOT_SUPPORTED:
                        Log.d(LOG_TAG, "onUserDataResponse NOT_SUPPORTED failed, status code is " + status);
                        break;
                }
            }

            /**
             * 检索应用中销售的SKU的信息
             * 使用来自ProductDataResponse对象的有效SKU。
             *
             * @param response
             */
            @Override
            public void onProductDataResponse(final ProductDataResponse response) {
                final ProductDataResponse.RequestStatus status = response.getRequestStatus();
                Log.d(LOG_TAG, "onProductDataResponse: RequestStatus (" + status + ")");

                switch (status) {
                    case SUCCESSFUL:
                        Log.d(LOG_TAG, "onProductDataResponse: successful.  The item data map in this response includes the valid SKUs");
                        final Set<String> unavailableSkus = response.getUnavailableSkus();
                        for (final String s : response.getUnavailableSkus()) {
                            Log.v(LOG_TAG, unavailableSkus.size() + " 不可用SKU:" + s);
                        }
                        final Map<String, Product> products = response.getProductData();
                        for (final String key : products.keySet()) {
                            Product product = products.get(key);
                            Log.v(LOG_TAG, String.format("可购买的产品:%s\n 类型:%s\n SKU:%s\n 价格:%s\n 描述:%s\n", product.getTitle(), product.getProductType(), product.getSku(), product.getPrice(), product.getDescription()));
                            // 处理产品
                        }
                        break;
                    case FAILED:
                    case NOT_SUPPORTED:
                        Log.d(LOG_TAG, "onProductDataResponse: failed, should retry request");
                        break;
                }
            }

            /**
             * 检索自上次调用该方法之后用户完成的所有购买交易
             * 仅可检索未履行和已取消的消费品购买
             * @param response
             */
            @Override
            public void onPurchaseUpdatesResponse(final PurchaseUpdatesResponse response) {

                Log.d(LOG_TAG, "PurchaseUpdatesResponse: requestId (" + response.getRequestId()
                        + ") Status ("
                        + response.getRequestStatus()
                        + ") userId ("
                        + response.getUserData().getUserId()
                        + ")");
                //获取请求状态
                final PurchaseUpdatesResponse.RequestStatus status = response.getRequestStatus();
                switch (status) {
                    case SUCCESSFUL:
                        Log.e(LOG_TAG, "========no consumeProduct==========" + response.getReceipts());
                        //PurchasingService.getProductData
                        for (final Receipt receipt : response.getReceipts()) {
                            LogD("购买收据 + receipt " + receipt.isCanceled() + "\n" + "收据:" + receipt.getReceiptId());
                            if (!receipt.isCanceled()) {
                                String localReceipt = SharedPreferencesUtil.getString(mContext, receipt.getReceiptId(), "");
                                Gson gson = new Gson();
                                Type type = new TypeToken<Hashtable<String, String>>(){}.getType();
                                Hashtable<String, String> localPurchase= gson.fromJson(localReceipt, type);
                                if(null!=localPurchase){
                                    myProductInfo = localPurchase;
                                }
                                receiptID = receipt.getReceiptId();
                                Log.e(LOG_TAG, "----------myProductInfo------------: " + myProductInfo);
                                consumeProduct(receipt,"2");
                            }
                        }

//                        if (response.hasMore()) {
//                            //如果不启用“待定购买”,则在每次getPurchaseUpdates(false)调用中只返回未履行的消费品收据
//                            PurchasingService.getPurchaseUpdates(false);
//                            return;
//                        }
                        break;
                    case NOT_SUPPORTED:
                        Log.d(LOG_TAG, "onProductDataResponse: failed, should retry request");
                        break;
                }
            }

            /**
             * purchase()用户拉起支付后,用于确定购买状态。
             *
             * @param response
             */
            @Override
            public void onPurchaseResponse(final PurchaseResponse response) {
                final String requestId = response.getRequestId().toString();
                final String userId = response.getUserData().getUserId();
                final PurchaseResponse.RequestStatus status = response.getRequestStatus();
                Log.d(LOG_TAG, "支付成功回调 onPurchaseResponse: requestId (" + requestId
                        + ") userId ("
                        + userId
                        + ") purchaseRequestStatus ("
                        + status
                        + ")");

                switch (status) {
                    case SUCCESSFUL:
                        //交易成功
                        final Receipt receipt = response.getReceipt();
                        Log.d(LOG_TAG, "onPurchaseResponse: receipt json:" + receipt.toJSON());
                        receiptID = receipt.getReceiptId();
                        Log.d(LOG_TAG, "onPurchaseResponse: receipt receiptID:" + receipt.getReceiptId());

                       //请求服务端跟amazon校验
                       //校验成功去消耗
                        
                          PurchasingService.notifyFulfillment(receiptID, FulfillmentResult.FULFILLED);

                        break;
//                    case PENDING:
//                        Log.d(LOG_TAG, "onPurchaseResponse: 等待远程批准——如果获得批准,购买将在 getPurchaseUpdates 中返回");
//                        break;
                    case ALREADY_PURCHASED:
                        //已经授权过的,属于成功,此时将道具给玩家即可
                        Log.d(LOG_TAG, "onPurchaseResponse: 已经授权过的,属于成功,此时将道具给玩家即可");
                        break;
                    case INVALID_SKU:
                        Log.d(LOG_TAG, "onPurchaseResponse: invalid SKU!无效SKU,无法识别");
                        break;
                    case FAILED:
                    case NOT_SUPPORTED:
                        Log.e(LOG_TAG, "支付失败 用户在完成之前取消了购买");
                        break;
                }
            }
        };

步骤四:注册监听(onCreate 生命周期方法中调用)

PurchasingService.registerListener(mContext, purchasingListener);

步骤五:通过 getUserData() 当前用户相关(用户ID和市场),我这边是放在了onCreate 生命周期方法中 

PurchasingService.getUserData();(onCreate 生命周期方法中调用)

步骤六:检索自上次调用该方法之后用户完成的所有购买交易,以确保获取最新的更新

PurchasingService.getPurchaseUpdates(true);(onCreate 生命周期方法中调用)
  • false - 返回自上次调用getPurchaseUpdates()之后的购买记录的分页响应。检索用户的未履行消费品、权利和订阅购买的收据。亚马逊应用商店建议在大部分情况下使用此方法。

     注意: 如果您的应用启用了待定购买,则亚马逊应用商店会在每次getPurchaseUpdates(false)调用中为用户返回所有未履行的消费品和权利收据,直到您的应用调用notifyFulfillment()为止。如果不启用“待定购买”,则在每次getPurchaseUpdates(false)调用中只返回未履行的消费品收据。

  • true - 检索用户的完整购买记录。需要将数据存储在某个位置(例如服务器端数据缓存),或将所有数据保留在内存中。

步骤七:验证SKU,购买中不会因 SKU 无效而意外失败。

 Set<String> productSkus = new HashSet<>();
                productSkus.add("skus1");
                productSkus.add("skus12");
                productSkus.add("skus3");
                ....
                PurchasingService.getProductData(productSkus);// 触发PurchasingListener.onProductDataResponse()

步骤八:拉起支付弹框支付

            final RequestId requestId =  PurchasingService.purchase("Product_Id");

注意:在消耗商品前,先完成后端服务器通过亚马逊的Receipt Verification Service (RVS)验证receiptId,从而验证购买所产生的收据。验证后再去消耗。

测试流程

1:从亚马逊应用商店将Amazon App Tester下载到手机上。App Tester模拟生产环境,下载链接

2:下载后台的amazon.sdktester.json 文件复制到手机的/sdcard/文件夹中,在Amazon App Tester应用中找到 IAP items in JSON File,看下是否有数据

       adb push F:/download/amazon.sdktester.json /mnt/sdcard/

3:adb shell setprop debug.amazon.sandboxmode debug 设置为沙盒模式

//检查应用是否处于测试模式

  Log.d(TAG, "Appstore SDK Mode: " + LicensingService.getAppstoreSDKMode()); 

  以上就是 Amazon 支付的接入流程,发布到 Amazon 后才可以正式付费,但正式付费跟测试付费显示效果是一样的.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 可以使用Android提供的一些API和框架连接云端,例如Google Cloud Platform、Amazon Web Services、Microsoft Azure等。这些云服务提供商都提供了适用于Android应用程序的开发工具包和API,以便应用程序可以与云服务进行交互。此外,也可以使用第三方库和工具来简化与云服务的连接。需要根据具体情况选择适合的方法和工具来实现Android连接云端的功能。 ### 回答2: Android 连接云端是指Android设备通过网络与云服务器进行通信和数据交换的过程。为了实现这一功能,我们需要在Android端使用网络请求的API来建立与云端服务器的连接,如HTTP协议、Socket等。在连接过程中,以下是一些重要的步骤和技术: 1. 网络权限:在Android应用程序的清单文件中,需要添加网络权限,以获取访问互联网的权限。 2. URL和连接建立:使用URL类或URI类创建用于连接到云端的URL或URI。通过URL.openConnection()方法建立与云端服务器的连接。 3. 身份验证:如果云端服务器需要身份验证,Android应用需要提供合适的身份验证信息,如用户名和密码等。 4. 请求和响应:通过连接对象的InputStream和OutputStream来读取和写入请求和响应数据。可以使用BufferedReader和PrintWriter等类来处理数据流。 5. 数据传输格式:云端服务器和Android设备之间的数据通常采用的是特定的数据传输格式,如JSON、XML等。在请求和响应过程中,需要使用相关的数据格式转换方法。 6. 网络状态检查:在实际应用中,需要检查手机的网络状态,比如是否有网络连接、网络类型是WiFi还是3G/4G等。这样可以在没有网络连接的情况下进行错误处理。 7. 异步任务处理:网络请求通常是耗时操作,为了避免阻塞主线程造成应用无响应,需要使用多线程或异步任务来处理网络请求。 总之, Android连接云端的过程涉及到网络权限的申请、URL的创建和连接的建立、身份验证、数据传输格式的处理等多个步骤。合理地处理这些步骤能够实现与云端的有效通信和数据交换,为Android设备提供更多的功能和服务。 ### 回答3: Android 连接云端可以通过以下几种方式进行。 首先,可以使用Android提供的Google云端平台(Google Cloud Platform,GCP)来建立与云端的连接。开发者可以在GCP上创建基于云的应用程序,使用Google提供的云存储、云计算和云数据库等服务。通过使用GCP提供的SDK和API,开发者可以将Android应用程序与云端进行通信和数据交换。 另外,Android还支持使用其他云平台提供的服务进行连接。例如,开发者可以使用Amazon Web Services(AWS)提供的云服务来与云端进行连接。AWS提供了多种用于Android应用程序的开发工具和服务,例如云存储(Amazon S3)和云通信(Amazon SNS),开发者可以使用这些服务实现与云端的连接。 此外,Android开发者还可以使用各种第三方云端服务提供商提供的服务进行连接。这些服务提供商通常提供了API和SDK供开发者使用,使开发者能够轻松地将Android应用程序连接到他们的云服务上。 综上所述,Android连接云端的方式多种多样。开发者可以根据实际需求选择适合自己的云平台或服务提供商,并使用相应的SDK和API来实现与云端的连接。这样,Android应用程序就可以与云端进行数据交互、存储和计算等操作,实现更丰富的功能和更高效的数据管理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

遥不可及zzz

我会用心写更多自己的经验。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值