Help us understand the problem. What is going on with this article?

Twilio Pay を使って電話決済を体験する(上級編)

More than 1 year has passed since last update.

はじめに

これは、2019/03/21(木・祝)開催 JP_Stripes Connect 2019のワークショップ『「電話でペイ!」(Twilio Pay)を試してみよう!』で使用する資料です。

Twilio を使って電話決済を体験する(初級編)
Twilio を使って電話決済を体験する(中級編)
Twilio を使って電話決済を体験する(上級編) ←こちら

Twilio を使って電話決済を体験する(上級編)では、初級編・中級編で作成したアプリケーションを利用して、2者(オペレータとクライアント)で電話で話をしている途中に、Twilio<Pay>によるクレジットカード入力(状況はWebページで確認)できるものを作成します。

前提

こちらは、Twilio を使って電話決済を体験する(中級編)にて、StripeやTwilioの設定・構築ができていることが前提となります。

注意事項

Twilio を使って電話決済を体験する(初級編)および、Twilio を使って電話決済を体験する(中級編)の注意事項に記載した費用が発生します。
また、TwilioConferenceとOutgoingAPIを利用します。その際に、料金が発生します。くわしくはこちら

得られるもの

Twilio三者通話(Conference)を利用して、Twilioの状況を電話で確認することが体験できます。
例えば、テレフォンショッピングなどの決済で、オペレータと会話しながら、電話決済を行う場合などに利用できます。

ざっくり構成

スクリーンショット 2019-03-14 18.10.40.png

  1. 発信:TwilMLApp(ブラウザフォン)からTwiiloFunctionsを実行、TwilioConferenceを生成し、自信のケータイ電話に発信する。※ブラウザフォンとケータイ電話とがTwilioConference内で通話できる状態となる。
  2. 実行:ブラウザからTwilioFunctionを実行
  3. 決済番号に発信:実行されたTwilioFunctionsが、決済番号に発信しTwilioConferenceと接続する(ブラウザフォン、ケータイ、決済番号への発信の三者間通話を構築)。決済番号は初級で作成した仕組みにしたがい、<Pay>の案内を発話、その内容がTwilioConferenceを介しブラウザフォンとケータイから聞こえる。

事前準備

ワークショップ

以下の手順になります。

  • TwilioConferenceを使った電話転送の仕組みを作成する
  • TwilioConferenceにTwilio<Pay>を割り込みさせる
  • 状況確認画面にTwilio<Pay>割り込みボタンを付ける。
  • テストする。

TwilioConferenceを使った電話転送の仕組みを作成する

今回、TwilioConferenceという複数人で通話する仕組みを利用します。
はじめに、TwilioConferenceの設定を変更します。
Twilioの管理コンソールからProgrammable Voice → Conferences設定 を選択します。
AGENT CONFERENCEを選択し、保存をクリックします。
スクリーンショット 2019-03-07 13.47.14.png

クライアントからの電話を受け、オペレーターへ電話をつなぐ処理をTwilioFunctionsで作成します。
まずは、Functionで利用する定数(環境変数)を便宜上登録しておきます。
Twilioの管理コンソールからRuntime → Functions設定 を選択します。
スクリーンショット 2019-03-05 13.19.22.png
Environmental Variablesにある赤いボタンプラスをクリックし、以下のKEY-VALUEを追加します。
入力が終わったら、画面下のSaveをクリックします。

KEY VALUE
PAY_NUMBER 初級編で購入した電話番号をE.164 形式(+81で始まる形式)で入力
PAY_MY_MOBILE_NUMBER オペレータ用番号(自分のケータイ番号)をE.164 形式(+81で始まる形式)で入力

Twilioの管理コンソールからRuntime → Functions を選択し、赤いプラスボタンをクリック、Functionを新規作成します。
テンプレートはBlankを選択し、Createをクリックします。表示された画面で、以下のように入力し、Saveをクリックします。

項目名 設定値
FUNCTION NAME PayForwarding
PATH /pay-forwarding
ACCESS CONTROL チェックあり
EVENT (未選択)
CODE 以下参照
exports.handler = function(context, event, callback) {
    const toNumber = event.To;

    // Conferenceを生成して発信元と接続
    const twiml = new Twilio.twiml.VoiceResponse();
    let dialParams = {}
    dialParams.callerId = toNumber
    dial = twiml.dial(dialParams)
    dial.conference({
        region: 'jp1',
        endConferenceOnExit: true,
    }, 'payConference')  

    // 自身のケータイへ発信、Conferenceに参加させる
    const client = context.getTwilioClient() 
    client
    .conferences('payConference')
    .participants.create({
        region: 'jp1',
        to: context.PAY_MY_MOBILE_NUMBER,
        from: toNumber,
        endConferenceOnExit: true,
        earlyMedia: true,
    })
    .then(participant => {
        console.log(participant.sid)
        callback(null, twiml)
    })
    .catch(error => {
        console.log(error)
        callback(error)
    })      
};

スクリーンショット 2019-03-08 16.47.12.png

一旦、動作確認をします。

動作確認は、TwiML Appsを使ってブラウザフォンで行います。
Twilioの管理コンソールからProgrammable VoiceTwiMLTwiML Appsを選択します。表示された画面でCreate new TwiML Appをクリックし、新規作成をおこないます。
スクリーンショット 2019-03-07 11.43.56.png
表示された画面に以下のように入力をします。入力し終わったら、Createをクリックします。

項目名 設定値
Properties FRIENDLY NAME PayForwardingTest
Voice REQUEST URL さきほど作成したFunction「PayForwarding」のPATH

スクリーンショット 2019-03-07 11.57.00.png
作成されると、TwiMLAppsの一覧画面が表示されますので、作成した「PayForwardingTest」をクリックします。
スクリーンショット 2019-03-07 11.58.06.png
表示された画面の右側にあるCallをクリックします。
スクリーンショット 2019-03-07 11.59.46.png
ブラウザフォンが表示され、Functionが実行され、オペレータ用番号(自分のケータイ番号)に電話がかかってきます。
通話ができることを確認してください。
スクリーンショット 2019-03-07 12.03.52.png

TwilioConferenceにTwilio<Pay>を割り込みさせる

クライアントとオペレーターとでTwilioConferenceを介して通話ができるようになりました。
この通話に、Twilio<Pay>を割り込みさせる処理をTwilioFunctionsで作成します。
Twilioの管理コンソールからRuntime → Functions を選択し、赤いプラスボタンをクリック、Functionを新規作成します。
テンプレートはBlankを選択し、Createをクリックします。表示された画面で、以下のように入力し、Saveをクリックします。
これは、受付用電話番号から決済用電話番号に電話をかける処理になります。

項目名 設定値
FUNCTION NAME PayGuideStart
PATH /pay-guide-start
ACCESS CONTROL チェックなし
EVENT (未選択)
CODE 以下参照
exports.handler = function(context, event, callback) {
    const client = context.getTwilioClient();
    client
    .conferences('payConference')
    .participants.create({
        region: 'jp1',
        to: context.PAY_NUMBER,
        from: context.PAY_NUMBER,
    })
    .catch(error => {
        console.log(error);
        callback(error);
    });  
};

ここでのポイントは、toとfromを同じ番号としておくことです。

状況確認画面にTwilio<Pay>割り込みボタンを付ける。

中級編で作成した状況確認画面に、先ほど作成したTwilio<Pay>の割り込み処理を呼び出すボタンを追加します。
以下のURLからファイルをダウンロードしてください。
https://heady-sea-5045.twil.io/assets/paystatus_advanced.zip

Twilioの管理コンソールからRuntimeAssetsを選択します。
Add an Assetsをクリックし、上記zipファイルを展開したものをアップロードします。
※中級編ですでに同名のファイルをアップロード済みですので、上書きしてください。
以下、内容を記載しておきます。Guideボタンを追加しています。

paystatus.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Twilio Pay Status Page</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js"></script>
    <script src="https://media.twiliocdn.com/sdk/js/sync/releases/0.8.4/twilio-sync.min.js"></script>
    <script src="./paystatus.js?version=1.1"></script>
  </head>
  <body>
    <div class="container">
        <h3>Twilio Pay Status</h3>
        <div class="form-group">
            <label>Status</label>
            <label id="Status"></label>
        </div>
        <div class="form-group">
            <label>PaymentCardNumber</label>
            <input id="PaymentCardNumber" type="text" class="form-control" readonly>
        </div>
        <div class="form-group">
            <label>ExpirationDate</label>
            <input id="ExpirationDate" type="text" class="form-control" readonly>
        </div>
        <div class="form-group">
            <label>SecurityCode</label>
            <input id="SecurityCode" type="text" class="form-control" readonly>
        </div>
        <button id="btnClear" type="button" class="btn btn-danger">Clear</button>
        <!-- こちらのボタンを追加 -->
        <button id="btnGuide" type="button" class="btn btn-info">Guide</button>
        </div>
  </body>
</html>
paystatus.js
let syncDoc, syncClient;

$(function() {

    $.getJSON('../pay-status-sync-token', function (tokenResponse) {
        syncClient = new Twilio.Sync.Client(tokenResponse.token, { logLevel: 'info' });
        syncClient.document('PayStatus')
        .then(function(doc) {
            syncDoc = doc;
            syncDoc.on('updated', event => {
                console.log("Sync updated.");
                console.log(event);
                $('#PaymentCardNumber').val(event.value.PaymentCardNumber);
                $('#ExpirationDate').val(event.value.ExpirationDate);
                $('#SecurityCode').val(event.value.SecurityCode);
                $('#Status').html(event.value.Status);
            });
        })
        .catch(function(error) {
            console.log(error);
        });

        syncClient.on('tokenAboutToExpire', () => {
            $.getJSON('../pay-status-sync-token', function (tokenResponse) {
                syncClient.updateToken(tokenResponse.token);
            });
        });
    });

    $('#btnClear').on('click', function() {
        const value = {
            PaymentCardNumber : "",
            ExpirationDate    : "",
            SecurityCode      : "",
            Status            : "",
        };
        syncDoc.set(value);
    });

    // こちらの処理を追加
    $('#btnGuide').on('click', function() {
        $.ajax({
                url:'../pay-guide-start',
                type:'POST',
            })
            .done( (data) => {
                alert('Sending completed');
            }
        );
    });

});

Assetにアップロードできたら、htmlファイルのPATHのコピーボタンをクリックし、コピーしておきます。

テストする

さきほど動作確認で利用したTwiMLAppsにてテストを行います。

  • TwiML Appsを使ってブラウザフォンでテストを行ってください。Twilioの管理コンソールからProgrammable VoiceTwiMLTwiML Appsを選択、上記で作成したPayForwardingTestをクリックし、表示された画面でCallをクリックします。
  • 通話途中で、状況表示画面のGuideボタンをクリックします。
  • この処理は初級編で作成した決済番号へ電話をかける処理です。トライアルアカウントの場合は、ガイダンスが流れますので、聞いた後、ケータイ電話でなにかキーをプッシュしてください
  • 通話中にTwilio<Pay>の音声が流れるので、クレジットカード番号、有効期限、セキュリティコードを入力します。
  • 随時、状況表示画面が更新されていることを確認します。 スクリーンショット 2019-03-05 17.59.43.png

お片付け

Twilioアカウントをアップグレードされた場合、そのままにしておくと別途費用が発生します。
以下の内容に従い、お片付けをすることを推奨します。

Stripeアカウントについて

Stripeアカウントは、本番利用しないと料金は発生しませんので、何もしなくてOKです。
今後ご利用にならない場合は、アカウント自体を削除してください。

Twilioアカウントについて

Number Phonesについては、そのままにしてくと費用が発生します。それ以外はそのままにしておいても費用は発生しませんが、外部からアクセスされたことにより、通話などが発生し、結果費用が発生する場合がありますので、必要なければ削除を推奨します。

Number Phones

1つの電話番号につき108円/月の費用が発生します。
Twilioの管理コンソールからPhone Numbers → 番号の管理アクティブな電話番号 を選択します。
スクリーンショット 2019-03-05 18.09.20.png
該当の番号をクリックし、表示された画面の下部にあるこの番号をリリースするをクリックします。
スクリーンショット 2019-03-05 18.10.42.png

TwilioAssets

アップロードしたファイルを削除します。そのままにしていても費用は発生しませんが、不用意にアクセスされた場合、費用が発生することがあります。

  • 画面にアクセスするとTwilioSyncが動作し、費用が発生します。
  • 画面にアクセスしGuideボタンをクリックすると、発信するため通話料が発生します。 Twilioの管理コンソールからRuntime → Aeets を選択し、該当のファイルの右側にあるゴミ箱アイコンをクリックします。 スクリーンショット 2019-03-05 18.18.18.png

TwilioFunctions

作成したFunctionを削除します。そのままにしていても費用は発生しませんが、不用意にアクセスされた場合、費用が発生することがあります。

  • 作成したFunctionsによっては、発信をするため通話料が発生します。 Twilioの管理コンソールからRuntime → Functions を選択します。 スクリーンショット 2019-03-05 18.21.19.png 該当のFunctionをクリックし、表示された画面の下部にあるDelete this Functionをクリックします。 スクリーンショット 2019-03-05 18.23.02.png

Twilio TwiML Bins

作成したTwiML Binsを削除します。そのままにしていても費用は発生しません。削除する場合は以下のように行います。
Twilioの管理コンソールからRuntime → TwiML Bins を選択します。
スクリーンショット 2019-03-05 18.31.26.png
該当のTwiMLを選択し、表示された画面の下部にあるDelete this TwiML Binをクリックします。
スクリーンショット 2019-03-05 18.32.29.png

TwilioSync

作成したTwilioSyncを削除します。
利用しなければ費用は発生しませんが、気になる場合は、削除しておきます。
※例えば、TwilioAssetでアップロードしている決済状況表示画面にアクセスするだけで、利用したことになります。
Twilioの管理コンソールからSync → Service を選択します。
スクリーンショット 2019-03-05 18.38.29.png
作成したSyncServiceの名前を選択、表示された画面の下部にあるDelete this serviceをクリックします。
スクリーンショット 2019-03-05 18.40.08.png

補足

この状態だと、クレジットカード番号をプッシュしている音声がオペレータ役に聞こえてしまうので、聞こえないようにConferenceのMute機能を実装する必要があります。

お礼

今回の資料を作成するにあたり、以下を参考にさせていただきました。ありがとうございます。
https://qiita.com/mobilebiz/items/4490fe5a03c5192ce06f

takeshifurusato
TwilioJP-UG Okayama(Twilio Champions) / JAWS-UG Okayama / JP_Stripes Okayama / Okayama WordPress Meetup / SORACOM UG Okayama
https://takeshi.furusato.blog
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away