Document Status | Status |
---|
colour | Blue |
---|
title | in-progress |
---|
|
|
---|
Document Owner(s) | Capovilla, Evandro |
---|
Reviewers | |
---|
🛠️ Potential Solutions
Assumptions
We are sending the name as the first string until de empty string.
We are sending the surname as the rest of the name after the first empty string
We are using the same feature flag to send user details to send first name and last name data
#1 - Send cardholder name field to paycomet
...
Mandatory fields are still being sent (email and/or cell phone)
The workPhone and homePhone fields are not mandatory due to the rule above
The IpAddress field has already been sent - No changes necessary
The cardholderName field only requires updates in BE
#1 - Send cardholder name field to paycomet
The idea is to send the cardholder name in the merchantData in the make payment request to paycomet.
...
✅ We guarantee that the name is related to the credit card
#2 - Send profile user’s name to paycomet
The idea is to get the profile user’s name to send the information to paycomet.
...
We can’t guarantee that the name is related to the credit card
✅ Proposed Solution
...
Send cardholder name field to paycomet
One time
Payment made with a new credit card
...
Whitelabel App (Already done)
The frontend will be responsible for displaying and retrieving the cardholderName field and sending this information to paycomet. Nowadays this information is already sent via Paycomet forms, but they also need it to be sent via the merchantData field.
...
Expand |
---|
title | src/pages/cart/payment/order-payment/use-order-payment.ts |
---|
|
Code Block |
---|
| commitInput = {
creditType: payCometValues.cardType,
order,
payment: {
fullName: payCometValues.nameOnCard || '',
...,
},
...,
}; |
|
GraphQL
Today we get the username from user accounts instead of getting the credit card name, which is already sent by whitelabel.
Expand |
---|
title | src/functions/graphql/resolvers/orders.ts |
---|
|
Before Code Block |
---|
paycometSale = {
...,
fullName: paymentUserDetails.name!,
...,
}; |
After Code Block |
---|
paycometSale = {
...,
fullName: payment?.fullName || paymentUserDetails.name!,
...,
}; |
|
Fulfillment
The same that we did for graphql we need to replicate in the fulfillment
Expand |
---|
title | src/modules/legacy/legacy.service.ts |
---|
|
Before Code Block |
---|
paycometSale = {
...,
fullName: paymentUserDetails.name!,
...,
}; |
After Code Block |
---|
paycometSale = {
...,
fullName: payment?.fullName || paymentUserDetails.name!,
...,
}; |
|
Payment Service (Already done)
Expand |
---|
title | src/functions/graphql/utils/make-payment.ts |
---|
|
Code Block |
---|
private mapPaymentMethod(
params: IPaycometPaymentSaleEvent,
): {
paymentMethodType: string;
paymentMethod: string;
} {
const isVaultedPayment = !params.storePaymentMethod && params.storedPaymentMethodId;
if (isVaultedPayment) {
return {
paymentMethodType: params.paymentType,
paymentMethod: JSON.stringify({
...,
cardholderName: params?.fullName,
...,
}),
};
}
return {
paymentMethodType: params.paymentType,
paymentMethod: JSON.stringify({
...,
cardholderName: params?.fullName,
...,
}),
};
} |
|
Paycomet Service
Expand |
---|
title | src/paycomet-core/commons.types.ts |
---|
|
Code Block |
---|
| export class VaultedSchemeDto extends PaymentMethodBase {
@ApiProperty({
required: false,
example: 'John Smith',
description: 'Cardholder name',
})
@IsString()
@IsOptional()
public cardholderName?: string;
} |
|
...
Expand |
---|
title | src/paycomet-core/paycomet-helper.ts |
---|
|
Create two function parseName and parseSurname, to handle the The idea here is to update the buildUserDetails function to handle first and last name, since the responsibility of this function is to generate the customer field. Create two function parseName and parseSurname, to handle the cardholderName to send to paycomet. Update the buildUserDetails function and tests. Code Block |
---|
public buildUserDetails = (
region: string,
cellphone?: string,
email?: string,
paymentMethod?: PaymentMethod
): TCustomer | undefined => {
if (!cellphone && !email && !paymentMethod.cardholderName) {
return undefined;
}
return {
mobilePhone: cellphone ? this.parsePhoneNumber(cellphone, region) : undefined,
email: email || undefined,
name: parseName(paymentMethod.cardholderName)
surname: parseSurname(paymentMethod.cardholderName)
};
}; |
|
Expand |
---|
title | src/payment/payment.service.ts |
---|
|
Code Block |
---|
| public async handlePurchase(...){
...
const customer = this.paycometHelper.buildUserDetails(region, cellphone, email, request);
...
} |
|
...
Pre-auth
Payment made with a new credit card and pre-auth is enabled
...
Whitelabel App (Already done)
Expand |
---|
title | src/pages/cart/payment/order-payment/paycomet-hosted-page-payment/paycomet-vaulted-card.tsx |
---|
|
Code Block |
---|
generateCreatePreAuthorization({
variables: {
input: {
...,
cardHolderName: paymentValues.nameOnCard,
...,
},
},
}); |
|
GraphQL (Already done)
Expand |
---|
title | src/functions/graphql/providers/payments.ts |
---|
|
Code Block |
---|
public async createPreAuthorizationPaycomet({...}){
const paycometPreauth =
await this.paymentsClient.paycometClient.request<ICreatePreAuthorizationResponse>((apis) =>
apis.paymentsApi.createPreAuthorization({
iCreatePreAuthorizationRequest: {
...,
cardHolderName,
...,
},
region: regionCountry,
}),
);
}
|
|
Paycomet Service
Expand |
---|
title | src/payment/preauth/preauth.service.ts |
---|
|
Code Block |
---|
| public async processPreAuth(...){
...
const customer = this.paycometHelper.buildUserDetails(region, cellphone, email, request);
...
} |
|
...
Vaulted
Payment made with a vaulted card
Whitelabel App (Already done)
...
title | src/pages/cart/payment/order-payment/use-order-payment.ts |
---|
...
...
No update required
...
Vaulted - Pre-auth
No update required
...
Update phoneNumber field to use user accounts or delivery data
The idea here is to mainly use the phoneNumber from the cart page ( delivery mode ) and if it doesn't exist, we use the phoneNumber from the user data ( restaurant mode ). If neither of these fields exist, we are sending that data as empty.
Whitelabel App
Expand |
---|
title | cart/payment/order-payment/use-order-payment.ts |
---|
|
One-time: Code Block |
---|
const {
...,
orderPhoneNumber,
} = useOrderContext();
const placeOrder = useCallback(async () => {
...
const userPaymentDetails = enablePaycometPaymentUserDetails
? {
phoneNumber: orderPhoneNumber ?? auth.user?.details?.phoneNumber,
email: auth.user?.details?.email,
}
: undefined;
...
} |
Vaulted: Code Block |
---|
const {
...,
orderPhoneNumber,
} = useOrderContext();
const processOrderWithAccount = useCallback(async () => {
...
const userPaymentDetails = enablePaycometPaymentUserDetails
? {
phoneNumber: orderPhoneNumber ?? user?.details.phoneNumber,
email: user?.details?.email,
}
: undefined;
...
} |
|
Expand |
---|
title | paycomet-hosted-page-payment/paycomet-vaulted-card.tsx |
---|
|
Code Block |
---|
const { setRepriceOrderAfterNavigate, orderPhoneNumber } = useOrderContext();
...
if (rbiOrder?.rbiOrderId && accountIdentifier && vaultedPaymentConfirmed) {
...
const userPaymentDetails = enablePaycometPaymentUserDetails
? {
phoneNumber: orderPhoneNumber ?? auth.user?.details?.phoneNumber,
email: auth.user?.details?.email,
}
: undefined;
...
} |
|
Expand |
---|
title | paycomet-hosted-page-payment/paycomet-credit-card-form/paycomet-credit-card-form.tsx |
---|
|
Code Block |
---|
const { setRepriceOrderAfterNavigate, orderPhoneNumber } = useOrderContext();
...
if (rbiOrder?.rbiOrderId && tpvToken) {
...
const userPaymentDetails = enablePaycometPaymentUserDetails
? {
billingAddress, phoneNumber: orderPhoneNumber }?? user?.details?.phoneNumber,
} ...
} |
|
Paycomet Service (Should already be done by one-time task)
Expand |
---|
title | src/payment/payment.service.ts |
---|
|
Code Block |
---|
| public async handlePurchase(...){
...
const customer = this.paycometHelper.buildUserDetails(region, cellphone, email, request) email: user?.details?.email,
}
: undefined;
...
} |
|
Vaulted - Pre-auth
...
🎛️ Configuration
Info |
---|
Include here any configuration required (Sanity, LaunchDarkly flags, etc.) required to enable the solution. |
🧑🚒 QA Plan
⚠️ Call-outs
This functionality is made exclusively for the PSP Paycomet which is used in the Spanish and Portuguese environments.