前回の続き
Androidアプリで定額課金を実装する際には、購入が正当なものかのチェックをサーバー側で行う必要がある。
前回は購入時にストアから返る電子署名のチェックをサーバーで行った。
またストアに問い合わせる際に必要なアクセストークンを、GoogleOAuth認証を通じて取得した。
今回はこのアクセストークンを用いて、ストアから最新レシートを取得し検証を行う。
前回の記事はこちらから。
最新レシートの取得
GooglePlayDeveloperAPIへリクエストを行う。
パッケージ名と購入トークンでエンドポイントを決定する。
※subscriptionsv2とsubscriptionsでレスポンスが変わるので注意
APIの詳細はこちら
$package_name = 'com.example.app'; //パッケージ名
$purchase_token = $receipt_data["purchaseToken"];//購入トークン
$google_api_get_endpoint = 'https://androidpublisher.googleapis.com/androidpublisher/v3/applications/'.$package_name.'/purchases/subscriptionsv2/tokens/'.$purchase_token;
あとはアクセストークンをHeaderに付けGETリクエストを送る。
$ch = curl_init($google_api_get_endpoint);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ["Authorization: Bearer ".$access_token],
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
]);
$ch_response = curl_exec($ch);
$response_code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$response_array = json_decode($ch_response, true);
if($response_code == 200) {
$latest_receipt_info = $response_array["lineItems"];//アイテム情報
}
レスポンスのlineItemsにはアイテム単位で最新レシートデータが入っている。
その中に有効期限もあるため、こちらを使用して検証を行う。
プロダクトIDと有効期限の確認
購入したアイテムが間違っていないかと、有効期限をチェックする。
問題なければ最後に購入確定処理(acknowledge)を入れ、適宜データベースなどに保存する。
//決済確定処理のAPIエンドポイント
$google_api_acknowledge_endpoint = 'https://androidpublisher.googleapis.com/androidpublisher/v3/applications/'.$package_name.'/purchases/subscriptions/'.$product_id.'/tokens/'.$purchase_token.':acknowledge';
foreach($latest_receipt_info as $info) {
//契約自動更新の場合true
if($info["autoRenewingPlan"]["autoRenewEnabled"]) {
//productIDのチェック
if($product_id == $info["productId"]) {
$expires_date = new DateTime($info["expiryTime"]);
$now_date = new DateTime('UTC');
$now_date = $now_date->format(DateTime::RFC3339);
//有効期限のチェック
if($now_date < $expires_date) {
//決済確定処理
$ch = curl_init($google_api_acknowledge_endpoint);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ["Authorization: Bearer ".$access_token],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_decode(["developerPayload" => ""])
]);
$ch_response = curl_exec($ch);
$response_code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if($response_code == 204 && $ch_response == "") {
//決済完了
//適宜DBに保存。クライアントへ通知。
} else {
//エラー処理
}
} else {
//エラー処理
}
break;
} else {
//エラー処理
}
}
}
プロダクトIDのチェックは、APIレスポンスのproductIDと、購入時クライアントから送られるproductIDでチェックを行う。
有効期限のチェックは、タイムゾーンをUTCにして現在時刻を取り比較する。
問題なければ必ず決済確定処理を入れる。
※確定処理を入れないと払い戻しになる。
決済確定処理について詳しくはこちら
最後に
今回はAndroidアプリのレシート検証をPHPで行いました。
アプリ外での定期購入のステータス変更を検知する、リアルタイムデベロッパー通知[RTDN]についても後日まとめる予定です。