forked from paypal/react-paypal-js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BraintreePayPalButtons.tsx
115 lines (106 loc) · 4.43 KB
/
BraintreePayPalButtons.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import React, { FC, useState, useEffect } from "react";
import { loadCustomScript } from "@paypal/paypal-js";
import {
DATA_CLIENT_TOKEN,
BRAINTREE_SOURCE,
BRAINTREE_PAYPAL_CHECKOUT_SOURCE,
} from "../../constants";
import { PayPalButtons } from "../PayPalButtons";
import { useScriptProviderContext } from "../../hooks/scriptProviderHooks";
import { getBraintreeWindowNamespace } from "../../utils";
import { decorateActions } from "./utils";
import { DISPATCH_ACTION } from "../../types";
import type {
BraintreePayPalButtonsComponentProps,
PayPalButtonsComponentProps,
} from "../../types";
/**
This `<BraintreePayPalButtons />` component renders the [Braintree PayPal Buttons](https://developer.paypal.com/braintree/docs/guides/paypal/overview) for Braintree Merchants.
It relies on the `<PayPalScriptProvider />` parent component for managing state related to loading the JS SDK script.
Use props for customizing your buttons. For example, here's how you would use the `style`, `createOrder`, and `onApprove` options:
```jsx
import { PayPalScriptProvider, BraintreePayPalButtons } from "@paypal/react-paypal-js";
<PayPalScriptProvider options={{ "client-id": "test" }}>
<BraintreePayPalButtons
style={{ layout: "horizontal" }}
createOrder={(data, actions) => {
// the paypalCheckoutInstance from the braintree sdk integration is added to `actions.braintree`
return actions.braintree.createPayment({
flow: "checkout",
amount: "10.0",
currency: "USD",
intent: "capture"
})
}}
onApprove={(data, actions) => {
return actions.braintree.tokenizePayment(data)
.then((payload) => {
// call server-side endpoint to finish the sale
})
}
/>
</PayPalScriptProvider>
```
*/
export const BraintreePayPalButtons: FC<BraintreePayPalButtonsComponentProps> =
({
className = "",
disabled = false,
children,
forceReRender = [],
...buttonProps
}: BraintreePayPalButtonsComponentProps) => {
const [, setErrorState] = useState(null);
const [providerContext, dispatch] = useScriptProviderContext();
useEffect(() => {
Promise.all([
loadCustomScript({ url: BRAINTREE_SOURCE }),
loadCustomScript({ url: BRAINTREE_PAYPAL_CHECKOUT_SOURCE }),
])
.then(() => {
const clientToken = providerContext.options[
DATA_CLIENT_TOKEN
] as string;
const braintreeNamespace = getBraintreeWindowNamespace();
return braintreeNamespace.client
.create({
authorization: clientToken,
})
.then((clientInstance) => {
return braintreeNamespace.paypalCheckout.create({
client: clientInstance,
});
})
.then((paypalCheckoutInstance) => {
dispatch({
type: DISPATCH_ACTION.SET_BRAINTREE_INSTANCE,
value: paypalCheckoutInstance,
});
});
})
.catch((err) => {
setErrorState(() => {
throw new Error(
`An error occurred when loading the Braintree scripts: ${err}`
);
});
});
}, [providerContext.options, dispatch]);
return (
<>
{providerContext.braintreePayPalCheckoutInstance && (
<PayPalButtons
className={className}
disabled={disabled}
forceReRender={forceReRender}
{...(decorateActions(
buttonProps,
providerContext.braintreePayPalCheckoutInstance
) as PayPalButtonsComponentProps)}
>
{children}
</PayPalButtons>
)}
</>
);
};