支払いを受け付ける
リスナーの早期登録、プラグイン初期化、リーダー接続、PaymentIntent の確定という順で Stripe Terminal の対面決済を処理します。
アプリケーションレベルのリスナーを登録する
Terminal のイベントリスナーは JavaScript アプリケーションの起動ごとに一度だけ、初期化や操作開始より前に登録し、所有者が存続する間は保持します。
enum TerminalEventsEnum
| Member | Value |
|---|---|
Loaded |
'terminalLoaded' |
DiscoveredReaders |
'terminalDiscoveredReaders' |
DiscoveringReaders |
'terminalDiscoveringReaders' |
CancelDiscoveredReaders |
'terminalCancelDiscoveredReaders' |
ConnectedReader |
'terminalConnectedReader' |
DisconnectedReader |
'terminalDisconnectedReader' |
ConnectionStatusChange |
'terminalConnectionStatusChange' |
UnexpectedReaderDisconnect |
'terminalUnexpectedReaderDisconnect' |
ConfirmedPaymentIntent |
'terminalConfirmedPaymentIntent' |
CollectedPaymentIntent |
'terminalCollectedPaymentIntent' |
Canceled |
'terminalCanceled' |
Failed |
'terminalFailed' |
RequestedConnectionToken |
'terminalRequestedConnectionToken' |
ReportAvailableUpdate |
'terminalReportAvailableUpdate' |
StartInstallingUpdate |
'terminalStartInstallingUpdate' |
ReaderSoftwareUpdateProgress |
'terminalReaderSoftwareUpdateProgress' |
FinishInstallingUpdate |
'terminalFinishInstallingUpdate' |
BatteryLevel |
'terminalBatteryLevel' |
ReaderEvent |
'terminalReaderEvent' |
RequestDisplayMessage |
'terminalRequestDisplayMessage' |
RequestReaderInput |
'terminalRequestReaderInput' |
PaymentStatusChange |
'terminalPaymentStatusChange' |
ReaderReconnectStarted |
'terminalReaderReconnectStarted' |
ReaderReconnectSucceeded |
'terminalReaderReconnectSucceeded' |
ReaderReconnectFailed |
'terminalReaderReconnectFailed' |
型付き addListener は大半のメンバーを扱います。ネイティブ探索の DiscoveringReaders と CancelDiscoveredReaders には専用オーバーロードがありません。
初期化
RequestedConnectionToken と setConnectionToken を使ったアプリ側の認証付きリクエストを推奨します。通常の認証情報を付与し、失敗を検証できます。SDK は必要になるたび新しい一回限りの接続トークンを要求するため、リスナーを initialize より前に登録します。開発中は isTest を設定します。
method initialize(...)
Initializes the Stripe Terminal SDK and its connection-token provider.
Call this once before discovering readers.
When tokenProviderEndpoint is provided, the plugin sends a POST request
and expects { secret: string }. When it is omitted, handle
RequestedConnectionToken and call setConnectionToken() instead.
initialize(options: StripeTerminalInitializationOptions) => Promise<void>
tokenProviderEndpoint 互換モード
単純な構成では利用できますが、v8.2.1 のネイティブクライアントは認証ヘッダーも本文も付けられない空の HTTP POST を送信します。別の方法で認証・保護できる場合だけ使用し、無制限に公開されたトークン作成エンドポイントを用意しないでください。
レスポンスは secret 文字列を持つ JSON でなければなりません。
{ "secret": "pst_..." }
接続トークンはサーバーで Stripe のシークレット API キーを使って作成します。シークレットキー、トークン作成可能な制限付きキー、生の接続トークンをアプリ、ログ、公開設定へ含めてはいけません。
Web の initialize は新しいプラグインインスタンスを必要とし、成功後の再呼び出しは例外になります。
接続トークンを安全に渡す
tokenProviderEndpoint を省略し、initialize より前に RequestedConnectionToken を登録します。通常の認証方式で取得し、成功レスポンスと secret を検証して setConnectionToken({ token }) へ渡します。取得要求中だけ呼び出し、レスポンスやトークンをログへ出さないでください。
method setConnectionToken(...)
Supplies a connection-token secret after RequestedConnectionToken is
emitted. Create each token on your server and use it only once.
setConnectionToken(options: SetConnectionTokenOptions) => Promise<void>
バックエンドでPaymentIntentを作成する
サーバーで PaymentIntent を作成し、クライアントシークレットだけをアプリへ返します。
payment_method_typesにcard_presentを含める- Stripe のシークレットキーをサーバーに保持する
- クライアントシークレットだけを
collectPaymentMethodへ渡す - 公開可能キーで card-present PaymentIntent を作成・確定しない
await stripe.paymentIntents.create({
amount: 1000,
currency: 'usd',
payment_method_types: ['card_present'],
capture_method: 'automatic',
});
リーダーを探索する
TerminalConnectTypes と、接続方式が必要とする Stripe Terminal の locationId を指定して、近くのリーダーまたはシミュレーションリーダーを探索します。
- Web は
Internetだけに対応します。 - iOS Bluetooth はスキャン更新ごとに
DiscoveredReadersを複数回通知します。bluetoothScanWaitTimeで Promise が現在の一覧を返すまでの待ち時間を指定できます。 - Android は実行時の
ACCESS_FINE_LOCATION権限が必要です。 - 利用者が探索画面を離れたら
cancelDiscoverReadersを呼び、長い探索を止められるUIを用意します。
Promise に加えて DiscoveredReaders も監視してください。
method discoverReaders(...)
Discovers readers using the requested transport. The returned readers are
snapshots; listen for DiscoveredReaders when continuous discovery can
produce additional results.
discoverReaders(options: DiscoverReadersOptions) => Promise<{ readers: ReaderInterface[]; }>
interface DiscoverReadersOptions
| Prop | Type | Description | Since |
|---|---|---|---|
type |
TerminalConnectTypes |
Discovery method and reader transport to use. | 5.1.0 |
locationId |
string |
Stripe Terminal Location ID used to scope internet reader discovery and reader registration where required. | 5.1.0 |
bluetoothScanWaitTime |
number |
Only applies to Bluetooth scan discovery (iOS only). During discovery, readers are reported via DiscoveryDelegate.didUpdateDiscoveredReaders. This timeout controls how long to wait before resolving the discoverReaders method with the current list. If this setting is not specified or is set to 0, the initial scan results will be returned. |
7.2.0 |
enum TerminalConnectTypes
| Member | Value |
|---|---|
Simulated |
'simulated' |
Internet |
'internet' |
Bluetooth |
'bluetooth' |
Usb |
'usb' |
TapToPay |
'tap-to-pay' |
HandOff |
'hand-off' |
リーダーへ接続する
支払い情報の収集前に、現在の探索結果から得た reader を接続します。autoReconnectOnUnexpectedDisconnect の既定値は false です。iOS Tap to Pay の merchantDisplayName と onBehalfOf は接続設定へ適用され、Android では PaymentIntent 側に設定します。
method connectReader(...)
Connects to a reader returned by discoverReaders().
connectReader(options: ConnectReaderOptions) => Promise<void>
支払い方法を収集する
バックエンドから受け取った PaymentIntent のクライアントシークレットを collectPaymentMethod へ渡します。
method collectPaymentMethod(...)
Collects a payment method for a server-created PaymentIntent. Confirm the
collected intent with confirmPaymentIntent().
collectPaymentMethod(options: CollectPaymentMethodOptions) => Promise<void>
PaymentIntentを確定する
収集済み PaymentIntent を処理・確定します。収集成功前に呼ぶと拒否されます。
method confirmPaymentIntent()
Confirms the PaymentIntent most recently collected by the reader.
confirmPaymentIntent() => Promise<void>
ConfirmedPaymentIntent はクライアント UI 用の信号です。注文はバックエンドが payment_intent.succeeded などの Stripe Webhook を検証した後だけ確定してください。
キャンセルとエラーを処理する
cancelCollectPaymentMethodは進行中の収集をキャンセルし、成功時にCanceledを通知します。- 収集または確定の失敗時には
Failedが通知され、Promise も拒否されます。 - 予期しない切断には
ConnectionStatusChangeではなくUnexpectedReaderDisconnectを使用します。
method cancelCollectPaymentMethod()
Cancels an in-progress collectPaymentMethod() call.
cancelCollectPaymentMethod() => Promise<void>
リーダーを切断する
支払いフロー完了後、またはリーダーが不要になったときに切断します。
method disconnectReader()
Disconnects the active reader. Resolves immediately if none is connected.
disconnectReader() => Promise<void>
import {
StripeTerminal,
TerminalConnectTypes,
TerminalEventsEnum,
} from '@capacitor-community/stripe-terminal';
const paymentStatusListener = await StripeTerminal.addListener(
TerminalEventsEnum.PaymentStatusChange,
({ status }) => console.log(status),
);
const confirmedListener = await StripeTerminal.addListener(
TerminalEventsEnum.ConfirmedPaymentIntent,
() => console.log('Payment processed; waiting for the server webhook'),
);
const failedListener = await StripeTerminal.addListener(
TerminalEventsEnum.Failed,
(error) => console.error(error),
);
// Register the authenticated RequestedConnectionToken provider first.
await StripeTerminal.initialize({ isTest: true });
const { readers } = await StripeTerminal.discoverReaders({
type: TerminalConnectTypes.TapToPay,
locationId: '**************',
});
const reader = readers[0];
if (!reader) throw new Error('No compatible reader found');
await StripeTerminal.connectReader({
reader,
});
try {
const response = await fetch('https://example.com/connection/intent', {
method: 'POST',
headers: { Authorization: `Bearer ${accessToken}` },
});
if (!response.ok) throw new Error(`PaymentIntent request failed: ${response.status}`);
const { paymentIntent } = (await response.json()) as { paymentIntent: string };
await StripeTerminal.collectPaymentMethod({ paymentIntent });
await StripeTerminal.confirmPaymentIntent();
} finally {
await StripeTerminal.disconnectReader();
}
// Remove the three listeners when their application-level owner is destroyed.
import { StripeTerminal, TerminalEventsEnum } from '@capacitor-community/stripe-terminal';
await StripeTerminal.addListener(
TerminalEventsEnum.RequestedConnectionToken,
async () => {
try {
const response = await fetch('https://example.com/connection/token', {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) throw new Error(`Connection token request failed: ${response.status}`);
const data = (await response.json()) as { secret?: unknown };
if (typeof data.secret !== 'string' || !data.secret) {
throw new Error('Connection token response is missing secret');
}
await StripeTerminal.setConnectionToken({ token: data.secret });
} catch (error) {
// An empty token fails the pending native callback instead of leaving it hanging.
try {
await StripeTerminal.setConnectionToken({ token: '' });
} finally {
console.error('Unable to supply a connection token', error);
}
}
},
);
await StripeTerminal.initialize({
isTest: true,
});