おはこんばんにちは、みなとです。

少し空き時間ができたので、近頃よくある「Webサイトからスマホのブラウザ上で直接決済」というのを試してみました。

作ったもの

例によってGitHubで公開しています。

step63r/ios-paymentsheet-sample

Demo

決済が完了すると、Stripeに明細が入ります。

全体の流れ

StripeのAPIを使いました。サンプルアプリで、独自ドメインを使って公開するほどのものではなかったので、ngrokというツールで自宅PCに立てたWebサーバを一時的に公開して動かしました。

下記はClaudeポン出しのシーケンスです。基本的には Stripe.js の中でiOS Apple PayのSDKを呼び出しているようで、細かい動きまでは追えていないところではありますが、思ったよりはお手軽な実装かなと思います。

sequenceDiagram
    actor U as ユーザー
    participant B as ブラウザ<br/>(app.js / checkout.js)
    participant SJ as Stripe.js
    participant OS as iOS Apple Pay
    participant S as Express<br/>(server.js)
    participant ST as Stripe API

    Note over ST: 事前: ngrokのドメインをStripeに登録<br/>(Stripe→Appleで検証)

    U->>B: URLを開く
    B->>S: GET /config, GET /products
    S-->>B: 公開可能キー・通貨 / 商品一覧
    U->>B: カートに入れる(localStorageに保存)
    U->>B: レジに進む(/checkout)
    B->>SJ: elements({mode:'payment', amount, currency})<br/>expressCheckout.mount()
    SJ-->>B: ready(Apple Pay利用可否)

    U->>SJ: Apple Payボタンを押す
    SJ->>OS: 支払いシートを起動
    U->>OS: Face IDで承認
    OS-->>SJ: 承認結果
    SJ-->>B: confirmイベント
    B->>SJ: elements.submit()
    B->>S: POST /create-payment-intent {items:[{id,qty}]}
    S->>S: 商品IDと数量から金額を再計算・検証
    S->>ST: paymentIntents.create(amount, jpy)
    ST-->>S: client_secret
    S-->>B: client_secret
    B->>SJ: confirmPayment(elements, client_secret)
    SJ->>ST: 決済確定(Apple Payのトークン)
    ST-->>SJ: succeeded
    SJ-->>B: paymentIntent
    B->>B: カートを空にして /complete へ