Stripeの請求書や顧客データを取得・表示するkintoneプラグインを作ってみた

この記事は、[kintoneアドベントカレンダー](https://qiita.com/advent-calendar/2022/kintone)23日目の記事です。

[JP_Stripes](https://jpstripes.connpass.com/)コミュニティなどで、「バックオフィス業務に使うkintoneと、請求処理に利用するStripeの相性が良いのでは？」という声を聞くことが増えてきました。

以前JP_Stripesイベントにて、Stripeからkintoneに接続する方法を紹介しましたので、今回はkintoneからStripeのデータにアクセスすることに挑戦してみます。

**Stripe Appsとkintoneの連携に挑戦した際の資料はこちら**

https://speakerdeck.com/stripehideokamoto/jp-stripes-nagoya

## 使用するkintoneサンプルアプリ

今回は[顧客リストアプリ](https://kintone-sol.cybozu.co.jp/apps/031-kokyaku-list.html)を利用します。

ダミーのデータを登録した状態で作成できますので、こちらも活用しましょう。

![スクリーンショット 2022-12-23 18.24.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/ca378a3b-af47-f3b3-d100-51dd5a7ceaa0.png)


## kintoneプラグインをセットアップする

はじめにプラグインをセットアップします。

[@kintone/create-plugin](https://www.npmjs.com/package/@kintone/create-plugin)コマンドを利用しましょう。

```bash
$ 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
```


セットアップに成功すれば、次のようなメッセージが表示されます。

```bash

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側へのアップロードが必要です。

コマンドを実行して、初期状態のアプリをアップロードしましょう。

```bash
$ npm run build
$ npm run upload
```

`--watch`オプションを付けることで、`npm run build`に成功すると自動でアップロードしてくれます。

また、ユーザー名などの情報をワンライナーで設定することもできます。

```bash
$ npm run upload \
 --base-url https://YOUR_SPACE_NAME.cybozu.com/ \
 --username user@example.com \
 --password xxxx \
 --watch
```

## kintoneプラグインからStripeの情報を取得する

Stripe SDKをこの方法でセットアップしたアプリに追加すると、以下のビルドエラーが発生します。

```bash
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を用意しました。

```js
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を呼び出すコードを実装します。

```typescript
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上にある請求書のデータを一覧表示できます。

![スクリーンショット 2022-12-23 18.23.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/2e9ce2aa-1b31-2d59-68bb-a47796aeaef9.png)

## 本格的な組み込みに向けて

kintoneとStripeを連携させるシンプルなサンプルを紹介しました。

`kintone.plugin.app.proxy`や`kintone.plugin.app.setProxyConfig`を利用することで、連携したいデータを個別に設定したり、StripeのAPIキーを管理画面から登録できるようにすることも可能です。

https://developer.cybozu.io/hc/ja/articles/203661160-kintone-%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3JavaScript-API-#list2