当前位置: 首页 > news >正文

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><actionandroid:name="com.amazon.inapp.purchasing.NOTIFY" /></intent-filter></receiver>

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

 purchasingListener = new PurchasingListener() {/*** 确定当前登录用户的UserId和marketplace。* @param response*/@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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.getProductDatafor (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*/@Overridepublic 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 后才可以正式付费,但正式付费跟测试付费显示效果是一样的.

相关文章:

android amazon 支付接入

流程&#xff1a; 申请 Amazon 开发者帐号 ---> 在 amazon 控制台添加应用 ---> 添加应用内商品&#xff08;消费类商品&#xff0c;授权类商品&#xff0c;订阅类商品&#xff09;---> 导出 JSON 文件 --->集成 Amazon 支付 ---> 将导出的 JSON 文件 copy 到 …...

Vue2-快速搭建pc端后台管理系统

一.推荐二次开发框架 vue-element-admin Star(84k)vue-antd-admin Star(3.5k) 二.vue-element-admin 官网链接:https://panjiachen.github.io/vue-element-admin-site/zh/ 我这里搭建的是基础模版vue-admin-template(推荐) # 克隆项目 git clone https://github.com/PanJi…...

【产品文档】团队介绍PPT模板

今天和大家免费分享团队介绍的PPT模板。团队介绍是向他人展示团队的实力、专业性和能力的重要方式。通过一个有力的团队介绍&#xff0c;您可以突出团队的成员、经验、技能和取得的成就&#xff0c;从而增加信任、吸引合作伙伴、客户或投资者的兴趣 【模板预览】 动态演示效果…...

组件库的使用和自定义组件

目录 一、组件库介绍 1、什么是组件 2、组件库介绍 3、arco.design 二、组件库的使用 1、快速上手 2、主题定制 3、暗黑模式 4、语言国际化 5、业务常见问题 三、自定义组件 2、组件开发规范 3、示例实践guide-tip 4、业务组件快速托管 一、组件库介绍 1、什么是…...

网站和API支持HTTPS,最好在Nginx上配置

随着我们网站用户的增多&#xff0c;我们会逐渐意识到HTTPS加密的重要性。在不修改现有代码的情况下&#xff0c;要从HTTP升级到HTTPS&#xff0c;让Nginx支持HTTPS是个很好的选择。今天我们来讲下如何从Nginx入手&#xff0c;从HTTP升级到HTTPS&#xff0c;同时支持静态网站和…...

UnitTest笔记: 拓展库DDT的使用

DDT (Data-Drivers- Tests) 允许使用不同的测试数据运行同一个测试用例&#xff0c;展示为不同的测试用例。 第一步&#xff1a; pip安装 ddt 第二步&#xff1a; 创建test_baidu_ddt.py 1. 测试类要使用ddt 修饰 2. 不同形式的参数化&#xff1a; 列表&#xff0c;字典&a…...

裂缝检测,只依赖OPENCV,基于YOLO8S

裂缝检测&#xff0c;只依赖OPENCV&#xff0c;YOLOV8S 现在YOLOV8S训练目标非常方便&#xff0c;可以直接转换成ONNX让OPENCV调用&#xff0c;支持C/PYTHON&#xff0c;原理很简单&#xff0c;自己找博客&#xff0c;有兴趣相互交流...

python编程环境使用技巧3-程序打包pyinstaller

前言 在Python中&#xff0c;打包指的是将Python代码和相关资源&#xff08;如配置文件、图像等&#xff09;整合到一个可执行的文件或安装包中&#xff0c;以便于在其他环境中使用。 下面是使用pyinstaller进行打包的简要步骤&#xff1a; 1-安装pyinstaller&#xff1a;在命…...

Go 自学:defer关键字

我们可以使用defer关键字延迟代码的执行&#xff0c;相当于我们把代码放入一个stack中&#xff0c;遵循last in first out的原则输出代码。 package mainimport ("fmt" )func myDefer() {for i : 0; i < 5; i {defer fmt.Print(i)} }func main() {defer fmt.Prin…...

【云计算】Docker特别版——前端一篇学会

docker学习 文章目录 一、下载安装docker&#xff08;一&#xff09;Windows桌面应用安装&#xff08;二&#xff09;Linux命令安装 二、windows注册登录docker三、Docker的常规操作(一)、基本的 Docker 命令(二)、镜像操作(三)、容器的配置(四)、登录远程仓库 四、镜像管理(一…...

.net使用RabbitMQ小记

使用RabbitMQ的优点 1.性能全面&#xff0c;rabbitmq性能比较全面&#xff0c;是消息中间件的首选 2.高并发&#xff0c;rabbitmq实现语言是天生就具备高并发高可用的erlang语言 3.任务异步处理&#xff0c;将不需要同步处理的并且耗时长的操作由消息队列通知消息接受方进行异步…...

layUI 中 穿梭框无法获取值的细节问题

初始化的时候一定要指定id&#xff0c;不然就会出现无法调用 获得右侧数据和实例重载的方法...

Kaggle回归问题Mercedes——Benz Greener Manufacturing

目录 前言1 题目介绍2 数据清洗3 数据可视化分析4 模型训练5 源码 前言 这是我在大三选修课的课程设计&#xff0c;内容参考了Kaggle上高赞的代码&#xff0c;有详细批注&#xff0c;整体比较基础&#xff0c;结构相对完整&#xff0c;便于初学者学习。这个是一个回归问题&…...

天润融通「微藤大语言模型平台2.0」以知识驱动企业高速增长

8月23日&#xff0c;天润融通&#xff08;又称“天润云”,2167.HK&#xff09;&#xff0c;正式发布「微藤大语言模型平台2.0」。 “大模型企业知识企业知识工程”。 “不能有效记录和管理知识的企业是不能持续进步的。在企业的生产流程中&#xff0c;相比于其他场景&#xff0…...

【BUG】解决安装oracle11g或12C中无法访问临时位置的问题

项目场景&#xff1a; 安装oracle时&#xff0c;到第二步出现oracle11g或12C中无法访问临时位置的问题。 解决方案&#xff1a; 针对客户端安装&#xff0c;在cmd中执行命令&#xff1a;前面加实际路径setup.exe -ignorePrereq -J"-Doracle.install.client.validate.cli…...

2. 使用IDEA创建Spring Boot Hello项目并管理依赖——Maven入门指南

前言&#xff1a;本文将介绍如何使用IDEA创建一个Spring Boot Hello项目&#xff0c;并通过Maven来管理项目的依赖。我们从项目的创建到代码的编写&#xff0c;再到项目的构建和运行&#xff0c;一步步演示了整个过程。 &#x1f680; 作者简介&#xff1a;作为某云服务提供商的…...

Python在电路课程中的应用

1 需求 课程中有大量的计算&#xff0c;电路方程、复数计算&#xff0c;之前都是用的MATLAB online&#xff0c;可现在要过期了&#xff0c;只能更换平台。 2 工具 https://www.online-python.com/ Python3 在线工具 | 菜鸟工具 (runoob.com) 3 Sinusoid 章节 涉及到复数计…...

Spark SQL join的三种实现方式

引言 join是SQL中的常用操作&#xff0c;良好的表结构能够将数据分散到不同的表中&#xff0c;使其符合某种规范(mysql三大范式)&#xff0c;可以最大程度的减少数据冗余&#xff0c;更新容错等&#xff0c;而建立表和表之间关系的最佳方式就是join操作。 对于Spark来说有3种…...

wazuh环境配置和漏洞复现

1.wazuh配置 虚拟机 &#xff08;OVA&#xff09; - 替代安装 (wazuh.com)在官方网页安装ova文件 打开VMware选择打开虚拟机&#xff0c;把下载好的ova文件放入在设置网络改为NAT模式 账号:wazuh-user 密码:wazuh ip a 查看ip 启动小皮 远程连接 账号admin …...

九五从零开始的运维之路(其三十六)

文章目录 前言一、集群概述1.负载均衡技术类型&#xff08;一&#xff09;四层负载均衡器&#xff08;二&#xff09;七层负载均衡器 2.负载均衡实现方式&#xff08;一&#xff09;硬件负载均衡产品&#xff1a;&#xff08;二&#xff09;软件负载均衡产品&#xff1a; 二、L…...

同步和异步有什么区别,使用场景?

同步(Synchronous)和异步(Asynchronous)是用于描述不同的操作和通信模式的术语。它们在处理任务、执行代码以及处理通信时有很大的异同。 同步(Synchronous) 同步操作是指程序的执行顺序按照代码的先后顺序进行,一个操作完成后才能执行下一个操作。在同步操作中,调用一…...

webassembly009 transformers.js 网页端侧推理

之前试用过两个网页端的神经网络框架&#xff0c;一个是 Tensorflow PlayGround&#xff0c;它相当与实现了一个网页端的简单的训练框架&#xff0c;有关节点的数据结构可看这篇。另一个是onnx的网页端(nodejs绿色免安装try onnx on web(chrome))&#xff0c;需要自己转换onnx模…...

Android动态添加和删除控件/布局

一、引言 最近在研究RecyclerView二级列表的使用方法&#xff0c;需要实现的效果如下。 然后查了一些博客&#xff0c;觉得实现方式太过复杂&#xff0c;而且这种方式也不是特别受推荐&#xff0c;所以请教了别人&#xff0c;得到了一种感觉还不错的实现方式。实现的思路为&…...

maven下载不了仓库地址为https的依赖jar,配置参数忽略ssl安全检查

问题原因 私服使用的https地址&#xff0c;然后安全证书过期的或没有&#xff0c;使用maven命令时&#xff0c;可以添加以下参数&#xff0c;忽略安全检查 mvn -Dmaven.wagon.http.ssl.insecuretrue -Dmaven.wagon.http.ssl.allowalltrue -Dmaven.wagon.http.ssl.ignore.vali…...

3.Redis 单线程模型

redis 单线程模型 redis 只使用一个线程来处理所有的命令请求&#xff0c;并不是说一个 redis 服务器进程内部真的就只有一个线程&#xff0c;其实也有多个线程&#xff0c;多个线程是再处理网络 IO。 那么在多线程中&#xff0c;针对类似于这样的场景两个线程尝试同时对一个…...

0基础学习VR全景平台篇 第90篇:智慧眼-数据统计

【数据统计】是按不同条件去统计整个智慧眼项目中的热点&#xff0c;共包含四大块&#xff0c;分别是数据统计、分类热点、待审核、回收站&#xff0c;下面我们来逐一进行介绍。 1、数据统计 ① 可以按所属分类、场景分组、所属场景、热点类型以及输入热点名去筛选对应的热点&…...

【Go】Goland项目配置运行教程

Golang项目配置运行教程 1.安装Golang下载安装包安装 2.Goland配置2.1 环境2.2 goland配置2.2.1 没有makefile的情况2.2.2 有makefile的情况 3.跨平台项目4.补充 注意&#xff0c;本项目描述的是git clone下来的Golang项目配置运行教程&#xff0c;并不是从头创建一个Golang项目…...

Docker容器与虚拟化技术:Docker consul 实现服务注册与发现

目录 一、理论 1.Docker consul 二、实验 1.consul部署 2. consul-template部署 三、总结 一、理论 1.Docker consul &#xff08;1&#xff09;服务注册与发现 服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的&#xff0c;不保障高可用性&…...

【大模型AIGC系列课程 2-2】大语言模型的“第二大脑”

1. 大型语言模型的不足之处 很多人使用OpenAI提供的GPT系列模型时都反馈效果不佳。其中一个主要问题是它无法回答一些简单的问题。 ● 可控性:当我们用中文问AI一些关于事实的问题时,它很容易编造虚假答案。 ● 实时性:而当你询问它最近发生的新闻事件时,它会干脆地告诉你…...

Java基础数据结构

二叉查找树 二叉查找树&#xff0c;又称二叉树或者二叉搜索树 特点&#xff1a;每一个节点上最多又两个子节点 任意节点左子树上的值都小于当前节点 任意节点右子树上的值都大于当前节点 二叉查找树添加节点&#xff1a;规则 小的存左边 大的存右边 一样的不存 平衡二叉树&am…...