Przelew tradycyjny na potwierdzeniu zamówienia
UI (komponenty z hookami i JSX) jest specyficzne dla React / Next.js. W innym frameworku weź zapytanie z zakładki Raw i napisz własny widok.
Co zbudujesz
Sekcję „Dane do przelewu" na stronie potwierdzenia zamówienia dla sklepów przyjmujących przelew tradycyjny: odbiorca, bank, numer rachunku i tytuł przelewu do skopiowania jednym kliknięciem oraz aktualna kwota do zapłaty. Wszystko przychodzi z API w polu Order.bankTransferInstructions — storefront nie trzyma numeru konta w konfiguracji ani w kodzie, więc gdy sklep zmieni rachunek w panelu, strona potwierdzenia od razu pokazuje właściwe dane.
Sedno przepisu to jeden warunek:
const instructions = order.bankTransferInstructions;
if (!instructions) return null; // inna metoda płatności, zamówienie opłacone lub anulowane
Przelew tradycyjny to metoda offline — order.canCreatePayment jest dla niej false i nie wywołuje się paymentCreate. Kupujący wykonuje przelew samodzielnie, a sklep księguje wpłatę w panelu. Do tego czasu strona potwierdzenia (i mail z potwierdzeniem zamówienia, który platforma wysyła automatycznie z tą samą sekcją) to jedyne miejsca, z których kupujący bierze dane do przelewu.
Wymagania
- Skonfigurowany SDK i provider — Konfiguracja Next.js.
- Strona potwierdzenia pobierająca zamówienie po tokenie — Zamówienia (sekcja o
orderByToken). - Sklep z włączoną metodą „Przelew tradycyjny" i uzupełnionymi danymi rachunku w panelu.
Krok 1 — Pobierz zamówienie z danymi do przelewu
Zapytanie o zamówienie po tokenie z cartComplete.order.accessToken zwraca komplet danych potwierdzenia — w tym bankTransferInstructions:
- Raw (dowolny framework)
Brak gotowego helpera SDK dla tej operacji — użyj raw operation (działa w każdym frameworku).
// Działa w dowolnym frameworku (Vue, Svelte, vanilla JS, Node, Edge)
const QUERY = `query OrderByToken($token: String!, $email: String) {
orderByToken(token: $token, email: $email) {
...Order
}
}
fragment Order on Order {
id
orderNumber
accessToken
totals {
total {
...Money
}
subtotal {
...Money
}
totalTax {
...Money
}
totalShipping {
...Money
}
feeTotal {
...Money
}
feeAllocations {
label
amount {
...Money
}
}
pricesIncludeTax
}
status
paymentStatus
fulfillmentStatus
processedAt
confirmedAt
cancelledAt
expiredAt
shippingAddress {
...MailingAddress
}
itemCount
customerNote
discountAllocations {
discountCode
amount {
...Money
}
}
canCreatePayment
paymentMethodType
bankTransferInstructions {
bankName
accountNumber
accountHolder
transferTitle
amount {
...Money
}
}
}
fragment MailingAddress on MailingAddress {
id
streetLine1
streetLine2
buildingNumber
flatNumber
city
company
country
countryCode
firstName
lastName
name
phone
state
stateCode
postalCode
isDefault
taxId
vatNumber
regon
pickupPoint {
...PickupPoint
}
}
fragment PickupPoint on PickupPoint {
provider
pointId
name
address
paymentAvailable
}
fragment Money on Money {
amount
currencyCode
}`;
const res = await fetch(`${apiUrl}/storefront/graphql`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: QUERY, variables: { token: '…', email: '…' }, }),
});
const { data } = await res.json();
Pole jest wypełnione tylko wtedy, gdy wszystkie warunki są spełnione naraz:
- zamówienie jest opłacane przelewem tradycyjnym (
paymentMethodType=BANK_TRANSFERi metoda offline — nie mylić z szybkim przelewem przez bramkę, który ma sesję online), - zamówienie wciąż czeka na wpłatę (nie jest opłacone, anulowane ani wygasłe),
- sklep ma uzupełnione dane rachunku w panelu.
W każdym innym przypadku przychodzi null — jeden warunek w komponencie załatwia całą logikę pokazywania sekcji.
bankTransferInstructions odzwierciedla bieżący stan: rachunek to ten, który sklep ma dziś w panelu, a amount to aktualne saldo do zapłaty — po częściowej wpłacie albo zmianie pozycji zamówienia przez sklep kwota jest już przeliczona. Kupujący wracający na potwierdzenie z maila po kilku dniach zawsze widzi właściwe dane.
Krok 2 — Sekcja „Dane do przelewu"
Komponent jest weryfikowany typami przeciw @doswiftly/storefront-sdk — błędne pole nie przejdzie weryfikacji. Numer rachunku i tytuł przelewu mają przyciski „Kopiuj", bo to wartości, które kupujący wkleja do bankowości — literówka w rachunku to nieodwracalny przelew w złe miejsce:
'use client';
import { useState } from 'react';
import type { Order, BankTransferInstructions } from '@doswiftly/storefront-sdk';
// Przycisk „Kopiuj" przy numerze rachunku i tytule przelewu — kupujący wkleja
// wartości do bankowości bez ryzyka literówki.
function CopyButton({ value, label }: { value: string; label: string }) {
const [copied, setCopied] = useState(false);
const copy = async () => {
await navigator.clipboard.writeText(value);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
return (
<button type="button" onClick={copy} aria-label={label}>
{copied ? 'Skopiowano' : 'Kopiuj'}
</button>
);
}
// Sekcja „Dane do przelewu" na stronie potwierdzenia zamówienia.
// `order.bankTransferInstructions` jest wypełnione TYLKO dla zamówień opłacanych
// przelewem tradycyjnym, które wciąż czekają na wpłatę — dla każdej innej metody,
// zamówień opłaconych i anulowanych przychodzi null, więc jeden warunek załatwia
// całą logikę pokazywania sekcji.
export function BankTransferSection({ order }: { order: Order }) {
const instructions: BankTransferInstructions | null | undefined = order.bankTransferInstructions;
if (!instructions) return null;
return (
<section aria-labelledby="bank-transfer-heading">
<h2 id="bank-transfer-heading">Dane do przelewu</h2>
<p>Aby opłacić zamówienie, wykonaj przelew na poniższy rachunek:</p>
<dl>
<div>
<dt>Odbiorca</dt>
<dd>{instructions.accountHolder}</dd>
</div>
<div>
<dt>Bank</dt>
<dd>{instructions.bankName}</dd>
</div>
<div>
<dt>Numer rachunku</dt>
<dd>
{instructions.accountNumber}
<CopyButton value={instructions.accountNumber} label="Skopiuj numer rachunku" />
</dd>
</div>
<div>
<dt>Tytuł przelewu</dt>
<dd>
{instructions.transferTitle}
<CopyButton value={instructions.transferTitle} label="Skopiuj tytuł przelewu" />
</dd>
</div>
<div>
{/* Kwota to bieżące saldo do zapłaty — po częściowej wpłacie lub zmianie
pozycji zamówienia przez sklep wartość jest już przeliczona. */}
<dt>Kwota do zapłaty</dt>
<dd>
{instructions.amount.amount} {instructions.amount.currencyCode}
</dd>
</div>
</dl>
<p>
Zamówienie <strong>{order.orderNumber}</strong> zrealizujemy po zaksięgowaniu wpłaty. Te same dane znajdziesz w
mailu z potwierdzeniem zamówienia.
</p>
</section>
);
}
transferTitle przychodzi gotowy (zawiera numer zamówienia, w języku sklepu) i ten sam tytuł trafia do maila z potwierdzeniem. Własny format w storefroncie oznaczałby, że kupujący widzi dwa różne tytuły dla jednego zamówienia — a sklep księguje wpłaty po tytule.
Typy
Renderowane ze schematu GraphQL — nigdy nie rozjeżdżają się z API:
BankTransferInstructions
Everything the buyer needs to pay for an order by manual bank transfer — render it on the confirmation page for orders where `paymentMethodType` is BANK_TRANSFER and `canCreatePayment` is false. Reflects the merchant's CURRENT bank account details (not a snapshot), so a returning buyer always sees the account that is valid right now.
| Pole | Typ | Opis |
|---|---|---|
accountHolder | String! | Transfer recipient name (the merchant's legal or trading name). |
accountNumber | String! | Bank account number to transfer to (IBAN, formatted as the merchant entered it). Offer a copy-to-clipboard action next to it. |
amount | Money! | Amount the buyer should transfer — the current outstanding balance of the order (order total minus recorded payments), in the order currency. |
bankName | String! | Name of the merchant's bank, as configured in the shop panel. |
transferTitle | String! | Ready-made transfer title that identifies the order (localized, contains the order number). Show it as the value the buyer should paste into the transfer title field. |
Powiązane
- Strona potwierdzenia i
orderByToken— Zamówienia. - Wybór metody płatności w checkoucie — Checkout i Instrumenty płatności.
- Kontrakt operacji
OrderByToken— Referencja GraphQL API.