Google play 实时开发者通知——一次性购买
若使用通知需要先配置,详见:http://www.cuiwei.net/p/1632593347/
实时开发者通知 有三种类型
- 订阅购买 - SubscriptionNotification
- 一次性购买 - OneTimeProductNotification
- play管理中心发出的测试消息 - TestNotification
这篇文章只说 TestNotification和OneTimeProductNotification两种
TestNotification
这个没什么好说的,就是你配置完实时开发者通知
,在play管理中心发出的测试通知
OneTimeProductNotification
Google play将应用内商品购买称为一次性购买
属性名称 | 值 | 说明 |
---|---|---|
version | string | 此通知的版本。最初,此值为“1.0”。此版本与其他版本字段不同。 |
notificationType | int | 通知的类型。它可以具有以下值:(1) ONE_TIME_PRODUCT_PURCHASED - 用户成功购买了一次性商品。(2) ONE_TIME_PRODUCT_CANCELED - 用户已取消待处理的一次性商品购买交易。 |
purchaseToken | string | 购买时向用户设备提供的令牌。 |
sku | string | 购买的一次性商品的商品 ID(例如“sword_001”)。 |
注意:仅针对某些类型的一次性购买发送 OneTimeProductNotification。
如上,官方只是说“仅针对某些类型的一次性购买发送”,很模糊;经过测试,只有“客户没有在规定的时间范围内完成付款”才会发送这种消息。也就是说,正常支付是收不到OneTimeProductNotification
消息的1️⃣
服务端需要做什么
解析通知,得到3个参数:packageName
,productId
,purchaseToken
,然后请求Google Play Developer API
得到购买详情,判断是否购买,是否确认,没有确认就确认,已购买并且已确认就可以认为支付成功
如何配置Google Play Developer API,请参考 使用服务账号请求Google Play Developer API
/**
* google play支付异步回调
* 只有延迟支付才会通知
*/
public function postPlayback() {
$json=file_get_contents('php://input');
$this->log($json);
$arr= json_decode($json, true);
$oneTimeProductNotification=base64_decode($arr['message']['data']);
$arr['message']['data']=$oneTimeProductNotification;
$this->log($arr);
$notify=json_decode($oneTimeProductNotification, true);
if ($notify['oneTimeProductNotification']['notificationType']==1){
//notificationType: 1.用户成功购买了一次性商品 2.用户已取消待处理的一次性商品购买交易
var_dump($notify['packageName'], $notify['oneTimeProductNotification']['sku'], $notify['oneTimeProductNotification']['purchaseToken']);
$configLocation = $this->app->path.'/config/pc-api-***-797-ac21a2656c65.json';
// echo file_get_contents($configLocation);exit;
//将 JSON 设置环境变量
putenv('GOOGLE_APPLICATION_CREDENTIALS='.$configLocation);
try {
$google_client = new \Google_Client();
$google_client->useApplicationDefaultCredentials();
$google_client->addScope(\Google_Service_AndroidPublisher::ANDROIDPUBLISHER);
$androidPublishService = new \Google_Service_AndroidPublisher($google_client);
$result = $androidPublishService->purchases_products->get(
$notify['packageName'],
$notify['oneTimeProductNotification']['sku'],
$notify['oneTimeProductNotification']['purchaseToken']
);
// echo json_encode($result, JSON_UNESCAPED_UNICODE);
//purchaseState: 0.Purchased 1.Canceled 2.Pending
//acknowledgementState: 0.Yet to be acknowledged 1.Acknowledged已确认
//consumptionState: 0.Yet to be consumed 1.Consumed已消耗
//已确认和已消耗的区别:
//- 没有确认的,超时会自动退款
//- 消耗,只能app端消耗,服务端操作不了。所以会出现已确认但未消耗的情况
//- 消耗,会自动确认
//- 未消耗,app端如果不处理,再次点击该sku会提示"您已经拥有此内容",无法再次购买
if($result->purchaseState==0){//已支付
if ($result->acknowledgementState == 0) {//未确认
$androidPublishService->purchases_products->acknowledge(
$notify['packageName'],
$notify['oneTimeProductNotification']['sku'],
$notify['oneTimeProductNotification']['purchaseToken'],
new \Google\Service\AndroidPublisher\ProductPurchasesAcknowledgeRequest((array)$result->toSimpleObject())
);
}
//支付成功发货的逻辑,同时标记该订单已经支付完成
}
}catch (Exception $exception){
return show(0, $exception->getMessage());
}
}
}
⚠️注意,这里有个坑,purchaseState的值app端和服务端不一致!!
服务端:purchaseState: 0.Purchased 1.Canceled 2.Pending
详见:https://developers.google.cn/android-publisher/api-ref/rest/v3/purchases.products#ProductPurchase
app端:Purchase.PurchaseState 0.UNSPECIFIED_STATE 1.PURCHASED 2.PENDING
详见:https://developer.android.google.cn/reference/com/android/billingclient/api/Purchase.PurchaseState
参考
1️⃣ 关于一次性购买收不到异步通知
网友收到谷歌的回复:
对于一次性购买,今天只为待定交易发送实时开发人员通知。“测试卡,始终批准”不是待定交易,这就是为什么今天没有发送通知。我们将努力在文档中更清楚地说明这一点。
是什么让所有这些实时开发人员通知变得毫无用处,因为您无法有一个地方始终如一地处理所有购买。