商品信息需要自行配置,这里不做说明描述了,配置完后以json格式下载下来,后面的沙盒测试会用到的。
步骤:
1.导入相关文件
下载例子,将Appstore_SDK_<version>.jar文件导入项目的libs文件夹,在开发者后台Additional information(其他信息)部分,单击View public key(查看公有密钥)。在显示的“Public Key”(公有密钥)对话框中,单击AppstoreAuthenticationKey.pem链接,下载PEM文件。该文件包含您的公有密钥。复制AppstoreAuthenticationKey.pem文件。将其粘贴到Android Studio项目的assets文件夹中(LWA已经对assets文件进行了说明)。api_txt导入请看amazon的LWA接入
2.代码部分(只接入了消费品;其他购买方式没有接入)
AndroidManifest.xml修改
<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>
初始化
final AmazonPurchasingListener purchasingListener = new AmazonPurchasingListener(this);
PurchasingService.registerListener(context, purchasingListener);
本次接入,sku信息不在本地存储,是取自每次登录成功时的回包并记录在内存里所以本地不再做sku鉴定;本次购买时先下单,下单成功再去调用购买,此下单是游戏客户端与服务器行为和sdk无关,购买成功再验单,验单成功才会获取对应奖励)
点击购买时,将sku传入
PurchasingService.purchase(sku);
购买回调
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(TAG, "onPurchaseResponse: requestId (" + requestId
+ ") userId ("
+ userId
+ ") purchaseRequestStatus ("
+ status
+ ")");
switch (status) {
case SUCCESSFUL:
final Receipt receipt = response.getReceipt();
Log.d(TAG, "onPurchaseResponse: receipt json:" + receipt.toJSON());
//TODO这里去处理验单
doYanDan(receipt, response.getUserData());
break;
case PENDING:
Log.d(TAG, "onPurchaseResponse: pending remote approval -- purchase will be returned in getPurchaseUpdates if approved");
break;
case ALREADY_PURCHASED:
Log.d(TAG, "onPurchaseResponse: already purchased, should never get here for a consumable.");
// This is not applicable for consumable item. It is only
// application for entitlement and subscription.
// check related samples for more details.
break;
case INVALID_SKU:
Log.d(TAG,
"onPurchaseResponse: invalid SKU! onProductDataResponse should have disabled buy button already.");
final Set<String> unavailableSkus = new HashSet<>();
unavailableSkus.add(response.getReceipt().getSku());
iapManager.disablePurchaseForSkus(unavailableSkus);
break;
case FAILED:
case NOT_SUPPORTED:
Log.d(TAG, "onPurchaseResponse: failed so remove purchase request from local storage");
iapManager.showPurchaseFailedMessage(response.getReceipt().getSku());
break;
}
}
购买成功之后走验单流程。验单是客户端和游戏服务器之间的校验。验单成功处理游戏相关逻辑并回调notifyStorePayOrderResponse,在notifyStorePayOrderResponse里面会向amazon发送消息notifyFulfillment通知amazon此次交易已经顺利完成后续不再收到关于此次交易的推送了。
如果完成购买后由于某些原因没有走验单流程,每次在onResume时通过
public void onResume() {
activate();
Log.d(TAG, "onResume: call getUserData");
PurchasingService.getUserData();
Log.d(TAG, "onResume: getPurchaseUpdates");
PurchasingService.getPurchaseUpdates(false);
}
PurchasingService.getPurchaseUpdates(false)会
去拉取最近的交易,回调onPurchaseUpdatesResponse中会包含未完成的商品信息,然后继续之后的流程即可。
public void onPurchaseUpdatesResponse(final PurchaseUpdatesResponse response) {
Log.d(TAG, "onPurchaseUpdatesResponse: requestId (" + response.getRequestId()
+ ") purchaseUpdatesResponseStatus ("
+ response.getRequestStatus()
+ ") userData ("
+ response.getUserData()
+ ")");
final PurchaseUpdatesResponse.RequestStatus status = response.getRequestStatus();
switch (status) {
case SUCCESSFUL:
iapManager.setAmazonUserId(response.getUserData().getUserId(), response.getUserData().getMarketplace());
for (final Receipt receipt : response.getReceipts()) {
//TODO这里去处理验单
doYanDan(receipt, response.getUserData());
}
if (response.hasMore()) {
PurchasingService.getPurchaseUpdates(false);
}
// iapManager.refreshOranges();
break;
case FAILED:
case NOT_SUPPORTED:
Log.d(TAG, "onProductDataResponse: failed, should retry request");
iapManager.disableAllPurchases();
break;
}
}
public void doYanDan(final Receipt receipt, final UserData userData) {
switch (receipt.getProductType()) {
case CONSUMABLE:
// try to do your application logic to fulfill the customer purchase
//和后端交互,验单
sendDataToServerForYandan(receipt, userData);
break;
case ENTITLED:
// check entitled sample app to know how to handle entitled
// purchases
break;
case SUBSCRIPTION:
// check subscription sample app to know how to handle subscription
// purchases
break;
}
}
notifyStorePayOrderResponse是客户端和服务交互验单成功后调用的函数
public void notifyStorePayOrderResponse(JSONObject jsonObject) {
final String receiptId = jsonObject.optString("purchaseToken");
if (receiptId != null) {
VertiFyPurchas vertiFyPurchas = vertifyPurchaseList.get(receiptId);
if (vertiFyPurchas != null) {
Receipt receipt = vertiFyPurchas.getReceipt();
grantConsumablePurchase(receipt, vertiFyPurchas.getUserData());
}
}
}
private void grantConsumablePurchase(final Receipt receipt, final UserData userData) {
try {
// following sample code is a simple implementation, please
// implement your own granting logic thread-safe, transactional and
// robust
// create the purchase information in your app/your server,
// And grant the purchase to customer - give one orange to customer
// in this case
createPurchase(receipt.getReceiptId(), userData.getUserId());
//客户端不在验证sku信息
// final MySku mySku = MySku.fromSku(receipt.getSku(), userIapData.getAmazonMarketplace());
// // Verify that the SKU is still applicable.
// if (mySku == null) {
// Log.w(TAG, "The SKU [" + receipt.getSku() + "] in the receipt is not valid anymore ");
// // if the sku is not applicable anymore, call
// // PurchasingService.notifyFulfillment with status "UNAVAILABLE"
// updatePurchaseStatus(receipt.getReceiptId(), null, PurchaseStatus.UNAVAILABLE);
// PurchasingService.notifyFulfillment(receipt.getReceiptId(), FulfillmentResult.UNAVAILABLE);
// return;
// }
if (updatePurchaseStatus(receipt.getReceiptId(), PurchaseStatus.PAID, PurchaseStatus.FULFILLED)) {
// Update purchase status in SQLite database success
// userIapData.setRemainingOranges(userIapData.getRemainingOranges() + 1);
// saveUserIapData();
Log.i(TAG, "Successfully update purchase from PAID->FULFILLED for receipt id " + receipt.getReceiptId());
// update the status to Amazon Appstore. Once receive Fulfilled
// status for the purchase, Amazon will not try to send the
// purchase receipt to application any more
PurchasingService.notifyFulfillment(receipt.getReceiptId(), FulfillmentResult.FULFILLED);
} else {
// Update purchase status in SQLite database failed - Status
// already changed.
// Usually means the same receipt was updated by another
// onPurchaseResponse or onPurchaseUpdatesResponse callback.
// simply swallow the error and log it in this sample code
Log.w(TAG, "Failed to update purchase from PAID->FULFILLED for receipt id " + receipt.getReceiptId()
+ ", Status already changed.");
}
} catch (final Throwable e) {
// If for any reason the app is not able to fulfill the purchase,
// add your own error handling code here.
// Amazon will try to send the consumable purchase receipt again
// next time you call PurchasingService.getPurchaseUpdates api
Log.e(TAG, "Failed to grant consumable purchase, with error " + e.getMessage());
}
}
3.沙盒支付测试
使用以下命令将应用App Tester设置为沙盒模式:
adb shell setprop debug.amazon.sandboxmode debug
要退出沙盒模式,请运行以下命令
adb shell setprop debug.amazon.sandboxmode none
在开发者后台配置好应用的购买信息后,下载json文件,将该文件复制到设备文件系统内的/sdcard/
文件夹中:
adb push [_您的JSON文件夹_]/amazon.sdktester.json /sdcard/amazon.sdktester.json
4.动态应用测试LAT(需要amazon设备)
开发者后台点击对应的应用,选择动态应用测试,上传最新的包体,选择测试组人员,提交。等待5-30分钟,等状态变为测试中即可点击推送邀请发送给测试者。