At some point we all face the need to integrate a payment gateway. It may seem difficult, but actually it's not. There are many payment gateways to choose from, but the good point is that most of them work the same way. You just need to understand the high-level picture and you're ready to integrate any of them into your project.
As I mentioned before, there are many payment systems, but basically they all work in the same way:
1. A user visits the site and creates an order. It may be anything: goods, services and so on. After this step, you have a placed order in your own system.
2. The user is redirected to the payment gateway page where he can choose a payment method and pay for the order.
3.A. If the user cancels the payment, he will be redirected to the cancel URL.
4.A. It may be any page of your site, for example, a home page or a page where you ask the user about any issues with payment and motivate him to complete the order.
3.B. If the user pays, then he will be redirected to the success URL.
4.B. At this page, I usually tell the user a few warm words like "Thank you". Keep in mind: when a user lands on this page, it doesn't mean that you got the real payment. So, you may write something like: "Thank you for choosing us. The service will be provided as soon as the payment processing is done". Never rely on this page to decide if you should provide a service to the user right away.
5. After the real payment is done, the payment gateway will notify your callback URL.
6. This page isn't for public use. On this page, you must process callbacks from the payment gateway. They send you all necessary data to understand what order has been paid. For example, they send you the order id in your own system, transaction id in their system, amount, currency and so on.
7. Some payment systems allow users to cancel the payment. This means that you may get such a callback and your site must handle it properly. For example, reject the service for the user, update payment statistics in your system and so on.
Security
1. Your callback URL must be accessible to non authenticated users. In Symfony we can achieve this via:
security: firewalls: payment_callbacks: pattern: ^/paymentcallback/ security: false
2. Some payment systems provide lists of white IPs that you must check for to treat a request as a legal one.
3. Almost all payment gateways encode data they transfer with private keys.
Simplified Controller
Again, I'm going to use Symfony for all examples, but they are simple and you can easily understand them and modify the code sample for your own framework and language. All actions are described below the code sample.
<?php // ... class OrderController extends Controller { /** * @Route("/pay/{hash}", name="OrderView") * @Method({"GET"}) */ public function payOrderAction($hash) { $order = // get order by hash or ID $payUrl = // This URL you will form it using parameters like order id in your system, amount, currency and so on. It depends on the particular payment system you work with. Please check their docs. return new RedirectResponse($url); } /** * @Route("/thank-you/{orderId}", name="OrderThankYou", requirements={"orderId": "\d+"}) * @Method({"GET"}) * @Template() */ public function thankYouAction($orderId) { return [ 'id' => $orderId, ]; } /** * @Route("/paymentcallback/custom-super-secret-endpoint", name="PaymentCallback") */ public function callbackAction(Request $request) { // log callback // get data from $request ($_GET, $_POST...) $isValid = // validate data from the request if ($isValid) { // give the user his service } // return a response to the payment gateway. Usually it's a simple 'OK', 200 status code. return new Response('OK'); } }
So, we have three main actions:
1. Pay Order.
Here we form the URL for the user. At this URL, the user will see the payment method or methods to choose from. Usually such URL must contain parameters like:
orderId - order ID in your system
amount - payment amount
currency - currency, like USD, EUR and so on.
email/userId - a user email or id in your system
accepturl - we set up here a URL to the Thank You page. I also put there the order id to be able to show more information to the user.
cancelurl - just points to the home page or any other page you want
callbackurl - URL for payment gateway callbacks
2. Thank You
This page is to notify the user that he will get his service as soon as the payment processing is done.
3. Callback
Only here you process the result of a real payment. First of all, you need to get request data, then validate it and if everything is OK, then you have to provide the user his service and return the 200 response. Usually a response to a callback must containt simple work like "OK" or something similar. You will find this in the payment gateway documentation. You can also dispatch an event and attach any useful listeners to it. For example, you may send an email to the user, update payment stats and so on.
Testing
When you start, you develop new things on your local machine. You need to be sure that everything works fine before you go live and that's why you need ability to test payments locally. Many of payment systems allow to make test payments without using real money. Usually you need to complete a few steps to enable testing in a payment gateway:
1. Enable the test mode on their side via UI.
2. Allow requests from any sites to the payment gateway endpoint. Many payment systems accept requests only from a set of configured in your account domains.
3. Finally, you need to provide a special parameter in the URL, like "test".
Ok, now you know what to do to enable test mode, but we still have one problem. As I mentioned before, after you complete payment, a payment gateway will ping your server (remember callback URL). As you make payments from a local machine, they won't be able to reach your local host.
Here payment gateways (not all of them) provide some useful options:
1. In their admin panel they have a simple HTML form and using it you can imitate any kind of a callback request. This is one of the best options, because you won't have any issues with your local domain (you just submit a form via browser and your local domain will work fine). You don't have to do any additional programming.
2. Some of them add all data they would return at callback to the success/accept URL. This is useful, too. You just can modify your "Thank you" action a little:
<?php //... public function thankYouAction($orderId, Request $request) { $testModeEnabled = // check if test mode enabled in your application if ($testModeEnabled) { // get data from $request ($_GET, $_POST...) $isValid = // validate data from the request if ($isValid) { // give the user his service } } return [ 'id' => $orderId, ]; }
That's it. This way you will be able to test payments locally in a test mode.
Potential caveats
- documentation is outdated. Yes, this still happens. In such cases you need to contact their tech guys or think twice if you still want to integrate such payment gateway.
- zero instruments to test payments before go live. If this is your case, you can log their callbacks to your production server or make a payment gateway available only to a test user.
- personal data approvement before you can use a gateway even in a test mode
- a gateway doesn’t support recurring payments
Conclusions
Don't be afraid, integration is easy no matter what gateway you plan to choose.