Przejdź do głównej zawartości

Przelew tradycyjny na potwierdzeniu zamówienia

Framework: React / Next.js
Pobieranie danych jest przenośne — w blokach z przykładami zakładka Raw pokazuje czysty fetch działający w dowolnym frameworku.
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 offlineorder.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:

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_TRANSFER i 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.

Dane są aktualne, nie zamrożone

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:

bank-transfer-section.tsx
'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>
);
}
Nie buduj tytułu przelewu samodzielnie

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

BankTransferInstructionsobjectPełna referencja →

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.

PoleTypOpis
accountHolderString!Transfer recipient name (the merchant's legal or trading name).
accountNumberString!Bank account number to transfer to (IBAN, formatted as the merchant entered it). Offer a copy-to-clipboard action next to it.
amountMoney!Amount the buyer should transfer — the current outstanding balance of the order (order total minus recorded payments), in the order currency.
bankNameString!Name of the merchant's bank, as configured in the shop panel.
transferTitleString!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