How we integrated the payment system into the Russian project

image

Five months ago, we published an NPM module for working with the new version of Yandex.Kassa, which was released in October 2017. Our module got into the official documentation, and it has already been downloaded more than 1,300 times.

image

At Habré, together with colleagues from Yandex, we already talked about the experience of creating a module, but our experience remained behind the scenes, which we got when faced with the integration of the payment system for Russian customers.

Therefore, today we want to tell you how for one of our domestic clients we switched from integrating our usual foreign payment systems to Russian counterparts, what difficulties we faced and how we solved them.

How to work with payment systems


Previously, we worked only with payment systems of foreign customers. We had integration experience with Authorize.net, Paypal, Braintree, Stripe, Payoneer, Wirecard and Svea.

It is easy to interact with these payment systems and realize different functions. For example, when we worked on the freight transportation service in Europe, we integrated several payment systems into the project and wrote an algorithm — it implemented the complex logic of monetary transactions. When the user ordered the service, the system transferred money from the customer’s account to the service account, and the algorithm performed the transactions: recalculated payment in case of delivery problems, converted it into currency, performed return and postponement of payments, wrote off the interest for using the service.

The best representatives of payment systems allow you to start development in the sandbox, even without registration. Many have excellent documentation, and almost all help solve problems without the active participation of support. Developers can manage rights and access from a personal account. Payment systems have an SDK for most popular platforms, which is already now an unspoken standard.

To integrate the payment system, the developer needs to:

  1. Register on the site and access the sandbox.
  2. Download the SDK and connect it. Insert in the right places the application calls the functions of the payment system.
  3. Test all scripts and make sure everything works correctly.
  4. Deal with other tasks while the customer solves financial and legal issues.
  5. At the right time, switch payments to the “combat” mode.

What has changed


A year ago, we began to work in the domestic market. One of the first projects was the Sellsay app . It helps users develop skills in negotiations, and is also a platform for mutual professional assistance.

The application has many features besides the standard functions: authorization and registration, creating and editing projects. Through the service you can contact
to a business coach. If you have the necessary knowledge, you can get a certificate and become an independent trainer, participate in events and trainings
from the creators of the app, make money.

In order for the service to pay, it was necessary to integrate a payment system — one where you can pay in rubles and dollars, postpone payment and make a refund, save cards and not enter data when making repeated purchases, use Apple and Android Pay. To do this, we chose the Braintree system.

And here we made a huge file. We agreed and implemented the basic functionality of working with the payment system, but did not take into account one important detail. We learned about it two weeks before the release, when we were preparing the project for launch. We did not take into account that Braintree does not work with companies from Russia. Registering a company in the states is not an option. We have only one way out: to replace the payment system as soon as possible.

Yandex.Cash: work with the first version of the API


After analyzing the systems, we stopped at Yandex.Kassa: the service allowed us to implement almost all of the functionality, suited the client for the price and solved the 54- problem by connecting the online cash register.

A little later, we realized that our vision of integration is fundamentally different from the vision of Yandex.Money and its security services. The whole integration stage was remembered more by endless contracts, forms and phoning, rather than writing code.

So, to get test keys, you must provide a link to the application in the Apple Store or Google Play. Where did we get the link, if payment acceptance is a mandatory requirement for publishing an application? This problem was solved, but then there were situations when it was necessary to implement and publish the functionality for its activation by the manager.

Yes, almost all requests are resolved by communication with a personal manager. But if the questions in the personal account get to the personal manager, then when you call, it is likely to get on a random, free on line manager and get a completely random answer. After some time - get on another manager and get the opposite answer to the same question.

Another disadvantage: Yandex supports API of several generations. Even Yandex.Cash has several subsystems that use different documentation, authentication, and so on. As a result, you have to simultaneously implement unrelated APIs. For example, you implement payment acceptance, and to cancel, you must start all over again: requests, contract, calls, study and API integration.

The final weeks before the launch turned into hell. To start the project on time, we had to strengthen the team and work overtime, while Yandex.Kassa, meanwhile, did not miss the opportunity to give us nervous.

Comparison of Yandex.Cash with Stripe


In the developer community, Stripe is a leader in ease of integration and work with the payment system. They are the first to take care of programmers and make the payment system as convenient and flexible as possible. This allowed the developers not only to breathe a sigh of relief, but to speed up and cheapen the integration process.

Yandex.Cash and Stripe can find a lot in common. For example, both systems are built on REST-like principles, use HTTP response codes, support CORS (and responses come in JSON), both support idempotency. There is a “sandbox” - a complete copy of the real store, and the transition between modes is done only by replacing the keys: you do not need to change the API or URL.

But at the same time they are very different, and in order to show how these systems have different approaches, we will look at the implementation of some stages with specific examples.

Since on this project we implemented the server part on Node.js, then I will give examples for it.

We connect to the project .

Stripe:

var stripe = require('stripe')('sk_test_...'); 

Yandeks.Kassa:

  ,    ;   

We are requesting card data

Stripe:

Connect to the client library in the same way and request a token with the display of the card input form.

 var stripe = Stripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh'); var elements = stripe.elements(); // Create an instance of the card Element var card = elements.create('card', { style: style }); // Add an instance of the card Element into the `card-element` <div> card.mount('#card-element'); // On form submit stripe.createToken(card).then(function(result) { // Send the token to your server stripeTokenHandler(result.token); } ); 

On server

 stripe.charges.create({ amount: 2000, currency: "usd", source: "token from previous step", // obtained with Stripe.js description: "Charge for william.brown@example.com" }, function(err, charge) { // asynchronously called }); 

Yandeks.Kassa:

   :    ,   .   : <a href="https://money.yandex.ru/eshop.xml?shopId=12345&scid=1234566&sum=3000&customerNumber=73">https://money.yandex.ru/eshop.xml?shopId=12345&scid=1234566&sum=3000&customerNumber=73</a> 

In truth, the site should be a payment form. When the user clicks Pay, this form is sent to the above address and sends the parameters using the POST method. But we have a mobile application, so we had to abandon the form and form a link on the server side with the opening in WebView.

This link is given to the client to enter the card data and confirm the payment. But here we were waited by another surprise: at the end of 2017, Yandex.Cassa does not support responsive design. All sorts of manipulations with the settings did not give results.

image
The design does not adapt to the mobile application.

It turned out to switch the appearance of the payment page to the adaptive mode, you need to leave a request in your account. We had to contact tech support again.

image
Hooray, adapted design for mobile phone in 2017!

But only for payment by bank cards

Checking the fact of payment

Stripe:

Payment is checked during the payment generation process and in case of an error, the API function will return the corresponding exception.

Yandeks.Kassa:

Users pay on the Yandex.Cash side, but the user's application still does not know about the fact of payment. Therefore, Yandex.Cash must inform the server that payment has been made. To do this, developers must create a WebHook and configure Yandex.Cash so that she can use the addresses from WebHook to transfer the fact of payment.

Server notification about payment occurs in 2 stages:


But here we are waiting for surprises:

  1. To change the addresses, you need to send a request to the manager and wait again.
  2. It is necessary to implement a special algorithm for checking the validity of data from Yandex.Cash.
  3. The server must return specially crafted XML. We were able to find a ready-made module for the formation of the correct answer.

Cancel payment

Stripe:

 stripe.refunds.create({ charge: "ch_1BTuEo2eZvKYlo2CSGqKz76n" }, function(err, refund) { // asynchronously called }); 

Yandeks.Kassa:

     X.509    MWS.     .,        .. 

As you can guess, the coordination and connection took some time. It smoothly went beyond the deadline.

We save cards

Stripe:

 stripe.customers.create({ email: "paying.user@example.com", source: "src_18eYalAHEMiOZZp1l9ZTjSU0", }, function(err, customer) { // asynchronously called }); 

Yandeks.Kassa:

We describe the cancellation rules for saving cards and implement the ability to delete. Then we send the application for review to the Yandex.Money security service and wait for a response.

If the answer is yes, it is possible to save the cards after a successful payment and make repeated payments using the MWS protocol.

Sample request from documentation:

 POST https://server:port/webservice/mws/api/repeatCardPayment DATA: clientOrderId=123456789&invoiceId=2000000123&amount=10.00&cvv=643 

From the examples it is clear that Stripe is more suitable for developers and has a large variety of functions and capabilities. But there is one big BUT: Stripe, like Braintree, does not work in Russia, although it can accept payments from different countries. The owner of the Stripe account must be a resident of the countries available to him - Russia is not among them.

What's the result


Even taking into account the fact that we had to do a lot of additional work and communicate with support, we not only managed to finish almost everything on time, but also carried out additional work. A week before the release, a new version of the Yandex.Cash API came out and we created the NPM module and rewrote the code.

When we understood the new version of the API, we were pleasantly surprised: the developers clearly looked at foreign analogues and applied the best practices. Some problems of the previous version have been resolved. The documentation for the new API did not have the SDK for Node.js. We plan to work on the Russian market in the future as well, and we will need such a tool. Therefore, we decided to create an NPM-module, which anyone can integrate into their own project.

Source: https://habr.com/ru/post/412643/


All Articles