Android定額課金のレシート検証をサーバーで行う (2/2)

前回の続き

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]についても後日まとめる予定です。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール