LoginSignup
5

Twilio Functionsからkintoneに対して読み書きする方法

Last updated at Posted at 2019-01-21

2023年5月1日を持ちまして、株式会社KDDIウェブコミュニケーションズのTwilioリセール事業が終了したため、本記事に記載されている内容は正確ではないことを予めご了承ください。

はじめに

電話やSMS、チャットやFAXなどのクラウド型コミュニケーションAPIを提供するTwilioと、同じくクラウド型ビジネスアプリ作成ツールであるkintoneは、とても相性がよい組み合わせです。電話やチャットなど、ビジネスにおける「フロー」を制御するTwilioと、データを「ストック」して分析するkintoneは、お互いを補完し合う仲と言えるでしょう。

この記事では、Twilioのサーバーレスプログラム実行環境である「Twilio Functions」と、kintoneのAPIを連携させて、Functionsからkintone上のデータにアクセスする方法について記載しています。
Twilio FunctionsはNode.jsベースの開発環境となりますので、今回はkintoneのNode.jsライブラリ「kintone-nodejs-sdk」を利用します。
kintone-nodejs-sdkの概要については、こちらのドキュメントが参考になります。

必要なもの

  • Twilioトライアルアカウント(取得方法はこちら
  • kintone開発者ライセンス(取得方法はこちら

どちらも通常のアカウントでももちろん構いません。

kintone側の準備

今回はサンプルデータとして準備されている「顧客リスト」を使っていきます。

新しいアプリの作成

  • 登録済みの開発者ライセンスを使ってkintoneにログインします。
  • サービス画面が表示されたら、kintoneに入ります。
スクリーンショット 2018-08-06 08.45.01.png
  • アプリの右側にある**+**アイコンを押して、新しいアプリを作成します。
  • kintoneアプリストアが表示されたら、おすすめのアプリの中の顧客リストを選択します。
スクリーンショット 2018-08-06 08.46.50.png
  • 左側に表示されているこのアプリを追加ボタンを押します。(サンプルデータを含めるはチェックしておきます)
  • アプリの追加ダイアログが表示されたら、追加ボタンを押します。
スクリーンショット 2018-08-06 08.49.12.png
  • ポータル画面に戻り、アプリの欄に今追加した顧客リストが表示されていることを確認します。
スクリーンショット 2018-08-06 08.50.41.png

APIトークンの取得

kintoneを外部からアクセスするためのAPIトークンを取得します。

  • アプリの中から先程追加した顧客リストを選択します。
  • 顧客一覧が表示されているすぐ上の表示されている歯車アイコンを押して、アプリの設定画面に移動します。

kintone連携_歯車アイコン.png

  • 設定タブに移動し、カスタマイズ/サービス連携の中の**APIトークンを選択します。
  • 生成するボタンを押します。
  • APIトークンが表示されます。アクセス権に元々チェックされている「レコード閲覧」以外に、「レコード追加」「レコード編集」「レコード削除」にもチェックを入れます。
  • 後ほど使うので、表示されているAPIトークン(文字列)をメモ帳などに記録しておきます。
  • 画面上部にある保存ボタンを忘れずに押します。

kintone連携_APIトークン.png

  • アプリの設定画面に戻るので、右上にあるアプリを更新ボタンを押します。

Twilio側の準備

続いて、Twilio側の準備をしていきます。

  • こちらの画面からログインをして、Twilioの管理コンソールを開きます。

Functionsの環境設定

  • 左側に表示されているドットが3つ表示されているアイコンをクリックすると、スライドメニューが開きます。

kintone連携_スライドメニューアイコン.png

  • DEVELOPER TOOLSの中にあるRuntimeを選択します。
  • その中のFunctionsを選択し、さらにConfigureを選びます。
  • Enable ACCOUNT_SID and AUTH_TOKENのチェックを入れます。
スクリーンショット 2018-08-08 15.34.06.png
  • Environmental Variablesの中の赤い+アイコンを2回押して、枠を2行作ります。
  • 以下の内容を記載します。
KEY VALUE
KINTONE_API_TOKEN 先程控えておいたAPIトークン(文字列)
KINTONE_APP_URI kintoneのURLに含まれるドメイン文字列(xxxxx.cybozu.com)
  • Dependenciesの設定内にある、「Twilio」のVERSIONを「3.23.1」に変更します。
スクリーンショット 2018-08-08 17.14.11.png
  • 更に、赤い+アイコンを1回押して、以下の内容を設定します。
NAME VERSION
kintone-nodejs-sdk 0.1.1
  • Saveボタンを押して、設定を保存します。

Functionsからkintoneへのアクセス

準備が整いましたので、いよいよTwilioからkintoneのデータにアクセスしてみましょう。
今回は、すべてサンプルコードを用意したので、基本的にはコピー&ペーストでテストできるはずです。

kintoneデータの読み込み

まずは、kintone上に保存されているデータをTwilioから読み込むコードを書いてみます。
コードを書く前に必要な情報を整理してみます。

項目 説明
kintoneアプリのドメイン名 先程Functionsの環境設定で、KINTONE_APP_URIで指定したもの
アプリID kintoneの顧客リストアプリを開いた時に、URLの途中に指定されている数値(xxxxx.cybozu.com/k/1/ の「1」の部分)
クエリー 読み込むデータの条件を指定する文字列。例えば、電話番号が「090-1234-5678」のデータを検索するには、「TEL = '090-1234-5678'」のように指定します。このときの「TEL」は、kintoneアプリで各フィールドに設定したフィールドコードとなります。詳しいドキュメントはこのあたりにあります

ではまず、顧客リストアプリのレコード番号が7の以下のデータを検索してみたいと思います。

スクリーンショット 2018-08-08 21.47.19.png

レコード番号を使って検索するためには、getRecordというメソッドを利用します。
getRecordの使い方の詳細は、こちらを御覧ください。

  • Twilioの管理コンソールで、先ほどと同じようにRuntimeFunctionsを選択します。
  • さらにManageを選択し、Create a new Functionもしくは、赤い+アイコンを押して、新しいFunctionを作成します。
  • テンプレートを選択するダイアログが表示されるので、Blankを選択した後、Createボタンを押します。
スクリーンショット 2018-08-08 21.56.20.png
  • FUNCTION NAME欄に「getRecord」と入力します。
  • PATH欄に「/get-record」と入力します。
スクリーンショット 2018-08-08 21.58.32.png
  • CODE欄に予め書かれているコードをすべて削除し、以下のコードを貼り付けます。
const kintone = require('kintone-nodejs-sdk');

exports.handler = function(context, event, callback) {
    // kintone認証設定(API KEY)
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken(context.KINTONE_API_TOKEN);
    
    // コネクション作成
    let kintoneConnection = new kintone.Connection(context.KINTONE_APP_URI, kintoneAuth);    

    // レコード作成
    let kintoneRecord = new kintone.Record(kintoneConnection);
    
    let appID = 1; // アプリID ※ここの値は皆さんの環境に合わせて変更してください
    let recordID = 7;  // 検索したいレコード番号

    kintoneRecord.getRecord(appID, recordID)
    .then((resp) => {
        Object.keys(resp.record).forEach(function(key) {
            console.log(key, resp.record[key]);
        });
        callback(null, 'OK');
    })
    .catch((err) => {
        const error = err.get();
        Object.keys(error).forEach(function(key) {
            console.log(key, error[key]);
        });
        callback(error.message);
    });
};
  • Saveボタンを押します。
  • デプロイが自動で実行され、しばらくするとデプロイ完了の緑色のバナーが表示されれば完成です。
  • PATH欄の右側にあるコピーアイコンをクリックしてURLをコピーします。
  • ブラウザで新しいタブを開き、URLを貼り付けて実行します。
  • Function側の画面に以下のようなログが表示されれば成功です(URLを貼り付けた方のタブにはOKとだけ表示されています)。
スクリーンショット 2018-08-08 22.25.26.png

続いて、もう少し複雑な読み込みを行ってみます。
シナリオとして、住所(フィールドコード「Address」)が「栃木県」から始まるの会社名の一覧を取得してみましょう。

  • FunctionsManageを選択し、赤い+アイコンを押して、新しいFunctionを作成します。
  • テンプレートを選択するダイアログが表示されるので、Blankを選択した後、Createボタンを押します。
  • FUNCTION NAME欄に「getRecords」と入力します。
  • PATH欄に「/get-records」と入力します。
  • CODE欄に予め書かれているコードをすべて削除し、以下のコードを貼り付けます。
const kintone = require('kintone-nodejs-sdk');

exports.handler = function(context, event, callback) {
    // kintone認証設定(API KEY)
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken(context.KINTONE_API_TOKEN);
    
    // コネクション作成
    let kintoneConnection = new kintone.Connection(context.KINTONE_APP_URI, kintoneAuth);    

    // レコード作成
    let kintoneRecord = new kintone.Record(kintoneConnection);
    
    let appID = 1; // アプリID ※ここの値は皆さんの環境に合わせて変更してください
    let query = `Address like "栃木県"`;
    let fieldsCode = [
        '文字列__1行_', // 会社名のフィールドコード
    ];
    let isShowTotalCount = true;

    kintoneRecord.getRecords(appID, query, fieldsCode, isShowTotalCount)
    .then((resp) => {
        if (resp.records.length === 0) {
            callback(null, `該当するデータが見つかりません`);
        } else {
            Object.keys(resp.records).forEach(function(key) {
                console.log(key, resp.records[key]);
            });
            console.log(`1件目の会社名は、${resp.records[0]['文字列__1行_'].value}です。`);
            callback(null, `${resp.totalCount}件のデータが抽出されました`);
        }
    })
    .catch((err) => {
        const error = err.get();
        Object.keys(error).forEach(function(key) {
            console.log(key, error[key]);
        });
        callback(error.message);
    });
};
  • Saveボタンを押します。
  • デプロイが自動で実行され、しばらくするとデプロイ完了の緑色のバナーが表示されれば完成です。
  • PATH欄の右側にあるコピーアイコンをクリックしてURLをコピーします。
  • ブラウザで新しいタブを開き、URLを貼り付けて実行します。
  • Function側の画面に以下のようなログが表示されれば成功です(URLを貼り付けた方のタブには抽出件数が表示されています)。
スクリーンショット 2018-08-08 22.49.36.png

戻ってくる値は、各レコードの値がJSON形式の配列になっています。
具体的には、resp.records[n]のnが戻ってきたレコード配列のインデックスとなり、その値を取得するにはフィールドコードのValue値を取ればOKです(該当するレコードがない場合は、resp.records配列が空となります)。
たとえば、上の読み込みサンプルで、1件目の会社名(フィールドコードが「文字列__1行_」)だけを抜き出す場合は、以下のようなコードとなります。
console.log(`1件目の会社名は、${resp.records[0]['文字列__1行_'].value}です。`);

また、今回のデータ抽出に関しての条件は以下の部分で指定しています。
let query = `Address like "栃木県"`;
これは、Addressフィールドに、栃木県という文字が含まれているかどうかを表しています。
like以外にも、以下のような比較演算子が使えます。

比較演算子 意味
= 完全一致
!= 完全一致の否定
> より大きい
< より小さい
>= 以上
<= 以下
in いずれかと一致。例:Field in ("A", "B")
not in いずれでもない
like が含まれる
not like が含まれない
or 複数の比較の和。例:Field = "A" or Field = "B"
and 複数の比較の積。例:Field = "A" and Name = "Tanaka"

kintoneデータの追加

ここからは、Functions内に記載するコードのみで説明をします。
kintoneのデータを追加するには、たとえば次のようなコードを使います。

const kintone = require('kintone-nodejs-sdk');

exports.handler = function(context, event, callback) {
    // kintone認証設定(API KEY)
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken(context.KINTONE_API_TOKEN);
    
    // コネクション作成
    let kintoneConnection = new kintone.Connection(context.KINTONE_APP_URI, kintoneAuth);    

    // レコード作成
    let kintoneRecord = new kintone.Record(kintoneConnection);
    
    let appID = 1; // アプリID ※ここの値は皆さんの環境に合わせて変更してください

    // 追加したいデータを定義
    let recordData = {
        "文字列__1行_": {   // 会社名
            value: "KDDIウェブコミュニケーションズ"
        },
        "文字列__1行__2": {   // 担当者名
            value: "高橋克己"
        },
        "TEL": {   // 電話番号
            value: "090-1234-5678"
        },
    };

    kintoneRecord.addRecord(appID, recordData)
    .then((resp) => {
        Object.keys(resp).forEach(function(key) {
            console.log(key, resp[key]);
        });
        callback(null, 'OK');
    })
    .catch((err) => {
        const error = err.get();
        Object.keys(error).forEach(function(key) {
            console.log(key, error[key]);
        });
        callback(error.message);
    });
};

フィールドコードを省略した場合、そのフィールドの初期値で値が自動的に生成されます。
また、間違ったフィールドコードを指定した場合、そのフィールドは無視されます。

実行結果は以下のようになります。
スクリーンショット 2018-08-17 17.07.06.png

addRedordを実行すると、追加されたレコード番号(id)を取得することができます(addRecordの戻り値であるresp.id)。

同時に複数のレコードを追加するには、addRecordの代わりにaddRecordsを利用します。addRecordとの違いは、2番めの引数に配列を使用する点です。
例えば以下のようなコードとなります。

const kintone = require('kintone-nodejs-sdk');

exports.handler = function(context, event, callback) {
    // kintone認証設定(API KEY)
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken(context.KINTONE_API_TOKEN);
    
    // コネクション作成
    let kintoneConnection = new kintone.Connection(context.KINTONE_APP_URI, kintoneAuth);    

    // レコード作成
    let kintoneRecord = new kintone.Record(kintoneConnection);
    
    let appID = 1; // アプリID ※ここの値は皆さんの環境に合わせて変更してください

    // 追加したいデータを定義
    let recordData = [
        {
            "文字列__1行_": {   // 会社名
                value: "会社名A"
            },
            "文字列__1行__2": {   // 担当者名
                value: "〇〇〇〇"
            },
            "TEL": {   // 電話番号
                value: "090-1234-5678"
            },
        },
        {
            "文字列__1行_": {   // 会社名
                value: "会社名B"
            },
            "文字列__1行__2": {   // 担当者名
                value: "△△△△"
            },
            "TEL": {   // 電話番号
                value: "090-1234-5678"
            },
        },
    ];

    kintoneRecord.addRecords(appID, recordData)
    .then((resp) => {
        Object.keys(resp).forEach(function(key) {
            console.log(key, resp[key]);
        });
        callback(null, 'OK');
    })
    .catch((err) => {
        const error = err.get();
        Object.keys(error).forEach(function(key) {
            console.log(key, error[key]);
        });
        callback(error.message);
    });
};

addRedordsを実行すると、追加されたレコード番号(id)を配列として取得することができます(addRecordsの戻り値であるresp.ids)。

kintoneデータの更新

データの更新は3種類の方法があります。

  • レコードIDを使った単一レコード更新
  • アップデートキーを使った単一レコード更新
  • 複数レコードの同時更新

レコードIDを使った単一レコード更新

最もシンプルな更新方法です。更新したいレコードIDと更新したいフィールドの内容を指定して更新することができます。
例えば、電話番号だけを更新したい場合は、以下のようなコードとなります。

const kintone = require('kintone-nodejs-sdk');

exports.handler = function(context, event, callback) {
    // kintone認証設定(API KEY)
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken(context.KINTONE_API_TOKEN);

    // コネクション作成
    let kintoneConnection = new kintone.Connection(context.KINTONE_APP_URI, kintoneAuth);    

    // レコード作成
    let kintoneRecord = new kintone.Record(kintoneConnection);

    let appID = 1; // アプリID ※ここの値は皆さんの環境に合わせて変更してください
    let recordID = 7; // 更新したいレコードのID

    // 更新したいデータを定義
    let recordData = {
        "TEL": {   // 電話番号
            value: "090-9999-9999"
        },
    };

    kintoneRecord.updateRecordById(appID, recordID, recordData)
    .then((resp) => {
        Object.keys(resp).forEach(function(key) {
            console.log(key, resp[key]);
        });
        callback(null, 'OK');
    })
    .catch((err) => {
        const error = err.get();
        Object.keys(error).forEach(function(key) {
            console.log(key, error[key]);
        });
        callback(error.message);
    });
};

更新が正常に完了すると、更新後のリビジョン番号(revision)が戻ります。

スクリーンショット 2019-01-21 10.47.17.png

なお、更新作業がコンフリクトしないようにする(排他制御)には、次のようにupdateRecordByIdの引数に更新したいリビジョン番号を追加することができます。

updateRecordById(appID, recordID, recordData, revision)

更新したいリビジョンデータが他のユーザなどによって更新されてしまっている場合はエラーが戻ります。

アップデートキーを使った単一レコード更新

アプリ内に、レコードID以外にユニークになるフィールドがある場合は、そちらを使って更新することもできます。
ユニークになるフィールドは、「文字列(1行)」か「数字」で、値の重複を禁止するにチェックが入っている必要があります。

スクリーンショット 2019-01-21 11.21.47.png

const kintone = require('kintone-nodejs-sdk');

exports.handler = function(context, event, callback) {
    // kintone認証設定(API KEY)
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken(context.KINTONE_API_TOKEN);

    // コネクション作成
    let kintoneConnection = new kintone.Connection(context.KINTONE_APP_URI, kintoneAuth);    

    // レコード作成
    let kintoneRecord = new kintone.Record(kintoneConnection);

    let appID = 1; // アプリID ※ここの値は皆さんの環境に合わせて変更してください
    
    // 更新したいレコードをユニークで特定できるキーと値
    let updateKey = {
        field: "TEL",
        value: "090-9999-9999"
    };

    // 更新したいデータを定義
    let recordData = {
        "文字列__1行__2": {   // 担当者名
            value: "山田太郎"
        },
    };

    kintoneRecord.updateRecordByUpdateKey(appID, updateKey, recordData)
    .then((resp) => {
        Object.keys(resp).forEach(function(key) {
            console.log(key, resp[key]);
        });
        callback(null, 'OK');
    })
    .catch((err) => {
        const error = err.get();
        Object.keys(error).forEach(function(key) {
            console.log(key, error[key]);
        });
        callback(error.message);
    });
};

なお、上記コードはTELフィールドをアップデートキーにしていますが、顧客リストアプリではTELフィールドは値の重複を禁止していないため、このままではエラーになります。また、アップデートキーに指定したフィールド自体を更新することはできません。
排他制御を実装するために、リビジョン番号を引数に指定することもできます。

updateRecordByUpdateKey(appID, updateKey, recordData, revision)

複数レコードの同時更新

同時に複数のレコードを更新するためには、updateRecordsを利用することができます。
たとえば、レコード番号25と26のデータに対して、電話番号を「090-1234-5678」に書き換えるためには、以下のようにコーディングすることができます。

const kintone = require('kintone-nodejs-sdk');

exports.handler = function(context, event, callback) {
    // kintone認証設定(API KEY)
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken(context.KINTONE_API_TOKEN);

    // コネクション作成
    let kintoneConnection = new kintone.Connection(context.KINTONE_APP_URI, kintoneAuth);    

    // レコード作成
    let kintoneRecord = new kintone.Record(kintoneConnection);

    let appID = 1; // アプリID ※ここの値は皆さんの環境に合わせて変更してください

    // 更新したいデータを定義
    let recordData = {
        "TEL": {   // 電話番号
            value: "090-1234-5678"
        },
    };
    
    // 更新対象データの定義
    let recordsDataUpdate = [
        {
            id: 25,
            record: recordData
        },
        {
            id: 26,
            record: recordData
        },
    ];

    kintoneRecord.updateRecords(appID, recordsDataUpdate)
    .then((resp) => {
        Object.keys(resp).forEach(function(key) {
            console.log(key, resp[key]);
        });
        callback(null, 'OK');
    })
    .catch((err) => {
        const error = err.get();
        Object.keys(error).forEach(function(key) {
            console.log(key, error[key]);
        });
        callback(error.message);
    });
};

この例では、更新対象データをレコードIDで指定しましたが、アップデートキーを使って指定することもできます。

let recordsDataUpdate = [
    {
        updateKey: {
            field: '{your_field_code}',
            value: '{your_field_code_value}'
        },
        record: {
            '{your_field_code}': '{your_field_code_value}'
        },
    },
    {
        updateKey: {
            field: '{your_field_code}',
            value: '{your_field_code_value}'
        },
        record: {
            '{your_field_code}': '{your_field_code_value}'
        },
    },
};

排他制御を行う場合は、リビジョン番号を指定することもできます。

let recordsDataUpdate = [
    {
        updateKey: {
            field: '{your_field_code}',
            value: '{your_field_code_value}'
        },
        record: {
            '{your_field_code}': '{your_field_code_value}'
        },
        revision: {record_revision_number}
    },
};

kintoneデータの削除

データの削除方法としては、以下の2種類があります。

  • 複数のレコードIDを指定して削除する
  • リビジョン番号を指定していて複数レコードを削除する

複数のレコードIDを指定して削除する

特定のレコードIDを配列にして削除する方法となります。単一レコードを削除する場合もこちらをご利用ください。

const kintone = require('kintone-nodejs-sdk');

exports.handler = function(context, event, callback) {
    // kintone認証設定(API KEY)
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken(context.KINTONE_API_TOKEN);

    // コネクション作成
    let kintoneConnection = new kintone.Connection(context.KINTONE_APP_URI, kintoneAuth);    

    // レコード作成
    let kintoneRecord = new kintone.Record(kintoneConnection);

    let appID = 1; // アプリID ※ここの値は皆さんの環境に合わせて変更してください
    let recordIDs = [25, 26]; // 削除したいレコードのIDの配列

    kintoneRecord.deleteRecords(appID, recordIDs)
    .then((resp) => {
        Object.keys(resp).forEach(function(key) {
            console.log(key, resp[key]);
        });
        callback(null, 'OK');
    })
    .catch((err) => {
        const error = err.get();
        Object.keys(error).forEach(function(key) {
            console.log(key, error[key]);
        });
        callback(error.message);
    });
};

レコードIDとリビジョン番号を指定して複数レコードを削除する

削除にも排他処理を実装したい場合は、以下のようにリビジョン番号とIDとペアで指定することができます。
この例では、レコードIDが27と28で、それぞれリビジョン番号が1のものを削除します。

const kintone = require('kintone-nodejs-sdk');

exports.handler = function(context, event, callback) {
    // kintone認証設定(API KEY)
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken(context.KINTONE_API_TOKEN);

    // コネクション作成
    let kintoneConnection = new kintone.Connection(context.KINTONE_APP_URI, kintoneAuth);    

    // レコード作成
    let kintoneRecord = new kintone.Record(kintoneConnection);

    let appID = 1; // アプリID ※ここの値は皆さんの環境に合わせて変更してください
    let idsWithRevision = {
        27: 1,
        28: 1,
    };  // 削除したいIDとリビジョン番号を列挙
    
    kintoneRecord.deleteRecordsWithRevision(appID, idsWithRevision)
    .then((resp) => {
        Object.keys(resp).forEach(function(key) {
            console.log(key, resp[key]);
        });
        callback(null, 'OK');
    })
    .catch((err) => {
        const error = err.get();
        Object.keys(error).forEach(function(key) {
            console.log(key, error[key]);
        });
        callback(error.message);
    });
};

まとめ

以上が基本的なkintoneアクセスの方法となります。
これ以外にも、テーブルの操作やコメントの操作などもあるので、これらについては追って記事を書きたいと思います。


Twilio(トゥイリオ)とは

https://twilio.kddi-web.com
Twilioは音声通話、メッセージング(SMS/チャット)、ビデオなどの 様々なコミュニケーション手段をアプリケーションやビジネスへ容易に組み込むことのできるクラウドAPIサービスです。初期費用不要な従量課金制で、各種開発言語に対応しているため、多くのハッカソンイベントやスタートアップなどにも、ご利用いただいております。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5