feat: Shopier payment integration with 3DS callback + unified checkout action

This commit is contained in:
kovakmedya
2026-04-30 21:57:51 +03:00
parent 196036c0d8
commit 00a8351f66
7 changed files with 466 additions and 12 deletions
+50
View File
@@ -11,6 +11,7 @@ import { DATABASE_ID, TABLES, type SubscriptionPayment, type TenantPlan } from "
import { createAdminClient } from "./server";
import { requireRole, requireTenant } from "./tenant-guard";
import { PLAN_CATALOG } from "./subscription-types";
import { isShopierEnabled } from "../payments/shopier";
const PRO_VALIDITY_DAYS = 30;
@@ -218,3 +219,52 @@ export async function downgradeToFreeAction(): Promise<void> {
revalidatePath("/settings/billing");
redirect(`/settings/billing?downgraded=1`);
}
export async function startShopierCheckoutAction(formData: FormData): Promise<void> {
const plan = String(formData.get("plan") ?? "") as TenantPlan;
if (plan !== "pro") throw new Error("Geçersiz plan.");
const ctx = await requireTenant();
requireRole(ctx, ["owner"]);
const catalog = PLAN_CATALOG[plan];
const orderId = generateOrderId();
const { tablesDB } = createAdminClient();
await tablesDB.createRow(
DATABASE_ID,
TABLES.subscriptionPayments,
ID.unique(),
{
tenantId: ctx.tenantId,
createdBy: ctx.user.id,
orderId,
plan,
amount: catalog.price,
currency: catalog.currency,
status: "pending",
provider: "shopier",
},
teamRowPermissions(ctx.tenantId),
);
await logAudit({
tenantId: ctx.tenantId,
userId: ctx.user.id,
action: "create",
entityType: "subscription_payment",
entityId: orderId,
changes: { plan, amount: catalog.price, provider: "shopier" },
});
redirect(`/settings/billing/checkout/${orderId}/shopier`);
}
// Unified entry point — branches on PAYMENT_PROVIDER env variable.
// Set PAYMENT_PROVIDER=shopier in production; leave unset (or "mock") for testing.
export async function startCheckoutAction(formData: FormData): Promise<void> {
if (isShopierEnabled()) {
return startShopierCheckoutAction(formData);
}
return startMockCheckoutAction(formData);
}