SDK наплата
Објавено издание: SDK 0.1.3 е јавно достапен на npm. Инсталацијата не активира серверски функции.
Трите npm пакети
Дел „Трите npm пакети“@kordiva/sdk— серверски Node клиент со таен Store API клуч за каталог,checkout.createTestво TEST,checkout.createHostedиpayments.confirmво LIVE.@kordiva/checkout— безбедна проверка на exact-origin URL и пренасочување, без клуч и без обработка на картички.@kordiva/react— React/Next.js копче Купи што го повикува вашиот заштитен backend и го отвора URL.
Вообичаен тек: Копче Купи → ваш автентициран backend → Kordiva серверски SDK → постојна Kordiva/Stripe хостирана наплата → серверска потврда. URL за враќање не докажува успешно плаќање. CMS продавниците, директниот API и Checkout Links остануваат поддржани без SDK.
- На сервер автентицирајте го купувачот и одобрете ја кошничката. Изберете одобрени UUID на производи/варијанти и количини; не прифаќајте износ од прелистувач како цена.
- За LIVE повикајте
client.checkout.createHosted({ lineItems, idempotencyKey, checkoutLanguage: 'en' }). SDK задолжително користиstripe_hosted. Добиениот Kordiva/q/…води кон постојниот хостиран тек; не мора да е директен Stripe URL. - Зачувајте го добиениот
sessionIdзаедно со стабилниот обид и овластениот купувач/кошничка во трајно заштитено складиште. Серијализирајте создавање наплата по кошничка. Не создавајте нов клуч само поради истечено барање. - Предадете само
{ url: session.checkoutUrl }на прелистувачот и проверете точен доверлив origin. - По враќање, на сервер повикајте
client.payments.confirm({ sessionId }).pendingилиexpiredне значат платено. Проверете дали купувачот има право да ја види нарачката пред да вратите детали. - Исполнувајте преку соодветниот Kordiva тек. Individual даночни/локациски/задржани платежни и дигитални проверки остануваат; платена проекција сама не дава право на преземање.
Како мојата веб-страница дознава дека е платено? Kordiva ги прима потпишаните Stripe известувања. Вашиот сервер ги чува session UUID и овластениот обид за кошничката. UI потоа повикува заштитен endpoint на вашиот сервер, кој во LIVE повикува client.payments.confirm({ sessionId, idempotencyKey }). Само потврден paid со применливите услови за испорака дозволува исполнување. SDK 0.1.3 додава одделен потпишан Business канал; за претплати видете ги Business водичите подолу. Видете го водичот за статус и webhooks со тестиран Node пример и ограничено проверување.
POST никогаш не се повторува автоматски, ни со idempotency клуч. Серверското пребарување на претходни обиди е ограничено, врзано за клуч и истекува; не гарантира атомско извршување точно еднаш. Усогласете неизвесни резултати пред контролирано повторување со исто тело/клуч. Ротацијата го менува идентитетот за повторување.
Тестираниот обработувач подолу е пример за еден производ. Пред јавна употреба обезбедете вистинска сесиска/кошничка авторизација, ограничување на големина, ограничување по корисник, трајно заклучување и складиште за усогласување. Примерот не е целосен трговски сервер.
import type { Kordiva } from "@kordiva/sdk";export interface CheckoutRouteOptions { client: Kordiva; /** Product is selected from your approved server-side catalog. */ productId: string; storefrontOrigin: string; /** Authenticate your customer session AND authorize this cart; return a stable opaque actor ref. */ authorize: (request: Request) => Promise<string | null>;}/** Shared Web Request/Response handler for a Node backend or Next.js App Router. */export function createCheckoutRoute({ client, productId, storefrontOrigin, authorize,}: CheckoutRouteOptions) { return async function POST(request: Request): Promise<Response> { const headers = { "cache-control": "no-store" }; if (request.method !== "POST") return Response.json( { error: "Method not allowed" }, { status: 405, headers }, ); if (request.headers.get("origin") !== storefrontOrigin) return Response.json( { error: "Origin rejected" }, { status: 403, headers }, ); const actor = await authorize(request); if (!actor || !/^[A-Za-z0-9_-]{1,48}$/.test(actor)) return Response.json({ error: "Unauthorized" }, { status: 401, headers }); if (!request.headers.get("content-type")?.startsWith("application/json")) return Response.json( { error: "JSON required" }, { status: 415, headers }, ); const raw = await request.text(); if (raw.length > 1024) return Response.json( { error: "Request too large" }, { status: 413, headers }, ); let input: unknown; try { input = JSON.parse(raw); } catch { return Response.json({ error: "Invalid JSON" }, { status: 400, headers }); } const attempt = input && typeof input === "object" && "attempt" in input ? input.attempt : null; if (typeof attempt !== "string" || !/^[A-Za-z0-9_-]{8,64}$/.test(attempt)) return Response.json( { error: "Stable cart attempt required" }, { status: 400, headers }, ); try { if (client.environment === "TEST") { const checkout = await client.checkout.createTest({ productId, testSaleMarket: "AU", }); return Response.json({ url: checkout.url }, { headers }); } const checkout = await client.checkout.createHosted({ lineItems: [{ productId, quantity: 1 }], idempotencyKey: `${actor}:${attempt}`, checkoutLanguage: "en", }); return Response.json({ url: checkout.checkoutUrl }, { headers }); } catch { // Production host supplies per-actor rate limiting and a durable cart lock. return Response.json( { error: "Checkout unavailable. Reconcile this attempt before retrying.", }, { status: 502, headers }, ); } };}Поврзани водичи
Дел „Поврзани водичи“SDK · Checkout · Безбедност · API
Business integration
Дел „Business integration“Recurring checkout and subscription reads → Signed Business events → Raw-body verification → Business refunds → API reference. Individual MoR follows its separate refund process.
Individual Merchant of Record: информации пред купување
Дел „Individual Merchant of Record: информации пред купување“Вашата страница може да го задржи својот бренд. За Individual продажби, Kordiva, LLC е правниот продавач / Merchant of Record; креаторот ја обезбедува дигиталната содржина. Преземете ги канонските информации преку backend пред да го прикажете копчето Купи, и прикажете ги вратениот текст и линковите до копчето. Business/TP добива неприменлив резултат и го задржува својот модел.
GET /public/catalog/stores/:storeId/buyer-disclosure?locale=enAuthorization: Bearer <SERVER_ONLY_STORE_API_KEY>// Backend / Next.js server component only. Never import this module into a client bundle.import type { Kordiva } from "../../../../../../packages/kordiva-sdk/src/index.js";export async function loadBuyerDisclosure( client: Kordiva, locale: "mk" | "en",) { return client.buyerDisclosure.get({ locale });}import React from "react";import type { BuyerDisclosure } from "../../../../../../packages/kordiva-sdk/src/types.js";/** Presentation only: consume server-returned wording and links, never reconstruct legal policy. */export function BuyerDisclosureBlock({ disclosure,}: { disclosure: BuyerDisclosure;}) { if (!disclosure.applicable) return null; return ( <aside aria-label="Purchase information"> <p>{disclosure.shortDisclosure}</p> <nav aria-label="Purchase policies"> <a href={disclosure.links.purchaseTerms}>Purchase Terms</a>{" "} <a href={disclosure.links.refunds}>Refund Policy</a>{" "} <a href={disclosure.links.privacy}>Privacy</a>{" "} <a href={disclosure.links.support}>Purchase Support</a> </nav> </aside> );}const escape = (v: string) => v.replace( /[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[ c ]!, );export function renderBuyerDisclosureHtml(disclosure: BuyerDisclosure): string { if (!disclosure.applicable) return ""; return `<aside aria-label="Purchase information"><p>${escape(disclosure.shortDisclosure)}</p><nav aria-label="Purchase policies">${[ ["purchaseTerms", "Purchase Terms"], ["refunds", "Refund Policy"], ["privacy", "Privacy"], ["support", "Purchase Support"], ] .map( ([key, label]) => `<a href="${escape(disclosure.links[key as keyof typeof disclosure.links])}">${label}</a>`, ) .join(" ")}</nav></aside>`;}<!-- Plain HTML: your backend escapes and inserts the returned text and URLs. --><aside aria-label="Purchase information"> <p><!-- buyerDisclosure.shortDisclosure, escaped --></p> <a href="{{purchaseTerms}}">Purchase Terms</a> <a href="{{refunds}}">Refund Policy</a> <a href="{{privacy}}">Privacy</a> <a href="{{support}}">Purchase Support</a></aside>Користете locale: "mk" за македонска наплата. Користете ги вратените вредности; не копирајте правен текст и не составувајте policy URL-адреси. Читањето е преку постојната LIVE API автентикација и може да ја ажурира само постојната телеметрија на клучот. Никогаш не изложувајте API клуч во browser. Тестираните backend, HTML и React примери се во apps/store/src/lib/examples/individual-buyer-disclosure.
Kordiva наплатата независно ги прикажува задолжителните информации и бара потврда плус server-issued preflight proof. Надворешниот блок не ја заменува оваа проверка. Приватноста е известување; не се откажуваат законските права за рефундации или откажување. Browser redirect не е доказ за плаќање: користете payments.confirm() преку backend.
Новиот SDK метод бара идна SDK верзија; тековните објавени верзии можеби не го содржат. Дотогаш користете го REST endpoint по одобрено серверско пуштање. Испраќањето е-пошта останува посебна следна фаза.
Individual е-пошта за потврда: планирана следна фаза
Дел „Individual е-пошта за потврда: планирана следна фаза“Оваа промена не овозможува испраќање е-пошта од Kordiva. Канонската Individual патека го финализира Order и враќа пред заедничкиот email/PDF pipeline; Stripe потврдите зависат од одделна provider конфигурација. Идната потврда за купувачот ќе користи финализиран Order.billingEmail и непроменлив checkout locale, а не земја на продавач, Store email language или Stripe locale: auto. Известувањето за креаторот независно ќе го користи Store email language. Испораката бара трајни уникатни outbox настани при финализација, не директно испраќање од webhook. Известувањата за достапни средства и банкарска исплата остануваат одделни.