株式会社スマレジの開発部でスマレジのサーバサイドを作っています

Nuxt.jsからプラットフォームAPIをコールする(expressで認証編)

こんにちは!株式会社スマレジ 、開発部のmasaです。
緊急事態宣言が延長になり、masaもリモートワークの日が増えました。

僕自身は会社の近くに住んでいるので、通勤のリスクは少ないのですが、知らないうちに移してしまうリスクもあるので、たとえ体調が悪くなくても、毎朝の検温の結果やその他体の異常を少しでも感じたらリモートワークに切り替えるようにしています。

ワクチン摂取が進むまで、もうしばらく頑張りましょう!

今回は、前々回にNuxt.jsのサーバミドルウェアにExpressを導入したので、スマレジ プラットフォームAPIの認証を行います。

プラットフォームAPIの認証

 認証の流れについては最新の仕様書を確認していただければと思います。

developers.smaregi.dev

 

今回は、認証コードの取得が完了して、ユーザアクセストークンの取得を実施するところからの実装となります。

 

ソースコード(Node.js + Express)

いつの間にかはてなブログIDEのスタイルそのままでコピペができるようになっているので、使ってみました。

今回はサンプルコードのため、共通化やバリデーションなどは行っていませんのでご了承ください。

想定は、

POST http;//(連携アプリのURL)/auth

でRequestとして、

{
   "code": "認証コード"
}

がフロントエンドから送られてくる想定です。

他の設定値については仕様書を確認しながらお読みください。

const bodyParser = require('body-parser')
const app = require('express')()
const request = require('request');
let contractId = null;

app.use(bodyParser.json())

app.post('/auth', (req, res) => {
const smaregiVerificationCode = req.query.code;
if (typeof smaregiVerificationCode === "undefined" || smaregiVerificationCode.length === 0) {
console.log("empty error");
res.json({data: null, message: "スマレジ のとの認証に失敗しました" });
return;
}
const URL = 'https://id.smaregi.dev/authorize/token';
const BASIC_CODE = 'クライアントID:クライアントシークレットをbase64エンコーディングしたもの';
//オプションを定義
const options = {
url: URL,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + BASIC_CODE
},
json: true,
form: {
"grant_type": "authorization_code",
"code": smaregiVerificationCode,
"redirect_uri": "環境設定で指定したリダイレクトURI"
}
}

//リクエスト送信(ユーザアクセストークン取得 -> 契約ID取得 -> 部門一覧API実行の順)
request(URL, options, function (error, response, body) {
//ユーザアクセストークン取得
const userInfoUrl = "https://id.smaregi.dev/userinfo";
const userInfoOptions = {
headers: {
Authorization: "Bearer " + body.access_token
}
}
console.log(body);
request(userInfoUrl, userInfoOptions, function (error, response, body) {
//契約ID取得
const bodyObj = JSON.parse(body);
console.log(bodyObj);
const contractInfo = bodyObj.contract;
if (typeof contractInfo === "undefined") {
return;
}
contractId = contractInfo.id;
if (typeof contractId === "undefined") {
return;
}
const accessTokenUrl = "https://id.smaregi.dev/app/" + contractId + "/token";
const accessTokenOptions = {
url: accessTokenUrl,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + BASIC_CODE
},
json: true,
form: {
"grant_type": "client_credentials",
"scope": "pos.products:read pos.products:write" // 必要なスコープを半角スペース区切りで指定
}
}
request(accessTokenUrl, accessTokenOptions, function (error, response, body) {
//部門一覧API実行
const accessToken = body.access_token;
if (typeof accessToken === "undefined") {
return;
}
const smaregiCategoryUrl = "https://api.smaregi.dev/" + contractId + "/pos/categories";
const smaregiCategoryOptions = {
url: smaregiCategoryUrl,
method: 'GET',
headers: {
'Authorization': 'Bearer ' + accessToken
},
json: true,
qs: {
"limit": "1000"
}
}
request(smaregiCategoryUrl, smaregiCategoryOptions, function (error, response, body) {
...
});
});
res.json({contract_id:contractId});
  });
});
});

module.exports = app