SP-APIについて前回はとにかく動かしてみるというブログを書きましたが、こちらへのアクセス数がそれなりにあり需要がありそうなので、引き続きSP-APIについてブログを執筆したいと思います。
今回はJavaでのSP-API実装についてです。
アマゾンが提供するJava、SP-APIライブラリを利用すると認証部分が実装されているので、リフレッシュトークンさえあれば、アクセストークンの再取得を全く意識する必要がないためとても楽です。
逆にこれを利用しないで認証部分をスクラッチで作るとなると相当の開発コストがかかると思うのでJavaでSP-APIを利用する場合はアマゾンから提供されているライブラリ利用しましょう
JavaでのSP-API実装はSP-APIのマニュアル通りに進めれば、アマゾンが提供するSP-API、Javaライブラリの生成までは比較的簡単に行えます。
アマゾンのマニュアルにしては難易度低いなと思って進めていくと、やっぱりアマゾン、トラップあります。
相変わらずマニュアル通りに行っていくと動かない〜なぜだ〜、となりました。(泣
この記事を読んでいただいて、誰もがJavaプログラムでSP-APIを呼び出して実行できるようになっていただければと思います。
1.前提条件
この記事を進めるうえでの前提条件としてはJavaの知識がありライブラリを読み込ませて実行が行えること、WindowsPCでJavaが動作することが前提です。
2.SwaggerでのAmazon、SP-APIライブラリ生成
最初にSwaggerでのアマゾンライブラリの生成です。
Mavenでサクッとjarライブラリ取得ではなく、Swaggerでのライブラリ生成となるため、手間がかかります。
私自身Swaggerというのが今回初めてなので利点などはまったくわかっていませんが、Mavenでサクッとライブラリダウンロードできれば楽なのにと思うのですが、技術の進歩についてけてないだけかもしれません。
コード生成の方法はアマゾンのSP-APIのマニュアルの以下に記載されています。
マニュアルに記載されていますが、とりあえずこのようにやっていけばOKというのを以下に記載していきます。
2-1. Swaggerダウンロード
ブラウザーに以下URLを張り付けてアマゾンSP-APIのライブラリを生成するために、swagger-codegen-cli-2.4.13.jarをダウンロードします。
https://repo1.maven.org/maven2/io/swagger/swagger-codegen-cli/2.4.13/swagger-codegen-cli-2.4.13.jar
2-2. SP-API定義取得
次にSP-APIのライブラリを生成するために、定義になるモデルを取得します。
モデル一覧は以下マニュアルで確認できます。
https://developer-docs.amazon.com/sp-api/page/sp-api-models
アマゾンSP-APIのmodel自体はgitで取得可能
https://github.com/amzn/selling-partner-api-models/
git利用してない方は直接json取得してください。
2-3 . SP-SPI、Javaライブラリ生成
ここで取得したmodel、アマゾンSP-APIの定義データのjsonファイルを利用しSP-APIのJavaライブラリを生成します。
今回は注文情報取得をSP-APIで行ってみます。
Cドライブ直下に、SwaggerToCLと言う名前のフォルダーを作成し、上記でダウンロードしたjar、swagger-codegen-cli-2.4.13.jarを置き以下コマンドをコマンドプロンプトから実行します。
置き場所やフォルダー名変えた場合はコマンドを適時変更してください。
java -jar C:\SwaggerToCL\swagger-codegen-cli-2.4.13.jar generate -i C:\SwaggerToCL\ordersVO.json -l java -o C:\SwaggerToCL\ordersV0_JavaCL --api-package com.amazon.client --api-package com.amazon.client.orders_vo --model-package com.amazon.client.orders_vo
上記コマンドでは、C:\SwaggerToCL\ordersV0_JavaCLフォルダーにパッケージ名com.amazon.client.orders_voとしてordersVOのライブラリを生成しています。
以下に設定したパッケージ名でライブラリが生成されています。
C:\SwaggerToCL\ordersV0_JavaCL\src\main\java\
この生成されたライブラリをJavaで読み込んで利用します。
3.Java、SP-API認証ライブラリの生成(2023/09/14追記)
各API機能のライブラリは「2.SwaggerでのAmazon、SP-APIライブラリ生成」で作成されましたが、実際の認証を行う部分のライブラリは別途作成が必要です。
記載していなかったので追記しました。
以下gitからselling-partner-api-modelsをダウンロードして認証用のjarファイルを作成します。
https://github.com/amzn/selling-partner-api-models
gitからチェックアウトでも、zipでダウンとロードどちらでもOKです。
チェックアウト、もしくは展開した以下のフォルダに移動します。
C:\selling-partner-api-models-main\clients\sellingpartner-api-aa-java\
ここで「mvn package」コマンドを実行します。
コマンド実行により、同じフォルダにtargetフォルダが生成され、
sellingpartnerapi-aa-java-1.0.jar
sellingpartnerapi-aa-java-1.0-jar-with-dependencies.jar
の2つのjarファイルが生成されます。
sellingpartnerapi-aa-java-1.0-jar-with-dependencies.jarは依存関係のあるライブラリのclassも含まれるためこちらをライブラリに追加すればそのまま利用できます。
ただし自分の環境ではslack-apiと相性が悪いようでsellingpartnerapi-aa-java-1.0-jar-with-dependencies.jarを利用しmavenでwarを作ってtomcatにデプロイした場合にslack通知がエラーも出さずに処理が止まるという状態になってしまいました。
warではなく手動で配置したり、展開されたwarのライブラリだけ一旦別の場所にコピーして戻すと正常に動作したりと、中身がまったく一緒なのにmavenでwarにした場合だけslack-apiが動かなくなるという原因不明の問題が発生してしまいかなり嵌ってしまいました。
仕方が無いのでsellingpartnerapi-aa-java-1.0.jar利用として必要なライブラリは別途pomに追加でwarにしたところ問題なくslack-apiも動作するようになりました。原因は特定できませんでしたが、どうやらokhttp回りが問題を起こしているようです。
4.Java、SP-APIライブラリを使用して注文情報を取得してみる
今回生成されたのはordersVOということで注文関連のライブラリになります。
他の機能のSP-APIが利用したい場合は、2-2.で行った手順でそれぞれの機能が定義されているjsonを利用してswaggerのgenerateでコードを生成します。
では実際に生成したSP-APIの注文ライブラリを使用して注文を取得してみます。
今回のトラップポイントですが、認証部分をアマゾンのマニュアル通り書いてもエラーになりなぜか動きません。試せるだけ試して試行錯誤の結果動きました。ロール権限の設定とかでアマゾンのマニュアル通りで動くのかもしれませんが、よくわかりません。
注文取得ソースは以下です。
import com.amazon.SellingPartnerAPIAA.AWSAuthenticationCredentials;
import com.amazon.SellingPartnerAPIAA.LWAAuthorizationCredentials;
import com.amazon.client.ApiException;
import com.amazon.client.orders_vo.GetOrdersResponse;
import com.amazon.client.orders_vo.Order;
import com.amazon.client.orders_vo.OrderList;
import com.amazon.client.orders_vo.OrdersV0Api;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import org.json.JSONObject;
/**
 * Amazon、SP-API受注取得
 *
 */
public class AmazonSpAPIGetOrder {
  public static String END_POINT = "https://api.amazon.com/auth/o2/token"; // SP-APIのエンドポイント、規定値
  public static String MAKET_PLACE_ID = "A1VC38T7YXB528"; // 日本だとこの値
  public static String REGION = "us-west-2"; // 日本だとこの値
  // リフレッシュトークン: Amazonの新しいAPI、SP-APIをとにかく動かしてみる 3-5. のリフレッシュトークン値
  public static String REFLESH_TOKEN = "Atzr|IwEBIABHaXRPj86Ei3xPolpsRT*************************************************************************************************************************************************************************************************************************************************************************************************************";// IAM
  // クライアントID: Amazonの新しいAPI、SP-APIをとにかく動かしてみる 3-7. のクライアントIDの値
  public static String CLIENT_ID = "amzn1.application-oa2-client.********************************";
  // クライアント機密情報: Amazonの新しいAPI、SP-APIをとにかく動かしてみる 3-5. のクライアント機密情報の値
  public static String CLIENT_SECRET = "e97cd855********************************************************";
  // アクセスキーID: Amazonの新しいAPI、SP-APIをとにかく動かしてみる 1-6. アクセスキーIDの値
  public static String ACCESS_KEY = "AKIA6***************";
  // シークレットアクセスキー: Amazonの新しいAPI、SP-APIをとにかく動かしてみる 1-6. シークレットアクセスキーの値
  public static String SECRET_ID = "Zuh069DUjSU/****************************";
  public static void main(String [] args) {
    getOrder();
  }
  /**
   * 受注取得
   *
   */
  private static void getOrder() {
    try {
      // 認証処理、認証処理は全てのSP-API呼び脱しで共通
      AWSAuthenticationCredentials awsAuthenticationCredentials = AWSAuthenticationCredentials.builder()
                                                                  .accessKeyId(ACCESS_KEY)
                                                                  .secretKey(SECRET_ID)
                                                                  .region(REGION)
                                                                  .build();
      LWAAuthorizationCredentials lwaAuthorizationCredentials = LWAAuthorizationCredentials.builder()
          .clientId(CLIENT_ID)
          .clientSecret(CLIENT_SECRET)
          .refreshToken(REFLESH_TOKEN)
          .endpoint(END_POINT)
          .build();
/*
      // SP-APIマニュアルに記載のロールとかwithScopesとか設定して試してみたが動かない。
      AWSAuthenticationCredentialsProvider awsAuthenticationCredentialsProvider = AWSAuthenticationCredentialsProvider.builder()
                                                                                  .roleArn("arn:aws:iam::649319782322:user/sp-api") // IAM/セラーセントラル
                                                                                  .roleSessionName("123123123")
                                                                                  .build();
      LWAAuthorizationCredentials lwaAuthorizationCredentials = LWAAuthorizationCredentials.builder()
                                                                .clientId(CLIENT_ID)
                                                                .clientSecret(CLIENT_SECRET)
                                                                .withScopes(SCOPE_NOTIFICATIONS_API, SCOPE_MIGRATION_API)
                                                                .endpoint(END_POINT) // 日本
                                                                .build();
*/
      // 受注取得処理
      List<String> marketplaceIds = new ArrayList<String>();
      marketplaceIds.add(MAKET_PLACE_ID);
      OrdersV0Api ordersApi = new OrdersV0Api.Builder()
          .awsAuthenticationCredentials(awsAuthenticationCredentials)
          .lwaAuthorizationCredentials(lwaAuthorizationCredentials)
          .endpoint("https://sellingpartnerapi-fe.amazon.com")
          .build();
      List<String> orderStatuses = new ArrayList<String>();
      String lastUpdateAfter = "2023-02-25 14:14:00";
      SimpleDateFormat format = new SimpleDateFormat();
      format.applyPattern("yyyy-MM-dd HH:mm:ss");
      Date date = format.parse(lastUpdateAfter);
      // 日付フォーマットをSP-APIに合わせる
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXX");
      sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
      String tempLastUpdatedAfter = sdf.format(date.getTime());
      // 受注リスト取得
      GetOrdersResponse respOrders = ordersApi.getOrders(marketplaceIds, "", null, tempLastUpdatedAfter, "", orderStatuses, null, null, "", "", 100, null, "", null, "", false, "");
      OrderList orderList = respOrders.getPayload().getOrders();
      for (Order order: orderList) {
        System.out.println(order.getAmazonOrderId());
        System.out.println(order.getLastUpdateDate());
      }
    } catch (ApiException e) {
      // SP-APIのエラー情報はApiExceptionで返却される
      e.printStackTrace();
      String code = "";
      String message = "";
      try {
        JSONObject jsonObject = new JSONObject(e.getResponseBody());
        JSONObject error = jsonObject.getJSONArray("errors").getJSONObject(0);
        code = error.getString("code");
        message = error.getString("message");
        System.out.println("code=" + code);
        System.out.println("message=" + message);
      } catch (Exception ee) {
        ee.printStackTrace();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
Eclipseなどで、生成したSP-APIライブラリを取り込んで、認証情報の値を適時変更してもらって、動作させれば、注文の取得が行えます。
少しでもSP-APIで困ってる人のお役に立てれば幸いです。
	
      

