Skip to content

Commit

Permalink
docs: add initial architecture section
Browse files Browse the repository at this point in the history
  • Loading branch information
blaggacao committed Nov 5, 2023
1 parent 30e5deb commit bb34009
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 11 deletions.
87 changes: 87 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Architecture

The Payment app provides an abstract payment controller and specific implementations for a growing number of Payment Gateways inside the _Payment Gateways_ module.

An additional _Payment Gateway_ doctype inside the _Payment_ module serves as the generic link target referencing and dispatching to the respective payment gateway controller and settings.

App adds custom fields to Web Form for facilitating payments upon installation and removes them upon uninstallation.

## Relation between RefDoc and Payment Gateway Controller

A reference document implements the surrounding business logic, links to the _Payment Gateway_ and hands over — typically on submit — to the specific payment gateway controller for initiating and handling the transaction.
After the transaction has been handled, the reference document may execute post-processing on the result and/or remit a specific payload (e.g. redirect link / success message) to the user via the payment gateway controller.

During the entire lifecycle of a payment, state is maintained on the _Integration Request_ doctype. It allows persisting free-form data and otherwise serves as a central log for interaction with remote systems.

### TX Data and TX Reference

The data is passed from the RefDoc to the Payment Gateway Controller via a standardized data structure called _TX Data_.

Then, all transaction lifecycle state is stored into a _Integration Request_.

The _Name_ of the _Integration Request_ will be the system's unique _TX Reference_.

It is not a payment gateway's _Correlation ID_ (the Sales Order Name could be one), however the _TX Reference_ should be carried in all requestes across the lifecycle to easily identify the transaction in the backend,
for example by using a payment gateway's meta fields. (Use the _Integration Request's_ `request_id` as _Correlation ID_, instead.)

TODO: specify this data structure

### RefDoc Flow

1. Call the payment gateway controller's `on_refdoc_submit` hook with `tx_data` (for validation)
2. Call the payment gateway controller's `initiate_payment` method with `tx_data` and store the _Integration Request_ name.
3. Call the payment gateway controller's `is_user_flow_initiation_delegated` predicate with `integration_request_name`.
4. If user flow initiation is not delegated (to the payment gateway): initiate/continue user flow, e.g. via Email, SMS, Whataspp, PhoneCall, etc.
5. Postprocess the payment status change via `on_{mandate,charge}_<status>` with a two-fold goal:
- continue business logic
- return buisness-logic-specific payload (e.g. message / redirect instructions) to payment gateway controller

### Payment Gateway Controller Flow

The payment gateway controller flow knows the following generic flow variants:

- Charge: a single payment
- Mandate Acquisition: aquire a mandate for present or future mandated charges
- Mandated Charge: a single payment that requires little or no user interaction thanks to a mandate

The distinguising factor is that a mandate representes some sort of pre-authorization for a future (mandated) charge. It can be used in diverse use cases such as:

- Subscription
- SEPA Mandate
- Preauthorized Charge ("hotel booking")
- Tokenized Charge ("one click checkout")

Therefore, the flow needs to decide which route to take, and looks like this:

1. Eventually throw on `on_refdoc_submit` execution, if there's an issue.
2. Decide wether to initiate a Charge, a Mandate Acquisition or a Mandated Charge. Mandate Acquisition is typically implemented as a pre-processing step of a (the first) Mandated Charge.
3. Wait for the user GO signal (e.g. via link, call, sms, click) then `procede`. We delay remote interactions as much as possible in order to:
- Initialize timeouts as late as possible
- Offer the customer choices until the last possible moment
4. Initiate the flow via the dedicated method `initiate_{charge,mandated_charge,mandate_acquisition}`.
5. Manage the capturing user flow in collaboration with the payment gateway.
6. Process the result via the dedicated method `process_{charge,mandated_charge,mandate_acquisition}_response`.
7. Invoke the RefDoc's `on_{mandate,charge}_<status>` method and manage the finalization user flow (e.g. via message and redirect).

### Schematic Overview

[![Schematic Overview](./overview.svg "Schematic Overview")](https://excalidraw.com/#json=O5_Mnthd9TgTQVnwaIT9J,iegjpeWt7u-kqxz-6JqUjg)

### And my Payment URL?

The payment URL is simply a well-known concatenation as follows and is one of the alternatives with which the user gives the GO signal to the Payment Gateway controller flow.

It is kept short, tidy and gateway agnostic as a means to impress susccinct trustworthyness on the user.

Format: `https://my.site.tld/checkout?ref=<TX Reference>`.

It is responsibility of `/checkout` to recover `TX Data` and the corresponding gateway controller from the `TX Reference` (from `integration_request_service` field).

## Other folders

All general utils are stored in [utils](payments/utils) directory. The utils are written in [utils.py](payments/utils/utils.py) and then imported into the [`__init__.py`](payments/utils/__init__.py) file for easier importing/namespacing.

[overrides](payments/overrides) directory has all the overrides for overriding standard frappe code. Currently it overrides WebForm DocType controller as well as a WebForm whitelisted method.

[templates](payments/templates) directory has all the payment gateways' custom checkout pages.

22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@ A payments app for frappe.
```
$ bench --site <sitename> install-app payments
```
## Supported Payment Gateways
## App Structure & Details
App has 2 modules - Payments and Payment Gateways.
- Razorpay
- Stripe
- Braintree
- Paypal
- PayTM
- Mpesa
- GoCardless
Payment Module contains the Payment Gateway DocType which creates links for the payment gateways and Payment Gateways Module contain all the Payment Gateway (Razorpay, Stripe, Braintree, Paypal, PayTM) DocTypes.
## Architecture
App adds custom fields to Web Form for facilitating payments upon installation and removes them upon uninstallation.
see [Architecture Document](./ARCHITECTURE.md)
All general utils are stored in [utils](payments/utils) directory. The utils are written in [utils.py](payments/utils/utils.py) and then imported into the [`__init__.py`](payments/utils/__init__.py) file for easier importing/namespacing.
[overrides](payments/overrides) directory has all the overrides for overriding standard frappe code. Currently it overrides WebForm DocType controller as well as a WebForm whitelisted method.
[templates](payments/templates) directory has all the payment gateways' custom checkout pages.
#
## License
MIT ([license.txt](license.txt))
Loading

0 comments on commit bb34009

Please sign in to comment.