feat: abonelik iptal ekranı (ayrılma nedeni + açıklama) & gerçek abonelik rozeti (yönetici erişimi aboneliği gizlemesin)
This commit is contained in:
@@ -187,3 +187,45 @@ export async function createCheckoutSession({ planId, email, periyot = 'yillik'
|
||||
if (!res.ok) throw new Error(data?.error?.message || `Stripe hatası: HTTP ${res.status}`);
|
||||
return { url: data.url, id: data.id };
|
||||
}
|
||||
|
||||
/** Ayrılma nedeni seçenekleri — arayüz ve Stripe aynı listeyi kullanır. */
|
||||
export const IPTAL_NEDENLERI = [
|
||||
{ id: 'too_expensive', label: 'Fiyat bütçemize uygun değil' },
|
||||
{ id: 'missing_features', label: 'İhtiyacım olan özellik yok' },
|
||||
{ id: 'switched_service', label: 'Başka bir hizmete geçtim' },
|
||||
{ id: 'unused', label: 'Yeterince kullanmıyorum' },
|
||||
{ id: 'too_complex', label: 'Kullanımı karmaşık geldi' },
|
||||
{ id: 'low_quality', label: 'Veri/sonuç kalitesi beklentimi karşılamadı' },
|
||||
{ id: 'customer_service', label: 'Destekten memnun kalmadım' },
|
||||
{ id: 'other', label: 'Diğer' },
|
||||
];
|
||||
|
||||
/**
|
||||
* Aboneliği dönem sonunda iptal eder (erişim ödenen sürenin sonuna kadar sürer)
|
||||
* ve ayrılma nedenini Stripe'a işler.
|
||||
*/
|
||||
export async function cancelSubscription({ subId, neden, aciklama }) {
|
||||
const key = process.env.STRIPE_SECRET_KEY;
|
||||
if (!key) throw new Error('Ödeme yapılandırılmamış (STRIPE_SECRET_KEY yok)');
|
||||
if (!subId) throw new Error('İptal edilecek abonelik bulunamadı');
|
||||
|
||||
const govde = { cancel_at_period_end: 'true' };
|
||||
if (IPTAL_NEDENLERI.some((n) => n.id === neden)) {
|
||||
govde['cancellation_details[feedback]'] = neden;
|
||||
}
|
||||
const not = String(aciklama || '').trim().slice(0, 500);
|
||||
if (not) govde['cancellation_details[comment]'] = not;
|
||||
|
||||
const res = await fetch(`https://api.stripe.com/v1/subscriptions/${encodeURIComponent(subId)}`, {
|
||||
method: 'POST',
|
||||
headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: formEncode(govde),
|
||||
});
|
||||
const data = await res.json().catch(() => ({}));
|
||||
if (!res.ok) throw new Error(data?.error?.message || `Stripe hatası: HTTP ${res.status}`);
|
||||
return {
|
||||
id: data.id,
|
||||
donemSonunda: Boolean(data.cancel_at_period_end),
|
||||
bitis: data.cancel_at ? new Date(data.cancel_at * 1000).toISOString() : null,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user