-
Notifications
You must be signed in to change notification settings - Fork 37
Integrating with third party services
It makes sence to implement integration with a third-party service as a single LiteCommerce module so that it can be contributed to the community and reused later. So, before working on the actual integration code you are to [create a LiteCommerce module](Creating LiteCommerce module).
In order to integrate with a payment system your payment module should add a payment processing class extended from one of the base payment classes.
Payment modules can be grouped as follows:
-
Modules that only collect payment information and don't submit it to third-party servers for processing. Such modules should extend the \XLite\Model\Payment\Processor\Offline base class.
-
Modules that display the payment form, collect payment information and submit it to third-party servers for processing. Such modules should extend the \XLite\Model\Payment\Base\Online base class. Note: using this integration method for collecting credit card details puts your server into the PCI DSS scope and may result into big fines by Visa/MasterCard in case of compromised cardholder data. We strongly recommend you to not host the payment form on your server or display it via our PA-DSS solution named X-Payments.
-
Modules that don't collect payment details and redirect customers to a payment form hosted by payment system. Such modules should extend the \XLite\Model\Payment\Base\WebBased base class.
-
Modules that don't collect payment details and use IFRAME to display a payment form hosted by payment system within your checkout pages. Such modules should extend the \XLite\Model\Payment\Base\IFrame base class.
In LiteCommerce there two different entities related to payment processing:
- orders
- payment transactions (attached to orders)
Payment modules should never change the order status directly. LiteCommerce updates the status automatically depending on the status of payment transactions attached to the order.
Orders become "Processed" when all attached payment transactions are successfull. Orders become "Failed" when the payment is unsuccessfull or cancelled by the gateway.
-
Merchant installs a payment module. The module:
- adds module settings which will appear on the module configuration page
- registers payment methods
- adds payment processing classes that handle the payment methods
- defines payment-method settings which will appear on configuration pages of the payment methods
Merchant configures the module and payment methods which the module adds.
-
Customer adds products to cart. System creates for Customer an instance of \XLite\Model\Cart that stores all payment-related information added during checkout and payment processing.
-
Customer goes to checkout. System gets a list of available payment methods from \XLite\Model\Cart::getPaymentMethods() and displays it to Customer. getPaymentMethods() looks through all registered payment methods, finds processing classes that handle the methods and checks (by executing <Processing Class>::isConfigured(\XLite\Model\Payment\Method $method) method) which payment methods should be removed from the list due to a wrong configuration.
-
Customer chooses a payment method. System creates a new payment transaction having STATUS_INITIALIZED ('I') status and attaches it to the order.
-
System checks whether the method collects payment information (by executing <Processing Class>::getInputTemplate() method returning a path to the payment-form template file) and displays the payment form on the checkout page. Customer completes the form
-
Customer confirms the order by clicking the "Place order" button. System changes the status of the payment transaction to STATUS_INPROGRESS ('P')
-
System calls the payment module. The payment module sends an API request to request the money transfer and, depending on the result, switches the transaction to one of the following statuses:
- STATUS_SUCCESS ('S')
- STATUS_FAILED ('F')
- STATUS_PENDING ('W')
The pending status is set when the API doesn't return the status in the response immediately. In this case the payment module should handle delayed call-backs from the API and update the status later.
Payment methods handled by a payment module should be registered through the install.yaml file as follows:
- service_name: <machine name of the payment method>
class: Module\<Developer>\<Module name>\Model\Payment\Processor\<name of the payment processing class that handles the payment method>
translations:
- code: en
name: <visible name of the payment method (in English)>
- code: <another language code>
name: <visible name of the payment method (in another language)>
settings:
- name: <machine name of the first method setting>
- name: <machine name of the second setting>
value: <default setting value>
- name: <machine name of the third setting>
If a payment method should be restricted to specific countries only (or hidden depending on other conditions) the payment module should override (through the [dynamic decoration feature](Extending the LiteCommerce functionality)) the getPaymentMethods() method of the \XLite\Model\Order class and remove the payment method from the returned list.
Although it is possible to handle multiple payment methods through a single payment processing class, we recommend you to have one payment method per processing class.
Settings defined in the install.yaml file are displayed on the payment-method configuration page in the back-end. The layout of the setting form is defined by a template file that you are to specify in the processing class:
public function getSettingsWidget()
{
return 'modules/<Developer>/<Module>/<template-file>.tpl';
}
If a default value isn't specified in the install.yaml file, it will be NULL.
During checkout you can hide payment methods which aren't configured properly. To do so define isConfigured(\XLite\Model\Payment\Method $method) method in your processing class and return false on a wrong configuration.
The 1.1.x core introduces a new payment configuration flow and requires some changes to be made to payment modules created for the previous 1.0.x version.
-
In your module's install.yaml file you should specify for each payment method two new properties:
- type - the module type, one of the following: "A" (payment solutions that include both the internet merchant account and the payment gateway for credit card processing), "C" (payment gateways for credit card processing), "N" (alternative on-line payment methods which let customers pay with their "accounts" in these systems) and "O" (off-line payment methods like checks, cash on delivery, and so on)
- adminDescription (it's a multilingual field, so you should specify it inside "translations" section) - the description that appears in the list of payment methods when it is shown in the shop back to the administrator
-
In your processor class (which inherits from the \XLite\Model\Payment\Base\Processor class) you should declare two more methods:
- isTestMode() - returns whether the payment method is configured to work in a test mode (so no real payments will be made)
- getAdminIconURL(\XLite\Model\Payment\Method $method) - returns URL to the icon that appears next to the payment method when it is show in the shop back end (in the list of payment methods on the new payment configuration page). The icon should be 107x27 pixels maximum.
You can put icons for your payment methods inside the "skins/admin/en/modules/[your-developer-id]/[your-module-id]/" directory and create the icon URL as follows: return \XLite\Core\Layout::getInstance()->getResourceWebPath("modules/[your-developed-id]/[your-module-id]/[path-to-the-icon-file]");.
If all your payment methods have the same icon, you can return "true" in the getAdminIconURL() method and put your icon there: "skins/admin/en/modules/[your-developer-id]/[your-module-id]/method_icon.png".