PHP library for working with Yandex.Money API
I have long wanted to try something new, and when I was offered to write examples of using the Yandex.Money API in different languages at work, I gladly accepted this challenge offer. Since most often such functionality is used in applications on various hosting sites, a strong-willed decision was made to first try to write this in PHP. Moreover, the API before that I have not even seen; moreover, I had no experience with PHP other than laboratory work at a university. The case promised to be interesting.
The first thing I came across: developing and deploying immediately to hosting is not very convenient. And I decided to download some gentleman's kit for the web developer. From student days, the name Denwer loomed in memory. I tried it, but quickly refused it. He lives a life of his own, and when I tried to configure it by rewriting something in the Apache conf file, he erased or did not erase it at his discretion, not allowing everything to be configured by hand. That is, it turned out that I did not configure it, but he did me. Reminded "if I had a horse - it would be a number ...". As a result, I, of course, defeated him, but decided to find a simpler WAMP-server. I want to note that Denwer is a good product and I have nothing against it, but I did not want to read the faxes and manuals on it.
Found a list pageWAMP'ov in wiki and began to sort them out. The main criterion for choosing was the project supportability, so that the build version was more or less fresh, and the ease of installation / launch. As a result, I can safely recommend The Uniform Server . It does not require installation (only unzip the archive), at startup it hangs in the tray and starts by lightly pressing =). He did not arbitrage, and I settled on him.
I read the instructions , downloaded the documentation, exposed a saber and rushed into battle. But in battle, I was quickly defeated by OAuth authentication. OAuth is a way to access any service / user account without entering and storing his username and password in his application. This came to us from the creator of Twitter and looks something like this: we make a request to the service (in our case, Yandex.Money), the user enters his username / password on the Yandex.Money server and gives our application permission to use his account. After that, the Yandex.Money server redirects to our application, and we get a temporary code whose lifetime is very short. Then, through another request to Yandex.Money, we change this temporary code to a constant token of the user and then for us, as a demobilization, all roads are open.
However, while I went through OAuth authentication, I came across a security problem. I tried to contact the Yandex.Money server, but PHP began to swear dirty and say something about certificates. Scooped a bit on the Internet and realized that it was necessary for our application to check the SSL-certificate of the server. I wanted to do well to guarantee users safety, and I continued to search. But there are almost no sane examples of the implementation of server certificate verification in RuNet. I'll tell you in order.
First, you had to register certificate verification in the code when sending requests. How to force cURL that I use to send certificate verification requests? Started to search and was amazed that the most popular tip for certificate errors: DISABLE verification. And this is offered on a bunch of sites and forums (for example,here ). Horror in general. Here is the code that is most often offered:
Remember it, children, and never write. “And now, son, we will repeat all those bad words that you must forget.” Thank God that not everything is so bad on the English-speaking Internet, and I found a link that explained everything. He did as it is written there, and it worked.
Then it was necessary to keep the Yandex.Money public certificate at home, so that there was something to compare when sending requests. I’m not quite retarded, but nevertheless it seemed to me rather difficult. Maybe it will help you in the future when working with SSL. We go to the desired site via https, poke in the certificates and export. But there are 3 of them, which one is needed? “Take a pie from the shelf; there are two of them, take the middle one. ” It turns out that you need to export a certificate of a certification authority (root) and intermediate (Yandex). The final certificate is changed once a year and if we enter it into a chain and forget to change it when it goes bad, then everything in our application will break. Therefore, we export only the indicated 2 certificates and just save them in one text file ( screenshot ). In my library he figures likeym.crt .
After that, the requests earned me. Hurrah! Further was a matter of technology. Everything was clear in the documentation; actually, that's why I actually copied it into the code documentation. I also make a reservation that I wrote it as an object; in my opinion, working with objects is good and convenient.
There were still some difficulties with encryption. At first, saving / restoring user tokens was implemented by the standard Mcrypt PHP library. But, as it turned out, there are problems with her. For example, from examples taken in the manual, only one deprecated function immediately worked. Other functions spat on my desire to make them work, and only said something about the failed module initialization. It was necessary to understand. Then it turned out that the hosters are not very fond of this library. I asked my hoster supportwhy, when creating a site in PHP 5.3, there is no Mcrypt module. They answered me (verbatim): “He’s been buggy for years in 5.2 - they didn’t automatically introduce it in 5.3 as a module that is remembered every five years, but there were problems with it.” I did not find other convenient standard libraries with symmetric encryption implementation in PHP (there is an OpenSSL library, but it is not quite for this). After that, I decided to change the encryption library to phpseclib , which is open and supports the popular AES algorithm. She earned immediately and without problems.
Also, for "training on cats", or rather testing and debugging, calls were made to library functions, which I subsequently ennobled with a layout for a pleasant-looking look, filled with comments and called examples of using the library.
As a result, calls to the following Yandex.Money API functions were implemented: account information, transaction history, detailed information on operations, money transfers to other users. Pros and features:
The library itself is a ym.crt certificate chain file and a ym.php file that contains:
Note: uses PHP version 5, as well as the cUrl standard library for http requests.
For those who will not install and watch detailed examples, we show a couple of challenges.
To perform operations with the account through the API, it is necessary to obtain user permission, that is, a token. It can be received by the following calls (for example, with access to view account information and transaction history):
When you create the $ ym object, the application identifier and the absolute path on the server to the certificate chain (ym.crt file) are passed to it. Both that, and another is usually registered in constants in any module (consts.php in our examples).
Well, let’s show how to get information about the user’s account. In the same way, create an object and then call the method, passing it the user token:
Account information received.
The situation is similar with other challenges.
As a result, they decided to call the library a big name SDK and put it on GitHub .
I will be glad to hear your comments and suggestions, as well as see forks and pull requests.
Choice of environment
The first thing I came across: developing and deploying immediately to hosting is not very convenient. And I decided to download some gentleman's kit for the web developer. From student days, the name Denwer loomed in memory. I tried it, but quickly refused it. He lives a life of his own, and when I tried to configure it by rewriting something in the Apache conf file, he erased or did not erase it at his discretion, not allowing everything to be configured by hand. That is, it turned out that I did not configure it, but he did me. Reminded "if I had a horse - it would be a number ...". As a result, I, of course, defeated him, but decided to find a simpler WAMP-server. I want to note that Denwer is a good product and I have nothing against it, but I did not want to read the faxes and manuals on it.
Found a list pageWAMP'ov in wiki and began to sort them out. The main criterion for choosing was the project supportability, so that the build version was more or less fresh, and the ease of installation / launch. As a result, I can safely recommend The Uniform Server . It does not require installation (only unzip the archive), at startup it hangs in the tray and starts by lightly pressing =). He did not arbitrage, and I settled on him.
OAuth Authentication
I read the instructions , downloaded the documentation, exposed a saber and rushed into battle. But in battle, I was quickly defeated by OAuth authentication. OAuth is a way to access any service / user account without entering and storing his username and password in his application. This came to us from the creator of Twitter and looks something like this: we make a request to the service (in our case, Yandex.Money), the user enters his username / password on the Yandex.Money server and gives our application permission to use his account. After that, the Yandex.Money server redirects to our application, and we get a temporary code whose lifetime is very short. Then, through another request to Yandex.Money, we change this temporary code to a constant token of the user and then for us, as a demobilization, all roads are open.
However, while I went through OAuth authentication, I came across a security problem. I tried to contact the Yandex.Money server, but PHP began to swear dirty and say something about certificates. Scooped a bit on the Internet and realized that it was necessary for our application to check the SSL-certificate of the server. I wanted to do well to guarantee users safety, and I continued to search. But there are almost no sane examples of the implementation of server certificate verification in RuNet. I'll tell you in order.
First, you had to register certificate verification in the code when sending requests. How to force cURL that I use to send certificate verification requests? Started to search and was amazed that the most popular tip for certificate errors: DISABLE verification. And this is offered on a bunch of sites and forums (for example,here ). Horror in general. Here is the code that is most often offered:
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
Remember it, children, and never write. “And now, son, we will repeat all those bad words that you must forget.” Thank God that not everything is so bad on the English-speaking Internet, and I found a link that explained everything. He did as it is written there, and it worked.
Then it was necessary to keep the Yandex.Money public certificate at home, so that there was something to compare when sending requests. I’m not quite retarded, but nevertheless it seemed to me rather difficult. Maybe it will help you in the future when working with SSL. We go to the desired site via https, poke in the certificates and export. But there are 3 of them, which one is needed? “Take a pie from the shelf; there are two of them, take the middle one. ” It turns out that you need to export a certificate of a certification authority (root) and intermediate (Yandex). The final certificate is changed once a year and if we enter it into a chain and forget to change it when it goes bad, then everything in our application will break. Therefore, we export only the indicated 2 certificates and just save them in one text file ( screenshot ). In my library he figures likeym.crt .
After that, the requests earned me. Hurrah! Further was a matter of technology. Everything was clear in the documentation; actually, that's why I actually copied it into the code documentation. I also make a reservation that I wrote it as an object; in my opinion, working with objects is good and convenient.
Encryption
There were still some difficulties with encryption. At first, saving / restoring user tokens was implemented by the standard Mcrypt PHP library. But, as it turned out, there are problems with her. For example, from examples taken in the manual, only one deprecated function immediately worked. Other functions spat on my desire to make them work, and only said something about the failed module initialization. It was necessary to understand. Then it turned out that the hosters are not very fond of this library. I asked my hoster supportwhy, when creating a site in PHP 5.3, there is no Mcrypt module. They answered me (verbatim): “He’s been buggy for years in 5.2 - they didn’t automatically introduce it in 5.3 as a module that is remembered every five years, but there were problems with it.” I did not find other convenient standard libraries with symmetric encryption implementation in PHP (there is an OpenSSL library, but it is not quite for this). After that, I decided to change the encryption library to phpseclib , which is open and supports the popular AES algorithm. She earned immediately and without problems.
Functionality and examples of use
Also, for "training on cats", or rather testing and debugging, calls were made to library functions, which I subsequently ennobled with a layout for a pleasant-looking look, filled with comments and called examples of using the library.
As a result, calls to the following Yandex.Money API functions were implemented: account information, transaction history, detailed information on operations, money transfers to other users. Pros and features:
- OAuth user authorization;
- work security (certificate chain validation is supported);
- convenience of work (server responses are represented as objects) and quick start;
- a relatively safe and simple solution for storing user tokens using encryption and without using a database. You can easily rewrite the implementation of this solution to your repositories.
The library itself is a ym.crt certificate chain file and a ym.php file that contains:
- IYandexMoney software interface;
- YandexMoney main class (interface implementation);
- enumeration class with access rights (scope);
- auxiliary classes (response-objects of the output of the results of requests to the API).
Note: uses PHP version 5, as well as the cUrl standard library for http requests.
For those who will not install and watch detailed examples, we show a couple of challenges.
To perform operations with the account through the API, it is necessary to obtain user permission, that is, a token. It can be received by the following calls (for example, with access to view account information and transaction history):
YandexMoney :: authorize (Consts :: CLIENT_ID, 'account-info operation-history', Consts :: REDIRECT_URL); // then on the redirect page initiate the creation of the object and obtaining the token $ ym = new YandexMoney (Consts :: CLIENT_ID, Consts :: CERTIFICATE_CHAIN_PATH); $ token = $ ym-> receiveOAuthToken ($ _ GET ['code'], Consts :: REDIRECT_URL);
When you create the $ ym object, the application identifier and the absolute path on the server to the certificate chain (ym.crt file) are passed to it. Both that, and another is usually registered in constants in any module (consts.php in our examples).
Well, let’s show how to get information about the user’s account. In the same way, create an object and then call the method, passing it the user token:
$ ym = new YandexMoney (Consts :: CLIENT_ID, Consts :: CERTIFICATE_CHAIN_PATH); $ accountInfoResponse = $ ym-> accountInfo ($ token); echo 'Account Number:'. $ accountInfoResponse-> getAccount (). "\ n"; echo 'Balance:'. $ accountInfoResponse-> getBalance (). "\ n"; echo 'Currency code:'. $ accountInfoResponse-> getCurrency (). "\ n";
Account information received.
The situation is similar with other challenges.
As a result, they decided to call the library a big name SDK and put it on GitHub .
I will be glad to hear your comments and suggestions, as well as see forks and pull requests.