Skip to content

Context

Introduction

The Cards subdomain is an essential component of the Payment Gateway, focusing on the management of Payment Cards (or simply Cards in this context). This subdomain centers around Cards and Card Holders.

  • Cards: These are instruments, either physical or virtual, issued to facilitate transactions. Managed from issuance to cancellation, Cards enable direct transactions by leveraging the funds in linked accounts, enhancing the financial operations within the system.

  • Card Holders: Individuals issued and utilizing the Cards for transactions. They are crucial for the operational use of the Cards, ensuring transactions are carried out on their behalf.

Cards are linked to specific Accounts where funds are stored for spending, but the management of these Accounts falls under the Accounts subdomain. The relationship between Cards and Accounts is foundational, enabling the operational utility of Cards by providing access to the Account's funds for transactions.

A Card Holder can have multiple Cards, creating a 1-n relationship between Card Holders and Cards.

An Account can have multiple Cards, creating a 1-n relationship between Accounts and Cards.

graph LR;
    CardHolder[Card Holder] -->|1..n| Card[Card]
    Account[Account] -->|1..m| Card[Card]
Hold "Alt" / "Option" to enable pan & zoom

Relation to Adyen's Concepts

In the Cards subdomain, our system's integration with Adyen plays a crucial role in the issuance and management of Cards:

  • Cards correspond to Adyen Payment Instruments. Every Payment Instrument belongs to a Balance Account.

  • Card Holders are unique to our platform and are essential for the operational use of Cards. Although there's no direct matching entity on Adyen's side for Card Holders, we utilize this entity to facilitate card issuance and tie transactions to a specific person. For example, we generate the card's display name or set the 3DS authentication method using their phone number, enhancing the user experience and security.

A Balance Account can have multiple Payment Instruments, creating a 1-n relationship between Accounts and Payment Instruments. This mimicks the relationship between our own entities.

graph LR;
    BalanceAccount[Balance Account] -->|1..m| PaymentInstrument[Payment Instrument]
Hold "Alt" / "Option" to enable pan & zoom

Our entities use the external_id field as a unique identifier, storing the corresponding Adyen ID for each entity within our system, thus ensuring a seamless mapping process between the two data models.

Source of Truth and Lifecycle Management

Cards

Info

The class CardLifecycleLogic is responsible for Card lifecycle management.

Cards lifecycles are fully managed within the component. Each Card on our platform is directly mirrored by a corresponding Adyen Payment Instrument.

Our component is the primary source of truth for the lifecycle management of Cards, with synchronization being one-way from our component to Adyen. This setup reflects our component's proactive role in managing these financial entities. Changes on the Adyen side need manual replication in our system; however, given our control over the full Card lifecycle, such situations are exceptional.

Card Holders

Info

The class CardHolderLogic is responsible for the whole scope of Card Holder management.

The component does not manage the lifecycle of Card Holders but focuses on the declaration of Card Holders into our platform. This is because Card Holder management is intricately tied to individuals, which is beyond the component's scope. Therefore, the component supports only declaration and termination operations.

There is no automatic synchronization with Adyen for Card Holders since there is no matching entity on Adyen's side. Any information required for the operational use of Cards, such as the Card Holder's details for 3DS authentication, is managed through our system's integration with Adyen.

Additional Card Management Features

This section outlines the management of additional aspects of Cards within our system.

Status Management

Info

The class [CardStatus][components.payment_gateway.public.entities.CardStatus] is responsible for Card status management.

Card status is primarily under the ownership of the component. The component manages the technical aspects of status changes involving Cards, specifically addressing situations such as activating, suspending, and closing Cards. Cards are inactive by default upon issuance.

  • Activate Card: Transitioning a Card to active status allows it to be used for transactions.
  • Suspend Card: Temporarily deactivates a Card, preventing its use. An optional reason for suspension can be provided for record-keeping and forensics.
  • Close Card: Permanently deactivates a Card, making it unusable. Like suspension, a reason for closing can also be provided for future reference.

The component keeps a trace of the entire status change history for each Card, ensuring a comprehensive record of all actions taken. This history supports transparency and aids in troubleshooting and auditing processes.

Status changes are executed through API calls and replicated on the Adyen side. However, Adyen remains the source of truth for a Card's status: the actual value after a status change request will be the one returned by Adyen after calling their API.

See CardStatusLogic for all the supported status values and transitions.

Warning

A Card's status can also change on Adyen's side independently of the component, for example, changing it manually on the dashboard, or if the Adyen fraud team decides to suspend or close a card. Adyen will send webhook events in such occurrences; however, at present, the component doesn't handle this event.

Incident Handling

Info

The class CardIncidentsLogic is responsible for Card incidents handling.

The component manages the technical aspects of incidents declaration involving Cards, specifically addressing the following situations:

  • Card is lost
  • Card is stolen
  • Card is damaged

For each of these incidents, the component's role is to execute the necessary technical steps to secure the Card and account, reflecting these changes in Adyen's system. However, the business aspects of handling these incidents, such as issuing replacements or dealing with fraud investigations, are managed outside the component's scope.

Delivery Tracking

Info

The class CardDeliveryLogic is responsible for Card delivery tracking.

The delivery tracking mechanism is applicable only to physical Cards. Virtual Cards, being digital, do not require physical delivery and hence are not part of this tracking process.

Delivery status updates are received through Adyen webhooks. These webhooks notify our system of any changes or updates in the delivery status of a Card, enabling real-time tracking. Adyen is the source of truth for card delivery status.

Warning

For now card delivery tracking is very scrappy and the implementation is incomplete. In particular, delivery incident management has been modelled but not implemented (for example, if a card has never been received by its card holder even though Adyen webhooks say otherwise)

Our component maintains a comprehensive log of all delivery status events received from Adyen. This log includes detailed information about each step of the delivery process, from the moment a Card is dispatched to its arrival at the Card Holder's designated address.

See [CardDeliveryStatus][components.payment_gateway.public.entities.CardDeliveryStatus] for all the supported status values.

Note

The component only supports a subset of those returned by Adyen, either because they are rare or difficult to reproduce in production, or because the documentation is not clear about them.

Miscellaneous

Info

The class CardLogic is responsible for other Card features and scopes not already covered elsewhere.

3DS authentication

From the moment of issuance, Cards provided by the component are enabled for 3DS authentication. This critical security feature utilizes the Card Holder's phone number for Multi-Factor Authentication (MFA), enhancing the security of online transactions. Additionally, the component generates a default password for online payments, further securing the process. For detailed implementation, refer to the function generate_card_password.

PAN/PIN reveal

The in-app reveal of a Card's Primary Account Number (PAN) and Personal Identification Number (PIN) involves a multi-stage authentication flow with Adyen. The component facilitates this process by serving as a proxy between the application and Adyen, ensuring the app remains Payment Service Provider (PSP)-agnostic. This setup allows for a seamless integration and user experience, regardless of the PSP involved.