4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

この記事は、Twilio Advent Calendar 2022 16日目の記事です。

ECやサブスクリプションビジネスにおいて、顧客との連絡手段を確保することはとても重要です。

中でも電話番号は、商品の発送時や、本人確認などのSMSを送信する時にも利用することがあります。

Stripeの場合、「リダイレクト型決済」のCheckoutでは、電話番号の情報入力もStripe側に任せることができます。

ただしElementsでサイトやアプリに埋め込む場合には、フィールドの作成などある程度の開発が必要です。

この記事では、ユーザーの操作ミスで、誤った電話番号が入力されたまま申し込みが完了しないように、TwilioのLookup APIを利用したバリデーションを組み込む方法を紹介します。

電話番号の検証付き決済フォームを実装する

Step1: クイックスタートのアプリをDLする

今回はStripeの組み込み作業を省力化するため、クイックスタートのサンプルアプリを利用します。

スクリーンショット 2022-12-15 17.28.12.png

記事と同じ設定で進めたい方は、以下の設定で[アプリ全体をダウンロード]ボタンをクリックしましょう。

  • プラットフォーム: Web
  • フロントエンド: React
  • バックエンド: Node
  • フロー: カスタムの決済フロー

stripe.com/docs のサンプルアプリは、ダッシュボードにログインした状態でDLしましょう。
サンプルコード内のAPIキーが、現在ログインしているアカウントのものに自動で切り替わります。

DLしたアプリのライブラリインストールと、サービスの起動を行いましょう。

% npm install
% npm start

http://localhost:3000/checkout にアクセスすると、決済フォームが表示されます。

スクリーンショット 2022-12-15 17.07.23.png

Step2: 電話番号入力フォームを追加する

サンプルアプリの用意ができましたので、早速電話番号の入力フォームを追加します。

まずは必要なライブラリを追加します。

$ npm install validator twilio

src/CheckoutForm.jsxを次のように変更しましょう。

      <PaymentElement id="payment-element" options={paymentElementOptions} />
+      <div
+        style={{
+          display: "flex",
+          justifyContent: "start",
+          flexDirection: "column",
+          margin: "10px auto",
+        }}
+      >
+        <label htmlFor="phone">Phone:</label>
+        <input
+          type="tel"
+          id="phone"
+          style={{
+            border: "1px solid rgb(230, 230, 230)",
+            width: "100%",
+            padding: "7px",
+            boxSizing: "border-box",
+          }}
+          />
+      </div>
      <button disabled={isLoading || !stripe || !elements} id="submit">

電話番号入力フォームが表示されました。

スクリーンショット 2022-12-15 18.54.34.png

入力された番号を、React Hookでstateに格納しましょう。

  const [isLoading, setIsLoading] = useState(false);
+  const [phoneNumber, setPhoneNumber] = useState('')

  useEffect(() => {

...
        <input
          type="tel"
          id="phone"
          style={{
            border: "1px solid rgb(230, 230, 230)",
            width: "100%",
            padding: "7px",
            boxSizing: "border-box",
          }}
+          onChange={e => {
+            setPhoneNumber(e.target.value)
+          }}
          />

Step3: 入力された電話番号を検証する

決済処理の中で、電話番号の検証を行いましょう。

まずは検証のためのAPIを用意します。

server.jsを次のように変更します。

const express = require("express");
+const { Twilio } = require("twilio");
+const client = new Twilio('username', 'password')

...

+app.post("/verify-phone-number", async (req, res) => {
+  const { 'phone_number': phoneNumber } = req.body;
+  try {
+    await client.lookups
+      .phoneNumbers(`+81${phoneNumber}`)
+      .fetch({ type: ['carrier'] });
+    res.status(200).send()
+  } catch (e) {
+    if (e.code === 20404) {
+      res.status(400).json({
+        message: "Invalid phone number"
+      })
+      return
+    }
+    res.status(e.status).json(e)
+  }
+});

app.listen(4242, () => console.log("Node server listening on port 4242!"));

TwilioのLookup APIを利用して、電話番号の検索を行います。

存在しない電話番号の場合には、エラーを返します。

今回は便宜上国コード(+81)を直接設定しています。
実際の運用では、入力フォーム側でコードを設定するか、自動判定するように実装しましょう。

続いてsrc/CheckoutForm.jsxで、追加したAPIを呼び出す処理を追加しましょう。


+  const [errorMessage, setErrorMessage] = useState('');
  const handleSubmit = async (e) => {
    e.preventDefault();

    if (!stripe || !elements) {
      // Stripe.js has not yet loaded.
      // Make sure to disable form submission until Stripe.js has loaded.
      return;
    }

    setIsLoading(true);

+    const result = await fetch('/verify-phone-number', {
+      method: "POST",
+      headers: {
+        "Content-Type": "application/json",
+      },
+      body: JSON.stringify({
+        phone_number: phoneNumber
+      })
+    });
+    if (!result.ok) {
+      const { message } = await result.json();
+      setErrorMessage(message);
+      setIsLoading(false);
+      return;
+    }
    const { error } = await stripe.confirmPayment({
      elements,
      confirmParams: {
        // Make sure to change this to your payment completion page
        return_url: "http://localhost:3000",
      },
    });

これで、フォームのSubmit処理の中で、電話番号の検証も行えるようになりました。

日本以外または存在しない電話番号を入力すると、エラーが発生し、決済が中断されるようになります。

スクリーンショット 2022-12-15 19.34.17.png

Verify APIでの、より強力な検証

Twilioでは、電話番号の確認だけでなくSMSや音声通話で確認コードを送信することもできます。

この機能を利用することで、より強力な本人確認を実装できます。

4
0
0

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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?