Skip to content

Commit

Permalink
Fix: PayPal order name and description violate PayPal's schema result…
Browse files Browse the repository at this point in the history
…ing in error 400
  • Loading branch information
aelassas committed Feb 6, 2025
1 parent 2af09be commit 4f79b53
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 15 deletions.
4 changes: 2 additions & 2 deletions api/src/controllers/paypalController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import * as bookingController from './bookingController'
*/
export const createPayPalOrder = async (req: Request, res: Response) => {
try {
const { bookingId, amount, currency, name }: bookcarsTypes.CreatePayPalOrderPayload = req.body
const { bookingId, amount, currency, name, description }: bookcarsTypes.CreatePayPalOrderPayload = req.body

const orderId = await paypal.createOrder(bookingId, amount, currency, name)
const orderId = await paypal.createOrder(bookingId, amount, currency, name, description)

return res.json(orderId)
} catch (err) {
Expand Down
4 changes: 2 additions & 2 deletions api/src/paypal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const getToken = async () => {
return res.data.access_token
}

export const createOrder = async (bookingId: string, amount: number, currency: string, name: string) => {
export const createOrder = async (bookingId: string, amount: number, currency: string, name: string, description: string) => {
const price = helper.formatPayPalPrice(amount)
const token = await getToken()
const res = await axios.post(
Expand Down Expand Up @@ -59,7 +59,7 @@ export const createOrder = async (bookingId: string, amount: number, currency: s
items: [
{
name,
description: name,
description,
unit_amount: {
currency_code: currency,
value: price,
Expand Down
16 changes: 6 additions & 10 deletions frontend/src/pages/Checkout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,7 @@ const Checkout = () => {
const _format = _fr ? 'eee d LLL yyyy kk:mm' : 'eee, d LLL yyyy, p'
const bookingDetailHeight = env.SUPPLIER_IMAGE_HEIGHT + 10
const days = bookcarsHelper.days(from, to)
const daysLabel = from && to && `
${helper.getDaysShort(days)} (${bookcarsHelper.capitalize(
format(from, _format, { locale: _locale }),
)}
- ${bookcarsHelper.capitalize(format(to, _format, { locale: _locale }))})`
const daysLabel = from && to && `${helper.getDaysShort(days)} (${bookcarsHelper.capitalize(format(from, _format, { locale: _locale }))} - ${bookcarsHelper.capitalize(format(to, _format, { locale: _locale }))})`

const handleFullNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setFullName(e.target.value)
Expand Down Expand Up @@ -413,9 +409,7 @@ const Checkout = () => {
currency: PaymentService.getCurrency(),
locale: language,
receiptEmail: (!authenticated ? driver?.email : user?.email) as string,
name: `${car.name}
- ${daysLabel}
- ${pickupLocation._id === dropOffLocation._id ? pickupLocation.name : `${pickupLocation.name} - ${dropOffLocation.name}`}`,
name: `${car.name} - ${daysLabel} - ${pickupLocation._id === dropOffLocation._id ? pickupLocation.name : `${pickupLocation.name} - ${dropOffLocation.name}`}`,
description: `${env.WEBSITE_NAME} Web Service`,
customerName: (!authenticated ? driver?.fullName : user?.fullName) as string,
}
Expand Down Expand Up @@ -944,9 +938,11 @@ const Checkout = () => {
<div className="payment-options-container">
<PayPalButtons
createOrder={async () => {
const name = `${car.name}`
const name = bookcarsHelper.truncateString(car.name, PayPalService.ORDER_NAME_MAX_LENGTH)
const _description = `${car.name} - ${daysLabel} - ${pickupLocation._id === dropOffLocation._id ? pickupLocation.name : `${pickupLocation.name} - ${dropOffLocation.name}`}`
const description = bookcarsHelper.truncateString(_description, PayPalService.ORDER_DESCRIPTION_MAX_LENGTH)
const amount = payDeposit ? depositPrice : price
const orderId = await PayPalService.createOrder(bookingId!, amount, PaymentService.getCurrency(), name)
const orderId = await PayPalService.createOrder(bookingId!, amount, PaymentService.getCurrency(), name, description)
return orderId
}}
onApprove={async (data) => {
Expand Down
19 changes: 18 additions & 1 deletion frontend/src/services/PayPalService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
import axiosInstance from './axiosInstance'
import * as UserService from '@/services/UserService'

/**
* Order item name max length 200 characters
* https://developer.paypal.com/docs/api/invoicing/v2/#invoices_create!ct=application/json&path=items/name&t=request
*
* @type {200}
*/
export const ORDER_NAME_MAX_LENGTH = 200

/**
* Order item description max length 1000 characters
* https://developer.paypal.com/docs/api/invoicing/v2/#invoices_create!ct=application/json&path=items/description&t=request
*
* @type {1000}
*/
export const ORDER_DESCRIPTION_MAX_LENGTH = 1000

/**
* Returns PayPal locale.
*
Expand All @@ -27,7 +43,7 @@ export const getLocale = () => {
* @param {string} sessionId
* @returns {Promise<number>}
*/
export const createOrder = (bookingId: string, amount: number, currency: string, name: string): Promise<string> =>
export const createOrder = (bookingId: string, amount: number, currency: string, name: string, description: string): Promise<string> =>
axiosInstance
.post(
'/api/create-paypal-order/',
Expand All @@ -36,6 +52,7 @@ export const createOrder = (bookingId: string, amount: number, currency: string,
amount,
currency,
name,
description,
}
)
.then((res) => res.data)
Expand Down
19 changes: 19 additions & 0 deletions packages/bookcars-helper/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -556,3 +556,22 @@ export const trim = (str: string, char: string): string => {
export const delay = (milliseconds: number) => new Promise((resolve) => {
setTimeout(resolve, milliseconds)
})

/**
* Truncates a string.
*
* @param {string} str
* @param {number} maxLength
* @returns {string}
*/
export const truncateString = (str: string, maxLength: number) => {
if (str.length <= maxLength) {
return str
}

if (maxLength >= 6) {
return `${str.slice(0, maxLength - 3)}...`
}

return str.slice(0, maxLength)
}
1 change: 1 addition & 0 deletions packages/bookcars-types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ export interface CreatePayPalOrderPayload {
amount: number
currency: string
name: string
description: string
}

export interface PaymentResult {
Expand Down

0 comments on commit 4f79b53

Please sign in to comment.