GoogleのAppEnginewithJavaでサブスクリプションのステータスを確認したい方のために、SOで見つかった多くのコードに基づいた私の作業例を次に示します。私は経験不足によって引き起こされた多くの間違いを解決するために数日を費やしました。サーバーでサブスクリプションのステータスを確認するための提案がたくさんありますが、AppEngineで行うのは簡単ではありませんでした。SOで答えが見つからなければ、私はこれを思い付くことができませんでした。
ステップ1
まず、Webブラウザーからコードを取得するまで、JonathanNaguinの回答にある「前提条件」セクションを確認する必要があります。今、あなたは持っています。
- クライアントID
- クライアントシークレット
- URIをリダイレクトする
- コード
準備。
以下に示すすべてのコードをAppEngineで実行することに注意してください。そして、私はこのようなロガーを使用しました。
static final Logger log = Logger.getLogger(MyClassName.class.getName());
ステップ2
更新トークンを取得する必要があります。[YOUR CLIENT ID]、[YOUR CLIENT SECRET]、[YOUR CODE]、[YOUR REDIRECT URI]を文字列に置き換えて、以下のコードを実行してください。
private String getRefreshToken()
{
try
{
Map<String,Object> params = new LinkedHashMap<>();
params.put("grant_type","authorization_code");
params.put("client_id",[YOUR CLIENT ID]);
params.put("client_secret",[YOUR CLIENT SECRET]);
params.put("code",[YOUR CODE]);
params.put("redirect_uri",[YOUR REDIRECT URI]);
StringBuilder postData = new StringBuilder();
for(Map.Entry<String,Object> param : params.entrySet())
{
if(postData.length() != 0)
{
postData.append('&');
}
postData.append(URLEncoder.encode(param.getKey(),"UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()),"UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
URL url = new URL("https://accounts.google.com/o/oauth2/token");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.getOutputStream().write(postDataBytes);
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuffer buffer = new StringBuffer();
for (String line = reader.readLine(); line != null; line = reader.readLine())
{
buffer.append(line);
}
JSONObject json = new JSONObject(buffer.toString());
String refreshToken = json.getString("refresh_token");
return refreshToken;
}
catch (Exception ex)
{
log.severe("oops! " + ex.getMessage());
}
return null;
}
更新トークンは期限切れにならないため、どこかに保存するか、コードにハードコーディングするだけです。(更新トークンを取得するには、上記のコードを1回実行するだけで済みます。)
ステップ3
アクセストークンを取得する必要があります。[YOUR CLIENT ID]、[YOUR CLIENT SECRET]、[YOUR REFRESH TOKEN]を文字列に置き換えて、以下のコードを実行します。
private String getAccessToken()
{
try
{
Map<String,Object> params = new LinkedHashMap<>();
params.put("grant_type","refresh_token");
params.put("client_id",[YOUR CLIENT ID]);
params.put("client_secret",[YOUR CLIENT SECRET]);
params.put("refresh_token",[YOUR REFRESH TOKEN]);
StringBuilder postData = new StringBuilder();
for(Map.Entry<String,Object> param : params.entrySet())
{
if(postData.length() != 0)
{
postData.append('&');
}
postData.append(URLEncoder.encode(param.getKey(),"UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()),"UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
URL url = new URL("https://accounts.google.com/o/oauth2/token");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.getOutputStream().write(postDataBytes);
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuffer buffer = new StringBuffer();
for (String line = reader.readLine(); line != null; line = reader.readLine())
{
buffer.append(line);
}
JSONObject json = new JSONObject(buffer.toString());
String accessToken = json.getString("access_token");
return accessToken;
}
catch (Exception ex)
{
log.severe("oops! " + ex.getMessage());
}
return null;
}
ステップ4
私が知りたかったのは、サブスクリプションのUTCを期限切れにすることです。以下に示すコードは、期限切れのUTCを返し、エラーが見つかった場合は0を返します。パッケージ名、製品ID(=サブスクリプションID)、ステップ3で取得したアクセストークン、および購入データにある購入トークンを提供する必要があります。
private long getExpireDate(String packageName,String productId,String accessToken,String purchaseToken)
{
try
{
String charset = "UTF-8";
String query = String.format("access_token=%s",URLEncoder.encode(accessToken,charset));
String path = String.format("https://www.googleapis.com/androidpublisher/v1/applications/%s/subscriptions/%s/purchases/%s",packageName,productId,purchaseToken);
URL url = new URL(path + "?" + query);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestProperty("Accept-Charset",charset);
connection.setRequestMethod("GET");
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuffer buffer = new StringBuffer();
for(String line = reader.readLine(); line != null; line = reader.readLine())
{
buffer.append(line);
}
JSONObject json = new JSONObject(buffer.toString());
return json.optLong("validUntilTimestampMsec");
}
catch (Exception ex)
{
log.severe("oops! " + ex.getMessage());
}
return 0;
}
製品IDまたはサブスクリプションIDは、開発者コンソールにある文字列であることに注意してください。サブスクリプションアイテムが名前/ID列とともに表示されます。こんな感じです。
Description of item(product id)
最後のステップ(楽しい部分)
これで、サブスクリプションが有効かどうかを確認するためのすべてのコンポーネントができました。私はこれが好きでした。[あなたのパッケージ名]、[あなたの製品ID]をあなたのものに置き換える必要があります。
iabHelperコードにあるPurchase#getOriginalJson()で取得できる購入データを提供する必要があります。
private boolean checkValidSubscription(String purchaseData)
{
String purchaseToken;
JSONObject json;
try
{
json = new JSONObject(purchaseData);
}
catch (JSONException e)
{
log.severe("purchaseData is corrupted");
return true; // false positive
}
purchaseToken = json.optString("purchaseToken");
if(purchaseToken.length() == 0)
{
log.severe("no purchase token found");
return true; // false positive
}
String accessToken = getAccessToken();
if(accessToken == null)
{
return true; // false positive
}
long expireDate = getExpireDate([YOUR PACKAGE NAME],[YOUR PRODUCT ID],accessToken,purchaseToken);
if(expireDate == 0)
{
log.severe("no expire date found");
return true; // false positive
}
expireDate += 86400000l; // add one day to avoid mis judge
if(expireDate < System.currentTimeMillis())
{
log.severe("subscription is expired");
return false;
}
// just for log output
long leftDays = (expireDate - System.currentTimeMillis()) / 86400000l;
log.info(leftDays + " days left");
return true;
}
デバッグに関する注意
Googleは応答用にJSON文字列を返します。コードが期待どおりに機能しない場合は、JSON文字列をログに記録すると何が問題なのかを理解するのに役立つ場合があります。
これが誰かに役立つことを願っています。