API との接続を 1 週間以上確立しようとしてきましたが、うまくいきません。(Magic Card Market の、あちこちに認証ドキュメントがあります)。XMLファイルを受け取ることになっています。
私は、MCM が API への「ウィジェット」アクセスと呼んでいるものを持っています。つまり、認証ヘッダー用の oauth_token (空の文字列であるはずです) を持っていないか必要とせず、受け取ったり使用したりすることは想定されていません。アクセス トークン/アクセス シークレット。
私が持っているのは、コンシューマ キー (アプリ トークンと呼ばれることもあります) とコンシューマ シークレットだけです。
Authorization ヘッダーを作成する方法は次のとおりです。
private static String buildOAuthAuthorization(String method, String request)
throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
String mkmAppToken = APICredentials.appToken;
String mkmAppSecret = APICredentials.appSecret;
String realm = "https://www.mkmapi.eu/ws/v1.1/games";
String oauthVersion = "1.0";
String oauthConsumerKey = mkmAppToken;
String oauthToken = "";
String oauthSignatureMethod = "HMAC-SHA1";
String oauthTimestamp = Long.toString(System.currentTimeMillis() / 1000);
String oauthNonce = Long.toString(System.currentTimeMillis());
String paramString = "oauth_consumer_key=" + oauthConsumerKey
+ "oauth_nonce=" + oauthNonce
+ "oauth_signature_method=" + oauthSignatureMethod
+ "oauth_timestamp=" + oauthTimestamp
+ "oauth_token=" + oauthToken
+ "oauth_version=" + oauthVersion;
String baseString = method + "&" + rawUrlEncode(realm) + "&" + rawUrlEncode(paramString);
String signingKey = rawUrlEncode(mkmAppSecret) + "&";
Mac mac = Mac.getInstance("HMAC-SHA1");
SecretKeySpec secret = new SecretKeySpec(signingKey.getBytes(), mac.getAlgorithm());
mac.init(secret);
byte[] digest = mac.doFinal(baseString.getBytes());
byte[] oauthSignature = Base64.encode(digest, Base64.URL_SAFE);
String authorizationProperty = "OAuth "
+ "realm=\"" + realm + "\", "
+ "oauth_version=\"" + oauthVersion + "\", "
+ "oauth_timestamp=\"" + oauthTimestamp + "\", "
+ "oauth_nonce=\"" + oauthNonce + "\", "
+ "oauth_consumer_key=\"" + oauthConsumerKey + "\", "
+ "oauth_token=\""+ oauthToken + "\", "
+ "oauth_signature_method=\"" + oauthSignatureMethod + "\", "
+ "oauth_signature=\"" + oauthSignature + "\"";
System.out.println(authorizationProperty);
return authorizationProperty;
}
実際のリクエストは AsyncTask にあります。
public static class oAuthRequest extends AsyncTask<String, Integer, StringReader> {
private int lastCode;
@Override
protected StringReader doInBackground(String... requestURLs) {
String method = requestURLs[0];
String url = requestURLs[1];
StringReader result = null;
try {
String authProperty = buildOAuthAuthorization(method, url);
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.addRequestProperty("Authorization:", authProperty);
lastCode = connection.getResponseCode();
System.out.println("RESPONSE CODE 1 " + lastCode);
// Get content
BufferedReader rd = new BufferedReader(new InputStreamReader(lastCode == 200 ? connection.getInputStream() : connection.getErrorStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
result = new StringReader(sb.toString());
} catch (NoSuchAlgorithmException | InvalidKeyException | IOException e) {
e.printStackTrace();
}
return result;
}
}
何を変更しても、常に 401 が返されるようです。
私が試したこと:
- Base64.encodeToString() を使用した文字列としての oauthSignature
- SecureRandom を使用したノンス生成
- 空の oauthToken の有無にかかわらず
- 別のタイムスタンプ生成方法 (覚えていませんが)
- アプリ トークンを使用する場合と使用しない場合の署名キー (理論的にはコンシューマー シークレットのみが必要ですが、わかりません)
- HttpURLConnection の代わりに HttpsURLConnection を使用する (URI は https で始まるので、ちょっと考えましたが、違います)
- 少なくとも 2 ~ 3 の他の異なる実装 (もちろん、基本的にはドキュメントの Java の例をコピー/貼り付けしたものでしたが、今でも 1 つです)
- (覚えてないこともたくさんあると思います)
この時点で、Postman アプリを使用して同じ結果のリクエストをテストしようとしたため、問題が私のキーに起因するのではないかと考えています。