Google Play Developer APIを利用したレシート検証の実装(2)

はじめに

前回の記事(Google Play Developer APIを利用したレシート検証の実装(1))では、APIを利用する目的や利用するための設定について書きました。
今回はその続き、プログラムでのAPIの利用方法について書こうと思います。

処理の流れ

大まかな流れとしては

  1. APIを呼ぶためのアクセストークンを取得する
  2. トークンをセットした状態でAPIをコールする

です。

アクセストークンを取得する際に、前回生成したサービスアカウントキーを用いるので、プログラムから読み込むのに適した場所にサービスアカウントキーのファイルを置くようにしてください。

事前準備

上記で書いたとおり、サービスアカウントキーをプロジェクトの適切な場所に置いてください。

次に、Googleでは複数のプログラミング言語に対してGoogle API Client ライブラリが用意されています。今回はPHPで実装したので、composerを用いてライブラリをインストールしました。

composer require google/apiclient

実装

ようやくAPIを呼び出す準備が整ったので、実装を進めます。
最終的に、APIを利用するユーティリティクラスを作成します。

まず、ライブラリ等を読み込みます。

require_once '/path/to/google-api-php-client/vendor/autoload.php';

次に、諸々の値を定数で定義しました。

use Google\Client;
use Google\Service\AndroidPublisher;

// トークンを取得するためのURI
const ANDROID_PUBLISHER_API_SCOPE = 'https://www.googleapis.com/auth/androidpublisher';
// アプリのパッケージ名
const PACKAGE_NAME_OF_APP = 'jp.co.package.name';

// サービスアカウントキーのパス
const PATH_TO_SERVICE_ACCOUNT_KEY = '/path/to/service/account/key/path';

そして、アクセストークンを取得・設定します。

// アクセストークンを取得・設定する
$client = new Client();
$client->setAuthConfig(GOOGLE_PLAY_DEVELOPER_API_SECRET_KEY_PATH);
$client->addScope(self::ANDROID_PUBLISHER_API_SCOPE);

$accessToken = '';
// アクセストークンの取得
try {
    if ($client->fetchAccessTokenWithAssertion()) {
        $accessToken = $client->getAccessToken()['access_token'];
    }

$client->setAccessToken($accessToken);

purchases.products.getはAndroidPublisherというクラスから呼び出すことができるので、インスタンスを生成します。このとき、引数に先ほどアクセストークンをセットしたクライアントインスタンスを渡します。

// Android Publisher APIのインスタンスを作成
$androidPublisherService = new AndroidPublisher($client);

あとはこのインスタンスのメソッドを呼び出すだけです。
パラメータとして、

  • packageName
  • productId
  • purchaseToken

が必要なので、それらを渡します。
下2つの値は購入時のレシートのJSONから抜き出した値を利用します。

$response = $androidPublisherService->purchases_products->get(
            PACKAGE_NAME_OF_APP,
            $productId,
            $purchaseToken
            );

エラーハンドリングを追加して、上記を全部をまとめると以下のようになります。

<?php

require_once Satlib::rootPath('vendor/autoload.php');

use Google\Client;
use Google\Service\AndroidPublisher;

/**
 * GooglePlayDeveloperAPIを利用するユーティリティクラス
 */
class GooglePlayDeveloperApiUtil {
    // トークンを取得するためのURI
    const ANDROID_PUBLISHER_API_SCOPE = 'https://www.googleapis.com/auth/androidpublisher';
    // アプリのパッケージ名(アプリのパッケージ名を指定してください)
    const PACKAGE_NAME_OF_APP = 'jp.co.package.name';

    // サービスアカウントキーのパス(ファイルを置いたパスを指定してください)
    const PATH_TO_SERVICE_ACCOUNT_KEY = '/path/to/service/account/key/path';

    /**
     * purchases.products.getを呼び出す
     */
    public static function purchasesProductsGet($productId, $purchaseToken)
    {
        // APIクライアントのインスタンスを生成し、値を設定する
        $client = new Client();
        $client->setAuthConfig(self::PATH_TO_SERVICE_ACCOUNT_KEY);
        $client->addScope(self::ANDROID_PUBLISHER_API_SCOPE);

        $accessToken = '';
        // アクセストークンの取得
        try {
            if ($client->fetchAccessTokenWithAssertion()) {
                $accessToken = $client->getAccessToken()['access_token'];
            }
        } catch (Google_Service_Exception $e) {
            return array('code' => $e->getCode(), 'body' => $e->getErrors());
        } catch (Exception $e) {
            return array($e->getErrors());
        }

        $client->setAccessToken($accessToken);

        // Android Publisher APIのインスタンスを作成
        $androidPublisherService = new AndroidPublisher($client);

        try {
            $response = $androidPublisherService->purchases_products->get(
                        self::PACKAGE_NAME_OF_APP,
                        $productId,
                        $purchaseToken
                );
            return $response;
        } catch (Google_Service_Exception $e) {
            return array('code' => $e->getCode(), 'body' => $e->getErrors());
        }
    }
}

APIを呼び出した際、200等の成功レスポンスでない場合は Google_Service_Exception という例外として返されるようです。
ステータスコードとエラーメッセージの取り出し方はソースコードのとおりです。

ちなみに、レスポンスのJSONは以下のようになります。

{
    "acknowledgementState": 0,
    "consumptionState": 0,
    "developerPayload": "",
    "kind": "androidpublisher#productPurchase",
    "obfuscatedExternalAccountId": "your_account_id",
    "obfuscatedExternalProfileId": null,
    "orderId": "GPA.xxxx-xxxx-xxxx-xxxxx",
    "productId": null,
    "purchaseState": 0,
    "purchaseTimeMillis": "xxxxxxxxxxxxx",
    "purchaseToken": null,
    "purchaseType": null,
    "quantity": null,
    "refundableQuantity": null,
    "regionCode": "JP"
}

パラメータで渡していたproductIdやpurchaseTokenはプロパティとして存在しているものの、nullで返ってくるので注意です。

まとめ

前回の記事ではAPIの利用設定、今回の記事ではGoogle Developer API のpurchases.products.getを呼んで購入情報を取得するまでをまとめてみました。

公式ドキュメントにはもちろん記載がありますが、複数ページに分散していて少し混乱したので、この記事がお役に立てると嬉しいです。

読んでいただき、ありがとうございました。