Files
meet-hub/supabase/functions/create-pakasir-payment/index.ts
dwindown a9f7c9b07a Create Pakasir payment edge function to fix CORS issue
- Create create-pakasir-payment edge function to handle payment creation server-side
- Update ConsultingBooking.tsx to use edge function instead of direct API call
- Update Checkout.tsx to use edge function instead of direct API call
- Add config.toml entry for create-pakasir-payment function
- Removes CORS errors when calling Pakasir API from frontend

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 21:20:40 +07:00

103 lines
3.3 KiB
TypeScript

import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
};
interface PakasirPaymentRequest {
order_id: string;
amount: number;
description: string;
}
serve(async (req: Request) => {
// Handle CORS preflight
if (req.method === "OPTIONS") {
return new Response(null, { headers: corsHeaders });
}
if (req.method !== "POST") {
return new Response("Method not allowed", { status: 405, headers: corsHeaders });
}
try {
const body: PakasirPaymentRequest = await req.json();
const { order_id, amount, description } = body;
if (!order_id || !amount) {
return new Response(
JSON.stringify({ success: false, error: "order_id and amount are required" }),
{ status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } }
);
}
const PAKASIR_PROJECT_SLUG = Deno.env.get("PAKASIR_PROJECT_SLUG") || "";
const PAKASIR_API_KEY = Deno.env.get("PAKASIR_API_KEY") || "";
const PAKASIR_CALLBACK_URL = `${Deno.env.get("SUPABASE_URL")}/functions/v1/pakasir-webhook`;
if (!PAKASIR_PROJECT_SLUG || !PAKASIR_API_KEY) {
console.error("[PAKASIR] Missing credentials");
return new Response(
JSON.stringify({ success: false, error: "Pakasir credentials not configured" }),
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
);
}
console.log("[PAKASIR] Creating payment transaction:", { order_id, amount });
// Call Pakasir API to create QRIS transaction
const pakasirResponse = await fetch(`https://app.pakasir.com/api/transactioncreate/qris`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
project: PAKASIR_PROJECT_SLUG,
order_id: order_id,
amount: amount,
api_key: PAKASIR_API_KEY,
description: description || `Order ${order_id}`,
callback_url: PAKASIR_CALLBACK_URL,
}),
});
if (!pakasirResponse.ok) {
const errorText = await pakasirResponse.text();
console.error("[PAKASIR] API error:", pakasirResponse.status, errorText);
return new Response(
JSON.stringify({
success: false,
error: "Pakasir API error",
details: errorText
}),
{ status: pakasirResponse.status, headers: { ...corsHeaders, "Content-Type": "application/json" } }
);
}
const result = await pakasirResponse.json();
console.log("[PAKASIR] Payment created:", result);
// Return payment URL and QR data
return new Response(
JSON.stringify({
success: true,
data: {
payment_url: `https://app.pakasir.com/pay/${PAKASIR_PROJECT_SLUG}/${amount}?order_id=${order_id}`,
qr_string: result.qr_string || result.qr || null,
order_id: order_id,
}
}),
{ headers: { ...corsHeaders, "Content-Type": "application/json" } }
);
} catch (error: any) {
console.error("[PAKASIR] Unexpected error:", error);
return new Response(
JSON.stringify({
success: false,
error: error.message || "Internal server error"
}),
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
);
}
});