Get started
Install orvacon, wire a gateway, and take your first payment.
orvacon installs into your own app — there is no hosted service. You bring a database and a gateway account; orvacon orchestrates the rest.
Install
bun add @orvacon/paykit @orvacon/connector-iyzico @orvacon/adapter-supabase @orvacon/adapter-nextjs postgresGenerate keys and schema
npx orvacon keys # Ed25519 webhook signing keypair → ORVACON_WEBHOOK_SIGNING_KEY
npx orvacon generate # Postgres schema with default-deny row-level securityConfigure
import { orvacon } from "@orvacon/paykit";
import { iyzico } from "@orvacon/connector-iyzico";
import { supabaseAdapter } from "@orvacon/adapter-supabase";
import postgres from "postgres";
const sql = postgres(process.env.SUPABASE_DB_URL!, { prepare: false });
export const orva = orvacon({
database: supabaseAdapter({ sql }),
connectors: [
iyzico({
apiKey: process.env.IYZICO_API_KEY!,
secretKey: process.env.IYZICO_SECRET_KEY!,
}),
],
webhookSigningKey: process.env.ORVACON_WEBHOOK_SIGNING_KEY!,
webhookUrl: "https://your-app.com/api/webhooks/orvacon",
});Config is validated fail-fast — a missing or malformed key throws at setup, not at the first payment.
Take a payment
import { idempotencyKey, money } from "@orvacon/paykit";
const outcome = await orva.authorize({
amount: money(1499, "TRY"), // 14.99 TRY, in minor units
source: { type: "card", card },
threeDSecure: true,
callbackUrl: "https://your-app.com/api/orva/callback/iyzico",
idempotencyKey: idempotencyKey(crypto.randomUUID()),
});
if (outcome.ok && outcome.status === "requires_action") {
renderChallenge(outcome.action); // { type: "html", content } — hand it to the browser
}A 3-D Secure payment returns requires_action; orvacon persists that state and resumes from the
signed finalize when the browser returns — it never trusts the raw callback POST. Check
outcome.ok first, then outcome.status.
Wire the callback (Next.js)
import { toNextJsHandler } from "@orvacon/adapter-nextjs";
import { orva } from "@/lib/orva";
export const { POST } = toNextJsHandler(orva, {
returnUrl: { success: "/checkout/done", failure: "/checkout/failed" },
});Make the callback route public
The gateway redirects the browser to your callback with no session — exclude
/api/orva/callback from your middleware, or an auth check will silently strand payments.