Introduction (Spec)

The External Payment Method-API defines the endpoints that the enfore platform will invoke on an external server component when an external payment method is being used.

The API defines endpoints for:

  • checking the availability status of the external payment method
  • validating payment vouchers
  • computing possible payments
  • processing of payments and payouts

Types of external payment methods

The enfore platform supports three types of external payment methods:

  • basic EPMs
  • CUWO-based EPMs
  • API-based EPMs

Basic EPMs are payment methods that do not have an actual integration with an external service, so in effect they can only be used to manually record a payment as "having been made via some external system" with no way for the enfore platform to validate this or to provide any user interface integration.

CUWO-based EPMs are backed by custom workflows, so when a payment or payout is to be performed using such an EPM, the enforePOS runtime will display the appropriate CUWO and that CUWO can perform the necessary user interaction. For more information on CUWO-based EPMs see the CUWO documentation

API-based EPMs are backed by an external service that must implement the API defined here. Whenever a payment or payout is to be performed using such an EPM, the enforePOS client will invoke the relevant endpoints of this API to process the payment/payout. Note that the API will not be directly invoked by the enforePOS client for technical reasons but that all invocations are routed through the enfore server backend.

Concepts

Availability check

Availability checks are only used for CUWO-based EPMs

The API provides the endpoint /org/{org-id}/status/ that is invoked by the enforePOS client for determining whether the external payment method is available.

For CUWO-based EPMs, this endpoint is invoked upon entering the payment flow UI to determine whether to enable the button for the EPM or not and what information to show there.

If the payment method reports that is it not available or when the status check fails (e.g., due to network error), the EPM is not available for selection by the user.

Payment vouchers & possible payments

Payment vouchers & possible payments are only supported by API-based EPMs

API-based EPMs support "payment vouchers". Payment vouchers are vouchers that can be translated into a payment. Payment vouchers are similar to discount coupons in that they have a monetary value and often (but not necessarly) have limitations/requirements that control when they can be used. For example a voucher might be defined as "2€ payment when bying 5 or more cans of beans".

The main difference between a payment voucher and a discount coupon is that a payment voucher does not reduce the invoiced amount but that, instead, it is used as a payment.

For example, assume a basket consisting of "10x cans of beans" where each can costs 5€. The line item/basket total would then be 50€. With a discount coupon of "2€ discount when bying 5 or more cans of beans", the line item/basket total would be reduced to 48€ and the user would receive an invoice with a total amount of 48€ and a "due amount" of 48€. With a payment voucher instead, the line item/basket total would stay at 50€ and the user would receive an invoice with a total amount of 50€, a 2€ payment, and a "due amount" of 48€.

During sales process

When the user presents a payment voucher during the sales process, the enforePOS runtime will use the EPM-API to validate it. The validation will only receive the voucher code and a payment context (POS location, device, customer, etc.) but not the full basket. Thus, it will not be able to validate any constraints like "when bying 5 or more of ..." that the voucher might have. The validation is to determine whether the voucher is valid "in general" but it cannot yet determine if it can actually be used.

Once the user chooses to start the check-out, the enfore system will invoke the API's "compute possible payments" endpoint. That endpoint receives all validated vouchers, the payment context, and the full basket. Based on that information, the external service is to compute what payments are actually possible.

Note that the computation of "possible payments" can also be configured to be done when no payment vouchers have been scanned. That way, payments can be generated based on additional information available only to the external service (e.g., vouchers activated via a mobile app).

After the "possible payments" have been computed, they are presented to the user as part of the checkout process. There, the user can check if the computed payments match his expectations and may deselect payments he does not want to perform or re-trigger computation (e.g., in case the first computation failed).

Once the user confirms the possible payments and enters the payment part of the checkout flow, the enfore system uses the "process payment" endpoints of the API to process the selected possible payments.

The following diagram shows how this fits into the UI flow for sales in the enforePOS register:

(*) Note that "processing a payment" may consist of multiple API calls

When voiding items

When voiding items from an invoice that was at least partially paid with payments returned from the "compute payments" API endpoint (that is, payments based on payment vouchers or some other configuration inherent to the EPM), it may be that the reason for those computed payments no longer exists. If that is the case, the customer must not receive the full payout amount. Instead, a part of or the full amount of the computed payment may need to be turned into a system-driven payout to offset the no-longer-valid payment.

For example, assume a customer did by "10x cans of beans" for 5€ each and used payment voucher woth 2€ with the limitation "when bying 5 or more cans of beans". The invoice total would be 50€ with 2€ paid via the voucher and 48€ paid by other means (let's assume cash for the sake of the example):

If the customer now returns all the cans for some reason, a credit memo for this would have a total of 50€ as that was the invoice amount. But the user should not receive a payout for the full 50€ as the would mean that he gained 2€ since he originally only paid 48€ from his own money.

Instead, the payment that resulted from the voucher must be offset by a special "offset payout" to reduce the remaining amount to be paid out to what the customer originally paid:

Note that it is not possible to simply revert the initial voucher payment. Doing so would just cause the original invoice to suddenly have an open due amount. And it would not do anything for the credit memo, whch would still need to be paid out in full.

It is also not possible to simply reduce the credit memo amount as that would imbalance the tax amounts of the invoice and the credit memo, causing a loss for the merchant.

In case of a partial void (e.g., customer returned only 4 or 6 cans), a decision must be made whether the voucher payment needs to be offset by an offset payout and to what amount.

For example, returning just 4 cans could mean no offset payout is necessary as the limitation of the voucher is still met. Returning 6 cans clearly causes the voucher limitation to no longer be met, but whether the full 2€ must be offset or just some part of the 2€ is a decision that depends on the voucher's conditions.

As the enfore platform cannot determine whether a void requires an offset payout and what the amount should be, the EPM API is invoked to let the EPM logic decide. This is done by invoking the "compute necessary offset payouts for void" endpoint. The EPM is expected to return the offset payouts that must be performed for the void. Those payouts will then be processed using the "grant payout" API endpoint like normal payouts with the addition of a reference to the original payment being passed as parameter. Additionally, the "compute necessary offset payouts for void" endpoint can add "external data" to the computed payouts that will also be passed as input to the "grant payout" endpoint.

The "compute necessary offset payouts for void" endpoint will not only receive the void basket but also the original sales basket items (including information about previously voided units) and the original EPM payments (including information about previously performed offset payouts). Note that any payments of the original invoice not performed via the EPM are not passed to the EPM for security and privacy reasons.

The following diagram shows how this fits into the UI flow for voiding an invoice that was at least partially paid by voucher payments via the enforePOS register:

(*) Note that "processing a payout" may consist of multiple API calls

Payment processing

In general, the enfore platform processes payments as a "payment request" that goes through the following steps:

  • Started - newly create PR, payment amount has not been reserved or moved yet
  • Authorized - payment amount has been reserved/approved (e.g., by a payment provider)
  • Captured - payment amount has been granted/transferred to the merchant
  • Booked - payment amount has been booked into the merchant's accounting system

Additionally, payment requests can "Fail" or become "Canceled".

Also note that not every payment method supports the distinction between "Authorized" and "Captured". For example, a basic cash payment does not have a "Authorization" stage but is immediately "Captured" when the customer has handed over the money.

Note that transitions from "Authorized" or "Captured" to "Canceled" only occur after a previous authorization/capture of money has been released/reverted. And that transitions from "Authorized" or "Captured" to "Failed" only occur after that release/reversal failed.

For the built-in payment methods, the enfore platform contains the logic to perform the operations necessary to transition the states of the payment/payout requests. For API-based external payment methods, that logic must be provided by the external service and exposed via the endpoints defined in the API:

  • for payments
    • /org/{org-id}/external-payments/payment-processing/authorize-or-capture-payment
    • /org/{org-id}/external-payments/payment-processing/capture-payment
    • /org/{org-id}/external-payments/payment-processing/cancel-payment
  • for payouts
    • /org/{org-id}/external-payments/payment-processing/revert-payment
    • /org/{org-id}/external-payments/payment-processing/grant-payout
    • /org/{org-id}/external-payments/payment-processing/cancel-payout

For payments, the possible activity flow looks like this:

For payouts, the flow is similar:

Note that the flows are almost identical to the ones defined for CUWO-based EPM with the exception that API-based EPMs do not define a "cancelled" result for the different operations. An operation can either succeed or fail, as there is no human interaction that could trigger a cancellation.