この記事は、kintoneアドベントカレンダー23日目の記事です。
JP_Stripesコミュニティなどで、「バックオフィス業務に使うkintoneと、請求処理に利用するStripeの相性が良いのでは?」という声を聞くことが増えてきました。
以前JP_Stripesイベントにて、Stripeからkintoneに接続する方法を紹介しましたので、今回はkintoneからStripeのデータにアクセスすることに挑戦してみます。
Stripe Appsとkintoneの連携に挑戦した際の資料はこちら
使用するkintoneサンプルアプリ
今回は顧客リストアプリを利用します。
ダミーのデータを登録した状態で作成できますので、こちらも活用しましょう。
kintoneプラグインをセットアップする
はじめにプラグインをセットアップします。
@kintone/create-pluginコマンドを利用しましょう。
$ npx @kintone/create-plugin hello-kintone-plugin-ts --lang ja --template modern
kintoneプラグインのプロジェクトを作成するために、いくつかの質問に答えてください :)
では、はじめましょう!
? プラグインの英語名を入力してください [1-64文字] hello-kintone-plugin-ts
? プラグインの説明を入力してください [1-200文字] hello-kintone-plugin-ts
? 日本語をサポートしますか? Yes
? プラグインの日本語名を入力してください [1-64文字] (省略可)
? プラグインの日本語の説明を入力してください [1-200文字] (省略可)
? 中国語をサポートしますか? No
? プラグインの英語のWebサイトURLを入力してください (省略可)
? プラグインの日本語のWebサイトURLを入力してください (省略可)
? モバイルページをサポートしますか? Yes
? @kintone/plugin-uploaderを使いますか? Yes
依存ライブラリをインストールします
(⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂) ⠙ idealTree:hello-kintone-plugin-ts: sill idealTree buildDeps
セットアップに成功すれば、次のようなメッセージが表示されます。
Success! Created hello-kintone-plugin at hello-kintone-plugin
npm start
ファイルの変更を監視してプラグインのzipを自動的に作成するプロセスを起動します
その後、@kintone/plugin-uploaderにより、プラグインのzipは自動的にアップロードされます
npm run build
プラグインのzipを作成します
npm run lint
ESLintを使ってJavaScriptのソースコードをチェックします
まずは次のコマンドを実行してください
その後、あなたのkintone環境の情報を入力してください
cd hello-kintone-plugin
npm start
kintoneプラグイン開発をはじめましょう!
開発に関する情報はcybozu developer network:
https://developer.cybozu.io
プラグインをアップロードする
プラグインを動かすには、kintone側へのアップロードが必要です。
コマンドを実行して、初期状態のアプリをアップロードしましょう。
$ npm run build
$ npm run upload
--watch
オプションを付けることで、npm run build
に成功すると自動でアップロードしてくれます。
また、ユーザー名などの情報をワンライナーで設定することもできます。
$ npm run upload \
--base-url https://YOUR_SPACE_NAME.cybozu.com/ \
--username user@example.com \
--password xxxx \
--watch
kintoneプラグインからStripeの情報を取得する
Stripe SDKをこの方法でセットアップしたアプリに追加すると、以下のビルドエラーが発生します。
ERROR in ./node_modules/stripe/lib/utils.js 4:15-32
Module not found: Error: Can't resolve 'crypto' in '/Users/sandbox/kintone/hello-kintone-plugin-ts/node_modules/stripe/lib'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
そのため今回はExpress.jsで次のようなAPIを用意しました。
app.use((request, response, next) => {
response.header('Access-Control-Allow-Origin', '*');
response.header('Access-Control-Allow-Methods', 'GET');
response.header(
'Access-Control-Allow-Headers',
'Content-Type, Stripe-Signature'
);
if (request.method.toLocaleUpperCase() === 'OPTIONS') {
return response.send(200);
}
next();
});
app.get('/customer/invoice', async (req, res) => {
const { data: customers } = await stripe.customers.list({ email: req.query.email });
if (!customers) return res.send(404);
const { data: invoices } = await stripe.invoices.list({ customer: customer.id });
res.json(invoices);
});
あとはsrc/js/desktop.ts
などに作成したAPIを呼び出すコードを実装します。
const PLUGIN_ID = kintone.$PLUGIN_ID;
kintone.events.on("app.record.detail.show", async (event) => {
const email = event.record["メールアドレス"]?.value;
if (!email) return;
const config = kintone.plugin.app.getConfig(PLUGIN_ID);
const gaia = document.getElementById("record-gaia");
if (!gaia) return;
const invoices = await new Promise((resolve, reject) => {
kintone.plugin.app.proxy(
PLUGIN_ID,
`https://YOUR_EXPRESS_API_URL.com/customer/invoices?email=${email}`,
"GET",
{},
{},
(response) => {
const result = JSON.parse(response);
resolve(result);
},
(e) => {
console.log(e);
reject(e);
}
);
});
const tableElement = document.createElement("table");
tableElement.setAttribute("class", "recordlist-gaia");
tableElement.setAttribute("style", "table-layout: fixed;");
const tableBodyElement = document.createElement("tbody");
tableBodyElement.innerHTML = `
<thead>
<tr>
<th class="recordlist-header-cell-gaia label-2170 recordlist-header-sortable-gaia">請求書番号</th>
<th class="recordlist-header-cell-gaia label-2170 recordlist-header-sortable-gaia">請求金額</th>
<th class="recordlist-header-cell-gaia label-2170 recordlist-header-sortable-gaia">PDF</th>
</tr>
</thead>
`;
(invoices as any).forEach((invoice: any) => {
const invoiceElement = document.createElement("tr");
invoiceElement.setAttribute("class", "recordlist-row-gaia");
invoiceElement.innerHTML = `
<td class="recordlist-cell-gaia recordlist-single_line_text-gaia value-2178">
<span class="control-label-text-gaia">${invoice.number}</span>
</td>
<td class="recordlist-cell-gaia recordlist-single_line_text-gaia value-2178">
<span>${invoice.amount_due.toLocaleString()} ${invoice.currency.toLocaleUpperCase()}</span>
</td>
<td class="recordlist-cell-gaia recordlist-single_line_text-gaia value-2178">
<a href="${invoice.invoice_pdf}">Open</a>
</td>
`;
tableBodyElement.appendChild(invoiceElement);
});
tableElement.appendChild(tableBodyElement);
gaia.appendChild(tableElement);
});
このコードをアップロードすると、[顧客リストアプリ]の顧客詳細ページにて、レコードのメールアドレスからStripe上にある請求書のデータを一覧表示できます。
本格的な組み込みに向けて
kintoneとStripeを連携させるシンプルなサンプルを紹介しました。
kintone.plugin.app.proxy
やkintone.plugin.app.setProxyConfig
を利用することで、連携したいデータを個別に設定したり、StripeのAPIキーを管理画面から登録できるようにすることも可能です。