
I have long wanted to try something new, and now, when I was at work offered to write examples of using the Yandex.Money API in different languages, I gladly accepted this challenge offer. Since most of the same functionality is used in applications on various hosting systems, it was a volitional decision to try to write this in PHP first. And before that I didn’t even see the API; moreover, I had no experience with PHP, except as a laboratory at the university. The thing promised to be interesting.
Choice of environment
The first thing I encountered was that it was not very convenient to develop and deploy to the hosting right there. And I decided to download some gentleman's set for a web developer. From his student days, the name Denwer loomed in his memory. I tried, but quickly refused it. He lives some kind of his life, and when I tried to set it up by rewriting something in the Apache conf-file, he overwritten it or not overwritten it on his own, not letting everything be adjusted by hand. That is, it turned out that it was not I who set it up, but he did me. He recalled "if I had a horse - it would be a number ...". As a result, I won it, of course, but at the same time I decided to find a simpler WAMP-server. I want to note that Denwer is a good product and I don’t have anything against it, but I didn’t want to read faky and manuals on it.
I found a page with a
list of WAMPs on the wiki and began sorting through them. The main criteria for the selection were the project support, so that the build version was more or less fresh, and ease of installation / launch. As a result, I can safely recommend
The Uniform Server . It does not require installation (only unpack the archive), when launched, it hangs in the tray and starts up with a light tap =). I did not begin to act willfully, and I settled on it.
OAuth authentication
I read the
instructions , downloaded the
documentation , exposed the checker and rushed into battle. But in combat, I was quickly defeated by OAuth authentication. OAuth is a way to access any service / account of a user without entering and storing his username and password in his application. It came to us from the creator of Twitter and looks like this: we make a request to the service (in our case, Yandex.Money), the user enters his login / password on the Yandex.Money server and gives our application permissions to use his account. After that, the Yandex.Money server redirects to our application, and we get a temporary code, the lifetime of which is very short. Then, by means of another request to Yandex. Money, we change this temporary code to a user's permanent token and then for us, as for demob, all roads are open.
')
However, while I was passing through OAuth authentication, I came across a security issue. I tried to contact the Yandex.Money server, but PHP began to swear dirty and say something about certificates. I rummaged a little on the Internet and understood that it was necessary for our application to verify the server's SSL certificate. I wanted to do well to ensure users safety, and I continued to search. But there are almost no imputed examples of the implementation of checking the server certificate in RuNet. I'll tell you in order.
First, it was necessary to register the verification of certificates in the code when sending requests. How to force cURL which I use to send requests with check of the certificate? He began to search and was amazed that the most popular advice for certificate errors: DISABLE check. And it 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 in the English-language Internet is not so bad, and I found such a
reference , which explained everything. I did what it says, and it all worked.
Then it was necessary to keep the Yandex.Money public certificate in order to be compared with anything when sending requests. I didn’t seem to be completely retarded, but nevertheless it seemed to me rather difficult. Maybe you in the future will help when working with SSL. We go to the desired site via https, poke into 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 the certificate of the certification center (root) and intermediate (Yandex). The final certificate changes once a year and, if we enter it into a chain and forget to change it when it is rotten, then everything in our application will break. Therefore, we export only the specified 2 certificates and simply save them into one text file (
screenshot ). In my library, it
appears as
ym.crt .
After that, the requests I have earned. Hooray! Further was a matter of technique. In the documentation, everything was clear; 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, it is good and convenient to work with objects.
Encryption
There were still some difficulties with encryption. At first, saving / restoring user tokens was implemented by the standard PHP library Mcrypt. But as it turned out, there are problems with it. For example, from the ejects taken in the manual, immediately earned only one deprecated-function. The remaining functions spat on my desire to make them work, and only said something about the unsuccessful initialization of the module. It was necessary to understand. Then it turned out that hosters are not very fond of this library. I asked the support of my
hosting provider why there is no Mcrypt module when creating a site for PHP 5.3. I was told (verbatim): “It buggy for years in 5.2 - it wasn’t automatically added to 5.3 as a module, which is remembered once every five years, and there were problems with it”. I did not find other convenient standard libraries with the implementation of symmetric encryption in PHP (there is an OpenSSL library, but it is not quite for that). 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 to library functions were written, which I subsequently refined with layout for a pleasant looking eye, filled with comments and called examples of using the library.
As a result, calls to the following Yandex.Money API functions are implemented: account information, transaction history, detailed information on operations, money transfers to other users. Pros and features:
- OAuth user authentication;
- security of work (checking certificate chains is supported);
- usability (server responses are presented as objects) and quick start;
- relatively safe and easy solution for storing users tokens using encryption and without using a database. You can easily rewrite the implementation of this solution to your storage.
The library itself is a file of certificate chain
ym.crt and file
ym.php , which contains:
- IYandexMoney software interface;
- YandexMoney main class (interface implementation);
- class-enumeration with access rights (scope);
- helper classes (response objects displaying results of API queries).
The library contains 2 files that implement encryption: Rijndael.php and AES.php. These files are taken from the
phpseclib library. They are needed in case you will use methods to save and restore tokens.
Note: uses PHP version 5, as well as the standard cUrl library for http requests.
For those who will not install and watch detailed examples, we will show a couple of calls.
To perform operations with the account through the API, it is necessary to obtain the user's permission, that is, the 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 an object and the receipt of a token
$ ym = new YandexMoney (Consts :: CLIENT_ID, Consts :: CERTIFICATE_CHAIN_PATH);
$ token = $ ym-> receiveOAuthToken ($ _ GET ['code'], Consts :: REDIRECT_URL);
When you create an object $ ym, the application ID and the absolute path on the server to the certificate chain (the ym.crt file) are passed to it. Both are usually written in constants in some module (consts.php in our examples).
Well, show you 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.
Approximately the same is with other challenges.
As a result, the library decided to call the SDK a loud name and put it on
GitHub .
I will be glad to hear your comments and suggestions, as well as see forks and pull requests.