diff options
Diffstat (limited to 'src/components/SubscriptionPayPalButtons.astro')
| -rw-r--r-- | src/components/SubscriptionPayPalButtons.astro | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/components/SubscriptionPayPalButtons.astro b/src/components/SubscriptionPayPalButtons.astro new file mode 100644 index 0000000..bc77580 --- /dev/null +++ b/src/components/SubscriptionPayPalButtons.astro @@ -0,0 +1,112 @@ +--- +import env from '$lib/env'; +import type Price from '$types/Price'; + +interface Props { + successPageUrl: string; + productDescription: string; + shortDescription: string; + totalPrice: Price; +} + +const { successPageUrl, productDescription, shortDescription, totalPrice } = Astro.props; + +const PAYPAL_CLIENT_ID = + env.ENVIRONMENT === 'prod' ? env.PAYPAL_LIVE_CLIENT_ID : env.PAYPAL_SANDBOX_CLIENT_ID; +--- + +<subscription-paypal-buttons + data-paypal-client-id={PAYPAL_CLIENT_ID} + data-success-page-url={successPageUrl} + data-failure-page-url={failurePageUrl} +> + <div id="paypal-button-container"></div> +</subscription-paypal-buttons> + +<script> + import { PayPalNamespace, loadScript } from '@paypal/paypal-js'; + + const backendUrl = '/api'; + + class ProductPayPalButtons extends HTMLElement { + constructor() { + super(); + + const paypalClientId = this.getStringDataAttribute('paypalClientId'); + + const paypalOptions = { + clientId: paypalClientId, + locale: 'en_GB', + commit: false, + currency: 'GBP', + intent: 'capture', + }; + + loadScript(paypalOptions) + .catch((err) => { + throw new Error('Failed to load the PayPal JS SDK script. ', err); + }) + .then((paypal) => { + const constructButtons = paypal?.Buttons; + if (paypal && constructButtons) { + const successPageUrl = this.dataset['successPageUrl'] ?? '.'; + this.makePaypalButtons(constructButtons, successPageUrl).render( + '#paypal-button-container' + ); + } + }); + } + + makePaypalButtons( + constructButtons: Required<PayPalNamespace>['Buttons'], + successPageUrl: string + ) { + // TODO: figure out where subscriptionId is coming from! Probably it’s going to be + // generated by PayPal on the backend, and you don’t want it here at all. + + // TODO: get emailAddress from user session. + + return constructButtons({ + async createSubscription() { + try { + const response = await fetch("/api/create-subscription", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ subscriptionId, emailAddress }), + }); + + const data = await response.json(); + + if (data?.id) { + console.info('Subscription successful. Redirecting to confirmation page...'); + window.location.href = successPageUrl; + return data.id; + } else { + console.error( + { callback: "createSubscription", serverResponse: data }, + JSON.stringify(data, null, 2), + ); + console.info('Redirecting to failure page...'); + window.location.href = failurePageUrl; + } + } catch (error) { + console.error('Redirecting to failure page, because of an error creating a subscription.' error); + window.location.href = failurePageUrl; + } + }, + }).render("#paypal-button-container"); // Renders the PayPal button + } + + getStringDataAttribute(key: string): string { + const value = this.dataset[key]; + if (!value || typeof value !== 'string') { + throw new Error(`data-${key} attribute not provided to ProductPayPalButtons component.`); + } + return value; + } + } + + customElements.define('product-paypal-buttons', ProductPayPalButtons); +</script> |
