Medusa plugins
P

Paypal

Paypal payment provider for Medusa v2

Need customizations for this plugin?

Get in touch
npm install @lanqiu_tech/paypal
Category
other
Built by
lanqiu_tech
Type
unknown
Last updated
3 months ago
Monthly downloads
5

paypal

paypal is a integration of payment provider for Paypal.

Example

⚠️ Warn

| Requires Medusa v2.8.7 or later.

Installaction

Backend

// medusa-config.js
...
modules:[
{
resolve: "@medusajs/medusa/payment",
options: {
providers: [
{
resolve: "@lanqiu_tech/paypal/providers/payment-paypal",
id: "payment-paypal",
options: {
intent: process.env.PAYPAL_INTENT,
clientId: process.env.PAYPAL_CLIENT_ID,
clientSecret: process.env.PAYPAL_CLIENT_SECRET,
sandbox: process.env.PAYPAL_SANDBOX,
webhookId: process.env.PAYPAL_WEBHOOK_ID
},
}
]
}
}
]
plugins: [
{
resolve: "@lanqiu_tech/paypal",
options: {
intent: process.env.PAYPAL_INTENT,
clientId: process.env.PAYPAL_CLIENT_ID,
clientSecret: process.env.PAYPAL_CLIENT_SECRET,
sandbox: process.env.PAYPAL_SANDBOX,
webhookId: process.env.PAYPAL_WEBHOOK_ID
},
}
]

Store

  1. Create
"use client"
import { HttpTypes } from "@medusajs/types"
import { createContext } from "react"
import {
PayPalScriptProvider,
ReactPayPalScriptOptions,
} from "@paypal/react-paypal-js"
type PaypalWrapperProps = {
paymentSession: HttpTypes.StorePaymentSession
clientId: string
children: React.ReactNode
}
export const PaypalContext = createContext(false)
const PaypalWrapper: React.FC<PaypalWrapperProps> = ({
paymentSession,
clientId,
children,
}) => {
const initialOptions: ReactPayPalScriptOptions = {
clientId,
currency: paymentSession.currency_code.toLocaleUpperCase(),
intent: "capture",
components:"buttons",
debug:false
}
return (
<PayPalScriptProvider deferLoading={false} options={initialOptions}>
{children}
</PayPalScriptProvider>
)
}
export default PaypalWrapper
  1. Update
// add
// !!!isPaypal() is 'pp_paypal'
if (isPaypal(paymentSession?.provider_id) && paymentSession) {
return (
<PaypalWrapper
paymentSession={paymentSession}
clientId={paypaylClientId}
>
{children}
</PaypalWrapper>
)
}
  1. Update
// add paypal button
const PaypalPaymentButton = ({
cart,
notReady,
"data-testid": dataTestId,
}: {
cart: HttpTypes.StoreCart
notReady: boolean
"data-testid"?: string
}) => {
const [submitting, setSubmitting] = useState(false)
const [errorMessage, setErrorMessage] = useState<string | null>(null)
const onPaymentCompleted = async () => {
await placeOrder()
}
const handlePayment = async (
_data: OnApproveData,
actions: OnApproveActions
) => {
setSubmitting(true)
await actions?.order
?.capture()
.then((authorization) => {
if (authorization.status !== "COMPLETED") {
setSubmitting(false)
setErrorMessage(`An error occurred, status: ${authorization.status}`)
return
}
onPaymentCompleted()
})
.catch((error) => {
setErrorMessage(`An unknown error occurred, please try again.`)
setSubmitting(false)
})
}
const session = cart.payment_collection?.payment_sessions?.find(
(s) => s.status === "pending"
)
return (
<>
<PayPalButtons
disabled={submitting}
createOrder={async (data, actions) => {
return session?.data.id as string
}}
onApprove={handlePayment}
onError={(err) => {
console.error("PayPal Checkout onError", err)
}}
style={styles}
/>
<ErrorMessage
error={errorMessage}
data-testid="paypal-payment-error-message"
/>
</>
)
}
// Update PaymentButton
const PaymentButton: React.FC<PaymentButtonProps> = ({
...
switch (true) {
...
case isPaypal(paymentSession?.provider_id):
return (
<PaypalPaymentButton
notReady={notReady}
cart={cart}
data-testid={dataTestId}
/>
)
...
}
...
})