适用于Appstore SDK IAP的收据验证服务
适用于亚马逊应用内购买 (IAP) 的收据验证服务 (RVS) 可让您验证您应用的用户进行的购买。有关RVS的概述,请参阅收据验证服务概述。
设置RVS
RVS提供了两个环境选项,具体取决于应用是处于开发/测试阶段,还是已发布到亚马逊应用商店。
- RVS云沙盒: 在开发和测试应用时,请使用RVS沙盒环境验证App Tester测试工具生成的收据。要设置RVS云沙盒,请参阅使用RVS云沙盒。
- RVS生产服务器: 将应用发布到亚马逊应用商店后,您可以使用Amazon RVS生产服务器。请参阅适用于Appstore SDK IAP的RVS生产设置。
RVS请求语法
使用RVS来验证PurchaseResponse
对象或PurchaseUpdatesResponse
对象。可以从这些响应对象中提取一个用户ID字符串,它表示用户的唯一标识符。PurchaseResponse
对象包含ReceiptId
,它与用户ID联合用于对购买执行服务器端验证。出于安全原因,来自您的服务器的请求需要传递共享密钥以确认您的身份。
这些请求使用以下格式:
{protocol}//{server}[/{sandbox}]/version/{operation-version-number}/verifyReceiptId/developer/{shared-secret}/user/{user-id}/receiptId/{receipt-id}
花括号包含占位符和请求参数 - 将它们替换为要验证的交易中的值。下表列出了所需参数的描述。
参数 | 描述 |
---|---|
protocol | 用于与服务器或沙盒通信的协议,如https:。 |
server | 您要与之通信的RVS服务器URL。RVS云沙盒服务器和RVS生产服务器都使用URL "appstore-sdk.amazon.com"。 |
sandbox | 如果使用RVS云沙盒服务器,请使用值"sandbox"。如果使用RVS生产服务器,请省略此参数。 |
operation-version-number | verifyReceiptId 操作版本号。此版本号独立于IAP版本号。当前verifyReceiptId 版本号为“1.0”。 |
shared-secret | 用于标识发出请求的开发者的共享密钥。可在开发者控制台共享密钥页面上找到共享密钥:https://developer.amazon.com/zh/sdk/shared-key.html。对于RVS云沙盒,共享密钥可以是任何非空字符串。 |
user-id | 代表亚马逊应用商店应用中不同亚马逊客户的ID。从PurchaseResponse.getUserData().getUserId() 获取用户ID。 |
receipt-id | 购买的全局唯一ID。在PurchaseResponse.getReceipt().getReceiptId() 或PurchaseUpdatesResponse.getReceipts() → Receipt.getReceiptId() 中查找收据ID。 |
RVS响应语法
RVS提供了RESTful JSON API接口。作为最佳实践,使用JSON解析器类从RVS服务器读取JSON响应。
发出验证交易的请求后,RVS服务器或沙盒会返回响应代码来指示请求是否成功。如果成功,则返回的JSON响应包括有关交易的信息。
下例展示了一个成功响应:
{
"autoRenewing":false,
"betaProduct":false,
"cancelDate":null,
"cancelReason":null,
"freeTrialEndDate":null,
"fulfillmentDate":null,
"fulfillmentResult":null,
"gracePeriodEndDate":null,
"parentProductId":null,
"productId":"com.amazon.iapsamplev2.gold_medal",
"productType":"CONSUMABLE",
"promotions":null,
"purchaseDate":1399070221749,
"purchaseMetadataMap":null,
"quantity":1,
"receiptId":"wE1EG1gsEZI9q9UnI5YoZ2OxeoVKPdR5bvPMqyKQq5Y=:1:11",
"renewalDate":null,
"term":null,
"termSku":null,
"testTransaction":true
}
RVS响应代码
收据验证服务会使用以下代码之一进行响应,这些代码可以指示验证检查的结果。
响应代码 | 描述 |
---|---|
HTTP 200 | 成功: 收据ID、用户ID和共享密钥都是有效的。产品类型是以下项之一: ENTITLED 、CONSUMABLE 或SUBSCRIPTION |
HTTP 400 | 此receiptId 表示的交易无效,或没有找到此receiptId 的交易。 |
HTTP 410 | 此receiptId 表示的交易不再有效。请将其作为已取消的收据。 |
HTTP 429 | 该请求已被限制节流。请降低您的调用速率并稍后重试。 |
HTTP 496 | 共享密钥无效 |
HTTP 497 | 用户ID无效 |
HTTP 500 | 出现内部服务器错误 |
成功交易的RVS响应字段
下表列出并描述了成功交易的RVS响应中包含的字段。
字段 | 数据类型 | 描述 |
---|---|---|
autoRenewing |
布尔值 | 表示客户的订阅是否会自动续订。 |
betaProduct |
布尔值 | 指示所购买的产品是否是动态应用测试产品。 |
cancelDate |
长整数 | 取消购买的日期,或订阅到期的日期。如果购买未取消,则此字段为null。时间以毫秒为单位。 |
cancelReason |
整数 | 指示取消产品的原因。可能的值为null、0、1或2,其中每个整数分别代表一项取消原因: null - 购买未取消。0 - 当前无法提供取消原因,将在之后提供。1 - 客户取消了订单。2 - 亚马逊系统取消了购买。例如,客户用于购买订阅的付款无效,并且无法在宽限期内完成购买。如果亚马逊客户支持部门应客户要求取消订单,也会返回此代码。 |
freeTrialEndDate |
长整数 | 表示订阅处于免费试用期内。提供订阅免费试用的结束日期,以epoch(毫秒)为单位。如果订阅不在免费试用期内,则此字段为null。 |
fulfillmentDate |
长整数 | 在订阅购买中,为确认履行的日期。以纪元以后的毫秒数存储。如果未确认订阅履行,则为null。消费品和权利始终为null。 |
fulfillmentResult |
字符串 | 在订阅购买中,履行的状态。有效值:
|
gracePeriodEndDate |
长整数 | 表示订阅处于宽限期内。提供订阅宽限期的结束日期,以epoch(毫秒)为单位。如果订阅不在宽限期内,则此字段为null。 |
parentProductId |
字符串 | Null。预留以供将来使用。 |
productId |
字符串 | 您在应用中为此商品定义的SKU。 |
productType |
字符串 | 所购买产品的类型。有效产品类型为CONSUMABLE 、SUBSCRIPTION 和ENTITLED 。 |
promotions |
[列表]<促销> | 订阅购买的促销定价或留存优惠的详细信息。如果没有促销,则为Null。请参阅RVS中的促销。 |
purchaseDate |
长整数 | 购买日期,以纪元以后的毫秒数存储。对于订阅商品,purchaseDate 代表首次购买日期,而不是后续续订的购买日期。 |
purchaseMetadataMap |
[映射] <字符串,字符串> | 如果购买是通过快速订阅发起的,则值为{"QuickSubscribe":true} 。否则为null。 |
quantity |
整数 | 购买的数量。始终为null或1。 |
receiptId |
字符串 | 购买的全局唯一标识符。 |
renewalDate |
长整数 | 需要续订订阅购买的日期。日期以纪元以后的毫秒数存储。 |
term |
字符串 | 订阅IAP将保持有效的持续时间(期限从购买之日开始)。期限由数字和时间段(天、周、月、年)构成,如1周或2个月。 |
termSku |
字符串 | 对应于订阅期的唯一SKU。 |
testTransaction |
布尔值 | 表明此购买是否作为亚马逊发布和测试过程的一部分进行。 |
RVS中的促销
有关如何设置促销定价优惠的详细信息,请参阅设置促销定价。有关如何设置留存优惠的详细信息,请参阅留存优惠。如果客户以促销定价购买了订阅或以留存优惠折扣续订订阅,则通过RVS返回的收据包括促销详情。上一节所述的JSON响应包含一个promotions
(促销)字段。本节将更详细地介绍promotions
字段。促销详情仅显示在与客户以促销定价或留存优惠折扣购买的订阅相对应的收据上。
如果没有与收据相关联的促销,则promotions
字段为空。否则,该字段将包含Promotion
(促销)对象列表,其中包含以下字段。
字段 | 数据类型 | 描述 |
---|---|---|
promotionType |
字符串 | 促销类型。有效值:
|
promotionStatus |
字符串 | 该客户的促销状态。有效值:
|
示例:
"promotions": [
{
"promotionType":"Introductory Price - All Customers",
"promotionStatus":"Completed"
}
]
有效值描述
promotionType
字段有效的值为:
Introductory Price - All Customers
— 向所有客户(包括新客户和流失的客户)提供的优惠。Promotional Price - Lapsed Customers
— 仅对流失的客户提供的优惠。Retention Offer
— 计划取消订阅的符合条件的订阅者可享受的优惠。
promotionStatus
字段有效的值为:
Queued
— 客户使用促销定价优惠购买了订阅。目前,他们正在进行免费试用,尚未开始促销期。此字段不适用于留存优惠。InProgress
— 客户目前享受促销定价或留存优惠。Completed
— 客户已完成促销定价优惠的促销期。此字段不适用于留存优惠。
促销常见问题解答
以下是有关RVS中促销的常见问题解答 (FAQ)。
- 问: 是否所有客户订阅收据都会提供促销详情?
- 不是,促销详情仅显示在以促销优惠完成的订阅购买所对应的收据上。
- 问: 取消收据后是否显示促销详情?
- 是的,对于促销定价,如果客户的订阅被取消,则促销详细信息显示为
Completed
。但是,在客户享受了留存优惠后,其订阅将按正常价格续订,并且收据中不会提供促销详情。 - 问: 对于促销定价,如果客户在免费试用期间、续订为促销计划之前取消订阅,则促销状态是什么?
- 由于客户没有开始促销期,因此收据上不会显示任何与之相关联的促销详情。
取消日期和续订日期
cancelDate
字段包含订阅购买到期的日期或亚马逊客户服务取消购买的日期。取消日期表示客户失去相应内容访问权限的日期。如果客户通过关闭自动续订来取消其订阅,则取消日期是之前原定的续订日期。
renewalDate
字段包含自动续订订阅购买下一次需要续订的日期。此字段仅适用于订阅购买。如果客户按月订阅,则订阅会每月在与客户首次订阅相同的日期续订。如果下个月不包括该确切日期,则预订日期为距其最近的前一个日期。例如:
- 如果客户在1月2日订阅,则接下来的三个续订日期为2月2日、3月2日和4月2日。
- 如果客户在1月31日订阅,接下来的三个续订日期为2月28日(如果是闰年,则为2月29日)、3月31日和4月30日。
renewalDate
和cancelDate
字段以毫秒为单位存储。可以使用java.util.Date(timeInMillis)
将值转换为日期对象。
消费品或权利购买
在有效的收据中,取消日期和续订日期都包含null值。如果取消日期字段不为null,则会包含亚马逊客户服务取消购买的日期。
订阅购买
在有效的订阅收据中,取消日期为null。如果cancelDate
字段不为null,则会包含订阅到期的日期或亚马逊客户服务取消购买的日期。
renewalDate
字段包含自动续订订阅购买下一次需要续订的日期。如果订阅未设置为自动续订,则字段值为null。
在以下示例中,用户拥有已取消的订阅:
- 订阅的有效期为2023年1月1日至2023年3月1日。在此收据中,此订阅的
purchaseDate
设置为2023年1月1日,cancelDate
设置为2023年3月3日。 - 如果此订阅后来于2023年4月1日重新激活,则订阅会有第二个收据。第二个收据会显示
purchaseDate
为2023年4月1日,cancelDate
为null。
RVS沙盒和生产示例
Last updated: 2024年6月13日