web-dev-qa-db-ja.com

ユーザーのAndroidアプリ内サブスクリプションを確認するための手順は正しいですか?

ユーザーアカウント/ログインを必要とせず、ユーザーがサブスクリプションを購入できるアプリを作成しています。 Google Play Developer APIを使用して、ユーザーが購入済み/アクティブなサブスクリプションを持っているかどうかを確認したいと思います。すべてのドキュメントから、次の手順を収集しました。

それらは正しいですか、そしてあなたはそれらの2つの質問に答えることができますか?

  1. Google APIコンソールで サービスアカウント を作成します。
  2. 私に与えられた秘密鍵を保存します(どこに?-確かに私のコード/デバイスにはない this sample code 示唆する)
  3. JavaのGoogle APIクライアントライブラリ を使用して、秘密鍵でJWTを作成し、署名します(方法? ドキュメントにこれが記載されています 、しかしそれはJavaコードではありません...コードで何をしますか?)
  4. アクセストークンリクエストを作成し、APIにアクセスする
  5. アプリケーションは [〜#〜] get [〜#〜] リクエストをAPIに送信して、ユーザーがサブスクリプションを持っているかどうかを確認できるようになりました
  6. アクセストークンの有効期限が切れたら、手順3に戻ります。

また、私はWebサービスを持っていますが、WebサービスやWebサービスのプログラミングについては何も知りません...おそらくここで使用する必要があることを知っているだけです。

編集:これらの手順は正しくありませんでした。正しい手順については、以下の私の回答を参照してください。ただし、これはサービスアカウントの使用にのみ適用されることに注意してください(ユーザーにAPIアクセスを明示的に許可するように要求する必要がなかったため)

30
Kalina

結局のところ、私の手順は正しくありませんでした。これを理解するのに数週間かかり、他のどこにも文書化されていないようです。どういたしまして:

  1. Google APIs ConsoleWebアプリケーションアカウントを作成します。任意のWebサイトを「リダイレクトURI」として配置します。実際には使用しないため、問題ではありません。アカウントを作成すると、クライアントIDとクライアントシークレットが取得されます。

  2. コンピューターのブラウザーでhttps://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=[YOUR REDIRECT URI]&client_id=[YOUR CLIENT ID]にアクセスし、プロンプトが表示されたらアクセスを許可します。

  3. アドレスバーを見てください。最初に入力したURIの最後が更新トークンになります。 1/....のようになります。次のステップでこの「コード」が必要になります。更新トークンが期限切れになることはありません。

  4. https://accounts.google.com/o/oauth2/token?client_id=[YOUR CLIENT ID]&client_secret=[YOUR CLIENT SECRET]&code=[CODE FROM PREVIOUS STEP]&grant_type=authorization_code&redirect_uri=[YOUR REDIRECT URI]に移動して、この「コード」を「更新トークン」に変換します。結果の値をプログラムに直接保存できます。明示的に取り消されない限り、期限切れになることはありません。 (@ BrianWhiteによって挿入されたこのステップ-コメントを参照)POSTを使用していることを確認してください。(Gintasによって挿入)

  5. コードで、BasicNameValuePairs https://accounts.google.com/o/oauth2/token"grant_type","refresh_token""client_id",[YOUR CLIENT ID]"client_secret",[YOUR CLIENT SECRET]を使用して"refresh_token",[YOUR REFRESH TOKEN]にHttpPostリクエストを送信します。例として here を見てください。おそらくAsyncTaskを使用して、別のスレッドでこれを行う必要があります。これはJSONObjectを返します。

  6. 返されたJSONObjectからアクセストークンを取得します。例として here を見てください。文字列「access_token」を取得する必要があります。アクセストークンは1時間で期限切れになります。

  7. コードで、HttpGetリクエストをhttps://www.googleapis.com/androidpublisher/v1/applications/[YOUR APP'S PACKAGE NAME]/subscriptions/[THE ID OF YOUR PUBLISHED SUBSCRIPTION FROM YOUR Android DEVELOPER CONSOLE]/purchases/[THE PURCHASE TOKEN THE USER RECEIVES UPON PURCHASING THE SUBSCRIPTION]?accesstoken="[THE ACCESS TOKEN FROM STEP 4]"に送信します。例として here を見てください。

40
Kalina

。NETユーザー:この答えが誰かの悲しみを救ってくれることを願っています。

@Christophe Fondacciが2015年に述べたように、承認されたソリューションは数年前にうまく機能しました。現在は2017年であり、プロセスははるかに簡単で高速です

私の使用例は、アプリ内サブスクリプションを検証することです。モバイルアプリは、サブスクリプション購入情報をRESTfulサーバーに送信し、RESTfulサーバーは、Googleに連絡してサブスクリプション購入を検証します。

戦略は、ユーザーに代わって動作するサービスアカウントを作成することです。

  1. Google Play Dev Console にサインインし、セットアップするアプリをクリックします。
  2. 訪問設定->APIアクセス
  3. Service Accountsで、Create Service Accountボタンをクリックします。
  4. 2017年1月の時点で、サービスアカウントの設定に関する指示を含むダイアログが表示されます。ダイアログからGoogle API Consoleに移動します。そこから、

    A)Create Service Accountをクリックします

    B)意味のあるサービスアカウント名を作成します。 Androidパブリッシャーサービスへのアクセスに関心があるため、「パブリッシャー」を選択しました。

    C)役割については、何かを選択します-これは後で変更できます。

    D).Net実装の場合は、「新しい秘密鍵の提供」を選択し、P12を選択します。このファイルを紛失しないでください!

5)これで#4は完了です。新しいサービスアカウントが一覧表示されます。 [アクセスを許可]をクリックして有効にします。

6)「表示権限」へのリンクをタップします。ニーズとAPIに基づいて権限を変更する必要があります。

アプリ内購入を検証するには、Cog-> Change Permissionsにアクセスし、GLOBAL "Visiblity"および "Manage Orders"権限を有効にします。

これで、Google側ですべての設定が完了しました。次に、サーバー間をセットアップします。 .Net Consoleアプリを作成して実装をテストし、必要に応じてオフロードすることをお勧めします。

1)Android Nugetのパブリッシャークライアントライブラリを追加します

PM> Install-Package Google.Apis.AndroidPublisher.v2

2)P12ファイルをプロジェクトのルートに追加します

3)「ビルドアクション」が「コンテンツ」で、「出力ディレクトリにコピー」が「新しい場合はコピー」になるようにP12プロパティを変更します。

4)このようなものを実装して、アクセスをテストし、微調整します。

using System.Threading.Tasks;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Services;
using Google.Apis.Auth.OAuth2;
using Google.Apis.AndroidPublisher.v2;
...
public Task<SubscriptionPurchase> GetSubscriptionPurchase(string packageName, string productId, string purchaseToken)
{
    var certificate = new X509Certificate2(
                    "{{your p12 file name}}",
                    "{{ your p12 secret }}",
                    X509KeyStorageFlags.Exportable
                );
    var credentials = new ServiceAccountCredential(
            new ServiceAccountCredential.Initializer("{{ your service account email }}")
            {
                Scopes = new[] { AndroidPublisherService.Scope.Androidpublisher }
            }.FromCertificate(certificate))
            ;

    var service = new AndroidPublisherService(new BaseClientService.Initializer()
    {
        HttpClientInitializer = credentials,
        ApplicationName = "my server app name",
    });
    return service.Purchases.Subscriptions.Get(packageName, productId, purchaseToken).ExecuteAsync();
}

幸運を祈ります。これが誰かの役に立てば幸いです。

出典:

OAuthサーバー間アプリケーションの2.0)を使用する

Google.Apis.AndroidPublisher.v2の.Netクライアントライブラリ

14
RamblinRose

あなたが私のようなもので、[〜#〜] php [〜#〜]でこれを実行したい場合は、以下の手順に従ってください... Kalinaの回答のおかげで、それがどのように機能するかを理解するのに3日しかかかりませんでした:).

ここに行く:

  1. google開発者コンソール https://console.developers.google.com/ に移動し、Webアプリを作成します。 「developers.google.com/oauthplayground」を「リダイレクトURI」として配置します。手順2で使用します。アカウントを作成すると、クライアントIDとクライアントシークレットが取得されます。 Google Play Android Developer APIが追加されていることを確認してください。

  2. google oauth2プレイグラウンド https://developers.google.com/oauthplayground/ に移動します。この素晴らしいツールは、今後数日間のあなたの親友です。次に、設定に移動します:Use your own OAuth credentialsis seted。then only you you fill yourクライアントIDおよびクライアントシークレット以下の形式。

  3. Google oauth2 playgroundで、手順1に進みますAPIを選択して承認します入力します入力フィールドのスコープhttps://www.googleapis.com/auth/androidpublisher私はGoogle Playを見つけることができませんでしたAndroid開発者APIはリストにあります。後で追加される可能性があります。AUTORIZE APIS次の承認を行います。

  4. Google oauth2 playgroundで、手順2に進みますトークンの認証コードを交換します。問題がなければ、/ 4で始まる認証コードが表示されます。うまくいかなかった場合は、右側のエラーメッセージを確認してください。次に、「アクセストークンの更新」を押します。更新トークンをコピーします.../1で始まります...

  5. これで、いつでもアクセストークンを取得できます。ここに方法があります:

    $url ="https://accounts.google.com/o/oauth2/token";
    $fields = array(
       "client_id"=>"{your client id}",
       "client_secret"=>"{your client secret}",
       "refresh_token"=>"{your refresh token 1/.....}",
       "grant_type"=>"refresh_token"
    );
    
    $ch = curl_init($url);
    
    //set the url, number of POST vars, POST data
    curl_setopt($ch, CURLOPT_POST,count($fields));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    //execute post
    $lResponse_json = curl_exec($ch);
    
    //close connection
    curl_close($ch);
    

これでACCESS TOKENができました... JSONは次のようになります。

"access_token" : "{the access token}",  "token_type" : "Bearer",  "expires_in" : 3600

最後に、Googleに何か質問する準備が整いました。これを行う方法は次のとおりです。

$lAccessToken = "{The access token you got in}" ;
$lPackageNameStr = "{your apps package name com.something.something}";
$lURLStr =  "https://www.googleapis.com/androidpublisher/v1.1/applications/$lPackageNameStr/subscriptions/$pProductIdStr/purchases/$pReceiptStr";

$curl = curl_init($lURLStr);

curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 
$curlheader[0] = "Authorization: Bearer " . $lAccessToken;
curl_setopt($curl, CURLOPT_HTTPHEADER, $curlheader);

$json_response = curl_exec($curl);
curl_close($curl);

$responseObj = json_decode($json_response,true);

返されるJSONには、initiationTimestampMsecvalidUntilTimestampMsecサブスクリプションが有効な時間の2つのタイムスタンプが含まれます。どちらもミリ秒のnrであり、日付を1/1/1970に追加します。

8
Rudolfwm

2012年はわかりませんが、2015年は手動でこれらの手順を実行しないでください。ドキュメントを見つけるのに非常に苦労したので、誰かに役立つ場合に備えてここに投稿します。

  1. セキュリティ上の理由から、サーバーからのアプリ内購入のクエリのみを行う必要があります。そうしないと、購入プロセスの両端を信頼できないためです。

サーバー側で(絶対に必要な場合は、アプリから同じコードを使用できると思います)、google-api-services-androidpublisherクライアントライブラリをプロジェクトに含めます( https://developers.googleを参照)。 .com/api-client-library/Java/apis/androidpublisher/v1

おっしゃったように、P12ファイルのサービスアカウントが必要です(クライアントライブラリはP12ファイルのみを受け入れます)。

次に、次のコードが認証され、購入情報を適切に取得します。

    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    JsonFactory jsonFactory = new JacksonFactory();

    List<String> scopes = new ArrayList<String>();
    scopes.add(AndroidPublisherScopes.ANDROIDPUBLISHER);

    Credential credential = new GoogleCredential.Builder().setTransport(httpTransport).setJsonFactory(jsonFactory)
            .setServiceAccountId(googleServiceAccountId)
            .setServiceAccountPrivateKeyFromP12File(new File(googleServicePrivateKeyPath))
            .setServiceAccountScopes(scopes).build();
    AndroidPublisher publisher = new AndroidPublisher.Builder(httpTransport, jsonFactory, credential).build();
    AndroidPublisher.Purchases purchases = publisher.purchases();
    final Get request = purchases.get(packageName, productId, token);
    final SubscriptionPurchase purchase = request.execute();

    // Do whatever you want with the purchase bean

Javaクライアント認証に関する情報はここにあります: https://developers.google.com/identity/protocols/OAuth2ServiceAccount

6

承認された投稿の最終ステップ(#7)で問題が発生している場合、?access_token=ではなく?accessToken=が機能することがわかりました

スタックオーバーフローが悪すぎると、スレッドに直接コメントを付けることができません...

2
Butch128

あなたの質問を誤解しているかもしれませんが、あなたが参照しているリンクを使用してAndroidアプリが動作するようにアプリ内課金を取得する理由はわかりません。このページは非常に重要ですより役立つ:

http://developer.Android.com/guide/google/play/billing/index.html

含まれているデモアプリケーションを試すことができます(ダンジョン (http://developer.Android.com/guide/google/play/billing/billing_integrate.html#billing-download )。それはサブスクリプションではなく製品(1回限りの購入)を使用しますが、必要なものをテストするように変更できるはずです。

重要なのは、Google Playアカウントにアプリのサブスクリプションがあるかどうかを確認するためにサンプルで提供しているrestoreTransactionsメソッドだと思います。

@Override
public void onRestoreTransactionsResponse(RestoreTransactions request, int responseCode) {
    if (responseCode == BillingVars.OK) {                        
        // Update the shared preferences so that we don't perform a RestoreTransactions again.
        // This is also where you could save any existing subscriptions/purchases the user may have.
        SharedPreferences prefs = getSharedPreferences(my_prefs_file, Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = prefs.edit();
        edit.putBoolean(DB_INITIALIZED, true);
        edit.commit();
    } else {
        Log.e(TAG, "RestoreTransactions error: " + responseCode);
    }
}
2
Allison

アプリが呼び出すことができるWebサービスがあるので、秘密鍵をサーバーに安全に保存することをお勧めします。アプリ内のものを可能な限りサービスコールに移動する必要があります。 このリンク を参照してください。アプリ内サブスクリプションを実装しましたが、APIのこの部分がリリースされる前でした。私は独自の登録とセキュリティ検証を行う必要がありましたが、このAPIはOAuthを使用してほとんどのことを実行しているようですが、サブスクリプションのリクエスト/検証を保存する責任があるようです。

既存のライブラリでJWTに署名することについて説明している場合、それらはJavaライブラリ、Pythonライブラリ、およびPHPライブラリへのリンクを提供しているように見えます-Webサービスまたはサーバーコンポーネントの記述内容(私の場合はC#なので、RSACryptoServiceProviderを使用しています)は、署名された購入を確認するためのものです。実際のデータ転送にはJSONオブジェクトを使用しています。

1
John J Smith