Eine Zahlung abwickeln
Wickeln Sie eine Zahlung vor Ort mit Stripe Terminal ab: Registrieren Sie die Listener frühzeitig, initialisieren Sie das Plugin, verbinden Sie ein Lesegerät und bestätigen Sie einen PaymentIntent.
Voraussetzungen für den ersten Test
Bereiten Sie vor dem ersten Zahlungsversuch Folgendes vor:
- Die Plattformeinstellungen aus Konfiguration, einschließlich der erforderlichen Android-Berechtigungen
- Einen authentifizierten Endpunkt für Verbindungstoken, den Ihre App aufrufen kann
- Einen auf Ihrem Server erstellten Test-PaymentIntent mit
card_present - Eine Stripe-Terminal-
locationId, die zum gesuchten Verbindungstyp passt
Der erste erfolgreiche Ablauf ist: Lesegerät verbinden → Zahlungsmethode erfassen → PaymentIntent bestätigen und ConfirmedPaymentIntent empfangen. Die Auftragsabwicklung muss weiterhin auf Ihren Stripe-Webhook warten. Verwenden Sie für simulierte Lesegeräte einen unterstützten Verbindungstyp mit isTest: true, wie unter Konfiguration beschrieben. TerminalConnectTypes.Simulated ist nicht universell einsetzbar.
Listener auf Anwendungsebene registrieren
Registrieren Sie Terminal-Ereignislistener einmal pro Start der JavaScript-Anwendung, möglichst früh beim Bootstrap, etwa in main.ts, einem Anwendungsinitialisierer oder einem beim Start initialisierten Singleton-Service, und vor jeder Initialisierung oder Operation. Lassen Sie sie für die gesamte Lebensdauer ihrer zuständigen Instanz auf Anwendungsebene registriert.
enum TerminalEventsEnum
| Mitglied | Wert |
|---|---|
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' |
Die typisierten Überladungen von addListener decken die meisten dieser Einträge ab. DiscoveringReaders und CancelDiscoveredReaders werden beim Start und Abbruch der nativen Suche ausgelöst, haben aber keine eigenen Überladungen; siehe die Seite API.
Initialisieren
Bevorzugen Sie eine authentifizierte Anfrage aus der App über RequestedConnectionToken und setConnectionToken. So kann Ihre App ihre üblichen Autorisierungsdaten mitsenden und Fehler prüfen. Registrieren Sie den Listener vor initialize; das Terminal SDK fordert bei Bedarf jeweils ein neues Verbindungstoken zur einmaligen Verwendung an. Setzen Sie während der Entwicklung isTest.
method initialize(...)
Initialisiert das Stripe Terminal SDK und seinen Anbieter für Verbindungstoken.
Vor der Lesegerätesuche einmal aufrufen.
Wenn tokenProviderEndpoint angegeben ist, sendet das Plugin eine POST-Anfrage
und erwartet { secret: string }. Wenn der Wert fehlt, stattdessen
RequestedConnectionToken behandeln und setConnectionToken() aufrufen.
initialize(options: StripeTerminalInitializationOptions) => Promise<void>
Im Web erfordert initialize eine neue Plugin-Instanz: Ein erneuter Aufruf nach erfolgreicher Initialisierung löst Stripe Terminal has already been initialized aus.
Ein Verbindungstoken sicher bereitstellen
Lassen Sie tokenProviderEndpoint weg und registrieren Sie RequestedConnectionToken vor initialize. Benötigt das SDK ein Token, löst das Plugin dieses Ereignis aus und wartet auf setConnectionToken({ token }).
Rufen Sie das Token mit Ihrem üblichen Autorisierungsmechanismus ab, verlangen Sie eine erfolgreiche Antwort, prüfen Sie secret und übergeben Sie es als token. Rufen Sie setConnectionToken nur auf, während ein Tokenabruf aussteht; Android und iOS weisen zusätzliche Aufrufe mit Stripe Terminal do not pending fetchConnectionToken zurück. Protokollieren Sie niemals die Antwort oder das Token.
method setConnectionToken(...)
Übergibt ein Verbindungstoken-Secret, nachdem RequestedConnectionToken
ausgelöst wurde. Jeden Token auf dem Server erstellen und nur einmal verwenden.
setConnectionToken(options: SetConnectionTokenOptions) => Promise<void>
Kompatibilitätsmodus tokenProviderEndpoint
tokenProviderEndpoint steht für einfache Bereitstellungen zur Verfügung. Die nativen Clients der Version v8.2.1 senden jedoch einen einfachen HTTP-POST: Aufrufer können weder einen Autorisierungsheader noch einen Anfragekörper hinzufügen. Verwenden Sie ihn nur, wenn Ihr Server die Anfrage auf anderem Weg authentifizieren und absichern kann. Stellen Sie niemals einen uneingeschränkt öffentlichen Endpunkt zur Tokenerstellung bereit.
Ist tokenProviderEndpoint gesetzt, sendet das Plugin einen HTTP-POST mit leerem Anfragekörper. Die Antwort muss JSON mit einer Zeichenfolge secret sein:
{ "secret": "pst_..." }
Dieser Wert ist ein Stripe-Terminal-Verbindungstoken. Erstellen Sie es auf dem Server mit Ihrem geheimen API-Schlüssel (stripe.terminal.connectionTokens.create()). Hinterlegen Sie den geheimen Schlüssel, eingeschränkte Schlüssel mit Berechtigung zur Tokenerstellung oder unverarbeitete Verbindungstoken niemals im App-Binary, in Protokollen oder in einer öffentlichen Clientkonfiguration.
Die offizielle Demo stellt POST /connection/token bereit und gibt { secret } zurück; passen Sie deren Authentifizierung und Autorisierung an Ihre Anwendung an.
Einen PaymentIntent im Backend erstellen
Erstellen Sie den PaymentIntent auf Ihrem Server. Die offizielle Demo verwendet POST /connection/intent und gibt { paymentIntent } als Client-Secret zurück.
Voraussetzungen passend zum Plugin und zur Demo:
payment_method_typesmusscard_presententhalten- Bewahren Sie den geheimen Stripe-Schlüssel auf dem Server auf
- Übergeben Sie nur das Client-Secret an
collectPaymentMethod({ paymentIntent }) - Erstellen oder bestätigen Sie keine PaymentIntents für Zahlungen mit physisch vorliegender Karte mit einem veröffentlichbaren Schlüssel in der App
Serverbeispiel aus der Demo:
await stripe.paymentIntents.create({
amount: 1000,
currency: 'usd',
payment_method_types: ['card_present'],
capture_method: 'automatic',
});
Lesegeräte suchen
Suchen Sie nach Lesegeräten in der Nähe oder nach simulierten Lesegeräten. Geben Sie einen Wert aus TerminalConnectTypes und eine Stripe-Terminal-locationId an, sofern der Verbindungstyp sie benötigt.
locationId wird bei der Internetsuche verwendet und ist beim Verbinden von Tap-to-Pay-, Bluetooth- und Android-USB-Lesegeräten erforderlich. Die Internetsuche kann nach Standort filtern; Tap to Pay und Bluetooth übernehmen den Standort in die Verbindungskonfiguration.
Besonderheiten:
- Web unterstützt nur
Internet. Alle anderen Werte fürtypesind nicht verfügbar. - iOS Bluetooth meldet Lesegeräte mehrfach über
DiscoveredReaders, während sich die Suche aktualisiert. Siehe Stripe: Ein Bluetooth-Lesegerät verbinden (iOS). Setzen SiebluetoothScanWaitTime(in Millisekunden), damitdiscoverReadersvor der Auflösung mit der aktuellen Liste wartet. Bei0oder ohne Angabe wird das erste Suchergebnis zurückgegeben. - iOS löst beim Suchstart außerdem
DiscoveringReadersaus. USB, HandOff undSimulatedalstypesind nicht implementiert. - Android benötigt
ACCESS_FINE_LOCATIONzur Laufzeit; andernfalls wirddiscoverReadersabgewiesen.Simulatedwird als Bluetooth-Suche behandelt.HandOffentspricht Apps on Devices. - Rufen Sie
cancelDiscoverReadersauf, wenn der Nutzer die Suchoberfläche verlässt. Im Web hat der Abbruch keine Wirkung. Geben Sie dem Nutzer immer eine Möglichkeit, eine lange Bluetooth-Suche zu beenden.
Hören Sie zusätzlich zum Warten auf das Promise auf DiscoveredReaders. Unter iOS mit Bluetooth liefert der Listener die laufend aktualisierte Liste; das Promise kann bereits vor dem letzten Ereignis aufgelöst werden.
method discoverReaders(...)
Sucht Lesegeräte mit der gewünschten Verbindungsart. Die zurückgegebenen Lesegeräte sind
Momentaufnahmen; auf DiscoveredReaders reagieren, wenn die fortlaufende Suche
weitere Ergebnisse liefern kann.
discoverReaders(options: DiscoverReadersOptions) => Promise<{ readers: ReaderInterface[]; }>
interface DiscoverReadersOptions
| Eigenschaft | Typ | Beschreibung | Seit |
|---|---|---|---|
type |
TerminalConnectTypes |
Zu verwendende Suchmethode und Verbindungsart des Lesegeräts. | 5.1.0 |
locationId |
string |
Stripe Terminal Location ID zur Eingrenzung der Suche nach Internetlesegeräten und zur Lesegeräteregistrierung, soweit erforderlich. | 5.1.0 |
bluetoothScanWaitTime |
number |
Gilt nur für die Bluetooth-Suche (nur iOS). Während der Suche werden Lesegeräte über DiscoveryDelegate.didUpdateDiscoveredReaders gemeldet. Dieses Zeitlimit bestimmt, wie lange gewartet wird, bevor die Methode discoverReaders mit der aktuellen Liste aufgelöst wird. Wenn die Einstellung fehlt oder 0 ist, werden die ersten Suchergebnisse zurückgegeben. |
7.2.0 |
enum TerminalConnectTypes
| Mitglied | Wert |
|---|---|
Simulated |
'simulated' |
Internet |
'internet' |
Bluetooth |
'bluetooth' |
Usb |
'usb' |
TapToPay |
'tap-to-pay' |
HandOff |
'hand-off' |
Ein Lesegerät verbinden
Verbinden Sie eines der gefundenen Lesegeräte, bevor Sie Zahlungsdaten erfassen. Das Objekt reader muss aus dem aktuellen Suchergebnis stammen (serialNumber ist die primäre Kennung des Plugins).
autoReconnectOnUnexpectedDisconnect ist standardmäßig false und wird für Tap to Pay und Bluetooth angewendet. Android USB aktiviert derzeit die automatische Wiederverbindung in der nativen Verbindungskonfiguration. Internetverbindungen verwenden dieses Flag nicht.
merchantDisplayName und onBehalfOf gelten für iOS Tap to Pay (LocalMobileReader). Unter Android setzen Sie die Angaben zum verbundenen Konto und zur Anzeige stattdessen am PaymentIntent.
method connectReader(...)
Verbindet ein von discoverReaders() zurückgegebenes Lesegerät.
connectReader(options: ConnectReaderOptions) => Promise<void>
Eine Zahlungsmethode erfassen
Übergeben Sie das Client-Secret des PaymentIntent aus Ihrem Backend an collectPaymentMethod. Das Plugin ruft diesen PaymentIntent ab und erfasst anschließend die Zahlungsmethode am verbundenen Lesegerät.
method collectPaymentMethod(...)
Erfasst eine Zahlungsmethode für einen serverseitig erstellten PaymentIntent. Den
erfassten Intent mit confirmPaymentIntent() bestätigen.
collectPaymentMethod(options: CollectPaymentMethodOptions) => Promise<void>
Den PaymentIntent bestätigen
Verarbeiten und bestätigen Sie den PaymentIntent, dessen Zahlungsmethode erfasst wurde. confirmPaymentIntent wird abgewiesen, wenn die Erfassung zuvor nicht erfolgreich war (PaymentIntent not found for confirmPaymentIntent).
method confirmPaymentIntent()
Bestätigt den zuletzt vom Lesegerät erfassten PaymentIntent.
confirmPaymentIntent() => Promise<void>
ConfirmedPaymentIntent ist ein Signal für die Clientoberfläche und keine Freigabe zur Auftragsabwicklung. Wickeln Sie den Auftrag erst ab, nachdem Ihr Backend einen Stripe-Webhook wie payment_intent.succeeded geprüft hat.
Abbruch und Fehler behandeln
cancelCollectPaymentMethodbricht eine laufende Erfassung ab. Bei Erfolg wird das Promise aufgelöst undCanceledausgelöst.Failedwird ausgelöst, wenncollectPaymentMethododerconfirmPaymentIntentfehlschlägt. Das Promise desselben Aufrufs wird ebenfalls abgewiesen. Die Nutzdaten könnenmessage,codeunddeclineCodeenthalten.- Verwenden Sie
ConnectionStatusChangenicht zur Erkennung unerwarteter Verbindungsabbrüche. Nutzen SieUnexpectedReaderDisconnectund bei Bluetooth/USB zusätzlichDisconnectedReader. Siehe Lebenszyklus des Lesegeräts.
method cancelCollectPaymentMethod()
Bricht einen laufenden Aufruf von collectPaymentMethod() ab.
cancelCollectPaymentMethod() => Promise<void>
Das Lesegerät trennen
Trennen Sie das Lesegerät, wenn der Zahlungsablauf abgeschlossen ist oder das Lesegerät nicht mehr benötigt wird.
method disconnectReader()
Trennt die Verbindung zum aktiven Lesegerät. Wird sofort aufgelöst, wenn keines verbunden ist.
disconnectReader() => Promise<void>
Nach dem ersten erfolgreichen Ablauf
Siehe Lebenszyklus des Lesegeräts für Trennen, Wiederverbinden und Updates. Zum Akzeptieren von Zahlungen mit dem Telefon als Lesegerät siehe Tap to Pay. Die formalen Signaturen bleiben auf der Seite API.
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,
});