Skip to content

Payment Gateway

Martin Polanka edited this page May 13, 2017 · 11 revisions

Payment Gateway

One of the main feature of the CUK system is the ability to manage events organized by hosting officers. Officers can create events, modify them, adding images, etc. These created events are then visible to incomings who can join these events and most importantly pay for them using integrated payment gateway.

The Czech IFMSA is using FIO Bank as their account holder, therefore payment gateway provided by FIO is used within the system. FIO does not have their own gateway implementation, they are using EcommMerchant system. Due to unclear licensing of Ecomm API caller library, EcommMerchant\Merchant class is excluded from the source code and has to be provided externally.

If you want to use some different payment gateway, simple replacement of the Merchant class will not be enough. There is also App\Payment\EcommMerchant\EcommTransactionsHelper which parses responses from Ecomm server and this class has to be rewritten completely according to new communication format. Further modifications might be needed as well.

With regard to the IFMSA and their range of activities, it is obvious that they need payment gateway on the multiple places/servers. Easy solution would be to have separate payment gateway implementation on the every such server, or to have one really big system which handles everything. Either of this is feasible, the first one is illogical concerning finances, the second one is just rubbish.

Therefore it was decided that the CUK system should be able to handle external payments. This means the CUK system is integrating payment gateway from FIO, but also expose interface which can be used within some external service/webpage the same way CUK uses Ecomm payment gateway. Description of how to use CUK payment gateway follows below.

Implementation

Implementation of payment method is located in App\Payment namespace and access points to this are defined in EventsPaymentPresenter. Mentioned presenter is used within CUK system to internal event payments and also to external payments where JSON answers are engaged. Detail description of the particular protocol is below in the next chapter.

  • App\Payment - payment embracing namespace
    • EventsTransactionsHelper - Described below in more detail.
    • ExternalTransactionsHelper - Described below in more detail.
    • PaymentParams - general payment parameters loaded from configuration
  • App\Payment\EcommMerchant - defines functionality concerning Ecomm payment system
    • EcommParams - parameters which are used in Ecomm classes and helpers
    • EcommTransactionsHelper - Described below in more detail.
    • Merchant - not included - remote Ecomm server API caller
    • FakeMerchant - imitates interface of the Merchant class, but without calls to remote server
  • App\Payment\External - defines functionality concerning external services
    • ExternalService - represents one external service loaded from configuration
    • ExternalServices - holder of all external services which are parsed and loaded from configuration
  • EventsPaymentPresenter - Defines access points and API for accessing payment feature. Further description follows below.

EcommTransactionsHelper

Manages proper calling of the Ecomm payment server and also the work with database entities and proper storing of the information gained from the remote server. It contains following methods:

  • startTransaction() - Start transaction by calling Merchant and after that process results. Constructs proper database entities representing started transactions or payment error entities in case of failed start of transaction. In case of successful start this method returns URL and constructed database entity, otherwise it throws an exception.
  • processTransactionOk() - From the given transaction gets identification and based on that try to gets results from the Ecomm payment server. In case of successful transaction store results to the given transaction entity and return boolean information about transaction correctness. If the transaction was not successful store payment error into database and throw an exception.
  • processTransactionFail() - Payment gateway redirected user to the failed transaction endpoint. This method then gets results from the Ecomm payment server and store them into payment error entity.
  • reverseTransaction() - Tries to reverse transaction by calling Ecomm payment server. If the reversal was successful, then store its results into database, otherwise create and store payment error entity and throw an exception.
  • closeBusinessDay() - Calls Ecomm payment server for business day closure. If the closure was successful store results into batch payment entity, otherwise insert payment error entity and throw an exception.

EventsTransactionsHelper

Serves for proper management of internal CUK events transactions. It contains following methods:

  • startTransaction() - Constructs transaction description, amount and gets client ip address and start transaction using helper class. After that assign previously started transaction to appropriate participant and return redirection URL.
  • processTransactionOk() - Uses helper class to process transaction and if it was correct mark event as paid for appropriate participant.
  • reverseTransaction() - Reverses transaction and mark event as not paid for appropriate participant.

ExternalTransactionsHelper

Helper class for external transaction functionality. It contains following methods:

  • findService() - From all the registered external services given in the configuration, find the one with the right identification or throw an exception if it cannot be found.
  • startTransaction() - Finds proper service within all services and construct proper description for the transaction. After that just start transaction by calling Ecomm payment server. If successful then return URL to which users should be redirected and the transaction database entity.

EventsPaymentPresenter

Presenter containing all CUK endpoints concerning payment:

  • startEventTransaction - Accessible only to the incomings which wants to pay for the event. At first all kind of stuff has to be checked to be sure incoming can start the transaction. After that transaction is attempted to start by calling Ecomm payment gateway server. If successful user is redirected to payment gateway.
  • reverseEventTransaction - Implemented but not accessible!
  • transactionOk - User is redirected here from Ecomm payment gateway if the payment was executed and results have to be processed. In case of external transaction user is properly redirected to the external service. Otherwise (internal CUK transaction) results of transaction are stored. If the transaction was correct, then successful payment page is displayed, if it was incorrect user is forwarded to the transactionIncorrect page.
  • transactionIncorrect - Displays detail information about incorrect transaction based on given result code
  • transactionFail - User is redirected here from Ecomm payment gateway if the payment was unsuccessful and failed quite badly. In case of external transaction user is redirected to the external service failure page defined in configuration. Otherwise transaction failure is written into database and user is gifted with payment failure message.
  • closeBusinessDay - Has to be executed once a day, preferably at 00:00, using cron service. Endpoint is accessible only with proper access key
  • startExternalTransaction - Endpoint accessible only with POST request and proper access key. Response is returned in JSON format. Gets all needed parameters and attempt to start transaction with them using Ecomm payment gateway. In case of successful start return transaction identification and URL to which user should be redirected.
  • getExternalTransactionResult - Endpoint accessible only with POST request and proper access key. Response is returned in JSON format. Based on given transaction identification find transaction in database and return its results to the remote caller.

Integration within External Service

Description of step which needs to be done when integration CUK payment gateway into website follows.

Preparations

  • Make up unique identifier for new external service, which will serve for service identification
  • Decide items mentioned in Configuration concerning external services:
    • transactionParamId - transaction ID query (GET) parameter key which will be used when redirecting to okRedirectionUrl and failRedirectionUrl
    • errorParamId - error message query (GET) parameter key which will be used when redirecting to failRedirectionUrl
    • okRedirectionUrl - address to which user will be redirected after successful payment (have to be specified without query params)
    • failRedirectionUrl - address to which user will be redirected after failed payment (have to be specified without query params)
  • All previous parameters should be filled in correct format into CUK configuration by its administrator
  • Get access token key from CUK administrator, this key has to be used when accessing CUK endpoints as described below

External Service Implementation

Implement all necessary endpoints within external service, this includes:

  • startTransaction - In here these things should be done:
    • Prepare transaction description which might come in handy during debugging or some non-standard situations. Please note that this description can have only 125 characters.
    • Prepare amount of money which will be paid by user and currency of payment
    • Get IP address of user
    • Make POST request to the CUK system to Start Transaction endpoint with all previously prepared information (Detailed description of POST parameters needed by CUK is described below in Protocol and Endpoints section)
    • Process JSON response from the CUK system and if the transaction start was successful:
      • Store transaction details into database
      • Redirect user to the URL of the payment gateway taken from the CUK response
    • If the transaction start was not successful:
      • Store transaction failure into database
      • Display some human-readable error message to the user
  • transactionOk - Have to correspond with URL which is placed in CUK configuration. Furthermore following should be done here:
    • In here previously stated transactionParamId key should be used as query (GET) parameter name
    • From the transaction identification locate transaction within database
    • Make POST request to the CUK system to Get Transaction Results endpoint (Detailed description of POST parameters needed by CUK is described below in Protocol and Endpoints section)
    • Process JSON response from previous request, there are three possible situations:
      • Transaction was successful and is correct
        • Store all previously gained successful results of transaction into database
        • Mark your internal stuff (event or product) as paid
        • Display successful payment message to user
      • Transaction was not correctly executed and is not paid
        • Store all previously gained results of transaction into database
        • Display user information about not correctly executed payment and based on result code determine the cause of the problem
      • Transaction was not successful and failed misserably
        • Store payment error into database
        • Display user some human-readable error message
  • transactionFail - Have to correspond with URL which is placed in CUK configuration. Furthermore following should be done here:
    • Previously defined transactionParamId and errorParamId should be used here as query parameter names
    • Based on given transaction identification locate transaction in database
    • Make POST request to the CUK system to Get Transaction Results endpoint (Detailed description of POST parameters needed by CUK is described below in Protocol and Endpoints section)
    • Store failed transaction details alongside with response to the database

Real-life payment gateway integration example/website can be found below in Real-life Integration Example section.

Protocol and Endpoints

CUK endpoints for external payments are done in kind-of RESTfull way. Responses from server are encoded into JSON format. Externally there are only two exposed endpoints, one for the starting of the transaction and the second for the fetching transaction results. Please note that transaction identifier have to be urlencoded if used as query parameters! Description of endpoints and their responses can be found below.

Start Transaction

Endpoint: POST /events-payment/start-external-transaction

  • Query params:
    • key - access token defined by the CUK system
  • Post params:
    • service - identification of service which wants to use CUK payment gateway
    • amount - amount of money to pay in the most basic currency (for euros it is cents)
    • currency - currency code according to ISO 4217
    • ipAddress - IP address of client which requested payment
    • description - description of transaction, should be filled with some data identifying the transaction

Response:

  • error - present only if there was some error during transaction initiation, the other fields of response might not be included
  • url - address of actual payment gateway, where clients should be redirected
  • transactionId - identification of started transaction

Example Response:

{
	"error": "the description of the error"
}

OR

{
	"url": "https://payment.gateway/client?trans_id=zHE0CI%2BGO4n%2BJr9tXc7rXiy4M1I%3D",
	"transactionId":"TgWeDoqJkLblajc010fVf8+Ybla="
}

Get Transaction Results

Endpoint: POST /events-payment/get-external-transaction-result

  • Query params:
    • key - access token defined by the CUK system
  • Post params:
    • service - identification of service which wants to use CUK payment gateway
    • transactionId - identification of transaction to which results are wanted

Response:

  • error - present only if there was some error during transaction initiation, the other fields of response might not be included
  • transactionId - transaction identification, only returned back without any change
  • result - one of the following values: OK, FAILED, DECLINED, REVERSED, TIMEOUT, PENDING
  • resultCode - three numbers as returned by the payment server, the value 000 is for successful approved transaction
  • result3dsecure - one of the following: DECLINED, AUTHENTICATED, NOTPARTICIPATED, NO_RANGE, ATTEMPTED, UNAVAILABLE, ERROR, SYSERROR, UNKNOWNSCHEME, FAILED
  • cardNumber - usually filled with asterisks, not given from the bank

Example Response:

{
	"error": "the description of the error"
}

OR

{
	"transactionId": "TgWeDoqJkLblajc010fVf8+Ybla=",
	"result": "TIMEOUT",
	"resultCode": "",
	"result3dsecure": "FAILED",
	"cardNumber": ""
}

OR

{
	"transactionId":"TgWeDoqJkLblajc010fVf8+Ybla=",
	"result": "OK",
	"resultCode": "000",
	"result3dsecure": "AUTHENTICATED",
	"cardNumber": "****************"
}

Real-life Integration Example

The CUK payment gateway was already used within one IFMSA project - PRET & TNT Prague 2017. PRET&TNT is training event which might be attended by participants from abroad, therefore at least simple registration was needed. During development of PRET&TNT webpages it was decided that integration of payment gateway would be nice feature which will simplify finances management for both involved parties (IFMSA CZ and participants). And that is why the CUK system was rewritten to be also payment gateway provider.

Integration in PRET&TNT webpages is quite easy and straightforward. Description of important classes follows:

  • PaymentParams - Parameters loaded from configuration file, this holder is used withing following classes.
  • PaymentConnection - Realisation of very simple remote API calls pointing to the CUK system. This class is used only for execution of remote calls with the help of Guzzle library.
  • PaymentTransactionsHelper - Payment gateway transaction helper which manages connection to the remote server through PaymentConnection above and also takes care of persisting transaction states.
  • PaymentPresenter - Pages accessible to the users of the webpages. Important actions are startTransaction, transactionOk and transactionFail.
    • startTransaction - Starts new transaction by constructing all its parameters and requesting new transaction from the CUK system. If the start of the transaction on the CUK was successful, a URL address of the payment gateway is returned back and user is redirected to it.
    • transactionOk - If the transaction was successful then the CUK system will redirect user to this defined endpoint, where transaction is marked as correct or incorrect according to proper obtained state.
    • transactionFail - If the transaction was not successful then the CUK system will redirect user to this defined endpoint. Transaction is marked as failed and proper error message is displayed to the user.