idconvert/frontend/services/paymentService.js

60 lines
1.8 KiB
JavaScript

import { userService } from './userService.js'
let _stripe = null
async function getStripe() {
if (_stripe) return _stripe
const config = useRuntimeConfig()
const key = config.public.stripePublishableKey
if (!key) throw new Error('Stripe publishable key not configured')
const { loadStripe } = await import('@stripe/stripe-js')
_stripe = await loadStripe(key)
return _stripe
}
export const paymentService = {
/**
* Create a Stripe PaymentIntent via the backend and return the client_secret.
* pack: 'starter' | 'studio' | 'agency'
*/
async createPaymentIntent(pack) {
const config = useRuntimeConfig()
const token = userService.getToken()
const res = await fetch(`${config.public.apiBase}/api/payments/create-intent`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
body: JSON.stringify({ pack }),
})
if (!res.ok) {
const err = await res.json()
throw new Error(err.message || 'Failed to create payment intent')
}
return res.json()
},
/**
* Mount Stripe Elements into the given DOM element and confirm payment.
* Returns a promise that resolves when the payment is confirmed.
*/
async mountAndConfirm(mountElement, clientSecret) {
const stripe = await getStripe()
const elements = stripe.elements({ clientSecret })
const paymentElement = elements.create('payment')
paymentElement.mount(mountElement)
return {
elements,
confirm: async (returnUrl) => {
const { error } = await stripe.confirmPayment({
elements,
confirmParams: { return_url: returnUrl },
})
if (error) throw new Error(error.message)
},
}
},
}