Skip to end of metadata
Go to start of metadata

You are viewing an old version of this content. View the current version.

Compare with Current View Version History

« Previous Version 4 Next »

Document Status

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

The idea is to send the cardholder name in the merchantData in the make payment request to paycomet.

✅ The user will fill the cardholder name field that already exists

✅ 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 reuse the profile user’s name

(error) 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

image-20241029-181552.png
 https://sequencediagram.org/
title Make purchase/No pre-auth

FE->Graphql:CommitOrder
Graphql->Payment-Service:MakePayment
Payment-Service->Paycomet-Service:MakePayment
Paycomet-Service->Paycomet: executePurchase
Paycomet-Service<-Paycomet: result
Payment-Service<-Paycomet-Service:result
Graphql<-Payment-Service:result
FE<-Graphql:result

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.

This is an example of cardholder data recovery already developed.

 paycomet-hosted-page-payment/paycomet-hosted-page-payment.tsx
if (paymentMethod.source === CartPaymentCardType.CREDIT) {
        ...,
        const cardPayload = {
          ...,
          nameOnCard: paymentMethod.cardholderName || '',
          card: {
            ...,
          },
          ...,
        };
        
        handlePaycometSuccess({ ...cardPayload, paymentMethodBrand });
      }
 src/pages/cart/payment/order-payment/use-order-payment.ts
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.

 src/functions/graphql/resolvers/orders.ts

Before

paycometSale = {
  ...,
  fullName: paymentUserDetails.name!,
  ...,
};

After

paycometSale = {
  ...,
  fullName: payment?.fullName || paymentUserDetails.name!,
  ...,
};

Fulfillment

The same that we did for graphql we need to replicate in the fulfillment

 src/modules/legacy/legacy.service.ts

Before

paycometSale = {
  ...,
  fullName: paymentUserDetails.name!,
  ...,
};

After

paycometSale = {
  ...,
  fullName: payment?.fullName || paymentUserDetails.name!,
  ...,
};

Payment Service (Already done)

 src/functions/graphql/utils/make-payment.ts
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

 src/paycomet-core/commons.types.ts
export class VaultedSchemeDto extends PaymentMethodBase {
  @ApiProperty({
    required: false,
    example: 'John Smith',
    description: 'Cardholder name',
  })
  @IsString()
  @IsOptional()
  public cardholderName?: string;
}
 src/paycomet-core/api/api.post-execute-purchase.ts
interface ICustomerData {
  mobilePhone?: IMobilePhone;
  email?: string;
  name?: string;
  surname?: string;
}
 src/paycomet-core/paycomet-helper.ts

Create two function parseName and parseSurname, to handle the cardholderName to send to paycomet.

Update the buildUserDetails function and tests.

public buildUserDetails = (
    region: string,
    cellphone?: string,
    email?: string,
    paymentMethod?: PaymentMethod
  ): TCustomer | undefined => {
    if (!cellphone && !email) {
      return undefined;
    }
    return {
      mobilePhone: cellphone ? this.parsePhoneNumber(cellphone, region) : undefined,
      email: email || undefined,
      name: parseName(paymentMethod.cardholderName)
      surname: parseSurname(paymentMethod.cardholderName)
    };
  };
 src/payment/payment.service.ts
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

image-20241029-181815.png
 https://sequencediagram.org/
title Pre-auth

FE->Graphql:CreatePreAuth
Graphql->Paycomet-Service:CreatePreAuth
Paycomet-Service->Paycomet: createPreauthorization
Paycomet-Service<-Paycomet: result
Graphql<-Paycomet-Service:result
FE<-Graphql:result

Whitelabel App (Already done)

 src/pages/cart/payment/order-payment/paycomet-hosted-page-payment/paycomet-vaulted-card.tsx
generateCreatePreAuthorization({
        variables: {
          input: {
            ...,
            cardHolderName: paymentValues.nameOnCard,
            ...,
          },
        },
      });

GraphQL (Already done)

 src/functions/graphql/providers/payments.ts
public async createPreAuthorizationPaycomet({...}){
  const paycometPreauth =
    await this.paymentsClient.paycometClient.request<ICreatePreAuthorizationResponse>((apis) =>
      apis.paymentsApi.createPreAuthorization({
        iCreatePreAuthorizationRequest: {
          ...,
          cardHolderName,
          ...,
        },
        region: regionCountry,
      }),
    );
}

Paycomet Service

 src/payment/preauth/preauth.service.ts
public async processPreAuth(...){
  ...
  const customer = this.paycometHelper.buildUserDetails(region, cellphone, email, request);
  ...
}

Vaulted

No update required


Vaulted - Pre-auth

No update required


Update phoneNumber field to use user accounts or delivery data

Whitelabel App

 cart/payment/order-payment/use-order-payment.ts

One-time:

const {
  ...,
  orderPhoneNumber,
} = useOrderContext();

const placeOrder = useCallback(async () => {
  ...
  
  const userPaymentDetails = enablePaycometPaymentUserDetails
    ? {
        phoneNumber: orderPhoneNumber ?? auth.user?.details?.phoneNumber,
        email: auth.user?.details?.email,
      }
    : undefined;
    
  ...
  
}

Vaulted:

const {
  ...,
  orderPhoneNumber,
} = useOrderContext();

const processOrderWithAccount = useCallback(async () => {
  ...
  
  const userPaymentDetails = enablePaycometPaymentUserDetails
    ? {
        phoneNumber: orderPhoneNumber ?? user?.details.phoneNumber,
        email: user?.details?.email,
      }
    : undefined;
    
  ...
  
}
 paycomet-hosted-page-payment/paycomet-vaulted-card.tsx
const { setRepriceOrderAfterNavigate, orderPhoneNumber } = useOrderContext();

...

if (rbiOrder?.rbiOrderId && accountIdentifier && vaultedPaymentConfirmed) {
  ...
  const userPaymentDetails = enablePaycometPaymentUserDetails
      ? {
          phoneNumber: orderPhoneNumber ?? auth.user?.details?.phoneNumber,
          email: auth.user?.details?.email,
        }
      : undefined;
  ...
}
 paycomet-hosted-page-payment/paycomet-credit-card-form/paycomet-credit-card-form.tsx
const { setRepriceOrderAfterNavigate, orderPhoneNumber } = useOrderContext();

...

if (rbiOrder?.rbiOrderId && tpvToken) {
  ...
  const userPaymentDetails = enablePaycometPaymentUserDetails
      ? {
          phoneNumber: orderPhoneNumber ?? user?.details?.phoneNumber,
          email: user?.details?.email,
        }
      : undefined;
  ...
}

🎛️ Configuration

Include here any configuration required (Sanity, LaunchDarkly flags, etc.) required to enable the solution.

🧑‍🚒 QA Plan

We can create the test cases following the doc below

[Test Cases] [Deprecated] Visa/Sibs - new mandatory fields

⚠️ Call-outs

This functionality is made exclusively for the PSP Paycomet which is used in the Spanish and Portuguese environments.

  • No labels

0 Comments

You are not logged in. Any changes you make will be marked as anonymous. You may want to Log In if you already have an account.