diff options
| author | Joe Carstairs <65492573+Sycamost@users.noreply.github.com> | 2023-08-12 13:42:04 +0100 |
|---|---|---|
| committer | Joe Carstairs <65492573+Sycamost@users.noreply.github.com> | 2023-08-12 13:47:45 +0100 |
| commit | 4f23f539851e276417edcabd3c8bb0940b76c5bf (patch) | |
| tree | fa72e0b9d6ab3db48d6b278e623e463e444d7339 /src/components | |
| parent | b05ab19bd786a6e220bac7b64c110a0063cd8e35 (diff) | |
Defines PayPalButtons component
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/PayPalButtons.astro | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/components/PayPalButtons.astro b/src/components/PayPalButtons.astro new file mode 100644 index 0000000..0d9b606 --- /dev/null +++ b/src/components/PayPalButtons.astro @@ -0,0 +1,121 @@ +--- +import env from '../lib/env'; + +const PAYPAL_CLIENT_ID = env.ENVIRONMENT === 'prod' + ? env.PAYPAL_LIVE_CLIENT_ID + : env.PAYPAL_SANDBOX_CLIENT_ID; +--- + +<paypal-buttons data-paypal-client-id={PAYPAL_CLIENT_ID}> + <div id="paypal-button-container"></div> +</paypal-buttons> + +<script> + import { PayPalNamespace, loadScript } from '@paypal/paypal-js'; + + const backendUrl = '/api'; + + class PayPalButtons extends HTMLElement { + constructor() { + super(); + + const paypalClientId = this.dataset['paypalClientId']; + if (!paypalClientId || typeof(paypalClientId) !== 'string') { + throw new Error('PayPal Client ID not provided to PayPalButtons component.'); + } + + 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) { + this.makePaypalButtons(constructButtons).render('#paypal-button-container'); + } + }); + } + + makePaypalButtons(constructButtons: Required<PayPalNamespace>['Buttons']) { + return constructButtons({ + // This function is called to set up the transaction details without actually carrying it out + async createOrder() { + const body = JSON.stringify({ + productDescription: "my product description", + shortDescription: "my product", + totalPrice: 15.5, + }); + const headers = { + 'Content-Type': 'application/json' + }; + + let response; + try { + response = await fetch( + `${backendUrl}/order`, + { method: "POST", body, headers } + ); + } catch (err) { + throw new Error(`Failed to create order. ${err}`); + } + + if (!response.ok) { + throw new Error(` + Failed to create order. Backend response was + ${response.status} ${response.statusText}. ${await response.text()} + `); + } + + const { orderId, approvalLink } = await response.json(); + console.info(` + Successfully created order with ID + ${orderId}. Approval link: ${approvalLink} + `); + return orderId; + }, + + // This function is called after payment is confirmed + async onApprove(data) { + const body = JSON.stringify({ + id: data.orderID, + isApproved: true + }); + const headers = { + 'Content-Type': 'application/json', + }; + + let response; + try { + response = await fetch( + `${backendUrl}/order`, + { method: 'PATCH', body, headers } + ); + } catch (err) { + throw new Error(`Failed to capture order. ${err}`); + } + + if (!response.ok) { + throw new Error(` + Failed to capture order. Backend response was ${response.status} + ${response.statusText}. ${await response.text()} + `); + } + + const { orderId, requestStatus } = await response.json(); + console.info(` + Successfully captured order with ID ${orderId}, + request status is ${requestStatus}. + `); + } + }); + } + } + + customElements.define('paypal-buttons', PayPalButtons); +</script>
\ No newline at end of file |
