Advertisement
Guest User

QIWI CURL CLASS

a guest
Jan 11th, 2017
1,340
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 89.05 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Qiwi
  4.  *
  5.  * Класс для прямой работы с QIWI кошельком
  6.  *
  7.  * @link      http://phpcurlqiwi.com/
  8.  */
  9. use DOMDocument;
  10. use DOMXpath;
  11. use Exception;
  12. class QiwiApi
  13. {
  14.  
  15.     /**
  16.      *
  17.      * @var int $requestId         Содержит в себе номер транзакции при обнаружении поля с SMS подтверждением при платеже
  18.      *                             Содержит в себе номер заявки на изменение настроек безопасности, если нужно СМС подтверждение отключения
  19.      *
  20.      */
  21.     public $requestId = 0;
  22.  
  23.     /**
  24.      *
  25.      * @var string $cookieFile               Путь к файлу с куками
  26.      *
  27.      * @see Qiwi::setCookieFile()
  28.      *
  29.      */
  30.     public $cookieFile = __DIR__.'/cookie_qiwi.txt';
  31.  
  32.     /**
  33.      *
  34.      * @var string $proxy                    Строка с адресом и типом прокси, например socks5://127.0.0.1:9050
  35.      *
  36.      * @see Qiwi::setProxy()
  37.      *
  38.      */
  39.     private $proxy = '';
  40.     private $proxyScheme = '';
  41.  
  42.     /**
  43.      * @var $aBalances          Переменная для совместимости с другим классом
  44.      */
  45.     public $aBalances;
  46.  
  47.     /**
  48.      *
  49.      * Конструктор
  50.      *
  51.      * Не передавайте этому методу параметры. Они добавлены для совместимости с другим классом.
  52.      * Используйте QiwiWallet::login() и QiwiWallet::setCookieFile() для логина и установки пути к файлу с куками
  53.      *
  54.      * @param string $compatL               Сделано для совместимости с другим классом. Используйте Qiwi::login()
  55.      * @param string $compatP               Сделано для совместимости с другим классом. Используйте Qiwi::login()
  56.      * @param string $compatC               Сделано для совместимости с другим классом. Используйте Qiwi::setCookieFile()
  57.      *
  58.      */
  59.     public function __construct( $compatL = null, $compatP = null, $compatC = '')
  60.     {
  61.  
  62.         libxml_use_internal_errors(true);
  63.  
  64.         if( $compatC != '' )
  65.         {
  66.  
  67.             $this->cookieFile = $compatC;
  68.  
  69.         }
  70.  
  71.         if( !is_null( $compatL ) )
  72.         {
  73.  
  74.             $this->login( $compatL, $compatP );
  75.             $this->aBalances = $this->wallets();
  76.  
  77.         }
  78.  
  79.     }
  80.  
  81.     /**
  82.      *
  83.      * Авторизуется в кошельке, предварительно проверив, что еще не авторизован в нем.
  84.      *
  85.      * @param string $phone      Телефон QIWI кошелька
  86.      * @param string $passwd     Пароль QIWI кошелька
  87.      *
  88.      * @throws Exception         В случае ошибок выкидывает исключения
  89.      *
  90.      * @return void
  91.      *
  92.      */
  93.     public function login( $phone, $passwd )
  94.     {
  95.         // Есть ли файл с куками?
  96.         if( !file_exists( $this->cookieFile ) )
  97.         {
  98.  
  99.             $path = dirname( $this->cookieFile );
  100.             // Если нет, то можно ли писать в папку?
  101.             if( !is_writable( $path ) )
  102.             {
  103.  
  104.                 throw new Exception( 'Не могу создать файл cookie в ' . $path );
  105.  
  106.             }
  107.  
  108.             // можно ли в файл писать?
  109.         } elseif( !is_writable( $this->cookieFile ) ) {
  110.  
  111.             throw new Exception( 'Не могу записать cookie в ' . $this->cookieFile );
  112.  
  113.         }
  114.  
  115.         if( $phone[ 0 ] != '+' )
  116.             $phone = '+' . $phone;
  117.  
  118.         if( $this->isAuthenticated( $phone ) )
  119.         {
  120.  
  121.             return true;
  122.  
  123.         }
  124.  
  125.         // Получение первого тикета
  126.         $loginData = array(
  127.             'login' => $phone,
  128.             'password' => $passwd
  129.         );
  130.  
  131.         $json = @json_decode( $this->requestJSON( 'https://sso.qiwi.com/cas/tgts', $loginData ) );
  132.  
  133.         // На случай неправильного пароля
  134.         if( isset( $json->entity->error->message ) )
  135.         {
  136.  
  137.             throw new Exception( $json->entity->error->message );
  138.  
  139.         }
  140.  
  141.         if( !isset( $json->entity->ticket ) )
  142.         {
  143.  
  144.             throw new Exception( 'Failed to get first ticket' );
  145.  
  146.         }
  147.  
  148.         // Получение второго тикета
  149.         $loginData = array(
  150.             'ticket' => $json->entity->ticket,
  151.             'service' => 'https://qiwi.com/j_spring_cas_security_check',
  152.         );
  153.  
  154.         $json = @json_decode( $this->requestJSON( 'https://sso.qiwi.com/cas/sts', $loginData ) );
  155.  
  156.         if( !isset( $json->entity->ticket ) )
  157.         {
  158.  
  159.             throw new Exception( 'Failed to get second ticket' );
  160.  
  161.         }
  162.  
  163.         // Проверка тикета
  164.         $this->request( 'https://qiwi.com/j_spring_cas_security_check?ticket=' . $json->entity->ticket, NULL, array(
  165.                 CURLOPT_HTTPHEADER => array(
  166.                     'Accept: application/json, text/javascript, */*; q=0.01',
  167.                     'DNT: 1',
  168.                 ),
  169.             )
  170.         );
  171.  
  172.         if( !$this->isAuthenticated( $phone ) )
  173.         {
  174.  
  175.             throw new Exception( 'Неизвестная ошибка авторизации' );
  176.  
  177.         }
  178.  
  179.     }
  180.  
  181.     /**
  182.      *
  183.      * Проверяет, авторизован ли кошелек в QIWI
  184.      *
  185.      * @param string $phone      Номер кошелька
  186.      *
  187.      * @return bool
  188.      *
  189.      */
  190.     public function isAuthenticated( $phone )
  191.     {
  192.  
  193.         // Почему-то иногда устаревают куки от https://sso.qiwi.com/cas/tgts и он перестает отдавать тикеты.
  194.         // Проблема решается переавторизацией(TODO: без нее)
  195.         $info = $this->info();
  196.  
  197.         $json = @json_decode(
  198.             $this->requestJSON( 'https://sso.qiwi.com/cas/tgts', NULL, array(
  199.                     CURLOPT_HTTPHEADER => array(
  200.                         'Accept: application/vnd.qiwi.sso-v1+json',
  201.                         'Content-Type: application/json',
  202.                         'DNT: 1',
  203.                     )
  204.                 )
  205.             )
  206.         );
  207.  
  208.         if( isset( $info->data->person ) && $info->data->person == floatval( $phone ) && isset( $json->entity->ticket ) && $json->entity->ticket != '' )
  209.         {
  210.  
  211.             return true;
  212.  
  213.         }
  214.  
  215.         return false;
  216.  
  217.     }
  218.  
  219.     /**
  220.      *
  221.      * Получает номер телефона(без плюса) с сайта QIWI
  222.      *
  223.      * @throws Exception         Выкинет соответствующее исключение, если не авторизован
  224.      *
  225.      * @return string
  226.      *
  227.      */
  228.     public function getPerson()
  229.     {
  230.  
  231.         $info = $this->info();
  232.  
  233.         if( isset( $info->data->person ) )
  234.         {
  235.  
  236.             return $info->data->person;
  237.  
  238.         } else {
  239.  
  240.             throw new Exception( 'Я не авторизован в QIWI кошельке' );
  241.  
  242.         }
  243.  
  244.     }
  245.  
  246.     /**
  247.      *
  248.      * Получает информацию о кошельке с сайта QIWI
  249.      *
  250.      * @throws Exception         В случае ошибок выкидывает исключения
  251.      *
  252.      * @return array
  253.      *
  254.      */
  255.     public function info()
  256.     {
  257.  
  258.         $json = @json_decode(
  259.             $this->requestJSON( 'https://qiwi.com/person/state.action', array(), array(
  260.                     CURLOPT_HTTPHEADER => array(
  261.                         'Accept: application/json, text/javascript, */*; q=0.01',
  262.                         'X-Requested-With: XMLHttpRequest',
  263.                         'DNT: 1',
  264.                     )
  265.                 )
  266.             )
  267.         );
  268.  
  269.         if( !isset( $json->code->value ) )
  270.         {
  271.  
  272.             throw new Exception( 'QIWI не отвечает (не удается получить инфомацию об аккаунте)' );
  273.  
  274.         }
  275.  
  276.         return $json;
  277.     }
  278.  
  279.     /**
  280.      *
  281.      * Совершает платеж на QIWI кошелек
  282.      *
  283.      * @param string             $phone                 Телефон получателя
  284.      * @param float              $amount                Сумма
  285.      * @param string             $amountCurrency        Валюта суммы (RUB, KZT, USD, EUR)
  286.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  287.      * @param string             $comment    Необязательный комментарий
  288.      *
  289.      * @throws Exception         В случае ошибок выкидывает исключения
  290.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  291.      *
  292.      * @return int               Возвращает номер транзакции в случае успешного завершения
  293.      *
  294.      * @see Qiwi::paymentSmsConfirmation()
  295.      *
  296.      */
  297.     public function paymentQiwi( $phone, $amount, $amountCurrency, $sourceCurrency, $comment = '' )
  298.     {
  299.         if( $phone[ 0 ] != '+' )
  300.             $phone = '+' . $phone;
  301.  
  302.         $fields = array(
  303.             'account' => $phone
  304.         );
  305.  
  306.         return $this->paymentNew( 99, $amount, $amountCurrency, $sourceCurrency, $comment, $fields );
  307.     }
  308.  
  309.     /**
  310.      *
  311.      * Совершает платеж на Яндекс.Деньги
  312.      *
  313.      * @param string             $account               Счет получателя
  314.      * @param float              $amount                Сумма
  315.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  316.      * @param string             $comment               Необязательный комментарий
  317.      *
  318.      * @throws Exception         В случае ошибок выкидывает исключения
  319.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  320.      *
  321.      * @return int               Возвращает номер транзакции в случае успешного завершения
  322.      *
  323.      * @see Qiwi::paymentSmsConfirmation()
  324.      *
  325.      */
  326.     public function paymentYandex( $account, $amount, $sourceCurrency, $comment = '' )
  327.     {
  328.         $fields = array(
  329.             'account' => $account
  330.         );
  331.  
  332.         return $this->paymentNew( 26476, $amount, 'RUB', $sourceCurrency, $comment, $fields );
  333.     }
  334.  
  335.     /**
  336.      *
  337.      * Совершает платеж на рублевый кошелек WebMoney
  338.      *
  339.      * @param string             $account               Кошелек в формате R1234567890
  340.      * @param float              $amount                Сумма в рублях
  341.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  342.      * @param string             $comment               Необязательный комментарий
  343.      *
  344.      * @throws Exception         В случае ошибок выкидывает исключения
  345.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  346.      *
  347.      * @return int               Возвращает номер транзакции в случае успешного завершения
  348.      *
  349.      * @see Qiwi::paymentSmsConfirmation()
  350.      *
  351.      */
  352.     public function paymentWebMoney( $account, $amount, $sourceCurrency, $comment = '' )
  353.     {
  354.         $fields = array(
  355.             'account' => $account
  356.         );
  357.  
  358.         return $this->paymentNew( 56, $amount, 'RUB', $sourceCurrency, $comment, $fields );
  359.     }
  360.  
  361.     /**
  362.      *
  363.      * Совершает платеж на банковскую карту
  364.      *
  365.      * @param int           $cardNumber                     номер карточки
  366.      * @param float         $amount                         сумма(float)
  367.      * @param string        $amountCurrency                 Валюта суммы (RUB, KZT, USD, EUR)
  368.      * @param string        $sourceCurrency                 Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  369.      * @param string        $comment                        комментарий к платежу
  370.      * @param string        $recieverFirstName              имя получателя (нужно только для MasterCard)
  371.      * @param string        $recieverLastName               фамилия получателя (нужно только для MasterCard)
  372.      *
  373.      * @throws Exception                                    В случае ошибок выкидывает исключения
  374.      *
  375.      * @return int                                          Возвращает номер транзакции в случае успешного завершения
  376.      *
  377.      * @see Qiwi::paymentSmsConfirmation()
  378.      *
  379.      */
  380.     public function paymentCard( $cardNumber, $amount, $amountCurrency, $sourceCurrency, $comment, $recieverFirstName = '', $recieverLastName = '' )
  381.     {
  382.  
  383.         // Проверка номера и определение VISA/MC
  384.         $data = array(
  385.             'cardNumber' => $cardNumber
  386.         );
  387.  
  388.         $json = @json_decode( $this->request( 'https://qiwi.com/card/detect.action', $data ) );
  389.  
  390.         if( !isset( $json->code->value ) || !property_exists( $json, 'message' ) )
  391.         {
  392.  
  393.             throw new Exception( 'Не удалось определить банк получателя' );
  394.  
  395.         } elseif( $json->code->value != '0' ) {
  396.  
  397.             throw new Exception( $json->message );
  398.  
  399.         }
  400.  
  401.         $provider = $json->message;
  402.  
  403.         $fields = array(
  404.             'account' => (string)$cardNumber,
  405.             'termsId' => (string)$provider,
  406.             'reg_name_f' => $recieverFirstName,
  407.             'reg_name' => $recieverLastName
  408.         );
  409.  
  410.         return $this->paymentNew( $provider, $amount, $amountCurrency, $sourceCurrency, $comment, $fields );
  411.     }
  412.  
  413.     /**
  414.      *
  415.      * Совершает платеж на счет Промсвязьбанка
  416.      *
  417.      * @param int                $account               Номер счета
  418.      * @param float              $amount                Сумма
  419.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  420.      * @param string             $comment               Необязательный комментарий
  421.      *
  422.      * @throws Exception         В случае ошибок выкидывает исключения
  423.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  424.      *
  425.      * @return int               Возвращает номер транзакции в случае успешного завершения
  426.      *
  427.      * @see Qiwi::paymentSmsConfirmation()
  428.      *
  429.      */
  430.     public function paymentPromsvyaz( $account, $amount, $sourceCurrency, $comment = '' )
  431.     {
  432.         $fields = array(
  433.             'account_type' => '9',
  434.             'mfo' => '044525555',
  435.             'account' => (string)$account
  436.         );
  437.  
  438.         return $this->paymentNew( 821, $amount, 'RUB', $sourceCurrency, $comment, $fields );
  439.     }
  440.  
  441.     /**
  442.      *
  443.      * Совершает платеж на счет Сбербанка
  444.      *
  445.      * @param int                $account               Номер счета
  446.      * @param int                $bik                   БИК банка
  447.      * @param float              $amount                Сумма
  448.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  449.      * @param int                $urgent                0/1 - обычный/срочный платеж
  450.      * @param string             $lname                 Имя
  451.      * @param string             $fname                 Фамилия
  452.      * @param string             $mname                 Отчество
  453.      * @param string             $comment               Необязательный комментарий
  454.      *
  455.      * @throws Exception         В случае ошибок выкидывает исключения
  456.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  457.      *
  458.      * @return int               Возвращает номер транзакции в случае успешного завершения
  459.      *
  460.      * @see Qiwi::paymentSmsConfirmation()
  461.      *
  462.      */
  463.     public function paymentSberbank( $account, $bik, $amount, $sourceCurrency, $urgent, $lname, $fname, $mname, $comment = '' )
  464.     {
  465.         $fields = array(
  466.             'account_type' => '2',
  467.             'mfo' => (string)$bik,
  468.             'account' => (string)$account,
  469.             'urgent' => (string)$urgent,
  470.             'lname' => $lname,
  471.             'fname' => $fname,
  472.             'mname' => $mname
  473.         );
  474.  
  475.         return $this->paymentNew( 870, $amount, 'RUB', $sourceCurrency, $comment, $fields );
  476.     }
  477.  
  478.     /**
  479.      *
  480.      * Совершает платеж на счет Альфабанка
  481.      *
  482.      * @param int                $account               Номер счета
  483.      * @param float              $amount                Сумма
  484.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  485.      * @param string             $comment               Необязательный комментарий
  486.      *
  487.      * @throws Exception         В случае ошибок выкидывает исключения
  488.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  489.      *
  490.      * @return int               Возвращает номер транзакции в случае успешного завершения
  491.      *
  492.      * @see Qiwi::paymentSmsConfirmation()
  493.      *
  494.      */
  495.     public function paymentAlfabank( $account, $amount, $sourceCurrency, $comment = '' )
  496.     {
  497.         $fields = array(
  498.             'account_type' => '2',
  499.             'mfo' => '044525593',
  500.             'account' => (string)$account
  501.         );
  502.  
  503.         return $this->paymentNew( 464, $amount, 'RUB', $sourceCurrency, $comment, $fields );
  504.     }
  505.  
  506.     /**
  507.      *
  508.      * Совершает платеж на счет РусскогоСтандарт'а
  509.      *
  510.      * @param int                $account               Номер счета
  511.      * @param float              $amount                Сумма
  512.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  513.      * @param string             $comment               Необязательный комментарий
  514.      *
  515.      * @throws Exception         В случае ошибок выкидывает исключения
  516.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  517.      *
  518.      * @return int               Возвращает номер транзакции в случае успешного завершения
  519.      *
  520.      * @see Qiwi::paymentSmsConfirmation()
  521.      *
  522.      */
  523.     public function paymentRusskiyStandart( $account, $amount, $sourceCurrency, $comment = '' )
  524.     {
  525.         $fields = array(
  526.             'account_type' => '2',
  527.             'mfo' => '044583151',
  528.             'account' => (string)$account
  529.         );
  530.  
  531.         return $this->paymentNew( 815, $amount, 'RUB', $sourceCurrency, $comment, $fields );
  532.     }
  533.  
  534.     /**
  535.      *
  536.      * Совершает платеж на счет ВТБ24
  537.      *
  538.      * @param int                $account               Номер счета
  539.      * @param int                $bik                   БИК банка
  540.      * @param float              $amount                Сумма
  541.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  542.      * @param int                $urgent                0/1 - обычный/срочный платеж
  543.      * @param string             $lname                 Имя
  544.      * @param string             $fname                 Фамилия
  545.      * @param string             $mname                 Отчество
  546.      * @param string             $comment               Необязательный комментарий
  547.      *
  548.      * @throws Exception         В случае ошибок выкидывает исключения
  549.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  550.      *
  551.      * @return int               Возвращает номер транзакции в случае успешного завершения
  552.      *
  553.      * @see Qiwi::paymentSmsConfirmation()
  554.      *
  555.      */
  556.     public function paymentVtb24( $account, $bik, $amount, $sourceCurrency, $urgent, $lname, $fname, $mname, $comment = '' )
  557.     {
  558.         $fields = array(
  559.             'account_type' => '2',
  560.             'mfo' => (string)$bik,
  561.             'account' => (string)$account,
  562.             'urgent' => (string)$urgent,
  563.             'lname' => $lname,
  564.             'fname' => $fname,
  565.             'mname' => $mname
  566.         );
  567.  
  568.         return $this->paymentNew( 816, $amount, 'RUB', $sourceCurrency, $comment, $fields );
  569.     }
  570.  
  571.     /**
  572.      *
  573.      * Совершает платеж на счет в "Открытие"
  574.      *
  575.      * @param int                $account               Номер счета
  576.      * @param int                $bik                   БИК банка
  577.      * @param float              $amount                Сумма
  578.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  579.      * @param int                $urgent                0/1 - обычный/срочный платеж
  580.      * @param string             $lname                 Имя
  581.      * @param string             $fname                 Фамилия
  582.      * @param string             $mname                 Отчество
  583.      * @param string             $comment               Необязательный комментарий
  584.      *
  585.      * @throws Exception         В случае ошибок выкидывает исключения
  586.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  587.      *
  588.      * @return int               Возвращает номер транзакции в случае успешного завершения
  589.      *
  590.      * @see Qiwi::paymentSmsConfirmation()
  591.      *
  592.      */
  593.     public function paymentOtkritie( $account, $bik, $amount, $sourceCurrency, $urgent, $lname, $fname, $mname, $comment = '' )
  594.     {
  595.         $fields = array(
  596.             'account_type' => '2',
  597.             'mfo' => (string)$bik,
  598.             'account' => (string)$account,
  599.             'urgent' => (string)$urgent,
  600.             'lname' => $lname,
  601.             'fname' => $fname,
  602.             'mname' => $mname
  603.         );
  604.  
  605.         return $this->paymentNew( 876, $amount, 'RUB', $sourceCurrency, $comment, $fields );
  606.     }
  607.  
  608.     /**
  609.      *
  610.      * Совершает платеж на счет в Skype
  611.      *
  612.      * @param string             $login                 Логин Skype
  613.      * @param float              $amount                Сумма в USD
  614.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  615.      * @param string             $comment               Необязательный комментарий
  616.      *
  617.      * @throws Exception         В случае ошибок выкидывает исключения
  618.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  619.      *
  620.      * @return int               Возвращает номер транзакции в случае успешного завершения
  621.      *
  622.      * @see Qiwi::paymentSmsConfirmation()
  623.      *
  624.      */
  625.     public function paymentSkype( $login, $amount, $sourceCurrency, $comment = '' )
  626.     {
  627.         $fields = array(
  628.             'account' => $login
  629.         );
  630.  
  631.         return $this->paymentNew( 23195, $amount, 'USD', $sourceCurrency, $comment, $fields );
  632.     }
  633.  
  634.     /**
  635.      *
  636.      * Совершает платеж на счет мобильного телефона
  637.      *
  638.      * @param string             $phone                 Телефон
  639.      * @param float              $amount                Сумма
  640.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  641.      * @param string             $comment               Необязательный комментарий
  642.      *
  643.      * @throws Exception         В случае ошибок выкидывает исключения
  644.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  645.      *
  646.      * @return int               Возвращает номер транзакции в случае успешного завершения
  647.      *
  648.      * @see Qiwi::paymentSmsConfirmation()
  649.      *
  650.      */
  651.     public function paymentMobile( $phone, $amount, $sourceCurrency, $comment = '' )
  652.     {
  653.  
  654.         if( $phone[ 0 ] != '+' )
  655.             $phone = '+' . $phone;
  656.  
  657.         // Загрузить форму
  658.         $response = $this->request( 'https://qiwi.com/payment/mobile.action' );
  659.  
  660.         // Определить оператора
  661.         $data = array(
  662.             'phone' => $phone,
  663.         );
  664.  
  665.         $json = @json_decode(
  666.             $this->request( 'https://qiwi.com/mobile/detect.action', $data, array(
  667.                     CURLOPT_HTTPHEADER => array(
  668.                         'Accept: application/json, text/javascript, */*; q=0.01',
  669.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  670.                         'DNT: 1'
  671.                     )
  672.                 )
  673.             )
  674.         );
  675.         if( !isset( $json->code->value ) || !property_exists( $json, 'message' ) )
  676.         {
  677.  
  678.             throw new Exception( 'Не удается определить оператора' );
  679.  
  680.         } elseif( $json->code->value !== '0' ) {
  681.  
  682.             throw new Exception( $json->message );
  683.  
  684.         }
  685.  
  686.         $provider = $json->message;
  687.  
  688.         $fields = array(
  689.             'account' => $this->removeCountryCode( $phone )
  690.         );
  691.  
  692.         return $this->paymentNew( $provider, $amount, 'RUB', $sourceCurrency, $comment, $fields );
  693.     }
  694.  
  695.     /**
  696.      *
  697.      * Подтверждает начатый ранее платеж SMS кодом
  698.      *
  699.      * @param int    $transaction        Номер транзакции для подтверждения получается отловом исключения с текстом AwaitingSMSConfirmation из метода payment.
  700.      *                                   После этого исключения номер окажется в свойстве Qiwi::$transactionForSms
  701.      * @param int    $smsCode            Код из SMS
  702.      *
  703.      * @throws Exception         В случае ошибок выкидывает исключения
  704.      *
  705.      * @return int               Возвращает номер транзакции в случае успешного завершения
  706.      *
  707.      * @see Qiwi::$transactionForSms
  708.      *
  709.      */
  710.     public function paymentSmsConfirmation( $transaction, $smsCode )
  711.     {
  712.  
  713.         $data = array(
  714.             'smsCode' => (string)$smsCode
  715.         );
  716.  
  717.         $json = @json_decode( $this->requestJSON( 'https://qiwi.com/user/sinap/payments/' . $transaction . '/confirm/proxy.action', $data ) );
  718.  
  719.         if( !isset( $json->data->status ) )
  720.         {
  721.  
  722.             throw new Exception( 'Неверный формат ответа QIWI' );
  723.  
  724.         } elseif( $json->data->status != '200' ) {
  725.  
  726.             // Если есть ошибка от КИВИ
  727.             if( isset( $json->data->body->message ) )
  728.             {
  729.  
  730.                 throw new Exception( $json->data->body->message );
  731.  
  732.             } else {
  733.  
  734.                 throw new Exception( 'Неизвестная ошибка при подтверждении платежа' );
  735.  
  736.             }
  737.  
  738.         } elseif( !isset( $json->data->body->transaction->state->code ) ) {
  739.  
  740.             throw new Exception( 'Изменился формат ответа QIWI при подтверждении смской' );
  741.  
  742.         } elseif( $json->data->body->transaction->state->code != 'Accepted' ) {
  743.  
  744.             throw new Exception( 'Неизвестная ошибка при подтверждении платежа смской' );
  745.  
  746.         } elseif( !isset( $json->data->body->paymentId ) ) {
  747.  
  748.             throw new Exception( 'QIWI больше не отдает номер транзакции при платеже. Платеж совершен.' );
  749.  
  750.         } else {
  751.  
  752.             return $json->data->body->paymentId;
  753.  
  754.         }
  755.  
  756.     }
  757.  
  758.     /**
  759.      *
  760.      * Общий платежный метод, используется всеми остальными
  761.      *
  762.      * @param int                $provider    Код организации получателя
  763.      * @param float              $amount      Сумма
  764.      * @param string             $comment     Комментарий
  765.      * @param array              $fields      Массив с параметрами платежа
  766.      *
  767.      * @throws Exception         В случае ошибок выкидывает исключения
  768.      *                           При обнаружении СМС подтверждения выкидывает исключение с текстом AwaitingSMSConfirmation
  769.      *
  770.      * @return int               Возвращает номер транзакции в случае успешного завершения
  771.      *
  772.      * @see Qiwi::paymentSmsConfirmation()
  773.      *
  774.      */
  775.     public function paymentNew( $provider, $amount, $amountCurrency, $sourceCurrency, $comment, $fields )
  776.     {
  777.  
  778.         $amountCurrencyCode = $this->getCurrencyCode( $amountCurrency );
  779.         $sourceCurrencyCode = $this->getCurrencyCode( $sourceCurrency );
  780.  
  781.         $data = array(
  782.             'id' => time() . rand(100, 999),
  783.             'sum' => array(
  784.                 'amount' => (string)$amount,
  785.                 'currency' => (string)$amountCurrencyCode
  786.             ),
  787.             'source' => 'account_' . $sourceCurrencyCode,
  788.             'paymentMethod' => array(
  789.                 'type' => 'Account',
  790.                 'accountId' => (string)$sourceCurrencyCode
  791.             ),
  792.             'comment' => (string)$comment,
  793.             'fields' => $fields
  794.         );
  795.  
  796.         // Сама оплата
  797.         $data[ 'fields' ][ '_meta_pay_partner' ] = '';
  798.  
  799.         $json = @json_decode(
  800.             $this->requestJSON( 'https://qiwi.com/user/sinap/api/terms/' . $provider . '/payments/proxy.action', $data, array(
  801.                     CURLOPT_HTTPHEADER => array(
  802.                         'Accept: application/vnd.qiwi.v2+json',
  803.                         'Content-Type: application/json; charset=UTF-8',
  804.                         'DNT: 1'
  805.                     )
  806.                 )
  807.             )
  808.         );
  809.  
  810.         // на случай ошибок/включенного смс
  811.         if( !isset( $json->data->status ) )
  812.         {
  813.  
  814.             throw new Exception(  'Неверный формат ответа QIWI' );
  815.  
  816.         } elseif( $json->data->status != '200' ) {
  817.  
  818.             if( isset( $json->data->body->message ) )
  819.             {
  820.  
  821.                 throw new Exception( $json->data->body->message );
  822.  
  823.             } else {
  824.  
  825.                 throw new Exception( 'Неизвестная ошибка QIWI' );
  826.  
  827.             }
  828.  
  829.         } elseif( !isset( $json->data->body->transaction->state->code ) ) {
  830.  
  831.             throw new Exception( 'Изменился формат ответа QIWI' );
  832.  
  833.         } elseif ( $json->data->body->transaction->state->code == 'AwaitingSMSConfirmation' ) {
  834.  
  835.             $this->requestId = $json->data->body->id;
  836.  
  837.             throw new Exception( 'AwaitingSMSConfirmation' );
  838.  
  839.         } elseif( !isset( $json->data->body->transaction->state->code ) ) {
  840.  
  841.             throw new Exception( 'Изменился формат ответа QIWI при обычном подтверждении платежа' );
  842.  
  843.         } elseif( $json->data->body->transaction->state->code != 'Accepted' ) {
  844.  
  845.             throw new Exception( 'Неизвестная ошибка при обычном подтверждении платежа' );
  846.  
  847.         } elseif( !isset( $json->data->body->id ) ) {
  848.  
  849.             throw new Exception( 'QIWI больше не отдает номер транзакции при платеже. Платеж совершен.' );
  850.  
  851.         } else {
  852.  
  853.             return $json->data->body->id;;
  854.  
  855.         }
  856.  
  857.     }
  858.  
  859.     /**
  860.      *
  861.      * Переводит валюту между внутренними счетами QIWI
  862.      *
  863.      * @param int                $from          Откуда (RUB, KZT, USD, EUR)
  864.      * @param int                $to            Куда (RUB, KZT, USD, EUR)
  865.      * @param float              $amount        Сумма в конечной валюте
  866.      *
  867.      * @throws Exception         В случае ошибок выкидывает исключения
  868.      *
  869.      * @return void
  870.      *
  871.      */
  872.     public function convertCurrency( $from, $to, $amount )
  873.     {
  874.  
  875.         $cash = explode( '.', number_format( $amount, 2 ) );
  876.  
  877.         // Загрузить форму
  878.         $this->request( 'https://qiwi.com/settings/account/transfer.action?paymentModeType=QIWI' );
  879.  
  880.         // Получить первый токен
  881.         $data = array(
  882.             'extra' => array(
  883.                 '\'account\'' => $this->getPerson()
  884.             ),
  885.             'source' => 'qiwi_' . $from,
  886.             'amountInteger' => $cash[ 0 ],
  887.             'amountFraction' => $cash[ 1 ],
  888.             'currency' => $to,
  889.             'state' => 'CONFIRM',
  890.             'protected' => 'true',
  891.             'destination' => 'qiwi_' . $to,
  892.  
  893.         );
  894.  
  895.         $response = $this->request( 'https://qiwi.com/user/person/account/state.action', $data );
  896.         if( !preg_match( '/name=\"token\" value=\"([\-0-9]+)\"/i', $response, $matches ) )
  897.         {
  898.  
  899.             throw new Exception( 'Не удалось получить токен для начала платежа' );
  900.  
  901.         }
  902.  
  903.         // Отправить токен
  904.         $data[ 'token' ] = $matches[ 1 ];
  905.  
  906.         $response = $this->request( 'https://qiwi.com/user/person/account/state.action', $data );
  907.  
  908.         // Получить второй токен
  909.         $data = array(
  910.             'state' => 'PAY'
  911.         );
  912.  
  913.         $response = $this->request( 'https://qiwi.com/user/person/account/state.action', $data );
  914.         if( !preg_match( '/name=\"token\" value=\"([\-0-9]+)\"/i', $response, $matches ) )
  915.         {
  916.  
  917.             throw new Exception( 'Не удалось получить токен для начала платежа' );
  918.  
  919.         }
  920.  
  921.         // Подтверждение перевода
  922.         $data[ 'token' ] = $matches[ 1 ];
  923.  
  924.         $response = $this->request( 'https://qiwi.com/user/person/account/state.action', $data );
  925.  
  926.         if( mb_strpos( $response, 'transaction":"' ) === false )
  927.         {
  928.  
  929.             throw new Exception( 'Неизвестная ошибка при переводе между счетами' );
  930.  
  931.         }
  932.  
  933.     }
  934.  
  935.     /**
  936.      *
  937.      * Получает список транзакций
  938.      *
  939.      * @param string             $direction      Направление - in/out/inout (входящие/исходящие/все)
  940.      * @param string             $from           От какой даты в формате ДД.ММ.ГГГГ
  941.      * @param string             $to             До какой даты в формате ДД.ММ.ГГГГ
  942.      *
  943.      * @throws Exception         В случае ошибок выкидывает исключения
  944.      *
  945.      * @return array             Возвращает массив с транзакциями
  946.      *
  947.      */
  948.     public function transactions( $direction, $from, $to )
  949.     {
  950.  
  951.         $transactionsData = array(
  952.             'daterange' => 'true',
  953.             'start' => $from,
  954.             'finish' => $to
  955.         );
  956.  
  957.         // todo
  958.         if( $direction != 'inout' )
  959.         {
  960.  
  961.             $transactionsData[ 'settings' ] = 'true';
  962.             $transactionsData[ 'conditions.directions' ] = $direction;
  963.  
  964.         }
  965.  
  966.         $response = $this->request( 'https://qiwi.com/user/report/list.action', $transactionsData );
  967.         if( $response == '' )
  968.         {
  969.  
  970.             throw new Exception( 'Не удалось получить список транзакций' );
  971.  
  972.         }
  973.  
  974.         $doc = new DOMDocument();
  975.         if( !@$doc->loadHTML( mb_convert_encoding( $response, 'HTML-ENTITIES', 'UTF-8' ) ) )
  976.         {
  977.  
  978.             foreach ( libxml_get_errors() as $error )
  979.             {
  980.  
  981.                 throw new Exception( $error->message );
  982.  
  983.             }
  984.  
  985.             libxml_clear_errors();
  986.  
  987.         }
  988.         $transactions = array( );
  989.  
  990.         // Собсно блоки с транзакциями
  991.         $xpath = new DOMXpath( $doc );
  992.         $results = $xpath->query( '//div[@class="reportsLine status_SUCCESS"]' );
  993.         if( $results->length > 0 )
  994.         {
  995.  
  996.             foreach( $results as $row)
  997.             {
  998.  
  999.                 $transaction = array( );
  1000.  
  1001.                 // Номер транзакции
  1002.                 $result = $xpath->query( './/div[@class="transaction"]', $row );
  1003.                 $transaction[ 'transaction' ] = trim( $result->item( 0 )->nodeValue );
  1004.  
  1005.                 // Дата транзакции в формате ДД.ММ.ГГГГ
  1006.                 $result = $xpath->query( './/span[@class="date"]', $row );
  1007.                 $transaction[ 'date' ] = trim( $result->item( 0 )->nodeValue );
  1008.  
  1009.                 // Время транзакции в формате ЧЧ.ММ.СС
  1010.                 $result = $xpath->query( './/span[@class="time"]', $row );
  1011.                 $transaction[ 'time' ] = trim( $result->item( 0 )->nodeValue );
  1012.  
  1013.                 // Сумма
  1014.                 $result = $xpath->query( './/div[@class="cash"]', $row );
  1015.                 $transaction[ 'cash' ] = str_replace( ',', '.', $this->parseFloatFromCash( trim( $result->item( 0 )->nodeValue ) ) );
  1016.  
  1017.                 // Валюта прихода
  1018.                 $transaction[ 'currency' ] = $this->determineCurrencyFromCash( $result->item( 0 )->nodeValue );
  1019.  
  1020.                 // Сумма в оригинальной валюте
  1021.                 $result = $xpath->query( './/div[@class="originalExpense"]/span', $row );
  1022.                 $transaction[ 'originalCash' ] = str_replace( ',', '.', $this->parseFloatFromCash( trim( $result->item( 0 )->nodeValue ) ) );
  1023.  
  1024.                 // Оригинальная валюта
  1025.                 $transaction[ 'originalCurrency' ] = $this->determineCurrencyFromCash( $result->item( 0 )->nodeValue );
  1026.  
  1027.                 // Иденификатор отправителя(как правило телефон)
  1028.                 $result = $xpath->query( './/span[@class="opNumber"]', $row );
  1029.                 $transaction[ 'opNumber' ] = trim( $result->item( 0 )->nodeValue );
  1030.  
  1031.                 // Провайдер
  1032.                 $result = $xpath->query( './/div[@class="provider"]/span[1]', $row );
  1033.                 $transaction[ 'provider' ] = trim( $result->item( 0 )->nodeValue );
  1034.  
  1035.                 // Комментарий
  1036.                 $result = $xpath->query( './/div[@class="comment"]', $row );
  1037.                 $transaction[ 'comment' ] = trim( $result->item( 0 )->nodeValue );
  1038.  
  1039.                 // Направление
  1040.                 $result = $xpath->query( './/div[@class="IncomeWithExpend income"]', $row );
  1041.                 $transaction[ 'incoming' ] = ( $result->length > 0 ) ? true : false;
  1042.  
  1043.                 $transactions[] = $transaction;
  1044.  
  1045.             }
  1046.  
  1047.         }
  1048.  
  1049.         return $transactions;
  1050.  
  1051.     }
  1052.  
  1053.     /**
  1054.      *
  1055.      * Покупает ваучер
  1056.      *
  1057.      * @param float              $amount                Сумма
  1058.      * @param string             $sourceCurrency        Счет, с которого будет произведена оплата(RUB, KZT, USD, EUR)
  1059.      * @param string             $comment               Необязательный комментарий
  1060.      *
  1061.      * @throws Exception         В случае ошибок выкидывает исключения
  1062.      *
  1063.      * @return string            Возвращает код купленного ваучера
  1064.      *
  1065.      */
  1066.     public function buyEgg( $amount, $sourceCurrency, $comment = '' )
  1067.     {
  1068.  
  1069.         // Проверка валюты
  1070.         $this->getCurrencyCode( $sourceCurrency );
  1071.  
  1072.         // $ и центы
  1073.         $cash = explode( '.', number_format( $amount, 2, '.', '' ) );
  1074.  
  1075.         // Загрузить форму
  1076.         $response = $this->request( 'https://qiwi.com/eggs/buy/content/form.action' );
  1077.  
  1078.         // Получить первый токен
  1079.         $data = array(
  1080.             'extra' => array(
  1081.                 '\'to_account\'' => '',
  1082.                 '\'to_account_type\'' => 'undefind',
  1083.                 '\'account\'' => '708',
  1084.                 '\'comment\'' => $comment
  1085.             ),
  1086.             'source' => 'qiwi_' . $sourceCurrency,
  1087.             'amountInteger' => $cash[ 0 ],
  1088.             'amountFraction' => $cash[ 1 ],
  1089.             'currency' => 'RUB',
  1090.             'state' => 'CONFIRM',
  1091.             'protected' => 'true'
  1092.  
  1093.         );
  1094.  
  1095.         $response = $this->request( 'https://qiwi.com/user/payment/form/state.action', $data );
  1096.         if( !preg_match( '/name=\"token\" value=\"([\-0-9]+)\"/i', $response, $matches ) )
  1097.         {
  1098.  
  1099.             throw new Exception( 'Не удалось получить токен для открытия подтверждения покупки ваучера' );
  1100.  
  1101.         }
  1102.  
  1103.         $data[ 'token' ] = $matches[ 1 ];
  1104.         $data[ 'expire_days' ] = '2';
  1105.  
  1106.         // Точно ли это страница с кнопкой подтвердить
  1107.         $response = $this->request( 'https://qiwi.com/user/payment/form/state.action', $data );
  1108.         if( strpos( 'Подтвердить', $response ) )
  1109.         {
  1110.  
  1111.             throw new Exception( 'Не удалось перейти к подтверждению покупки ваучера' );
  1112.  
  1113.         }
  1114.  
  1115.         // И собственно подтверждение перевода
  1116.         $data = array(
  1117.             'state' => 'PAY'
  1118.         );
  1119.  
  1120.         $response = $this->request( 'https://qiwi.com/user/payment/form/state.action', $data );
  1121.         if( !preg_match( '/name=\"token\" value=\"([\-0-9]+)\"/i', $response, $matches ) )
  1122.         {
  1123.  
  1124.             throw new Exception( 'Не удалось получить токен для подтверждения оплаты ваучера' );
  1125.  
  1126.         }
  1127.  
  1128.         $data[ 'token' ] = $matches[ 1 ];
  1129.  
  1130.         // Получение кода ваучера
  1131.         $response = $this->request( 'https://qiwi.com/user/payment/form/state.action', $data );
  1132.         if( !preg_match( '/Код ваучера: ([a-z0-9]+)/i', $response, $matches ) )
  1133.         {
  1134.  
  1135.             throw new Exception( 'Не удалось получить токен для подтверждения оплаты ваучера' );
  1136.  
  1137.         }
  1138.  
  1139.         return $matches[ 1 ];
  1140.  
  1141.     }
  1142.  
  1143.     /**
  1144.      *
  1145.      * Активирует ваучер
  1146.      *
  1147.      * @param string   $code             Необязательный комментарий
  1148.      *
  1149.      * @throws Exception                 В случае ошибок выкидывает исключения
  1150.      *
  1151.      * @return array                     Возвращает массив c информацией об активированном ваучере
  1152.      *
  1153.      */
  1154.     public function activateEgg( $code )
  1155.     {
  1156.  
  1157.         // Активация
  1158.         $data = array(
  1159.             'code' => $code
  1160.         );
  1161.  
  1162.         $response = $this->request( 'https://qiwi.com/user/eggs/activate/content/form.action', $data );
  1163.         if( !preg_match( '/name=\"token\" value=\"([\-0-9]+)\"/i', $response, $matches ) )
  1164.         {
  1165.  
  1166.             throw new Exception( 'Не удалось получить токен для открытия подтверждения активации ваучера' );
  1167.  
  1168.         }
  1169.  
  1170.         $data[ 'token' ] = $matches[ 1 ];
  1171.  
  1172.         $response = $this->request( 'https://qiwi.com/user/eggs/activate/content/form.action', $data );
  1173.         if( !preg_match( '/<h2>(.*)<\/h2>/is', $response, $matches ) )
  1174.         {
  1175.  
  1176.             throw new Exception( 'Не удалось определить сумму ваучера' );
  1177.  
  1178.         }
  1179.  
  1180.         $info = array(
  1181.             'cash' => $this->parseFloatFromCash( $matches[ 1 ] ),
  1182.             'currency' => $this->determineCurrencyFromCash( $matches[ 1 ] )
  1183.         );
  1184.  
  1185.         $json = @json_decode( $this->request( 'https://qiwi.com/user/eggs/activate/content/activate.action', $data, array(
  1186.                 CURLOPT_HTTPHEADER => array(
  1187.                     'Accept: application/json, text/javascript, */*; q=0.01',
  1188.                     'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1189.                     'DNT: 1'
  1190.                 )
  1191.             )
  1192.         )
  1193.         );
  1194.  
  1195.         if( !isset( $json->code->value ) || $json->code->value != '0' )
  1196.         {
  1197.  
  1198.             throw new Exception( 'Не удалось активировать ваучер' );
  1199.  
  1200.         }
  1201.  
  1202.         return $info;
  1203.  
  1204.     }
  1205.  
  1206.     /**
  1207.      *
  1208.      * Выставляет счет
  1209.      *
  1210.      * @param string             $to           Кому выставляется счет
  1211.      * @param float              $amount       Сумма
  1212.      * @param string             $currency     Валюта
  1213.      * @param string             $comment      Необязательный комментарий
  1214.      *
  1215.      * @throws Exception         В случае ошибок выкидывает исключения
  1216.      *
  1217.      * @return void
  1218.      *
  1219.      */
  1220.     public function createInvoice( $to, $amount, $currency, $comment = '' )
  1221.     {
  1222.  
  1223.         // Загрузить форму
  1224.         $this->request( 'https://qiwi.com/order/form.action' );
  1225.  
  1226.         // Рубли и копейки
  1227.         $cash = explode( '.', number_format( $amount, 2, '.', '' ) );
  1228.  
  1229.         // Получение токена
  1230.         $data = array(
  1231.             'to' => $to,
  1232.             'value' => $cash[ 0 ],
  1233.             'change' => $cash[ 1 ],
  1234.             'amount' => $amount,
  1235.             'currency' => $currency,
  1236.             'comment' => $comment
  1237.         );
  1238.  
  1239.         $json = @json_decode(
  1240.             $this->request( 'https://qiwi.com/user/order/create.action', $data, array(
  1241.                     CURLOPT_HTTPHEADER => array(
  1242.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1243.                         'DNT: 1',
  1244.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1245.                         'X-Requested-With: XMLHttpRequest',
  1246.                     )
  1247.                 )
  1248.             )
  1249.         );
  1250.  
  1251.         if( !isset( $json->data->token ) || !preg_match( '/([0-9]+)/', $json->data->token ) )
  1252.         {
  1253.  
  1254.             throw new Exception(  'Не удалось получить токен для выставления счета' );
  1255.  
  1256.         }
  1257.  
  1258.         // Собственно выставление
  1259.         $data[ 'token' ] = $json->data->token;
  1260.  
  1261.         $json = @json_decode(
  1262.             $this->request( 'https://qiwi.com/user/order/create.action', $data, array(
  1263.                     CURLOPT_HTTPHEADER => array(
  1264.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1265.                         'DNT: 1',
  1266.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1267.                         'X-Requested-With: XMLHttpRequest',
  1268.                     )
  1269.                 )
  1270.             )
  1271.         );
  1272.  
  1273.         if( !isset( $json->code->value ) )
  1274.         {
  1275.  
  1276.             throw new Exception(  'Неверный формат ответа QIWI при выставлении счета' );
  1277.  
  1278.         } elseif( $json->code->value != '0' ) {
  1279.  
  1280.             if( isset( $json->message ) )
  1281.             {
  1282.  
  1283.                 throw new Exception( $json->message );
  1284.  
  1285.             } else {
  1286.  
  1287.                 throw new Exception( 'Неизвестная ошибка при выставлении счета' );
  1288.  
  1289.             }
  1290.  
  1291.         }
  1292.  
  1293.     }
  1294.  
  1295.     /**
  1296.      *
  1297.      * Получает список входящих счетов
  1298.      *
  1299.      * @param string             $start         От какой даты
  1300.      * @param string             $finish        До какой даты
  1301.      *
  1302.      * @throws Exception         В случае ошибок выкидывает исключения
  1303.      *
  1304.      * @return array             Возвращает массив со счетами
  1305.      *
  1306.      */
  1307.     public function listInvoices( $start, $finish )
  1308.     {
  1309.  
  1310.         // Текущий номер
  1311.         $person = $this->getPerson();
  1312.  
  1313.         $data = array(
  1314.             'daterange' => 'true',
  1315.             'start' => $start,
  1316.             'finish' => $finish
  1317.         );
  1318.  
  1319.         $data[ 'conditions.directions' ][] = 'in';
  1320.         $data[ 'conditions.directions' ][] = 'out';
  1321.  
  1322.         $response = $this->request( 'https://qiwi.com/user/order/list.action', $data );
  1323.  
  1324.         $doс = new DOMDocument();
  1325.  
  1326.         if( !$doс->loadHTML( mb_convert_encoding( $response, 'HTML-ENTITIES', 'UTF-8' ) ) )
  1327.         {
  1328.  
  1329.             foreach ( libxml_get_errors() as $error )
  1330.             {
  1331.  
  1332.                 throw new Exception( $error->message );
  1333.  
  1334.             }
  1335.  
  1336.             libxml_clear_errors();
  1337.  
  1338.         }
  1339.  
  1340.         $unpaid = array();
  1341.  
  1342.         // Оплаченные, отмененные, неоплаченные
  1343.         $xpath = new DOMXpath( $doс );
  1344.         $results = $xpath->query('//div[contains(@class, "PAID") or contains(@class, "CANCELED")]');
  1345.  
  1346.         if( $results->length > 0 )
  1347.         {
  1348.  
  1349.             foreach( $results as $row )
  1350.             {
  1351.  
  1352.                 $invoice = array( );
  1353.  
  1354.                 $invoice[ 'state' ] = substr( $row->getAttribute( 'class' ), 18 );
  1355.  
  1356.                 // ID (есть только у неоплаченных)
  1357.                 if( $invoice[ 'state' ] == 'NOT_PAID' )
  1358.                 {
  1359.  
  1360.                     $result = $xpath->query( './/div[@class="cancelOperation"]', $row );
  1361.                     $data_params_attribute = $result->item( 0 )->getAttribute( 'data-params' );
  1362.                     if( !preg_match( '/{"data":{"order":"([0-9]+)"}}/', $data_params_attribute, $matches ) )
  1363.                     {
  1364.  
  1365.                         continue;
  1366.  
  1367.                     }
  1368.  
  1369.                     $invoice[ 'id' ] = $matches[ 1 ];
  1370.  
  1371.                 } else {
  1372.  
  1373.                     $invoice[ 'id' ] = 0;
  1374.  
  1375.                 }
  1376.  
  1377.                 // Номер транзакции
  1378.                 $result = $xpath->query( './/div[@class="transaction"]', $row );
  1379.                 $invoice[ 'transaction' ] = trim( $result->item( 0 )->nodeValue );
  1380.  
  1381.                 // Кому
  1382.                 $result = $xpath->query( './/div[@class="to"]', $row );
  1383.                 $to = $result->item( 0 )->nodeValue;
  1384.                 if( $to == '' )
  1385.                 {
  1386.  
  1387.                     $invoice[ 'direction' ] = 'in';
  1388.  
  1389.                 } else {
  1390.  
  1391.                     $invoice[ 'direction' ] = 'out';
  1392.  
  1393.                 }
  1394.                 $invoice[ 'to' ] = $to;
  1395.  
  1396.                 // Создано
  1397.                 $result = $xpath->query( './/div[@class="orderCreationDate"]', $row );
  1398.                 $invoice[ 'orderCreationDate' ] = trim( $result->item( 0 )->nodeValue );
  1399.  
  1400.                 // От кого
  1401.                 $result = $xpath->query( './/div[@class="from"]/span', $row );
  1402.                 $invoice[ 'from' ] = trim( $result->item( 0 )->nodeValue );
  1403.  
  1404.                 // Комментарий
  1405.                 $result = $xpath->query( './/span[@class="commentItem"]', $row );
  1406.                 $invoice[ 'comment' ] = trim( $result->item( 0 )->nodeValue );
  1407.  
  1408.                 // Сумма
  1409.                 $result = $xpath->query( './/div[@class="amount"]', $row );
  1410.                 $invoice[ 'cash' ] = str_replace( ',', '.', $this->parseFloatFromCash( trim( $result->item( 0 )->nodeValue ) ) );
  1411.  
  1412.                 // Валюта прихода
  1413.                 $invoice[ 'currency' ] = $this->determineCurrencyFromCash( $result->item( 0 )->nodeValue );
  1414.  
  1415.                 $unpaid[] = $invoice;
  1416.  
  1417.             }
  1418.  
  1419.         }
  1420.  
  1421.         return $unpaid;
  1422.  
  1423.     }
  1424.  
  1425.     /**
  1426.      *
  1427.      * Оплачивает счет
  1428.      *
  1429.      * @param int                $id           ID счета
  1430.      * @param string             $currency     Валюта
  1431.      *
  1432.      * @throws Exception         В случае ошибок выкидывает исключения
  1433.      *
  1434.      * @return void
  1435.      *
  1436.      */
  1437.     public function payInvoice( $id, $currency = 'RUB' )
  1438.     {
  1439.  
  1440.         // Загрузка формы оплаты
  1441.         $data = array(
  1442.             'order' => $id
  1443.         );
  1444.  
  1445.         $this->request( 'https://qiwi.com/user/order/payment.action', $data );
  1446.  
  1447.         // Получение токена
  1448.         $data[ 'source' ] = 'qiwi_' . $currency;
  1449.  
  1450.         $json = @json_decode(
  1451.             $this->request( 'https://qiwi.com/user/order/accept.action', $data, array(
  1452.                     CURLOPT_HTTPHEADER => array(
  1453.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1454.                         'DNT: 1',
  1455.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1456.                         'X-Requested-With: XMLHttpRequest',
  1457.                     )
  1458.                 )
  1459.             )
  1460.         );
  1461.  
  1462.         if( !isset( $json->data->token ) || !preg_match( '/([0-9]+)/', $json->data->token ) )
  1463.         {
  1464.  
  1465.             throw new Exception(  'Не удалось получить токен для выставления счета' );
  1466.  
  1467.         }
  1468.  
  1469.         // Собственно выставление
  1470.         $data[ 'token' ] = $json->data->token;
  1471.  
  1472.         $json = @json_decode(
  1473.             $this->request( 'https://qiwi.com/user/order/accept.action', $data, array(
  1474.                     CURLOPT_HTTPHEADER => array(
  1475.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1476.                         'DNT: 1',
  1477.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1478.                         'X-Requested-With: XMLHttpRequest',
  1479.                     )
  1480.                 )
  1481.             )
  1482.         );
  1483.  
  1484.         if( !isset( $json->code->value ) )
  1485.         {
  1486.  
  1487.             throw new Exception(  'Неверный формат ответа QIWI при выставлении счета' );
  1488.  
  1489.         } elseif( $json->code->value != '5' ) {
  1490.  
  1491.             if( isset( $json->message ) )
  1492.             {
  1493.  
  1494.                 throw new Exception( $json->message );
  1495.  
  1496.             } else {
  1497.  
  1498.                 throw new Exception( 'Неизвестная ошибка при выставлении счета' );
  1499.  
  1500.             }
  1501.  
  1502.         }
  1503.  
  1504.     }
  1505.  
  1506.     /**
  1507.      *
  1508.      * Первый этап регистрации.
  1509.      *
  1510.      * Загружает форму и картику с кодом. Картинка по умолчанию сохраняется в signup_captcha.png.
  1511.      *
  1512.      * @param string             $path     Путь к картинке
  1513.      *
  1514.      * @throws Exception         В случае ошибок выкидывает исключения
  1515.      *
  1516.      * @return void
  1517.      *
  1518.      */
  1519.     public function signupStepOne( $path = 'signup_captcha.png' )
  1520.     {
  1521.  
  1522.         // Есть ли файл уже?
  1523.         if( !file_exists( $path ) )
  1524.         {
  1525.  
  1526.             $pathDir = dirname( $path );
  1527.             // Если нет, то можно ли писать в папку?
  1528.             if( !is_writable( $pathDir ) )
  1529.             {
  1530.  
  1531.                 throw new Exception( 'Не могу сохранить картинку с капчей в ' . $path );
  1532.  
  1533.             }
  1534.  
  1535.             // можно ли в файл писать?
  1536.         } elseif( !is_writable( $path ) ) {
  1537.  
  1538.             throw new Exception( 'Не могу сохранить картинку с капчей в ' . $path );
  1539.  
  1540.         }
  1541.  
  1542.         // Загрузка формы
  1543.         $response = $this->request( 'https://qiwi.com/register/form.action' );
  1544.  
  1545.         // Загрузка капчи
  1546.         file_put_contents( $path, $this->request( 'https://qiwi.com/register/captcha.action?random=0.' . time() ) );
  1547.  
  1548.         // Проверка капчи
  1549.         $finfo = finfo_open( FILEINFO_MIME_TYPE );
  1550.         $mime = finfo_file( $finfo, $path );
  1551.  
  1552.         if( $mime != 'image/png' )
  1553.         {
  1554.  
  1555.             throw new Exception( 'Не удалось загрузить картинку с капчей' );
  1556.  
  1557.         }
  1558.  
  1559.     }
  1560.  
  1561.     /**
  1562.      *
  1563.      * Второй этап регистрации.
  1564.      *
  1565.      * Отправляет заявку на регистрацию.
  1566.      *
  1567.      * @param string             $phone      Телефон
  1568.      * @param string             $captcha    Код с картинки из Qiwi::signupStepOne()
  1569.      *
  1570.      * @throws Exception         В случае ошибок выкидывает исключения
  1571.      *
  1572.      * @return int               Уникальный идентификатор заявки на регистрацию. Нужен для ее завершения в Qiwi::signupStepThree()
  1573.      *
  1574.      */
  1575.     public function signupStepTwo( $phone, $captcha )
  1576.     {
  1577.  
  1578.         if( $phone[ 0 ] != '+' )
  1579.             $phone = '+' . $phone;
  1580.  
  1581.         $data = array(
  1582.             'login' => $phone,
  1583.             'captcha' => $captcha,
  1584.             'agreement' => 'true'
  1585.         );
  1586.  
  1587.         $json = @json_decode(
  1588.             $this->request( 'https://qiwi.com/register/main.action', $data, array(
  1589.                     CURLOPT_HTTPHEADER => array(
  1590.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1591.                         'DNT: 1',
  1592.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1593.                         'X-Requested-With: XMLHttpRequest',
  1594.                     )
  1595.                 )
  1596.             )
  1597.         );
  1598.  
  1599.         if( !isset( $json->data->token ) || !preg_match( '/([0-9]+)/', $json->data->token ) )
  1600.         {
  1601.  
  1602.             throw new Exception(  'Не удалось получить токен для начала регистрации' );
  1603.  
  1604.         }
  1605.  
  1606.         // Собственно выставление
  1607.         $data[ 'token' ] = $json->data->token;
  1608.  
  1609.         $json = @json_decode(
  1610.             $this->request( 'https://qiwi.com/register/main.action', $data, array(
  1611.                     CURLOPT_HTTPHEADER => array(
  1612.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1613.                         'DNT: 1',
  1614.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1615.                         'X-Requested-With: XMLHttpRequest',
  1616.                     )
  1617.                 )
  1618.             )
  1619.         );
  1620.  
  1621.         if( !isset( $json->data ) || is_object( $json->data ) || !preg_match( '/([0-9]+)/', $json->data ) )
  1622.         {
  1623.  
  1624.             if( isset( $json->message ) )
  1625.             {
  1626.  
  1627.                 throw new Exception( $json->message );
  1628.  
  1629.             } else {
  1630.  
  1631.                 throw new Exception(  'Не удалось получить уникальный идентификатор этого процесса регистрации' );
  1632.  
  1633.             }
  1634.  
  1635.         }
  1636.  
  1637.         return $json->data;
  1638.  
  1639.     }
  1640.  
  1641.     /**
  1642.      *
  1643.      * Третий этап регистрации.
  1644.      *
  1645.      * Подтверждает регистрацию с SMS.
  1646.      *
  1647.      * @param int                $identifier      Код, полученный из Qiwi::signupStepTwo()
  1648.      * @param int                $smsCode         Код из SMS
  1649.      * @param string             $phone           Телефон
  1650.      * @param string             $passwd          Пароль
  1651.      * @param int                $period          Cрок действия 1/3/6/12 месяцев
  1652.      *
  1653.      * @throws Exception         В случае ошибок выкидывает исключения
  1654.      *
  1655.      * @return void
  1656.      *
  1657.      */
  1658.     public function signupStepThree( $identifier, $smsCode, $phone, $passwd, $period = 12 )
  1659.     {
  1660.  
  1661.         $periodCodes = array(
  1662.             1 => 1,
  1663.             3 => 2,
  1664.             6 => 3,
  1665.             12 => 4
  1666.         );
  1667.  
  1668.         if( $phone[ 0 ] != '+' )
  1669.             $phone = '+' . $phone;
  1670.  
  1671.         $data = array(
  1672.             'identifier' => $identifier,
  1673.             'type' => 'REGISTER',
  1674.             'phone' => $phone,
  1675.             'code' => $smsCode,
  1676.             'data[\'login\']' => $phone,
  1677.             'data[\'newPassword\']' => $passwd,
  1678.             'data[\'newPasswordRepeat\']' => $passwd,
  1679.             'data[\'period\']' => $periodCodes[ $period ],
  1680.  
  1681.         );
  1682.  
  1683.         $json = @json_decode(
  1684.             $this->request( 'https://qiwi.com/confirmation/confirm.action', $data, array(
  1685.                     CURLOPT_HTTPHEADER => array(
  1686.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1687.                         'DNT: 1',
  1688.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1689.                         'X-Requested-With: XMLHttpRequest',
  1690.                         'Referer: https://qiwi.com/register/password.action?identifier=' . $identifier
  1691.                     )
  1692.                 )
  1693.             )
  1694.         );
  1695.  
  1696.         if( !isset( $json->code->value ) || $json->code->value != '0' )
  1697.         {
  1698.  
  1699.             if( isset( $json->message ) )
  1700.             {
  1701.  
  1702.                 throw new Exception( $json->message );
  1703.  
  1704.             } else {
  1705.  
  1706.                 throw new Exception(  'Неизвестная ошибка при регистрации' );
  1707.  
  1708.             }
  1709.  
  1710.         }
  1711.  
  1712.     }
  1713.  
  1714.     /**
  1715.      *
  1716.      * Запрос привязки почты
  1717.      *
  1718.      * @param string             $email           Почта
  1719.      *
  1720.      * @throws Exception         В случае ошибок выкидывает исключения
  1721.      *
  1722.      * @return void
  1723.      *
  1724.      */
  1725.     public function requestEmailConfirmation( $email )
  1726.     {
  1727.  
  1728.         // Получение токена
  1729.         $data = array(
  1730.             'mail' => $email,
  1731.         );
  1732.  
  1733.         $json = @json_decode(
  1734.             $this->request( 'https://qiwi.com/user/person/email/create/send.action', $data, array(
  1735.                     CURLOPT_HTTPHEADER => array(
  1736.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1737.                         'DNT: 1',
  1738.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1739.                         'X-Requested-With: XMLHttpRequest',
  1740.                     )
  1741.                 )
  1742.             )
  1743.         );
  1744.  
  1745.         if( !isset( $json->data->token ) || !preg_match( '/([0-9]+)/', $json->data->token ) )
  1746.         {
  1747.  
  1748.             throw new Exception(  'Не удалось получить токен для запроса привязки почты' );
  1749.  
  1750.         }
  1751.  
  1752.         // Собственно запрос
  1753.         $data[ 'token' ] = $json->data->token;
  1754.  
  1755.         $json = @json_decode(
  1756.             $this->request( 'https://qiwi.com/user/person/email/create/send.action', $data, array(
  1757.                     CURLOPT_HTTPHEADER => array(
  1758.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1759.                         'DNT: 1',
  1760.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1761.                         'X-Requested-With: XMLHttpRequest',
  1762.                     )
  1763.                 )
  1764.             )
  1765.         );
  1766.  
  1767.         if( !isset( $json->code->value ) )
  1768.         {
  1769.  
  1770.             throw new Exception(  'Неверный формат ответа QIWI при запросе привязки почты' );
  1771.  
  1772.         } elseif( $json->code->value != '0' ) {
  1773.  
  1774.             if( isset( $json->message ) )
  1775.             {
  1776.  
  1777.                 throw new Exception( $json->message );
  1778.  
  1779.             } else {
  1780.  
  1781.                 throw new Exception( 'Неизвестная ошибка при запросе привязки почты' );
  1782.  
  1783.             }
  1784.  
  1785.         }
  1786.  
  1787.     }
  1788.  
  1789.     /**
  1790.      *
  1791.      * Подтверждает привязку почты
  1792.      *
  1793.      * @param string             $code           Код подтверждения с почты
  1794.      *
  1795.      * @throws Exception         В случае ошибок выкидывает исключения
  1796.      *
  1797.      * @return void
  1798.      *
  1799.      */
  1800.     public function confirmEmail( $code )
  1801.     {
  1802.  
  1803.         $response = $this->request( 'https://qiwi.com/settings/options/security/email/create.action?code=' . $code );
  1804.         if( !strpos( $response, 'привязана' ) )
  1805.         {
  1806.  
  1807.             throw new Exception( 'Ошибка при привязке почты' );
  1808.  
  1809.         }
  1810.  
  1811.     }
  1812.  
  1813.     /**
  1814.      *
  1815.      * Запрос на изменение настроек безопасности
  1816.      *
  1817.      * SMS_CONFIRMATION - Подтверждение платежей по SMS
  1818.      * TOKEN - Приложения Visa QIWI Wallet
  1819.      * PIN - Доступ в терминалах QIWI по PIN коду
  1820.      * SMS_PAYMENT - SMS платежи
  1821.      * CALL_CONFIRMATION - Подтверждение по USSD (Терминалы QIWI)
  1822.      *
  1823.      * @param  string       $type             Код настройки(SMS_CONFIRMATION/TOKEN/PIN/SMS_PAYMENT/CALL_CONFIRMATION)
  1824.      * @param  string       $value            true/false
  1825.      *
  1826.      * @throws Exception         В случае ошибок выкидывает исключения
  1827.      *
  1828.      * @return int               Идентификатор заявки на отлючение
  1829.      *
  1830.      * @see Qiwi::confirmSecurityChange()
  1831.      *
  1832.      */
  1833.     public function requestSecurityChange( $type, $value )
  1834.     {
  1835.  
  1836.         // Получение токена
  1837.         $data = array(
  1838.             'type' => $type,
  1839.             'value' => $value
  1840.         );
  1841.  
  1842.         $json = @json_decode(
  1843.             $this->request( 'https://qiwi.com/user/person/change/security.action', $data, array(
  1844.                     CURLOPT_HTTPHEADER => array(
  1845.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1846.                         'DNT: 1',
  1847.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1848.                         'X-Requested-With: XMLHttpRequest',
  1849.                     )
  1850.                 )
  1851.             )
  1852.         );
  1853.  
  1854.         if( !isset( $json->data->token ) || !preg_match( '/([0-9]+)/', $json->data->token ) )
  1855.         {
  1856.  
  1857.             throw new Exception(  'Не удалось получить токен для запроса на отключение ' . $type );
  1858.  
  1859.         }
  1860.  
  1861.         // Собственно запрос
  1862.         $data[ 'token' ] = $json->data->token;
  1863.  
  1864.         $json = @json_decode(
  1865.             $this->request( 'https://qiwi.com/user/person/change/security.action', $data, array(
  1866.                     CURLOPT_HTTPHEADER => array(
  1867.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1868.                         'DNT: 1',
  1869.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1870.                         'X-Requested-With: XMLHttpRequest',
  1871.                     )
  1872.                 )
  1873.             )
  1874.         );
  1875.  
  1876.         if( !isset( $json->code->value ) )
  1877.         {
  1878.  
  1879.             throw new Exception(  'Неверный формат ответа QIWI при запросе на отключение ' . $type );
  1880.  
  1881.         } elseif( $json->code->value == '0' && isset( $json->identifier ) ) {
  1882.  
  1883.             return $json->identifier;
  1884.  
  1885.         } elseif( $json->code->value == '4' && isset( $json->identifier ) ) {
  1886.  
  1887.             $this->requestId = $json->identifier;
  1888.  
  1889.             throw new Exception( 'AwaitingSMSConfirmation' );
  1890.  
  1891.         } else {
  1892.  
  1893.             if( isset( $json->message ) )
  1894.             {
  1895.  
  1896.                 throw new Exception( $json->message );
  1897.  
  1898.             } else {
  1899.  
  1900.                 throw new Exception( 'Неизвестная ошибка при запросе на отключение ' . $type );
  1901.  
  1902.             }
  1903.  
  1904.         }
  1905.  
  1906.     }
  1907.  
  1908.     /**
  1909.      *
  1910.      * Подтверждение изменения настроек безопасности
  1911.      *
  1912.      * SMS_CONFIRMATION - Подтверждение платежей по SMS
  1913.      * TOKEN - Приложения Visa QIWI Wallet
  1914.      * PIN - Доступ в терминалах QIWI по PIN коду
  1915.      * SMS_PAYMENT - SMS платежи
  1916.      * CALL_CONFIRMATION - Подтверждение по USSD (Терминалы QIWI)
  1917.      *
  1918.      * @param  string       $type              Код настройки(SMS_CONFIRMATION/TOKEN/PIN/SMS_PAYMENT/CALL_CONFIRMATION)
  1919.      * @param int           $identifier        Идентивикатор заявки, полученный из Qiwi::requestSecurityChange()
  1920.      * @param int           $smsCode           Код из SMS
  1921.      *
  1922.      * @throws Exception                В случае ошибок выкидывает исключения
  1923.      *
  1924.      * @return void
  1925.      *
  1926.      * @see Qiwi::requestSecurityChange()
  1927.      *
  1928.      */
  1929.     public function confirmSecurityChange( $type, $identifier, $smsCode )
  1930.     {
  1931.  
  1932.         $data = array(
  1933.             'identifier' => $identifier,
  1934.             'type' => $type,
  1935.             'code' => $smsCode
  1936.         );
  1937.  
  1938.         $json = @json_decode(
  1939.             $this->request( 'https://qiwi.com/user/confirmation/confirm.action', $data, array(
  1940.                     CURLOPT_HTTPHEADER => array(
  1941.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1942.                         'DNT: 1',
  1943.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  1944.                         'X-Requested-With: XMLHttpRequest',
  1945.                     )
  1946.                 )
  1947.             )
  1948.         );
  1949.  
  1950.         if( !isset( $json->code->value ) )
  1951.         {
  1952.  
  1953.             throw new Exception(  'Неверный формат ответа QIWI при подтверждении изменения ' . $type );
  1954.  
  1955.         } elseif( $json->code->value != '0' ) {
  1956.  
  1957.             if( isset( $json->message ) )
  1958.             {
  1959.  
  1960.                 throw new Exception( $json->message );
  1961.  
  1962.             } else {
  1963.  
  1964.                 throw new Exception( 'Неизвестная ошибка при подтверждении изменения ' . $type );
  1965.  
  1966.             }
  1967.  
  1968.         }
  1969.  
  1970.     }
  1971.  
  1972.     /**
  1973.      *
  1974.      * Создает заявку на смену пароля.
  1975.      *
  1976.      * Полученный идентификатор заявки надо передать в QiwiWallet::confirmPasswordChange()
  1977.      *
  1978.      * @throws Exception                      В случае ошибок выкидывает исключения
  1979.      *
  1980.      * @return int                            Идентификатор заявки
  1981.      *
  1982.      * @see QiwiWallet::confirmPasswordChange()
  1983.      *
  1984.      */
  1985.     public function requestPasswordChange( )
  1986.     {
  1987.  
  1988.         $json = @json_decode(
  1989.             $this->request( 'https://qiwi.com/user/person/change/password.action', array( 0 ), array(
  1990.                     CURLOPT_HTTPHEADER => array(
  1991.                         'Accept: application/json, text/javascript, */*; q=0.01',
  1992.                         'X-Requested-With: XMLHttpRequest',
  1993.                     )
  1994.                 )
  1995.             )
  1996.         );
  1997.  
  1998.         if( !isset( $json->identifier ) || !preg_match( '/([0-9]+)/', $json->identifier ) )
  1999.         {
  2000.  
  2001.             throw new Exception(  'Не удалось создать заявку на смену пароля' );
  2002.  
  2003.         }
  2004.  
  2005.         return $json->identifier;
  2006.  
  2007.     }
  2008.  
  2009.     /**
  2010.      *
  2011.      * Подтверждает заявку на смену пароля.
  2012.      *
  2013.      * @param  int          $identifier       Идентификатор заявки, полученный в QiwiWallet::requestPasswordChange()
  2014.      * @param  string       $old              Старый пароль
  2015.      * @param  string       $new              Новый пароль
  2016.      * @param  int          $period           Cрок действия 1/3/6/12 месяцев
  2017.      * @param  int          $code             Код из SMS
  2018.      *
  2019.      * @throws Exception                      В случае ошибок выкидывает исключения
  2020.      *
  2021.      * @return void
  2022.      *
  2023.      * @see QiwiWallet::confirmPasswordChange()
  2024.      *
  2025.      */
  2026.     public function confirmPasswordChange( $identifier, $old, $new, $period, $code )
  2027.     {
  2028.  
  2029.         $periodCodes = array(
  2030.             1 => 1,
  2031.             3 => 2,
  2032.             6 => 3,
  2033.             12 => 4
  2034.         );
  2035.  
  2036.         $data = array(
  2037.             'identifier' => $identifier,
  2038.             'type' => 'PASSWORD_CHANGE',
  2039.             'code' => $code,
  2040.             'data[\'oldPassword\']' => $old,
  2041.             'data[\'newPassword\']' => $new,
  2042.             'data[\'period\']' => $periodCodes[ $period ],
  2043.         );
  2044.  
  2045.         $json = @json_decode(
  2046.             $this->request( 'https://qiwi.com/user/confirmation/confirm.action', $data, array(
  2047.                     CURLOPT_HTTPHEADER => array(
  2048.                         'Accept: application/json, text/javascript, */*; q=0.01',
  2049.                         'DNT: 1',
  2050.                         'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  2051.                         'X-Requested-With: XMLHttpRequest',
  2052.                     )
  2053.                 )
  2054.             )
  2055.         );
  2056.  
  2057.         if( !isset( $json->code->value ) )
  2058.         {
  2059.  
  2060.             throw new Exception(  'Неверный формат ответа QIWI при подтверждении изменения ' . $type );
  2061.  
  2062.         } elseif( $json->code->value != '0' ) {
  2063.  
  2064.             if( isset( $json->message ) )
  2065.             {
  2066.  
  2067.                 throw new Exception( $json->message );
  2068.  
  2069.             } else {
  2070.  
  2071.                 throw new Exception( 'Неизвестная ошибка при подтверждении изменения ' . $type );
  2072.  
  2073.             }
  2074.  
  2075.         }
  2076.  
  2077.     }
  2078.  
  2079.     /**
  2080.      *
  2081.      * Отправляет данные о пользователе для упрощенной идентификации
  2082.      *
  2083.      * @param  string       $firstName         Имя
  2084.      * @param  string       $lastName          Фамилия
  2085.      * @param  string       $middleName        Отчество
  2086.      * @param  string       $birthDate         Дата рождения (ДД.ММ.ГГГГ)
  2087.      * @param  int          $passport          Номер и серия паспорта
  2088.      * @param  int          $inn               ИНН
  2089.      * @param  int          $snils             СНИЛС
  2090.      * @param  int          $oms               Полис ОМС
  2091.      *
  2092.      * @throws Exception                В случае ошибок выкидывает исключения
  2093.      *
  2094.      * @return void
  2095.      *
  2096.      */
  2097.     public function identificationLevelTwo( $firstName, $lastName, $middleName, $birthDate, $passport, $inn, $snils, $oms )
  2098.     {
  2099.  
  2100.         // Запрос тикета
  2101.         $json = @json_decode( $this->requestJSON( 'https://sso.qiwi.com/cas/tgts' ) );
  2102.         if( !isset( $json->entity->ticket ) || !isset( $json->links[0]->href ) )
  2103.         {
  2104.  
  2105.             throw new Exception( 'QIWI не отвечает (sso tgts при идентификации)' );
  2106.  
  2107.         }
  2108.  
  2109.         $tgtsTicket = $json->entity->ticket;
  2110.  
  2111.         // Отправка тикета
  2112.         $data = array(
  2113.             'ticket' => $tgtsTicket,
  2114.             'service' => 'https://qiwi.com/j_spring_cas_security_check'
  2115.         );
  2116.  
  2117.         $json = @json_decode( $this->requestJSON( 'https://sso.qiwi.com/cas/sts', $data ) );
  2118.         if( !isset( $json->entity->ticket ) )
  2119.         {
  2120.  
  2121.             throw new Exception( 'QIWI не отвечает (sso sts при идентификации)' );
  2122.  
  2123.         }
  2124.  
  2125.         // PUT
  2126.         $data = array(
  2127.             'firstName' => $firstName,
  2128.             'lastName' => $lastName,
  2129.             'middleName' => $middleName,
  2130.             'birthDate' => $birthDate,
  2131.             'passport' => $passport,
  2132.         );
  2133.  
  2134.         $string = json_encode( $data, JSON_FORCE_OBJECT );
  2135.  
  2136.         // Тут нужно отправить тикет, полученный в предыдущем запросе
  2137.         $response = $this->requestPUT( 'https://qiwi.com/rest/identifications/' . $this->getPerson(), $string, array(
  2138.                 CURLOPT_HTTPHEADER => array(
  2139.                     'Accept: application/json',
  2140.                     'Content-Type: application/json',
  2141.                     'Authorization: Token ' . $json->entity->ticket,
  2142.                     'Content-Length: ' . strlen( $string ),
  2143.                     'DNT: 1'
  2144.                 )
  2145.             )
  2146.         );
  2147.  
  2148.         if( $response !== 200 )
  2149.         {
  2150.  
  2151.             throw new Exception( 'Ошибка при отправке первой пачки данных идентификации' );
  2152.  
  2153.         }
  2154.  
  2155.  
  2156.         // Запрос тикета
  2157.         $json = @json_decode( $this->requestJSON( 'https://sso.qiwi.com/cas/tgts' ) );
  2158.         if( !isset( $json->entity->ticket ) || !isset( $json->links[0]->href ) )
  2159.         {
  2160.  
  2161.             throw new Exception( 'QIWI не отвечает (sso tgts при идентификации)' );
  2162.  
  2163.         }
  2164.  
  2165.         $tgtsTicket = $json->entity->ticket;
  2166.  
  2167.         // Отправка тикета
  2168.         $data = array(
  2169.             'ticket' => $tgtsTicket,
  2170.             'service' => 'https://qiwi.com/j_spring_cas_security_check'
  2171.         );
  2172.  
  2173.         $json = @json_decode( $this->requestJSON( 'https://sso.qiwi.com/cas/sts', $data ) );
  2174.         if( !isset( $json->entity->ticket ) )
  2175.         {
  2176.  
  2177.             throw new Exception( 'QIWI не отвечает (sso sts при идентификации)' );
  2178.  
  2179.         }
  2180.  
  2181.         // PUT
  2182.         $data = array(
  2183.             'inn' => $inn,
  2184.             'snils' => $snils,
  2185.             'oms' => $oms,
  2186.         );
  2187.  
  2188.         $string = json_encode( $data, JSON_FORCE_OBJECT );
  2189.  
  2190.         // Тут нужно отправить тикет, полученный в предыдущем запросе
  2191.         $response = $this->requestPUT( 'https://qiwi.com/rest/identifications/' . $this->getPerson() . '/docs', $string, array(
  2192.                 CURLOPT_HTTPHEADER => array(
  2193.                     'Accept: application/json',
  2194.                     'Content-Type: application/json',
  2195.                     'Authorization: Token ' . $json->entity->ticket,
  2196.                     'Content-Length: ' . strlen( $string ),
  2197.                     'DNT: 1'
  2198.                 )
  2199.             )
  2200.         );
  2201.  
  2202.         if( $response !== 200 )
  2203.         {
  2204.  
  2205.             throw new Exception( 'Ошибка при отправке второй пачки данных идентификации' );
  2206.  
  2207.         }
  2208.  
  2209.     }
  2210.  
  2211.     /**
  2212.      *
  2213.      * Определяет, включено ли СМС подтверждение
  2214.      *
  2215.      * Возвращает true, если смс подтверждение включено и false в противном случае(даже если не удалось загрузить страницу настроек).
  2216.      * ВНИМАНИЕ! Киви продолжает отдавать старый статус смс подтверждения вплоть до перелогина.
  2217.      *
  2218.      * @throws Exception         В случае ошибок выкидывает исключения
  2219.      *
  2220.      * @return bool
  2221.      *
  2222.      */
  2223.     public function isSmsOn ()
  2224.     {
  2225.  
  2226.         $response = $this->request( 'https://qiwi.com/settings/options/security.action' );
  2227.  
  2228.         if( $response == '' )
  2229.         {
  2230.  
  2231.             return false;
  2232.  
  2233.         }
  2234.  
  2235.         $doс = new DOMDocument();
  2236.  
  2237.         if( !$doс->loadHTML( mb_convert_encoding( $response, 'HTML-ENTITIES', 'UTF-8' ) ) )
  2238.         {
  2239.  
  2240.             foreach ( libxml_get_errors() as $error )
  2241.             {
  2242.  
  2243.                 throw new Exception( $error->message );
  2244.  
  2245.             }
  2246.  
  2247.             libxml_clear_errors();
  2248.  
  2249.         }
  2250.  
  2251.         $xpath = new DOMXpath( $doс );
  2252.         $results = $xpath->query('//div[@class="security-settings-item type_SMS_CONFIRMATION"]/div[@data-container-name="option-enabled"]');
  2253.  
  2254.         if( $results->length > 0 )
  2255.         {
  2256.  
  2257.             if( $results->item(0)->getAttribute( 'style' ) == '' )
  2258.             {
  2259.  
  2260.                 return true;
  2261.  
  2262.             }
  2263.  
  2264.         }
  2265.  
  2266.         return false;
  2267.  
  2268.     }
  2269.  
  2270.     /**
  2271.      *
  2272.      * Получает информацию о деньгах на счетах
  2273.      *
  2274.      * @throws Exception         В случае ошибок выкидывает исключения
  2275.      *
  2276.      * @return array
  2277.      *
  2278.      */
  2279.     public function wallets()
  2280.     {
  2281.  
  2282.         $info = $this->info();
  2283.  
  2284.         if( $info->code->value !== '0' || !isset( $info->data->balances ) )
  2285.         {
  2286.  
  2287.             throw new Exception( 'Не удалось получить баланс кошелька' );
  2288.  
  2289.         }
  2290.  
  2291.         return (array)$info->data->balances;
  2292.  
  2293.     }
  2294.  
  2295.     /**
  2296.      *
  2297.      * Определяет статус идентификации
  2298.      *
  2299.      * @throws Exception         В случае ошибок выкидывает исключения
  2300.      *
  2301.      * @return string|bool       Если все хорошо, вернет anonymous/standart/maximum.
  2302.      *                           Если не удалось определить, вернет false
  2303.      *
  2304.      */
  2305.     public function getStatus()
  2306.     {
  2307.  
  2308.         $response = $this->request( 'https://qiwi.com/settings.action' );
  2309.  
  2310.         $types = array( 'anonymous', 'standart', 'maximum', false );
  2311.  
  2312.         $doс = new DOMDocument();
  2313.  
  2314.         if( !$doс->loadHTML( mb_convert_encoding( $response, 'HTML-ENTITIES', 'UTF-8' ) ) )
  2315.         {
  2316.  
  2317.             foreach ( libxml_get_errors() as $error )
  2318.             {
  2319.  
  2320.                 throw new Exception( $error->message );
  2321.  
  2322.             }
  2323.  
  2324.             libxml_clear_errors();
  2325.  
  2326.         }
  2327.  
  2328.         $xpath = new DOMXpath( $doс );
  2329.         $results = $xpath->query( '//ul[@class="list_three_cols types_list"]/li' );
  2330.         $i = 0;
  2331.         if( $results->length > 0 )
  2332.         {
  2333.  
  2334.             foreach( $results as $node )
  2335.             {
  2336.  
  2337.                 if( strpos( $node->getAttribute( 'class' ), 'active' ) !== false )
  2338.                 {
  2339.  
  2340.                     break;
  2341.  
  2342.                 }
  2343.                 $i++;
  2344.  
  2345.             }
  2346.  
  2347.         } else {
  2348.  
  2349.             $i = 3;
  2350.  
  2351.         }
  2352.  
  2353.         return $types[ $i ];
  2354.  
  2355.     }
  2356.  
  2357.     /**
  2358.      *
  2359.      * Задает прокси
  2360.      *
  2361.      * @param string     $string     Например socks5://127.0.0.1:9050
  2362.      *
  2363.      * @return void
  2364.      *
  2365.      */
  2366.     public function setProxy( $string )
  2367.     {
  2368.  
  2369.         $params = parse_url( $string );
  2370.  
  2371.         $this->proxyScheme = $params[ 'scheme' ];
  2372.         $this->proxy = $string;
  2373.  
  2374.     }
  2375.  
  2376.     /**
  2377.      *
  2378.      * Устанавливает путь к файлу с куками
  2379.      *
  2380.      * @param string     $path
  2381.      *
  2382.      * @return void
  2383.      *
  2384.      */
  2385.     public function setCookieFile( $path )
  2386.     {
  2387.  
  2388.         $this->cookieFile = $path;
  2389.  
  2390.     }
  2391.  
  2392.     /**
  2393.      *
  2394.      * Удаляет файл с куками
  2395.      *
  2396.      * @return void
  2397.      *
  2398.      */
  2399.     public function removeCookieFile( )
  2400.     {
  2401.  
  2402.         unlink( $this->cookieFile );
  2403.  
  2404.     }
  2405.  
  2406.     /**
  2407.      *
  2408.      * Делает обыкновенный запрос, заворачивая данные в http_build_query
  2409.      *
  2410.      * При POST запросе отсылает следующие заголовки:
  2411.      *   'Accept: text/html,  *\/ *; q=0.01'
  2412.      *   'Content-Type: application/x-www-form-urlencoded; charset=UTF-8'
  2413.      *   'X-Requested-With: XMLHttpRequest'
  2414.      *   'DNT: 1'
  2415.      *
  2416.      * @param string     $url            Адрес
  2417.      * @param array      $postArray      Массив данных
  2418.      * @param array      $options        Массив параметров CURL
  2419.      *
  2420.      * @return string|bool
  2421.      *
  2422.      */
  2423.     public function request( $url, $postArray = null, $options = null )
  2424.     {
  2425.  
  2426.         if( is_array( $postArray ) )
  2427.         {
  2428.  
  2429.             $postArray = http_build_query( $postArray );
  2430.             $postArray = preg_replace( '/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $postArray );
  2431.  
  2432.         }
  2433.  
  2434.         $curl = curl_init();
  2435.  
  2436.         curl_setopt( $curl, CURLOPT_URL, $url );
  2437.         curl_setopt( $curl, CURLOPT_COOKIEFILE, $this->cookieFile );
  2438.         curl_setopt( $curl, CURLOPT_COOKIEJAR, $this->cookieFile );
  2439.         curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false );
  2440.         curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, false );
  2441.         curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 );
  2442.         curl_setopt( $curl, CURLOPT_HEADER, 0 );
  2443.         curl_setopt( $curl, CURLOPT_PROXY, $this->proxy );
  2444.         if( $this->proxyScheme == 'socks5' )
  2445.         {
  2446.  
  2447.             curl_setopt( $curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5 );
  2448.  
  2449.         }
  2450.  
  2451.         if( $postArray )
  2452.         {
  2453.  
  2454.             curl_setopt( $curl, CURLOPT_POST, 1 );
  2455.             curl_setopt( $curl, CURLOPT_POSTFIELDS, $postArray );
  2456.  
  2457.             curl_setopt( $curl, CURLOPT_HTTPHEADER, array (
  2458.                     'Accept: text/html, */*; q=0.01',
  2459.                     'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
  2460.                     'X-Requested-With: XMLHttpRequest',
  2461.                     'DNT: 1'
  2462.                 )
  2463.             );
  2464.  
  2465.         }
  2466.  
  2467.         if( is_array( $options ) && count( $options ) )
  2468.         {
  2469.  
  2470.             curl_setopt_array( $curl, $options );
  2471.  
  2472.         }
  2473.  
  2474.         $response = curl_exec( $curl );
  2475.  
  2476.         curl_close( $curl );
  2477.  
  2478.         if( $response === false )
  2479.         {
  2480.  
  2481.             throw new Exception( 'QIWI не отвечает на запрос' );
  2482.  
  2483.         }
  2484.  
  2485.         return $response;
  2486.  
  2487.     }
  2488.  
  2489.     /**
  2490.      *
  2491.      * Делает PUT запрос
  2492.      *
  2493.      * @param string     $url            Адрес
  2494.      * @param string     $fields         Строка с данными
  2495.      * @param array      $options        Массив параметров CURL
  2496.      *
  2497.      * @return int                       HTTP статус ответа
  2498.      *
  2499.      */
  2500.     public function requestPUT( $url, $fields, $options )
  2501.     {
  2502.  
  2503.         if( $curl = curl_init( $url ) )
  2504.         {
  2505.  
  2506.             curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, 'PUT' );
  2507.             curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
  2508.             curl_setopt( $curl, CURLOPT_POSTFIELDS, $fields );
  2509.             curl_setopt( $curl, CURLOPT_PROXY, $this->proxy );
  2510.             if( $this->proxyScheme == 'socks5' )
  2511.             {
  2512.  
  2513.                 curl_setopt( $curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5 );
  2514.  
  2515.             }
  2516.  
  2517.             if( is_array( $options ) && count( $options ) )
  2518.             {
  2519.  
  2520.                 curl_setopt_array( $curl, $options );
  2521.  
  2522.             }
  2523.  
  2524.             curl_exec( $curl );
  2525.  
  2526.             $status = curl_getinfo( $curl, CURLINFO_HTTP_CODE );
  2527.  
  2528.             curl_close( $curl );
  2529.  
  2530.             return (int) $status;
  2531.  
  2532.         } else {
  2533.  
  2534.             return false;
  2535.  
  2536.         }
  2537.  
  2538.     }
  2539.  
  2540.     /**
  2541.      *
  2542.      * Делает обыкновенный запрос, заворачивая данные в json_encode
  2543.      *
  2544.      * При POST запросе отсылает следующие заголовки:
  2545.      *   'Accept: application/vnd.qiwi.sso-v1+json'
  2546.      *   'Content-Type: application/json; charset=UTF-8'
  2547.      *   'X-Requested-With: XMLHttpRequest'
  2548.      *   'DNT: 1'
  2549.      *
  2550.      * @param string     $url            Адрес
  2551.      * @param array      $postArray      Массив данных
  2552.      * @param array      $options        Массив параметров CURL
  2553.      *
  2554.      * @return string|bool
  2555.      *
  2556.      */
  2557.     public function requestJSON( $url, $postArray = null, $options = null )
  2558.     {
  2559.  
  2560.         if( is_array( $postArray ) )
  2561.             $postArray = json_encode( $postArray, JSON_FORCE_OBJECT );
  2562.  
  2563.         $curl = curl_init();
  2564.  
  2565.         curl_setopt( $curl, CURLOPT_URL, $url );
  2566.         curl_setopt( $curl, CURLOPT_COOKIEFILE, $this->cookieFile );
  2567.         curl_setopt( $curl, CURLOPT_COOKIEJAR, $this->cookieFile );
  2568.         curl_setopt( $curl, CURLOPT_HTTPHEADER, array (
  2569.                 'Accept: application/vnd.qiwi.sso-v1+json',
  2570.                 'Content-Type: application/json; charset=UTF-8',
  2571.                 'X-Requested-With: XMLHttpRequest',
  2572.                 'DNT: 1'
  2573.             )
  2574.         );
  2575.         curl_setopt( $curl, CURLOPT_HEADER, 0 );
  2576.         curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false );
  2577.         curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, false );
  2578.         curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 );
  2579.         curl_setopt( $curl, CURLOPT_PROXY, $this->proxy );
  2580.         if( $this->proxyScheme == 'socks5' )
  2581.         {
  2582.  
  2583.             curl_setopt( $curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5 );
  2584.  
  2585.         }
  2586.  
  2587.         if( $postArray )
  2588.         {
  2589.  
  2590.             curl_setopt( $curl, CURLOPT_POST, 1 );
  2591.             curl_setopt( $curl, CURLOPT_POSTFIELDS, $postArray );
  2592.  
  2593.         }
  2594.  
  2595.         if( is_array( $options ) && count( $options ) )
  2596.         {
  2597.  
  2598.             curl_setopt_array( $curl, $options );
  2599.  
  2600.         }
  2601.  
  2602.         $response = curl_exec( $curl );
  2603.  
  2604.         curl_close( $curl );
  2605.  
  2606.         if( $response === false )
  2607.         {
  2608.  
  2609.             throw new Exception( 'QIWI не отвечает на запрос' );
  2610.  
  2611.         }
  2612.  
  2613.         return $response;
  2614.  
  2615.     }
  2616.  
  2617.     /**
  2618.      *
  2619.      * Вытаскивает из строки вида 1 000 000, 13 руб только числа и запятую, например 100000,13
  2620.      *
  2621.      * @param string     $str
  2622.      *
  2623.      * @return string
  2624.      *
  2625.      */
  2626.     public function parseFloatFromCash( $str )
  2627.     {
  2628.  
  2629.         $out = '';
  2630.         $symbol = null;
  2631.  
  2632.         for( $i = 0; $i < strlen( $str ); $i++ )
  2633.         {
  2634.  
  2635.             $symbol = $str[ $i ];
  2636.  
  2637.             if( is_numeric( $symbol ) || $symbol == ',' )
  2638.                 $out .= $symbol;
  2639.  
  2640.         }
  2641.  
  2642.         return $out;
  2643.  
  2644.     }
  2645.  
  2646.     /**
  2647.      *
  2648.      * Определяет валюту по строке вида 1 000 000, 13 руб
  2649.      *
  2650.      * @param string     $str
  2651.      *
  2652.      * @return string|null   RUB, EUR, KZT, USD
  2653.      *
  2654.      */
  2655.     public function determineCurrencyFromCash( $str )
  2656.     {
  2657.  
  2658.         $list = array( 'руб' => 'RUB', 'евро' => 'EUR', 'тенге' => 'KZT', 'долл' => 'USD' );
  2659.  
  2660.         foreach( $list as $key => $value )
  2661.         {
  2662.  
  2663.             if( strpos( $str, $key ) !== false )
  2664.             {
  2665.  
  2666.                 return $value;
  2667.  
  2668.             }
  2669.  
  2670.         }
  2671.  
  2672.         return null;
  2673.  
  2674.     }
  2675.  
  2676.     /**
  2677.      *
  2678.      * Убирает из номера телефона код страны
  2679.      *
  2680.      * @param string     $phone      Номер телефона в формате 79991231212
  2681.      *
  2682.      * @throws Exception             Если не удалось найти соответствующий код, кидает исключение
  2683.      *
  2684.      * @return string|null
  2685.      *
  2686.      */
  2687.     public function removeCountryCode( $phone )
  2688.     {
  2689.  
  2690.         $codes = array( array( 7, 1 ), array( 93, 2 ), array( 355, 3 ), array( 213, 3 ), array( 1684, 4 ), array( 376, 3 ), array( 244, 3 ), array( 1264, 4 ), array( 1268, 4 ), array( 54, 2 ), array( 374, 3 ), array( 297, 3 ), array( 61, 2 ), array( 43, 2 ), array( 994, 3 ), array( 1242, 4 ), array( 973, 3 ), array( 880, 3 ), array( 1246, 4 ), array( 375, 3 ), array( 32, 2 ), array( 501, 3 ), array( 229, 3 ), array( 1441, 4 ), array( 975, 3 ), array( 591, 3 ), array( 387, 3 ), array( 267, 3 ), array( 55, 2 ), array( 246, 3 ), array( 1284, 4 ), array( 673, 3 ), array( 359, 3 ), array( 226, 3 ), array( 257, 3 ), array( 855, 3 ), array( 237, 3 ), array( 1, 1 ), array( 238, 3 ), array( 599, 3 ), array( 1345, 4 ), array( 236, 3 ), array( 235, 3 ), array( 56, 2 ), array( 86, 2 ), array( 61, 2 ), array( 61, 2 ), array( 57, 2 ), array( 269, 3 ), array( 243, 3 ), array( 242, 3 ), array( 682, 3 ), array( 506, 3 ), array( 225, 3 ), array( 385, 3 ), array( 53, 2 ), array( 599, 3 ), array( 357, 3 ), array( 420, 3 ), array( 45, 2 ), array( 253, 3 ), array( 1767, 4 ), array( 1, 1 ), array( 593, 3 ), array( 20, 2 ), array( 503, 3 ), array( 240, 3 ), array( 291, 3 ), array( 372, 3 ), array( 251, 3 ), array( 500, 3 ), array( 298, 3 ), array( 679, 3 ), array( 358, 3 ), array( 33, 2 ), array( 594, 3 ), array( 689, 3 ), array( 241, 3 ), array( 220, 3 ), array( 995, 3 ), array( 49, 2 ), array( 233, 3 ), array( 350, 3 ), array( 30, 2 ), array( 299, 3 ), array( 1473, 4 ), array( 590, 3 ), array( 1671, 4 ), array( 502, 3 ), array( 44, 2 ), array( 224, 3 ), array( 245, 3 ), array( 592, 3 ), array( 509, 3 ), array( 504, 3 ), array( 852, 3 ), array( 36, 2 ), array( 354, 3 ), array( 91, 2 ), array( 62, 2 ), array( 98, 2 ), array( 964, 3 ), array( 353, 3 ), array( 44, 2 ), array( 972, 3 ), array( 39, 2 ), array( 1876, 4 ), array( 81, 2 ), array( 44, 2 ), array( 962, 3 ), array( 7, 1 ), array( 254, 3 ), array( 686, 3 ), array( 965, 3 ), array( 996, 3 ), array( 856, 3 ), array( 371, 3 ), array( 961, 3 ), array( 266, 3 ), array( 231, 3 ), array( 218, 3 ), array( 423, 3 ), array( 370, 3 ), array( 352, 3 ), array( 853, 3 ), array( 389, 3 ), array( 261, 3 ), array( 265, 3 ), array( 60, 2 ), array( 960, 3 ), array( 223, 3 ), array( 356, 3 ), array( 692, 3 ), array( 596, 3 ), array( 222, 3 ), array( 230, 3 ), array( 262, 3 ), array( 52, 2 ), array( 691, 3 ), array( 373, 3 ), array( 377, 3 ), array( 976, 3 ), array( 382, 3 ), array( 1664, 4 ), array( 212, 3 ), array( 258, 3 ), array( 95, 2 ), array( 264, 3 ), array( 674, 3 ), array( 977, 3 ), array( 31, 2 ), array( 687, 3 ), array( 64, 2 ), array( 505, 3 ), array( 227, 3 ), array( 234, 3 ), array( 683, 3 ), array( 672, 3 ), array( 850, 3 ), array( 1670, 4 ), array( 47, 2 ), array( 968, 3 ), array( 92, 2 ), array( 680, 3 ), array( 970, 3 ), array( 507, 3 ), array( 675, 3 ), array( 595, 3 ), array( 51, 2 ), array( 63, 2 ), array( 48, 2 ), array( 351, 3 ), array( 1, 1 ), array( 974, 3 ), array( 262, 3 ), array( 40, 2 ), array( 250, 3 ), array( 590, 3 ), array( 290, 3 ), array( 1869, 4 ), array( 1758, 4 ), array( 590, 3 ), array( 508, 3 ), array( 1784, 4 ), array( 685, 3 ), array( 378, 3 ), array( 239, 3 ), array( 966, 3 ), array( 221, 3 ), array( 381, 3 ), array( 248, 3 ), array( 232, 3 ), array( 65, 2 ), array( 1721, 4 ), array( 421, 3 ), array( 386, 3 ), array( 677, 3 ), array( 252, 3 ), array( 27, 2 ), array( 82, 2 ), array( 211, 3 ), array( 34, 2 ), array( 94, 2 ), array( 249, 3 ), array( 597, 3 ), array( 47, 2 ), array( 268, 3 ), array( 46, 2 ), array( 41, 2 ), array( 963, 3 ), array( 886, 3 ), array( 992, 3 ), array( 255, 3 ), array( 66, 2 ), array( 670, 3 ), array( 228, 3 ), array( 690, 3 ), array( 676, 3 ), array( 1868, 4 ), array( 216, 3 ), array( 90, 2 ), array( 993, 3 ), array( 1649, 4 ), array( 688, 3 ), array( 1340, 4 ), array( 256, 3 ), array( 380, 3 ), array( 971, 3 ), array( 44, 2 ), array( 1, 1 ), array( 598, 3 ), array( 998, 3 ), array( 678, 3 ), array( 39, 2 ), array( 58, 2 ), array( 84, 2 ), array( 681, 3 ), array( 212, 3 ), array( 967, 3 ), array( 260, 3 ), array( 263, 3 ), array( 358, 3 ) );
  2691.  
  2692.         foreach( $codes as $item )
  2693.         {
  2694.  
  2695.             if( substr( $phone, 1, $item[ 1 ] ) == $item[ 0 ] )
  2696.             {
  2697.  
  2698.                 return substr( $phone, ( 1 + $item[ 1 ] ) );
  2699.  
  2700.             }
  2701.  
  2702.         }
  2703.  
  2704.         throw new Exception( 'Не удается определить страну номера телефона' );
  2705.  
  2706.     }
  2707.  
  2708.     public function getCurrencyCode( $name )
  2709.     {
  2710.  
  2711.         $list = array(
  2712.             'RUB' => 643,
  2713.             'KZT' => 398,
  2714.             'USD' => 840,
  2715.             'EUR' => 978
  2716.         );
  2717.  
  2718.         if( !array_key_exists( $name, $list ) )
  2719.         {
  2720.  
  2721.             throw new Exception( 'Выбрана неподдерживаемая валюта для платежа' );
  2722.  
  2723.         }
  2724.  
  2725.         return $list[ $name ];
  2726.  
  2727.     }
  2728.  
  2729.     /**
  2730.      *
  2731.      * Метод-обертка, добавленный для совместимости с другим классом.
  2732.      * По факту вызывает методо Qiwi::transactions()
  2733.      * Не используйте его без необходимости
  2734.      *
  2735.      * @return mixed
  2736.      *
  2737.      */
  2738.     public function getHistory( $from, $to )
  2739.     {
  2740.  
  2741.         $in = $this->transactions( 'in', $from, $to );
  2742.         $out = $this->transactions( 'out', $from, $to );
  2743.  
  2744.         foreach( $in as $key => $transaction )
  2745.         {
  2746.  
  2747.             $in[ $key ][ 'iID' ] = $transaction[ 'transaction' ];
  2748.             $in[ $key ][ 'sDate' ] = $transaction[ 'date' ];
  2749.             $in[ $key ][ 'sTime' ] = $transaction[ 'time' ];
  2750.             $in[ $key ][ 'sWithExpend' ] = $transaction[ 'cash' ];
  2751.             $in[ $key ][ 'dWithExpend' ] = $transaction[ 'cash' ];
  2752.             $in[ $key ][ 'sType' ] = 'INCOME';
  2753.             $in[ $key ][ 'sCurrency' ] = $transaction[ 'originalCurrency' ];
  2754.             $in[ $key ][ 'sStatus' ] = 'SUCCESS';
  2755.             $in[ $key ][ 'dAmount' ] = $transaction[ 'originalCash' ];
  2756.             $in[ $key ][ 'sAmount' ] = $transaction[ 'originalCash' ];
  2757.             $in[ $key ][ 'sComment' ] = $transaction[ 'comment' ];
  2758.             $in[ $key ][ 'sProvider' ] = $transaction[ 'provider' ];
  2759.             $in[ $key ][ 'iOpponentPhone' ] = (int)$transaction[ 'opNumber' ];
  2760.  
  2761.         }
  2762.  
  2763.         foreach( $out as $key => $transaction )
  2764.         {
  2765.  
  2766.             $out[ $key ][ 'iID' ] = $transaction[ 'transaction' ];
  2767.             $out[ $key ][ 'sDate' ] = $transaction[ 'date' ];
  2768.             $out[ $key ][ 'sTime' ] = $transaction[ 'time' ];
  2769.             $out[ $key ][ 'sWithExpend' ] = $transaction[ 'cash' ];
  2770.             $out[ $key ][ 'dWithExpend' ] = $transaction[ 'cash' ];
  2771.             $out[ $key ][ 'sType' ] = 'EXPENDITURE';
  2772.             $out[ $key ][ 'sCurrency' ] = $transaction[ 'originalCurrency' ];
  2773.             $out[ $key ][ 'sStatus' ] = 'SUCCESS';
  2774.             $out[ $key ][ 'dAmount' ] = $transaction[ 'originalCash' ];
  2775.             $out[ $key ][ 'sAmount' ] = $transaction[ 'originalCash' ];
  2776.             $out[ $key ][ 'sComment' ] = $transaction[ 'comment' ];
  2777.             $out[ $key ][ 'sProvider' ] = $transaction[ 'provider' ];
  2778.             $out[ $key ][ 'iOpponentPhone' ] = (int)$transaction[ 'opNumber' ];
  2779.  
  2780.         }
  2781.  
  2782.         return array_merge( $in, $out );
  2783.  
  2784.     }
  2785.  
  2786.     /**
  2787.      *
  2788.      * Метод-обертка, добавленный для совместимости с другим классом.
  2789.      * По факту вызывает методо Qiwi::isSmsOn()
  2790.      * Не используйте его без необходимости
  2791.      *
  2792.      * @return mixed
  2793.      *
  2794.      */
  2795.     public function isSMSActive()
  2796.     {
  2797.  
  2798.         return $this->isSmsOn();
  2799.  
  2800.     }
  2801.  
  2802.     /**
  2803.      *
  2804.      * Метод-обертка, добавленный для совместимости с другим классом.
  2805.      * По факту вызывает методо Qiwi::isSmsOn()
  2806.      * Не используйте его без необходимости
  2807.      *
  2808.      * @return mixed
  2809.      *
  2810.      */
  2811.     public function isSMSAcive()
  2812.     {
  2813.  
  2814.         return $this->isSmsOn();
  2815.  
  2816.     }
  2817.  
  2818.     /**
  2819.      *
  2820.      * Метод-обертка, добавленный для совместимости с другим классом.
  2821.      * По факту вызывает методо Qiwi::paymentQiwi()
  2822.      * Не используйте его без необходимости
  2823.      *
  2824.      * @return mixed
  2825.      *
  2826.      */
  2827.     public function transfer( $phone, $amount, $currency, $comment )
  2828.     {
  2829.  
  2830.         return $this->paymentQiwi( $phone, $amount, $currency, $currency, $comment );
  2831.  
  2832.     }
  2833.  
  2834.     /**
  2835.      *
  2836.      * Метод-обертка, добавленный для совместимости с другим классом.
  2837.      * По факту вызывает методо Qiwi::paymentQiwi()
  2838.      * Не используйте его без необходимости
  2839.      *
  2840.      * @return mixed
  2841.      *
  2842.      */
  2843.     public function SendMoney( $phone, $amount, $currency, $comment )
  2844.     {
  2845.  
  2846.         return $this->paymentQiwi( $phone, $amount, $currency, $currency, $comment );
  2847.  
  2848.     }
  2849.  
  2850.     /**
  2851.      *
  2852.      * Метод-обертка, добавленный для совместимости с другим классом.
  2853.      * По факту вызывает методо Qiwi::wallets()
  2854.      * Не используйте его без необходимости
  2855.      *
  2856.      * @return mixed
  2857.      *
  2858.      */
  2859.     public function GetBalances()
  2860.     {
  2861.  
  2862.         return $this->wallets();
  2863.  
  2864.     }
  2865.  
  2866. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement