# Masterpass

**pz-masterpass** provides a set of modular and customizable components for Masterpass integration during checkout. This includes card management, OTP verification, and modal interactions.

## <mark style="color:red;">**Installation Method**</mark>

You can use the following command to install the extension with the latest plugins:

```bash
npx @akinon/projectzero@latest --plugins
```

## <mark style="color:red;">**Masterpass Provider**</mark>

Wraps your checkout context with Masterpass features. Use this at the top level of the checkout.

```bash
/src/app/[commerce]/[locale]/[currency]/orders/checkout/page.tsx
```

### <mark style="color:red;">**Usage Examples**</mark>

#### **Default Usage**

```javascript
<PluginModule
    component={Component.MasterpassProvider}
    props={{
translations: {
    genericErrorMessage: 'An error occurred. Please try again later.'
}
    }}
>
 ... ...
</PluginModule>
```

#### **Customized Usage Additional Params**

```javascript
<PluginModule
  component={Component.MasterpassProvider}
  props={{
    additionalParams: {
      order_product_name_arr: ['TEST'],
      order_product_code_arr: ['TST'],
      order_qty_arr: ['1'],
      order_product_info_arr: ['test']
    }
  }}
>
 ... ...
</PluginModule>
```

## <mark style="color:red;">**Delete Confirmation Modal**</mark>

Shows a modal when a user attempts to delete a saved card.

### <mark style="color:red;">**Props**</mark>

<table><thead><tr><th width="120.3125">Props</th><th width="166.22265625">Type</th><th width="104.3671875">Required</th><th>Description</th></tr></thead><tbody><tr><td>translations</td><td>type of defaultTranslations</td><td>Optional</td><td>Used to customize the default texts.</td></tr><tr><td>renderer</td><td>RendererProps</td><td>Optional</td><td>Renderer functions that can be used to customize all subcomponents.</td></tr></tbody></table>

### **RendererProps**

<table><thead><tr><th width="126.05078125">Props</th><th width="199.0625">Type</th><th>Description</th></tr></thead><tbody><tr><td>open</td><td>boolean</td><td>It is information whether the modal is open or not.</td></tr><tr><td>setOpen</td><td>(open:boolean) => void</td><td>Used to manage modal on/off operation.</td></tr><tr><td>onConfirm</td><td>() => void</td><td>This is the function that will perform the deletion operation.</td></tr><tr><td>onCancel</td><td>() => void</td><td>This is the function that will be run if the user cancels the deletion process.</td></tr><tr><td>loading</td><td>boolean</td><td>Indicates the loading status during the deletion process.</td></tr><tr><td>error</td><td>string / null</td><td>Error message to be displayed if an error occurs during deletion.</td></tr></tbody></table>

### <mark style="color:red;">**Usage Examples**</mark>

```bash
/src/apps/[commerce]/[locale]/[currency]/orders/checkot/page.tsx
```

#### **Default Usage**

```javascript
<PluginModule
 component={Component.MasterpassDeleteConfirmationModal}
 props={{
   translations: {
     title: 'Are you sure you want to delete this card?',
     delete_button: 'Remove',
     cancel_button: 'Delete'
   }
 }}
/>
```

#### **Customized Usage with Renderer**

```javascript
<PluginModule
 component={Component.MasterpassDeleteConfirmationModal}
 props={{
   renderer: {
     Content: ({ open, setOpen, onConfirm, onCancel, loading, error }) => (
       <Modal
         open={open}
         setOpen={setOpen}
         className="w-full sm:w-[28rem]"
         portalId="masterpass-remove-card-modal"
       >
         <div className="flex flex-col items-center p-5">
           <div className="text-xs mb-3">
             Are you sure you want to delete your card?
           </div>
           <Button onClick={onConfirm} className="bg-red-600 text-black">
             {loading ? 'Deletion...' : 'Delete'}
           </Button>
           <Button appearance="outlined" onClick={onCancel}>
             Cancel
           </Button>
           {error && (
             <p className="text-red-500 text-sm mt-2 text-center">
               🚨 {error}
             </p>
           )}
         </div>
       </Modal>
     )
   }
 }}
/>
```

## <mark style="color:red;">**OTP Modal**</mark>

Displays an OTP verification modal after card action (add).

### <mark style="color:red;">**Props**</mark>

<table><thead><tr><th width="116.3046875">Props</th><th width="171.21875">Type</th><th width="119.23828125">Required</th><th>Description</th></tr></thead><tbody><tr><td>translations</td><td>type of defaultTranslations</td><td>Optional</td><td>Used to customize the default texts.</td></tr><tr><td>renderer</td><td>RendererProps</td><td>Optional</td><td>Renderer functions that can be used to customize all subcomponents.</td></tr></tbody></table>

### <mark style="color:red;">**RendererProps**</mark>

<table><thead><tr><th width="130.86328125">Props</th><th width="196.55078125">Type</th><th>Description</th></tr></thead><tbody><tr><td>open</td><td>boolean</td><td>It is information whether the modal is open or not.</td></tr><tr><td>setOpen</td><td>(open:boolean) => void</td><td>Used to manage modal on/off operation.</td></tr><tr><td>onSubmit</td><td>(data: { otp_code:string }) => void</td><td>Sends the OTP code entered by the user.</td></tr><tr><td>loading</td><td>boolean</td><td>Indicates the loading status during validation.</td></tr><tr><td>error</td><td>string / null</td><td>Error message to be displayed if there is an error.</td></tr><tr><td>resendSms</td><td>() => void</td><td>Function triggered when the user requests SMS again.</td></tr><tr><td>resendSmsFetching</td><td>boolean</td><td>Indicates the loading status during the resending process.</td></tr><tr><td>targetDate</td><td>number</td><td>When the countdown will end (as a timestamp).</td></tr><tr><td>otpRef</td><td>string / null</td><td>Transaction reference number, if applicable.</td></tr></tbody></table>

### <mark style="color:red;">**Usage Examples**</mark>

```bash
/src/apps/[commerce]/[locale]/[currency]/orders/checkot/page.tsx
```

#### **Default Usage**

```javascript
<PluginModule
 component={Component.MasterpassOtpModal}
 props={{
   translations: {
     enter_the_verification_code: 'Enter the verification code',
     sms_code: 'SMS Code',
     verify: 'Verify',
     resend_sms: 'Resend SMS',
     // Or pass response code to show custom message
     5001: 'Please enter the OTP sent to your mobile number'
   }
 }}
/>
```

#### **Customized Usage with Renderer**

```javascript
<PluginModule
 component={Component.MasterpassOtpModal}
 props={{
   renderer: {
     Content: ({
       open,
       setOpen,
       onSubmit,
       loading,
       error,
       resendSms,
       resendSmsFetching,
       targetDate,
       otpRef
     }) => {
       const [code, setCode] = useState('');
       const [remainingSeconds, setRemainingSeconds] = useState(
         Math.ceil((targetDate - Date.now()) / 1000)
       );
       useEffect(() => {
         if (!targetDate) return;
         const interval = setInterval(() => {
           const secondsLeft = Math.ceil((targetDate - Date.now()) / 1000);
           setRemainingSeconds(secondsLeft);
           if (secondsLeft <= 0) {
             clearInterval(interval);
           }
         }, 1000);
         return () => clearInterval(interval);
       }, [targetDate]);
       return (
         <Modal
           open={open}
           setOpen={setOpen}
           className="w-full sm:w-[28rem]"
           portalId="otp-masterpass"
         >
           <div className="px-6 py-4">
             <h2 className="text-center text-xl text-primary-600 font-semibold">
               Verification Required
             </h2>
             <form
               onSubmit={(e) => {
                 e.preventDefault();
                 onSubmit({ otp_code: code });
               }}
               className="flex flex-col items-center mt-4"
             >
               <label
                 htmlFor="otp_code"
                 className="text-sm mb-1 text-gray-700"
               >
                 SMS Code
               </label>
               <input
                 id="otp_code"
                 maxLength={6}
                 value={code}
                 onChange={(e) => setCode(e.target.value)}
                 placeholder="••••••"
                 className="border p-2 rounded w-full max-w-[200px] text-center tracking-widest"
               />
               <Button
                 type="submit"
                 className="mt-4 px-4 py-2 bg-blue-600 text-black rounded"
               >
                 Verify
               </Button>
               {error && <p className="mt-2 text-xs text-red-500">{error}</p>}
             </form>
             <div className="mt-2 flex justify-center text-sm text-gray-600">
               {remainingSeconds > 0
                 ? `Time remaining: ${remainingSeconds} seconds`
                 : 'Time is up'}
             </div>
             <div className="mt-2 flex justify-center">
               <Button
                 onClick={resendSms}
                 disabled={loading}
                 className="mt-4 text-sm underline text-secondary-500"
               >
                 {resendSmsFetching
                   ? 'Code sent'
                   : 'Resend SMS code'}
               </Button>
             </div>
           </div>
         </Modal>
       );
     }
   }
 }}
/>
```

## <mark style="color:red;">**MasterpassLinkModal Component**</mark>

Prompts user to link their Masterpass card if one is detected.

### <mark style="color:red;">**Props**</mark>

<table><thead><tr><th width="132.078125">Props</th><th width="176.82421875">Type</th><th width="111.44921875">Required</th><th>Description</th></tr></thead><tbody><tr><td>translations</td><td>type of defaultTranslations</td><td>Optional</td><td>Used to customize the default texts.</td></tr><tr><td>renderer</td><td>RendererProps</td><td>Optional</td><td>Renderer functions that can be used to customize all subcomponents.</td></tr></tbody></table>

### <mark style="color:red;">**RendererProps**</mark>

<table><thead><tr><th width="115.51953125">Props</th><th width="197.484375">Type</th><th>Description</th></tr></thead><tbody><tr><td>open</td><td>boolean</td><td>It is information whether the modal is open or not.</td></tr><tr><td>setOpen</td><td>(open:boolean) => void</td><td>Used to manage modal on/off operation.</td></tr><tr><td>onClick</td><td>() => void</td><td>It is the function that is called when the user clicks the "Use" button.</td></tr><tr><td>loading</td><td>boolean</td><td>This is the loading status that will be displayed during the API request.</td></tr><tr><td>error</td><td>string / null</td><td>If there is an error in the API response, a message is displayed in this field.</td></tr></tbody></table>

### <mark style="color:red;">**Usage Examples**</mark>

```bash
/src/app/[commerce]/[locale]/[currency]/orders/checkout/page.tsx
```

#### **Default Usage**

```javascript
<PluginModule
 component={Component.MasterpassLinkModal}
 props={{
   translations: {
     use_masterpass_cards:
       'You have cards registered to your Masterpass account. Would you like to use your cards?',
     use: 'Use'
   }
 }}
/>
```

#### **Customized Usage with Renderer**

```javascript
<PluginModule
 component={Component.MasterpassLinkModal}
 props={{
   renderer: {
     Content: ({ open, setOpen, onClick, loading, error }) => (
       <Modal
         open={open}
         setOpen={setOpen}
         className="w-full sm:w-[28rem]"
         portalId="masterpass-check-user"
       >
         <div className="p-10">
           <p className="text-sm text-center">
             You have cards registered to your Masterpass account. Do you want to use your cards?
           </p>
           <Button
             onClick={onClick}
             disabled={loading}
             className="bg-green-600 text-error w-full py-2 mt-4"
           >
             {loading ? 'Loading...' : 'Use'}
           </Button>
           {error && <p className="text-error text-sm">{error}</p>}
         </div>
       </Modal>
     )
   }
 }}
/>
```

## <mark style="color:red;">**MasterpassCardList Component**</mark>

Displays all Masterpass-linked cards and allows selection or deletion.

### <mark style="color:red;">**Props**</mark>

<table><thead><tr><th width="125.37890625">Props</th><th width="180.796875">Type</th><th width="125.76953125">Required</th><th>Description</th></tr></thead><tbody><tr><td>className</td><td>string</td><td>Optional</td><td>It adds an extra style class to the outer container of the component.</td></tr><tr><td>translations</td><td>{ [key: string]: string }</td><td>Optional</td><td>Used to customize the default texts.</td></tr><tr><td>renderer</td><td>RendererProps</td><td>Optional</td><td>Renderer functions that can be used to customize all subcomponents.</td></tr></tbody></table>

### <mark style="color:red;">**RendererProps**</mark>

<table><thead><tr><th width="142.03125">Props</th><th width="229.8515625">Type</th><th>Description</th></tr></thead><tbody><tr><td>Header</td><td>JSX.Element</td><td>Used to customize the title area at the top of the card list.</td></tr><tr><td>CardItem</td><td>(params: { card, selectedCard, onSelect, DeleteButton }) => JSX.Element</td><td>It allows you to fully customize the card element.</td></tr><tr><td>Loader</td><td>() => JSX.Element</td><td>Used to define a custom loader component to be displayed when loading cards.</td></tr><tr><td>ErrorFallback</td><td>(params: { error: string; onRetry: () => void }) => JSX.Element</td><td>Custom widget to be shown if an error occurs while loading cards.</td></tr><tr><td>SwitchPaymentButton</td><td>(props: { onClick: () => void; label: string }) => JSX.Element</td><td>Used to customize the "Pay with a new card" option.</td></tr></tbody></table>

### <mark style="color:red;">**Usage Examples**</mark>

```bash
/src/views/checkout/steps/payment/options/credit-card/index.tsx
```

**Default Usage**

```javascript
<PluginModule 
    component={Component.MasterpassCardList}
    props={{
        className: 'p-10',
        Translations:
            { 
    title: 'Select a card to pay with',
    pay_with_new_card: 'Pay with a new card',
    retryFetchCards: 'Retry Fetching Cards'
}
    }}
/>
```

#### **Customized Usage with Renderer**

```javascript
<PluginModule
 component={Component.MasterpassCardList}
 props={{
   className: 'px-10',
   form: {
     control,
     register,
     errors,
     setFormValue,
     clearErrors
   },
   renderer: {
     Header: () => (
       <div className="flex items-center gap-2 mt-4 px-10 text-success">
         Select a card to pay
       </div>
     ),
     Loader: () => (
       <div className="flex justify-center items-center p-10">
         <span className="text-lg font-bold text-error">
           Loading your cards...
         </span>
       </div>
     ),
     ErrorFallback: ({ error, onRetry }) => (
       <div className="text-center p-8">
         <h2 className="text-red-500 text-xl mb-4">Oops! {error}</h2>
         <Button onClick={onRetry}>Try Again</Button>
       </div>
     ),
     CardItem: ({ card, onSelect, DeleteButton, selectedCard }) => (
       <li
         key={card.UniqueId}
         className="p-4 cursor-pointer rounded-[10px] border-gray border space-x-5 pl-5 mb-6 md:mb-2.5"
         onClick={() => onSelect(card)}
       >
         <div className="flex justify-between items-center">
           <div className="flex items-center">
             <Checkbox
               key={
                 selectedCard?.UniqueId === card.UniqueId
                   ? 'selected'
                   : 'not-selected'
               }
               checked={selectedCard?.UniqueId === card.UniqueId}
               onChange={() => onSelect(card)}
               className="mr-2"
             />
             <div>
               <h3 className="font-semibold">{card.Name}</h3>
               <p className="text-xs text-gray-500">{card.Value1}</p>
             </div>
           </div>
           <DeleteButton cardAliasName={card.Name} />
         </div>
       </li>
     ),
     SwitchPaymentButton: ({ onClick, label }) => (
       <div className="px-10">
         <button
           onClick={onClick}
           className="p-4 w-full text-left cursor-pointer rounded-[10px] border-gray border space-x-5 pl-5 mb-6 md:mb-2.5"
         >
           {label}
         </button>
       </div>
     )
   }
 }}
/>
```

## <mark style="color:red;">**MasterpassCardRegistration Component**</mark>

Form to add a new Masterpass card and consent to store it.

### <mark style="color:red;">**Props**</mark>

<table><thead><tr><th width="162.23046875">Props</th><th width="153.41796875">Type</th><th width="132.453125">Required</th><th>Description</th></tr></thead><tbody><tr><td>getValues</td><td>() => Record&#x3C;string, string></td><td>Required</td><td>Returns the values ​​of form fields.</td></tr><tr><td>className</td><td>string</td><td>Optional</td><td>Gives an additional CSS class to the outer container.</td></tr><tr><td>infoModalContent</td><td>React.ReactNode</td><td>Optional</td><td>Body content for the informational modal.</td></tr><tr><td>infoModalIcon</td><td>React.ReactNode</td><td>Optional</td><td>Used to override the notification icon.</td></tr><tr><td>translations</td><td>typeof defaultTranslations</td><td>Optional</td><td>Can be used to override default texts.</td></tr><tr><td>renderer</td><td>RendererProps</td><td>Optional</td><td>Renderer functions that can be used to customize all subcomponents.</td></tr></tbody></table>

### <mark style="color:red;">**RendererProps**</mark>

<table><thead><tr><th width="124.82421875">Props</th><th width="271.28125">Type</th><th>Description</th></tr></thead><tbody><tr><td>Content</td><td>props: { isChecked, toggle, setIsInfoModalOpen, onChange, onSubmit, loading, error, showGoBackLink?, onClickGoBackLink? }) => JSX.Element</td><td>Used to render the main content.</td></tr><tr><td>InfoModal</td><td>(props: { open: boolean; setOpen: (value: boolean) => void }) => JSX.Element</td><td>Can be used to override the notification modal.</td></tr></tbody></table>

### <mark style="color:red;">**Usage Examples**</mark>

```bash
/src/views/checkout/steps/payment/options/credit-card/index.tsx
```

#### **Default Usage**

```
<PluginModule
 component={Component.MasterpassCardRegistration}
 props={{
   // Do not remove getValues, it is used to get the form values
   getValues,
   translations: {
     enter_card_name: 'Enter card name',
     continue: 'Continue',
     pay_with_my_masterpass_card: 'Pay with my Masterpass card',
     terms_and_conditions: 'Masterpass terms and conditions',
     card_registration_consent:
       'I want to store my card information in the Mastercard infrastructure and use it again in my next purchase.'
   }
 }}
/>
```

#### **Customized Usage with className, infoModalContent, infoModalIcon**

```javascript
<PluginModule
 component={Component.MasterpassCardRegistration}
 props={{
   // Do not remove getValues, it is used to get the form values
   getValues,
   className: 'mt-5 mb-10 sm:px-10',
   infoModalContent: <div>Lorem...</div>,
   infoModalIcon: <Icon name="info" />,
   translations: {
     enter_card_name: 'Enter card name',
     continue: 'Continue',
     pay_with_my_masterpass_card: 'Pay with my Masterpass card',
     terms_and_conditions: 'Masterpass terms and conditions',
     card_registration_consent:
       'I want to store my card information in the Mastercard infrastructure and use it again in my next purchase.'
   }
 }}
/>
```

#### **Customized Usage with Renderer**

```javascript
<PluginModule
 component={Component.MasterpassCardRegistration}
 props={{
   // Do not remove getValues, it is used to get the form values
   getValues,
   renderer: {
     InfoModal: ({ open, setOpen }) => (
       <Modal
         open={open}
         setOpen={setOpen}
         portalId="masterpass-info-modal"
       >
         masterpass information
       </Modal>
     ),
     Content: ({
       isChecked,
       toggle,
       setIsInfoModalOpen,
       onChange,
       onSubmit,
       loading,
       error,
       showGoBackLink,
       onClickGoBackLink
     }) => (
       <div className="bg-[#F8F8F8] mx-10 mb-5 px-2 py-1">
         <div className="flex items-center gap-2 pb-4 mb-4">
           <Checkbox checked={isChecked} onChange={toggle} />
           <h1>Masterpass</h1>
           <div>
             <Icon
               name="info"
               size={15}
               className="fill-[#000000] cursor-pointer"
               onClick={() => {
                 setIsInfoModalOpen(true);
               }}
             />
           </div>
         </div>
         <p className="text-xs">
           I want to store my card information in the Mastercard infrastructure and use it again in my next purchase.
         </p>
         {isChecked && (
           <>
             <Input
               label="Give your card a name"
               onChange={(e) =>
                 onChange((e.target as HTMLInputElement).value)
               }
               className="mt-2"
             />
             <Button
               onClick={onSubmit}
               className="bg-green-600 text-black w-full mt-3"
             >
               {loading ? 'Loading...' : 'Save'}
             </Button>
             {error && (
               <p className="text-xs text-red-600 mt-2">🚨 {error}</p>
             )}
           </>
         )}
         {showGoBackLink && (
           <div>
             <button
               onClick={onClickGoBackLink}
               className="text-xs text-red-600 underline mt-3"
             >
               I want to pay with my card registered to Masterpass.
             </button>
           </div>
         )}
       </div>
     )
   }
 }}
/>
```
