開発者向けサポート

チュートリアル

  1. はじめに
  2. 開発用サイトの登録
  3. Appsの登録
  4. ebisumartライブラリのダウンロード
  5. Appsの開発

はじめに

このチュートリアルはJava、ServletによるWebアプリケーション開発を理解している開発者を対象としています。
このチュートリアルはパートナー登録後の開発者がebisumartライブラリを使用してアプリケーションの開発を行う際の流れを示し、設計、開発をスムーズに行えるよう支援します。

開発用サイトの登録(既に利用できるサイトがある場合、この操作は不要です。)

Apps作成後にAppsをインストールしてテストを行うための開発用サイトを作成します。
※開発用サイトでは初期設定では受注が100件までしか登録できません。制限に達した場合はお問い合わせください。

パートナーサイトの開発用サイト設定画面で新規登録ボタンを押下し、開発用サイト登録画面を開いてください。

ebisumartNo、サイト名称を入力し、確認を押下してください。

確認画面で登録を押下してください。
登録を押下してから完了までに数十秒かかります。

登録が完了すると、開発サイト一覧画面に戻ります。

Appsの登録

Appsの登録を参考にして登録を行ってください。

Apps登録後、Apps一覧から対象のAppsの「パスワード表示」を押下し、パスワードを確認してください。

ebisumartへAppsの認証を行う際、このパスワードが必要となります。

ebisumartライブラリのダウンロード

パートナーサイトから「ebisumartライブラリ」をダウンロードしてください。このライブラリがJavaでのApps開発を支援します。
ebisumartライブラリを使用したAppsのサンプルコードをダウンロードして、チュートリアルと合わせてご参照ください。

Appsの開発

Appsの開発について以下の流れで説明します。

  1. ebisumartへのAppsのインストール
  2. ebisumartのフックからのApps呼び出し(サーバ処理の場合)
  3. ebisumartのフックからのApps呼び出し(画面テンプレートの場合)
  4. Appsからebisumartのデータにアクセス

まず、最初に各処理共通で使用する通信用のデータを持つ処理を作成します。
jp.co.test.common.DataAccessClientHolder.javaに以下の処理を記述してください。
AppsパスワードはApps管理画面で表示されたものを設定してください。


public class DataAccessClientHolder {
 private static final String APP_CD = "APP_LIB_TEST"; // Appsコード
 public static String getAppCd() {return APP_CD;}
 private static final String APP_PASS = ""; // Appsパスワード
 public static String getAppPass() {return APP_PASS;}

 // ebisumart(API呼び出し)のルートURLです。
 private static String EBISU_API_HOST = "https://service-dev.ebisumart.com/"; 
 // ebisumart(認証コード取得用)のルートURLです。
 private static String EBISU_SCREEN_HOST = "https://service-dev.ebisumart.com/";
 // ※service-dev.ebisumart.comは検証店舗用のURLになります。実際に運用する店舗ではその店舗のドメインをご使用いただきますようお願いいたします。
    
 private static volatile DataAccessClient client = null;
 // 実際はリフレッシュトークンはDB等に保持すべきですが、この例ではMapに持っています
 private static final Map refreshTokenMap = new HashMap<>();
    
 public static synchronized void initialize() {
  client = new DataAccessClient(getAppCd(), getAppPass()) {
    @Override
    /**
    * リフレッシュトークンを取得します
    * @param shopId ebisumartNo
    * @return リフレッシュトークン
    */
    public String getRefereshToken(String shopId) {
      return refreshTokenMap.get(shopId);
    }
    @Override
    /**
    * UW用のルートURLを取得します
    * @param shopId ebisumartNo
    * @return UW用のルートURL
    */          
    public String getShopRootUrlForAPI(String shopId) {
      return getShopRootUriForApi(shopId);
    }
    @Override
    /**
    * SK用のルートURLを取得します
    * @param shopId ebisumartNo
    * @return SK用のルートURL
    */
    public String getShopRootUrlForScreen(String shopId) {
      return getShopRootUriForScreen(shopId)
    }
  };
 }

 /**
 * UW用のルートURLを設定します。実際に運用する店舗ではebisumartNoの指定は不要です。
 *
 * @param shopId ebisumartNo
 * @return UW用のルートURL
 */
 private static String getShopRootUriForApi(String shopId) {
  return EBISU_API_HOST + shopId + "/";
 }

    
 /**
 * SK用のルートURLを設定します。
 *
 * @param shopId ebisumartNo
 * @return SK用のルートURL
 */
 private static String getShopRootUriForScreen(String shopId) {
  return EBISU_SCREEN_HOST + shopId + "/";
 }

 /**
 * リフレッシュトークンを保存します。
 * @param shopId ebisumartNo
 * @param refreshToken リフレッシュトークン
 */
 public static void saveRefreshToken(String shopId, String refreshToken) {
  refreshTokenMap.put(shopId, refreshToken);
 } 
 /*
 * 保持しているDataAccessClientを返します。
 * まだDataAccessClientが作成されていない場合、作成します。
 * @return DataAccessClient
 */
 public static DataAccessClient get() {
  if (client == null) {
   initialize();
  }
  return client;
 }
}
ebisumartへのAppsのインストール

Appsのインストールについて、実際の画面の遷移を交えて説明をします。
インストール処理は、サンプルソースのうち以下のソースで行います。

  • install.html
  • jp.co.test.install.InstallServlet.java

まず、Appsのインストール時にユーザが最初に開く画面を作成します。
「install.html」ファイルを作成し、以下のフォームを記述してください。


<form action="http://[domein]/app_lib_test/install">
<input type="hidden" name="request" value="install">
<p>ebisumartNo<input type="text" name="SHOP_ID"></p>
<p><input type="submit" value="INSTALL"></p>
</form>

ユーザが「install.html」でebisumartNoを入力し「INSTALL」ボタンを押すとインストール処理が始まります。

上記フォームのリクエストをAppsが受信した後、ebisumartへリダイレクトする処理を作成します。
Appsのインストールの「ebisumartへリダイレクト」にあたります。
InstallServlet.javaに以下の処理を記述してください。


@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String req = request.getParameter("request");
    String shopId = request.getParameter("SHOP_ID");
    switch (req) {
    case "install":
        // 「install」ボタンが押されたので、oauthの認証エンドポイントにリダイレクト
        StringBuilder nextUrl = new StringBuilder();
        // DataAccessClientHolder.get().getShopRootUrlForScreen(shopId)は"https://service-dev.ebisumart.com/" + shopIdを返します
        nextUrl.append(DataAccessClientHolder.get().getShopRootUrlForScreen(shopId) + "admin_authorize.html");
        nextUrl.append("?response_type=code");
        nextUrl.append("&client_id=").append("APP_LIB_TEST");
        nextUrl.append("&redirect_uri=").append(URLEncoder.encode(getRedirectUri(shopId), "UTF-8"));
        nextUrl.append("&scope=item privacy");
        nextUrl.append("&state=").append(URLEncoder.encode(STATE_DATA, "UTF-8"));
        response.sendRedirect(nextUrl.toString());
        break;
    case …

redirect_uriとして設定しているgetRedirectUri(shopId)の値は以下のURLです。


https://[domain]/app_lib_test/install?request=authorized&SHOP_ID=えびす店舗No

※redirect_uriに設定したパラメータを除くURIが、上のApps登録で設定した「リダイレクトURI」と一致している必要があります。

scopeには実行に必要な権限を指定します。
処理カスタマイズAPI、データアクセスAPIの各処理の説明ページの必要権限を確認し、必要な権限を半角スペース区切りで指定してください。
必要な権限が指定されていない場合、処理カスタマイズAPIはフックの登録時にエラーとなります。データアクセスAPIは実行時にエラーとなります。


リダイレクト後、ユーザにはebisumartのログイン画面が表示されます。 ここでユーザは利用者ID、パスワードを入力してログインします。

ログイン後、以下のように「許可」「不許可」を選択する画面が表示されます。

ユーザが「許可」を押下すると、以下の元のウィンドウは以下の画面に遷移します。

ユーザが「不許可」を押下すると、元のウィンドウは以下の画面に遷移します。

「許可」「不許可」いずれを選択した場合も、新たなウィンドウが開き、そこからAppsへリクエストが送信されます。
先のebisumartへのリダイレクト時にredirect_uriとして設定したURIにパラメータが付加されたものです。

「許可」の場合


https://[domain]/app_lib_test/install?request=authorized&SHOP_ID=ebisumartNo&state=CheckXSRF&code=認証コード

「不許可」の場合


https://[domain]/app_lib_test/install?request=authorized&SHOP_ID=ebisumartNo&state=CheckXSRF&error=access_denied

Appsでの「許可」「不許可」受信時の処理を作成します。
まず、stateのチェック(XSRF対策)、errorのチェックを行います。
その後、アクセストークンの取得・保持、インストール(フックポイントの登録)を行います。
InstallServlet.javaに以下の処理を記述してください。


@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String req = request.getParameter("request");
String shopId = request.getParameter("SHOP_ID");

switch (req) {
case …
case "authorized":
    // 認証を受けてauthorization code(もしくはエラー情報)が送られてきた 
    String msg = req + " complete";
    String code = request.getParameter("code");
    String state = request.getParameter("state");
    String error = request.getParameter("error");
    // stateが一致しない場合、errorがnullでない場合(不許可も含まれる)、エラー。
    if (!STATE_DATA.equals(state) || error != null) {
        msg = (error != null) ? (req + " " + error) : (req + " error");
        response.getWriter().println(msg);
        break;
    } 
    try {
        // アクセストークンの取得・保持
        saveTokens(shopId, code);
        // インストール(フックポイントの登録)
        install(request.getParameter("SHOP_ID"));
    } catch (Exception e) {
        e.printStackTrace();
        msg = req + " error";
    }
    response.getWriter().println(msg);
    break;


アクセストークンの取得・保持を説明します。
まず、DataAccessClient.requestAccessTokenを呼び出し、アクセストークンの取得を行います。
そして、リフレッシュトークンの保持を行ってください。リフレッシュトークンの保持についてはライブラリでは提供していないので、実装を行ってください(サンプルソースではstatic値として保持しています)。
※アクセストークンは取得後、ライブラリ内で保持・利用されるので、その後、特に気にする必要はありません。

InstallServlet.javaに以下の処理を記述してください。


private void saveTokens(String shopId, String code) throws IOException {
    // 抽象クラスDataAccessClientを実装したクラスを取得します。
    DataAccessClient client = DataAccessClientHolder.get();
    // ebisumartへの認証要求時に渡したものと同じリダイレクト先URLです。
    String redirectUrl = getRedirectUri(shopId);
    // アクセストークン、リフレッシュトークンの取得を行います。
    AccessTokenResponse atr = client.requestAccessToken(shopId, code, redirectUrl);
    // リフレッシュトークンを保存します。アクセストークンの期限が切れ、再取得を行う際に使用します。
    DataAccessClientHolder.saveRefreshToken(atr.getShopId(), atr.getRefreshToken());
}

インストール(フックポイントの登録)を説明します。
InstallerServiceクラスを使ってフックポイント(処理カスタマイズAPI)の登録を行います。
詳細については、ebisumartのフックからのApps呼び出し(サーバ処理の場合)で説明します。

InstallServlet.javaに以下の記述をしてください。


protected void install (String shopId) throws Exception {
    // 抽象クラスDataAccessClientを実装したクラスを取得します。
    // 環境に合わせたDataAccessClientの実装を行っていただく必要があります。
    DataAccessClient client = DataAccessClientHolder.get();
    // EbisumartServiceはデータアクセスAPI共通で使用します。
    EbisumartService es = new EbisumartService(shopId, client);
    // InstallerServiceは処理カスタマイズAPI、管理画面カスタマイズAPIの登録に使用します。
    InstallerService is = es.getInstallerService();
    // 登録したい処理カスタマイズAPIの情報をCustomizeApiに設定します。
    CustomizeApi ca = new CustomizeApi();
    ca.setFlowName("*");
    ca.setName(CustomizeApiFunction.Userweb_Cart_CustomizeOrderDetailData_After.path());
    ca.setUrl(APP_API_HOST + "/CartCustomizeOrderDetailData");
    
    // ebisumartへの登録開始
    // データアクセスAPIのトランザクションを開始します。
    es.startTransaction();
    try {
        // 一度、このAppsが登録していた処理カスタマイズAPIをクリア
        is.deleteCustomizeApi();
        // 処理カスタマイズAPI登録
        is.add(ca);
        // トランザクションのコミット
        es.commitTransaction();
    } catch (Exception e) {
        // トランザクションのロールバック
        es.rollbackTransaction();
    } finally {
        // トランザクションリソースの開放
        es.endTransaction();
    }
}

登録の際にはトランザクションを使用し、登録済みの処理カスタマイズAPIをすべて削除した後、登録します。
トランザクションを使用する場合、必ず最後にトランザクションリソースの開放を行ってください。

最後に、新たに開かれていたウィンドウに処理が完了したことを表示します。
Appsでの「許可」「不許可」受信時の処理の以下の記述により、インストール処理の最後でメッセージが出力されます。


String msg = req + " complete";
…
response.getWriter().println(msg);


ebisumartのフックからのApps呼び出し(サーバ処理の場合)

ebisumartのサーバ処理からAppsを呼び出す場合、処理カスタマイズAPIを使用します。
ユーザWEBからの注文時に処理カスタマイズAPIによりAppsを呼び、Appsで商品情報の自由項目1を注文明細情報の自由項目1にコピーする処理を作成します。

ユーザWEBからの注文時にAppsを呼び出すために、処理カスタマイズAPIのページからフックポイントを探します。
本処理のために注文確定処理フロー受注明細カスタマイズ(userweb/cart/customize_order_detail_data)を使います。

インストール時に行うこと

受注明細カスタマイズの必要権限がprivacyなので、インストールの「ebisumartへリダイレクト」時に設定するパラメータscopeにprivacyを加えます。

そして、フックポイントとして受注明細カスタマイズをebisumartに登録を行います。
上で示したインストール(フックポイントの登録)にて、すでに登録は完了しています。
インストール(フックポイントの登録)のCustomizeApi.setNameでフックポイントとして使用する受注明細カスタマイズを指定しています。


ca.setName(CustomizeApiFunction.Userweb_Cart_CustomizeOrderDetailData_After.path());

ebisumartは登録されたフックポイントの処理実行時、Appsに対して処理カスタマイズAPIをPOSTでリクエストします。リクエスト先はCustomizeApi.setUrlで設定したURLになります。


ca.setUrl(APP_API_HOST + "/CartCustomizeOrderDetailData");

※CustomizeApiで設定しているパラメータについては、データアクセスAPIの処理カスタマイズAPIを参照してください。

フックポイントから呼ばれるAppsの処理

この処理はサンプルソースのうち以下のソースで行います。

  • jp.co.test.customize.CustomizeApiServlet.java
  • jp.co.test.customize.CartCustomizeOrderDetailData.java

Appsに上記のリクエスト受信時の処理を作成します。
CustomizeApiServlet.javaに以下の記述をしてください。


@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // アプリケーションのパスワード
    String appPass = DataAccessClientHolder.getAppPass();
    // 処理カスタマイズAPIの処理を実行
    CustomizeApiResponse apiRes = execute(new CustomizeApiRequest(request, appPass));
    // 結果を返却します。
    respondFromReturnValue(response, apiRes);
}

// 結果をJSON形式にして返します。
void respondFromReturnValue(HttpServletResponse response, Object ret) throws IOException {
    if (ret != null) {
        PrintWriter writer = response.getWriter();
        if (ret instanceof String) {
            writer.write((String) ret);
        } else {
            JSON.encode(ret, writer);
        }
    }
    response.setStatus(HttpServletResponse.SC_OK);
}

受注明細に設定する値を変更するために、resultに変更対象の項目名(自由項目1)、値(商品の自由項目1の値)を設定します。
商品の自由項目1はリクエストパラメータのcartから取得します。(複数商品を購入した場合、cartは複数の商品情報を持っています)
※リクエスト、レスポンスのパラメータは処理カスタマイズAPIを参照してください。

CartCustomizeOrderDetailData.javaに以下の処理を記述してください。


public class CartCustomizeOrderDetailData extends CustomizeApiServlet {

    @Override
    protected CustomizeApiResponse execute(CustomizeApiRequest req) {
        CustomizeApiResponse res = new CustomizeApiResponse();

        Map<String, String> orderD = (Map<String, String>)req.getArg("order_detail");
        String itemId = orderD.get("ITEM_ID");
        
        Map<String, String> map = (Map<String, String>)req.getCurrentResult(); 
        if (map == null) {
            map = new HashMap<>();
        }
        List<CartItem> cartList = req.getCartItems();
        String freeItem1 = null;
        for(CartItem cartItem: cartList) {
            String id = cartItem.getItemIdString();
            if (!(itemId == null) && itemId.equals(id)) {
                // cartオブジェクトから商品の自由項目1を取得
                freeItem1 = cartItem.getFreeItem(1);
                break;
            }
        }
        // 受注明細の自由項目1に商品の自由項目1から取り出した値を設定
        map.put("FREE_ITEM1", freeItem1);
        res.setResult(map);
        
        return res;
    }
}

処理カスタマイズAPIの結果を受け取ったebisumartは受注明細登録時にAppsで付加した自由項目1を設定して登録を行います。

ebisumartのフックからのApps呼び出し(画面テンプレートの場合)

画面テンプレートからAppsを呼び出す場合、ビューアドオンAPIを使用します。
TOP画面テンプレートがビューアドオンAPIでAppsを呼び出し、Appsが返したデータを表示する処理を作成します。
AppsはTEST_MSG(文字列)、msgList(TEST_MSG2(文字列)のリスト)を返し、TOP画面テンプレートはそれらの値を表示します。
この処理はサンプルソースのうち以下のソースで行います。

  • jp.co.test.view.ViewApiServlet.java
  • jp.co.test.view.ViewTestMsg.java
  • userweb/top.xhtml
画面テンプレートから呼ばれるAppsの処理

ビューアドオンAPIの受信部分を作成します。
ViewApiServlet.javaに以下の処理を記述してください。


@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    request.setCharacterEncoding("UTF-8");
    // アプリケーションのパスワード
    String appPass = DataAccessClientHolder.getAppPass();
    // ビューアドオンAPIの実行
    Object apiRes = execute(new ViewAddonRequest(request, appPass));
    // 結果を返却します
    respondFromReturnValue(response, apiRes);
}

// 結果をJSON形式にして返します。
void respondFromReturnValue(HttpServletResponse response, Object ret) throws IOException {
    if (ret != null) {
        PrintWriter writer = response.getWriter();
        if (ret instanceof String) {
            writer.write((String) ret);
        } else {
            JSON.encode(ret, writer);
        }
    }
    response.setStatus(HttpServletResponse.SC_OK);
}

画面に表示する値を設定する処理を作成します。
画面に表示する値をフィールドとして持つオブジェクトを作成し、そのオブジェクトに値を設定して返します。 ViewTestMsg.javaに以下の記述をしてください。


public class ViewTestMsg extends ViewApiServlet {
    
    /**
     * レスポンス用オブジェクト
     */
    static class ResponseElement {
        public String TEST_MSG;
        public List<Msg> msgList;
    }
    
    static class Msg {
        public String TEST_MSG2;
        Msg(String msg) {
            this.TEST_MSG2 = msg;
        }
    }
    
    @Override
    protected ResponseElement execute(ViewAddonRequest req) {
        ResponseElement result = new ResponseElement();
        result.TEST_MSG = "テンプレートでTEST_MSGを指定するとこの文字列が出力されます。";
        
        result.msgList = new ArrayList<>();
        result.msgList.add(new Msg("テンプレートでTEST_MSG2を指定するとこの文字列が出力されます。1"));
        result.msgList.add(new Msg("テンプレートでTEST_MSG2を指定するとこの文字列が出力されます。2"));
        return result;
    }
}
画面テンプレートに記述する処理

まず、ビューアドオンAPIを呼び出す画面テンプレートにXMLネームスペースを記述します。
top.xhtmlのhtmlタグに以下のように記述してください。


<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://mayaa.seasar.org" xmlns:appLibTest="eb:APP_LIB_TEST/view/ViewTestMsg" xml:lang="ja" lang="ja">

APP_LIB_TESTは「Appsの登録」で設定したAppsコードになります。
ebisumartのテンプレート表示の処理の際にAPP_LIB_TESTの部分が「ビューアドオンURI」に変換されます。その結果、Appsを呼び出す際のURIは以下のようになります。


http://[domein]/app_lib_test/view/ViewTestMsg

top.xhtml内でappLibTestを指定することで、APP_LIB_TESTAppsからの返却値を表示することができます。
以下のようにAppsから受け取った値を表示する処理を記述してください。
※画面テンプレートに記述可能な定義はビューアドオンAPIを参照してください。


<p><div appLibTest:write="TEST_MSG"></div></p>
<div appLibTest:loop="msgList">
  <p><div appLibTest:write="TEST_MSG2"></div></p>
</div>

変換後のtop.xhtmlの出力結果は以下のようになります。


<p>テンプレートでTEST_MSGを指定するとこの文字列が出力されます。</p>
<div>
<p>テンプレートでTEST_MSG2を指定するとこの文字列が出力されます。1</p>
</div><div>
<p>テンプレートでTEST_MSG2を指定するとこの文字列が出力されます。2</p>
</div>
Appsからebisumartのデータにアクセス

Appsからebisumartのデータにアクセスする際にはデータアクセスAPIを使用します。 データアクセスAPIを使用して、商品IDに一致する商品情報の取得を行います。

インストール時に行っておくこと

データアクセスAPIの必要権限がprivacyなので、インストールの「ebisumartへリダイレクト」時に設定するパラメータscopeにprivacyを加えます。

インストール時のInstallServlet.saveTokens()の処理を完了させる。

Appsに記述する処理

jp.co.test.dataaccess.DataAccessServlet.javaに以下の処理を記述してください。 shopIdにはAppsをインストールした店舗のebisumartNoを記述してください。


public class DataAccessServlet extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String shopId = "ebisumartNo";
        EbisumartService es = new EbisumartService(shopId, DataAccessClientHolder.get());
        ItemsService is = es.getItemsService();
        Item item = is.getItemById("1");
        
        response.getWriter().println(item.getItemName());
    }
}

このサーブレットを呼び出すと商品IDが1の商品の商品名が返されます。

データアクセスAPIを使用する際には、最初にEbisumartServiceのインスタンスを作成し、 そのインスタンスから各データアクセスAPIのサービスを取得してください。