Krok po kroku: API
Krok po kroku: integracja API
Ta ścieżka jest dla sklepów bez gotowego modułu. Sześć kroków poniżej to kompletny happy path — wszystko poza nimi jest opcjonalne. Przykłady celują w środowisko testowe; host produkcyjny podstawisz na końcu, zgodnie z checklistą uruchomienia.
Ścieżka wdrożenia
Sprawdź klucz i połączenie
Token autoryzacyjny przekazywany jest w nagłówku każdego żądania. Najprostsze wywołanie weryfikujące, że klucz działa:
curl -X GET https://api-ecommerce.craty.pl/v1/orders/{twój_identyfikator_zamówienia} \
-H "Content-Type: application/json" \
-H "Api-Key: {API-KEY}"
Przy nieprawidłowym lub brakującym kluczu otrzymasz 401 z treścią:
{
"message": "Authorization failed"
}
Pobierz oferty na stronie produktu (opcjonalnie)
Aby pokazać klientowi wysokość raty, zanim trafi do koszyka, pobierz dostępne produkty finansowe dla danej kwoty:
curl -X GET 'https://api-ecommerce.craty.pl/v1/financial-products?loanAmount=120000&loanTerm=6' \
--header "Content-Type: application/json" \
--header "Api-Key: {API-KEY}" \
--connection-timeout 5
Zamiast własnej implementacji możesz osadzić gotowy widget Comfino, który sam wykonuje to zapytanie.
Szczegóły produktów finansowych →
Utwórz wniosek kredytowy
W momencie złożenia zamówienia wyślij koszyk i dane klienta. Poniżej wyłącznie pola wymagane — pełną listę opcjonalnych parametrów (adres, numer konta, tytuł przelewu, VAT) znajdziesz w dokumentacji endpointu.
curl -X POST 'https://api-ecommerce.craty.pl/v1/orders' \
--header 'Api-Key: {API-KEY}' \
--header 'Content-Type: application/json' \
--data-raw '{
"returnUrl": "https://your-shop.tld/thanks",
"notifyUrl": "https://your-shop.tld/notify",
"orderId": "ZAM-001",
"loanParameters": {},
"cart": {
"totalAmount": 246000,
"products": [
{
"name": "Lenovo Ideapad 120S-14IAP",
"quantity": 1,
"price": 246000
}
]
},
"customer": {
"firstName": "Jan",
"lastName": "Kowalski",
"email": "customer@example.com",
"phoneNumber": "312213213",
"ip": "83.20.11.4"
}
}'
W odpowiedzi (201 Created) otrzymasz adres formularza wniosku:
{
"status": "CREATED",
"externalId": "{twój_identyfikator_zamówienia}",
"applicationUrl": "{url_do_przekierowania_na_stronę_formularza}"
}
price × quantity wszystkich pozycji musi być równa totalAmount. Koszt dostawy i dodatkowe opłaty przekazuj jako pozycję o kategorii ADDITIONAL_FEE, a rabaty jako pozycję o kategorii DISCOUNT z ujemną ceną. Pole orderId ma maksymalnie 36 znaków.notifyUrl jest formalnie opcjonalny, ale bez niego nie odbierzesz decyzji kredytowej — w praktyce traktuj go jako wymagany.
Przekieruj klienta na applicationUrl
Przenieś klienta pod adres zwrócony w polu applicationUrl. Dalszą część procesu — wybór oferty, formularz wniosku i kontakt z instytucją finansową — obsługuje Comfino.
Odbierz notyfikację o statusie
Comfino wywoła Twój notifyUrl metodą PUT (jeśli serwer odpowie 405 Method Not Allowed, próba zostanie ponowiona metodą POST) z dokumentem:
{
"status": "CREATED",
"externalId": "{twój_identyfikator_zamówienia:string}",
"changedAt": "{znacznik czasu informujący kiedy nastąpiła zmiana statusu:int}",
"paymentMethod": "{wybrana przez użytkownika metoda płatności:string}",
"productType": "{typ produktu (np. INSTALLMENTS_ZERO_PERCENT): string|null}"
}
200 OK powoduje ponawianie notyfikacji aż do skutku. Comfino może wysłać kilka żądań dla jednego zamówienia — obsłuż je idempotentnie i na każde odpowiedz 200 OK.Przed przetworzeniem zweryfikuj nagłówek CR-Signature, aby potwierdzić, że żądanie pochodzi od Comfino. Sygnatura to sha3-256(api-key + json-request-body):
$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_CR_SIGNATURE'] ?? '';
$expected = hash('sha3-256', $apiKey . $rawBody);
if (!hash_equals($expected, $signature)) {
http_response_code(403);
exit;
}
import { createHash, timingSafeEqual } from 'node:crypto'
const signature = req.headers['cr-signature'] ?? ''
const expected = createHash('sha3-256')
.update(apiKey + rawBody)
.digest('hex')
const valid = signature.length === expected.length
&& timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
if (!valid) return res.status(403).end()
Obsłuż powrót klienta
Po zakończeniu wniosku klient wraca pod adres returnUrl. Komunikat wyświetlaj na podstawie statusów końcowych:
| Wynik | Statusy |
|---|---|
| Finansowanie przyznane | ACCEPTED, WAITING_FOR_PAYMENT, PAID |
| Finansowanie nieprzyznane | REJECTED, CANCELLED_BY_SHOP |
Pozostałe statusy (CREATED, WAITING_FOR_FILLING, WAITING_FOR_CONFIRMATION, PRE_ACCEPTED) są przejściowe — traktuj je jako „wniosek w toku", nie jako wynik.