CUEBiC TEC BLOG

キュービックTECチームの技術ネタを投稿しております。

NetSuiteとAPI連携してみた_その3(RESTlets API編)

どうもーキュービックでテックリードをやっている尾﨑です。 本日は会計や組織データなどのマスタ管理を行なっているNetSuiteとAPI連携した時のお話をしたいと思います。

Komawoの全体アーキテクチャ
クラッチで連携した事例は希少だと思うので、困っている方の課題解決に繋がると嬉しいです。 今回は前回のクライアント証明書認証によるREST API連携に続いて、トークンベース認証によるRESTlet API連携をご紹介したいと思います。

・OAuth2.0トークン認証によるREST API連携
・OAuth2.0クライアント認証によるREST API連携
・トークンベース認証によるRESTlet  API連携★

本日はトークンベース認証によるRESTlet API連携とハマったポイントなどをご紹介したいと思います。

アーキテクチャ構成

1.ORACLE NETSUITEに登録されているマスターに更新が発生(登録/更新/削除)
2.Suite Scriptにて更新をトリガーにRestlet APIにて更新レコード情報を取得
3.Suite Scriptからtrocco APIをコールしてSaaSサービスtroccoにpostデータを送信
4.trocco からRedshiftにマスタ情報を連携

アーキテクチャ

前回の課題のおさらい

クライアント証明書認証によるREST API連携の課題

  • 証明書が2年おきに更新が必要(PJ離任時のリスク)
  • Netsuiteの更新トリガーではない
    • REST APIをコールコールする側でスケジューリングして実行
    • 任意のタイミングで手動で同期
    • RDBのデータと取得データをマッピングする必要があった

はまった点

アカウントに複数ロールが割当たっている場合にアクセストークンに不整合が起きた

  • トークンベース/ロール/アカウントが同一であるかを確認

AuthorizatonのRESTlet ヘッダーの生成には個別にスクリプティングが必須

  • パラメータのoauth_timestampは前回リクエスト時から更新する必要がある

解決策

アクセストークンの不整合の解消を試る

  • 1.Youtubeのこちらの動画を参考にAPI連携用のロールの作成とアカウントへの割り当てを実施
  • 2.API連携用のロールを割り当てたアカウントにてトークンベース認証を設定
  • 3.テクニカルサポートとビデオ会議でペアプロを行いつつpostmanで疎通に成功

実装に向けてRESTlet ヘッダーの生成を行う

  • 1.PHPで個別にRESTlet ヘッダーの生成スクリプトを実装
  • 2.この時点で疎通エラーとなったため再度、テクニカルサポートとペアプロを実施
  • 3.ペアプロでは問題がなかったため、テクニカルサポートに情報を連携し、詳細調査依頼
  • 4.アカウントIDの指定が微妙に異なる点が判明
    • URLでは「-小文字」だが「大文字指定」になる(-sb1はSB1となる)

フロー

順序としては1〜8になります。

  • 1.TBAのログインが行えるロールを新規作成する
  • 2.TBAのロールを付与するユーザーを新規作成する
  • 3.インテグレーションでTBA認証を作成する
    • consumner_keyを取得する
    • consumer_secretを取得する
  • 4.アクセストークンを作成する
    • アプリケーションはインテグレーションと紐付け
    • ※ユーザーに複数のロールが存在する場合は、ログインしているロールをTBAのロールに設定して実施する
  • 5.NetSuiteにscriptファイルをアップロードする
  • 6.NetSuiteにscriptファイルをデプロイする
  • 7.エンドポイントを取得する
  • 8.RESTlet ヘッダーの生成を行い、外部からRESTlets APIで連携する

手順

1〜7までは以下の解説動画を参考に進めてください。 www.youtube.com

今回は以下を中心に解説します

  • 8.RESTlet ヘッダーの生成を行い、外部からRESTlet APIで連携する

エンドポイントを以下のように取得したら、RESTlet ヘッダーの生成に進みます。 参考にした動画ではNETSUITE上で生成ができるようでしたが、生成できないようでした。

大項目 中項目 設定値
Authorization Signature Method HMAC-SHA256
Authorization Consumer Key インテグレーション作成時の消費者キー/クライアントID
Authorization Consumer Secret インテグレーション作成時の消費者のシークレット/クライアントのシークレット
Authorization Access Token アクセストークン作成時のトークンID
Authorization Token Secret アクセストークン作成時のトークン・シークレット
Authorization Timestamp 現在のunixtimeを指定。postmanでは自動補完されるので不要
Authorization Nonce ランダムな10文字以上の英数字を指定。postmanでは自動補完されるので不要
Authorization version 1.0
Authorization Realm アカウントID。URLでは小文字だが大文字指定かつハイフンがアンダースコートになる(-sb1だが_SB1)となる点に注意
Authorization Signature Method HMAC-SHA256
User-Agent-X - SuiteScript-Call(なくても大丈夫)
Content-Type - application/json

APIの設定

  • postmanであればRESTlet ヘッダーを生成しなくとも、疎通ができます。
  • 以下にjsonの例を示すので、コピーしてインポートしてください。
    • パラメータやエンドポイントなどは適宜ご自身の情報に更新してください。
{
    "info": {
        "_postman_id": "557cee83-97ed-470e-b0f2-c15b46bb3319",
        "name": "NETSUITE",
        "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json",
        "_exporter_id": "25370205"
    },
    "item": [
        {
            "name": "RestletTest",
            "request": {
                "auth": {
                    "type": "oauth1",
                    "oauth1": {
                        "consumerSecret": "youre consumerSecret",
                        "consumerKey": "youre consumerKey",
                        "tokenSecret": "your tokenSecret",
                        "token": "your token",
                        "realm": "your account_id",
                        "timestamp": "",
                        "nonce": "",
                        "signatureMethod": "HMAC-SHA256",
                        "addParamsToHeader": true,
                        "version": "1.0",
                        "addEmptyParamsToSign": false
                    }
                },
                "method": "GET",
                "header": [
                    {
                        "key": "User-Agent-X",
                        "value": "SuiteScript-Call",
                        "type": "text"
                    },
                    {
                        "key": "Content-Type",
                        "value": "application/json",
                        "type": "text"
                    }
                ],
                "url": {
                    "raw": "https://{your_account_id}.restlets.api.netsuite.com/app/site/hosting/restlet.nl?deploy={deploy_id}&script={script_id}",
                    "protocol": "https",
                    "host": [
                        "{your_account_id}",
                        "restlets",
                        "api",
                        "netsuite",
                        "com"
                    ],
                    "path": [
                        "app",
                        "site",
                        "hosting",
                        "restlet.nl"
                    ],
                    "query": [
                        {
                            "key": "",
                            "value": "",
                            "disabled": true
                        },
                        {
                            "key": "deploy",
                            "value": "{deploy_id}"
                        },
                        {
                            "key": "script",
                            "value": "{script_id}"
                        }
                    ]
                }
            },
            "response": []
        }
    ]
}

どうしてもTalend API TESTERで確認したいあなたへ

Talend API TESTERでどうしても疎通したい場合 PHPで以下を実装し、AuthorizatonのRESTlet ヘッダーを生成する。 ※$timestampは毎回新ものを生成する必要があるので注意

1.authのライブラリーの関数oauth_get_sbsを使用して居るので、oauthをインストールする

pecl install oauth

2.以下の要領でRESTlet ヘッダーを生成する

<?php

$requestUrl = 'https://{your_account_id}.restlets.api.netsuite.com/app/site/hosting/restlet.nl?deploy={deploy_id}&script={script_id}';
$consumerKey = 'youre Consumer Key';
$consumerSecret = 'youre Consumer Secret';
$nonce = 'aqwsedrftgyhujiko';
$timestamp = time();
$signatureMethod = 'HMAC-SHA256';
$tokenKey = 'youre Access Token';
$tokenSecret = 'youre Token Secret';
$version = '1.0';
$realm = 'youre account Name';
$httpMethod = 'GET';

$baseString = oauth_get_sbs($httpMethod, $requestUrl, array('oauth_consumer_key' => $consumerKey,
                                     'oauth_nonce' => $nonce,
                                     'oauth_signature_method' => $signatureMethod,
                                     'oauth_timestamp' => $timestamp,
                                     'oauth_token' => $tokenKey,
                                     'oauth_version' => $version));

var_dump("baseString:".$baseString);

$key = rawurlencode($consumerSecret) .'&'. rawurlencode($tokenSecret);
$signature = base64_encode(hash_hmac('sha256', $baseString, $key, true));


var_dump("signature:".$signature);

//認証ヘッダー
//https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_1534941295.html
$authorization = 'Authorization: OAuth '
         .'realm="' .rawurlencode($realm) .'", '
         .'oauth_consumer_key="' .rawurlencode($consumerKey) .'", '
         .'oauth_token="' .rawurlencode($tokenKey) .'", '
         .'oauth_nonce="' .rawurlencode($nonce) .'", '
         .'oauth_timestamp="' .rawurlencode($timestamp) .'", '
         .'oauth_signature_method="' .rawurlencode($signatureMethod) .'", '
         .'oauth_version="' .rawurlencode($version) .'", '
         .'oauth_signature="' .rawurlencode($signature) .'"' ;

var_dump("Authorization:".$authorization);

//疎通時のみ使用
//getRestletInfo($requestUrl,$authorization);
function getRestletInfo($requestUrl,$authorization){
  $header = [
  "Content-Type: application/json",
  $authorization
  ];

  var_dump($header);

  $curl=curl_init();
  curl_setopt($curl,CURLOPT_URL, $requestUrl);
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
  curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
  curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, FALSE); // 証明書の検証を無効化
  curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, FALSE); // 証明書の検証を無効化
  curl_setopt($curl,CURLOPT_RETURNTRANSFER, TRUE); // 返り値を文字列に変更
  curl_setopt($curl,CURLOPT_FOLLOWLOCATION, TRUE); // Locationヘッダを追跡

  $output= curl_exec($curl);

  // エラーハンドリング用
  $errno = curl_errno($curl);
  // コネクションを閉じる
  curl_close($curl);

  // エラーハンドリング
  if ($errno !== CURLE_OK) {
  //エラー処理
  }
  echo $output;
}
?>

3.以下の要領でリクエストを送信する

リクエスト情報

大項目 小項目
エンドポイント https://{your_account_id}.restlets.api.netsuite.com/app/site/hosting/restlet.nl
HTTPメソッド GET
  • ※site-idに関しては「アクセストークン取得」にて取得


ヘッダー 設定値
Authorization RESTlet ヘッダーの出力結果を使用する
User-Agent SuiteScript-Call
Content-type application/json
Accept application/json


パラメータ 概要 /設定値
script ビルド時に発行されたscript_id
deploy ビルド時に発行されたdeploy_id

最後に

如何でしたでしょうか?NetSuiteのAPIの連携方式に関して以下の3つの連携方式を その1その2、本記事の3回に分けてでご紹介しました。これから利用しようと思っている方の参考になると幸いです。

・OAuth2.0トークン認証によるREST API連携
・OAuth2.0クライアント認証によるREST API連携
・トークンベース認証によるRESTlet  API連携

次回は、Netsuiteに続いて、Komawoを構成しているアーキテクチャーのtroccoに関して 導入のメリットやはまった点などを中心に説明していきたいと思います。