@@ -6,9 +6,8 @@ import { getOrderSummary } from '@/lib/services/orders';
66import { OrderNotFoundError } from '@/lib/services/errors' ;
77import { orderIdParamSchema } from '@/lib/validation/shop' ;
88import { getStripeEnv } from '@/lib/env/stripe' ;
9- import { createPaymentIntent , retrievePaymentIntent } from '@/lib/psp/stripe' ;
10- import { setOrderPaymentIntent } from '@/lib/services/orders' ;
119import { logError } from '@/lib/logging' ;
10+ import { ensureStripePaymentIntentForOrder } from '@/lib/services/orders/payment-attempts' ;
1211
1312export const dynamic = 'force-dynamic' ;
1413export const revalidate = 0 ;
@@ -90,6 +89,7 @@ export default async function PaymentPage(props: PaymentPageProps) {
9089 const clearCart = shouldClearCart ( searchParams ) ;
9190 const cc = clearCart ? '&clearCart=1' : '' ;
9291 const { locale } = params ;
92+ const shopBase = `/${ locale } /shop` ;
9393
9494 const orderId = getOrderId ( params ) ;
9595
@@ -101,13 +101,13 @@ export default async function PaymentPage(props: PaymentPageProps) {
101101 >
102102 < nav className = "mt-6 flex justify-center gap-3" aria-label = "Next steps" >
103103 < Link
104- href = "/shop/ cart"
104+ href = { ` ${ shopBase } / cart` }
105105 className = "inline-flex items-center justify-center rounded-md border border-border px-4 py-2 text-sm font-semibold uppercase tracking-wide text-foreground hover:bg-secondary"
106106 >
107107 Go to cart
108108 </ Link >
109109 < Link
110- href = "/shop/ products"
110+ href = { ` ${ shopBase } / products` }
111111 className = "inline-flex items-center justify-center rounded-md bg-accent px-4 py-2 text-sm font-semibold uppercase tracking-wide text-accent-foreground hover:bg-accent/90"
112112 >
113113 Continue shopping
@@ -133,13 +133,13 @@ export default async function PaymentPage(props: PaymentPageProps) {
133133 aria-label = "Next steps"
134134 >
135135 < Link
136- href = "/shop/ cart"
136+ href = { ` ${ shopBase } / cart` }
137137 className = "inline-flex items-center justify-center rounded-md border border-border px-4 py-2 text-sm font-semibold uppercase tracking-wide text-foreground hover:bg-secondary"
138138 >
139139 Go to cart
140140 </ Link >
141141 < Link
142- href = "/shop/ products"
142+ href = { ` ${ shopBase } / products` }
143143 className = "inline-flex items-center justify-center rounded-md bg-accent px-4 py-2 text-sm font-semibold uppercase tracking-wide text-accent-foreground hover:bg-accent/90"
144144 >
145145 Continue shopping
@@ -165,48 +165,74 @@ export default async function PaymentPage(props: PaymentPageProps) {
165165
166166 // Ensure we have a clientSecret even when URL doesn't include ?clientSecret=...
167167 // Source of truth for payment finality is webhook; this only initializes Elements.
168+ // if (
169+ // paymentsEnabled &&
170+ // publishableKey &&
171+ // (!clientSecret || !clientSecret.trim())
172+ // ) {
173+ // const existingPi = order.paymentIntentId?.trim() ?? '';
174+ // let phase:
175+ // | 'retrievePaymentIntent'
176+ // | 'createPaymentIntent'
177+ // | 'setOrderPaymentIntent'
178+ // | 'unknown' = 'unknown';
179+
180+ // try {
181+ // if (existingPi) {
182+ // phase = 'retrievePaymentIntent';
183+ // const retrieved = await retrievePaymentIntent(existingPi);
184+ // clientSecret = retrieved.clientSecret;
185+ // } else {
186+ // phase = 'createPaymentIntent';
187+ // const snapshot = await readStripePaymentIntentParams(order.id);
188+ // const created = await createPaymentIntent({
189+ // amount: snapshot.amountMinor,
190+ // currency: snapshot.currency,
191+ // orderId: order.id,
192+ // idempotencyKey: `pi:${order.id}`,
193+ // });
194+
195+ // phase = 'setOrderPaymentIntent';
196+ // await setOrderPaymentIntent({
197+ // orderId: order.id,
198+ // paymentIntentId: created.paymentIntentId,
199+ // });
200+
201+ // clientSecret = created.clientSecret;
202+ // }
203+ // } catch (error) {
204+ // logError('payment_page_failed', error, {
205+ // orderId: order.id,
206+ // existingPi,
207+ // phase,
208+ // });
209+
210+ // // Leave clientSecret empty -> UI shows "Payment cannot be initialized"
211+ // }
212+ // }
213+
168214 if (
169215 paymentsEnabled &&
170216 publishableKey &&
171217 ( ! clientSecret || ! clientSecret . trim ( ) )
172218 ) {
173219 const existingPi = order . paymentIntentId ?. trim ( ) ?? '' ;
174- let phase :
175- | 'retrievePaymentIntent'
176- | 'createPaymentIntent'
177- | 'setOrderPaymentIntent'
178- | 'unknown' = 'unknown' ;
220+ let phase : 'ensureStripePaymentIntentForOrder' | 'unknown' = 'unknown' ;
179221
180222 try {
181- if ( existingPi ) {
182- phase = 'retrievePaymentIntent' ;
183- const retrieved = await retrievePaymentIntent ( existingPi ) ;
184- clientSecret = retrieved . clientSecret ;
185- } else {
186- phase = 'createPaymentIntent' ;
187- const created = await createPaymentIntent ( {
188- amount : order . totalAmountMinor ,
189- currency : order . currency ,
190- orderId : order . id ,
191- idempotencyKey : `pi:${ order . id } ` ,
192- } ) ;
193-
194- phase = 'setOrderPaymentIntent' ;
195- await setOrderPaymentIntent ( {
196- orderId : order . id ,
197- paymentIntentId : created . paymentIntentId ,
198- } ) ;
199-
200- clientSecret = created . clientSecret ;
201- }
223+ phase = 'ensureStripePaymentIntentForOrder' ;
224+ const ensured = await ensureStripePaymentIntentForOrder ( {
225+ orderId : order . id ,
226+ existingPaymentIntentId : existingPi || null ,
227+ } ) ;
228+
229+ clientSecret = ensured . clientSecret ;
202230 } catch ( error ) {
203231 logError ( 'payment_page_failed' , error , {
204232 orderId : order . id ,
205233 existingPi,
206234 phase,
207235 } ) ;
208-
209- // Leave clientSecret empty -> UI shows "Payment cannot be initialized"
210236 }
211237 }
212238
@@ -223,13 +249,13 @@ export default async function PaymentPage(props: PaymentPageProps) {
223249 aria-label = "Next steps"
224250 >
225251 < Link
226- href = { `/shop /checkout/success?orderId=${ order . id } ${ cc } ` }
252+ href = { `${ shopBase } /checkout/success?orderId=${ order . id } ${ cc } ` }
227253 className = "inline-flex items-center justify-center rounded-md bg-accent px-4 py-2 text-sm font-semibold uppercase tracking-wide text-accent-foreground hover:bg-accent/90"
228254 >
229255 View confirmation
230256 </ Link >
231257 < Link
232- href = "/shop/ products"
258+ href = { ` ${ shopBase } / products` }
233259 className = "inline-flex items-center justify-center rounded-md border border-border px-4 py-2 text-sm font-semibold uppercase tracking-wide text-foreground hover:bg-secondary"
234260 >
235261 Continue shopping
0 commit comments