Next.js
better-payment'i Next.js App Router ile entegre etme.
1. Tekil örneği oluşturun
// lib/payment.ts
import { betterPayment, iyzico } from 'better-payment';
const createPayment = () =>
betterPayment({
mode: process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',
providers: {
iyzico: iyzico({
apiKey: process.env.IYZICO_API_KEY!,
secretKey: process.env.IYZICO_SECRET_KEY!,
}),
},
handler: {
allowedActions: ['payment/init-3ds', 'payment/complete-3ds', 'callback'],
transformRequest: async (ctx) => buildPaymentRequestFromOrder(ctx.body?.orderId, ctx.body?.paymentCard),
onCallback: async (result) => markOrder(result.paymentId, result.status),
callbackRedirect: (result) => `/orders/${result.paymentId}?payment=${result.status}`,
},
});
let instance: ReturnType<typeof createPayment> | undefined;
export const getBetterPayment = () => (instance ??= createPayment());Örneği tembel (lazy) oluşturun: modül seviyesinde bir betterPayment(...) çağrısı yerine bir fonksiyon içinde. Aksi hâlde ortam değişkenleri yokken Next.js'in statik üretimi hata verebilir.
2. Catch-all route handler'ı oluşturun
// app/api/pay/[...path]/route.ts
import { toNextJsHandler } from 'better-payment/next';
import { getBetterPayment } from '@/lib/payment';
export const { GET, POST } = toNextJsHandler(getBetterPayment);getBetterPayment fonksiyonunu (sonucunu değil) vermek başlatmayı tembel tutar: örnek ilk istekte oluşturulur, böylece next build ortam değişkenleri olmadan da çalışır.
Adapter, JSON ve form-urlencoded gövdeleri (iyzico, Param, Akbank ve PayTR callback'leri) handler'a ham metin olarak geçirir ve handler'ın yanıtını değiştirmeden yazar:
- PayTR'nin düz metin
OKyanıtı JSON'a çevrilmez. - Yönlendirmeler (
callbackRedirect)Locationbaşlığını korur ve gövde taşımaz.
Route iki runtime'da da çalışır. Edge runtime'da çalıştırmak için export const runtime = 'edge' ekleyin.
3. Ödemeyi frontend'den başlatın
const res = await fetch('/api/pay/iyzico/payment/init-3ds', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ orderId, paymentCard }), // amounts come from transformRequest
});
const result = await res.json();
if (result.status === 'pending' && result.threeDSHtmlContent) {
document.open();
document.write(result.threeDSHtmlContent);
document.close();
}Ya da tipli client'ı kullanın:
import { createBetterPaymentClient } from 'better-payment/client';
const client = createBetterPaymentClient({ baseUrl: '/api/pay' });
const result = await client.iyzico.initThreeDSPayment(requestBuiltByTransformRequest);
// 422 (provider failure) resolves with status 'failure' instead of throwing4. Callback
callbackUrl'i https://yoursite.com/api/pay/<provider>/payment/complete-3ds olarak ayarlayın. Handler callback'i doğrular, onCallback'i çağırır ve müşteriyi callbackRedirect ile yönlendirir.
PayTR için PayTR panelindeki bildirim URL'sini https://yoursite.com/api/pay/paytr/callback olarak ayarlayın.