Подключал сайт к Wallet One. Механизм работы агрегатора стандартный, но есть определенные нюансы.
Самым сложным оказалось угадать, как формируется цифровая подпись при обращении к сайту из платежной системы.
Цифровая подпись для отправки данных «собралась» нормально, точно как и описывалось в примере из руководства по подключению. Поэтому проблема с подписью во время приема запроса была неприятной неожиданностью.
Теоретически, в этом случае можно обойтись без проверки подписи, так как адрес страницы, которая принимает данные, неизвестна внешнему пользователю. Я подозреваю, что многие так и делают. Но лично мне всегда хочется сделать «по уму».
Было ясно, что я как то не верно собираю подпись, не так как она собиралась у провайдера. Но все было сделано в точности как в примере, данном в руководстве.
Тогда я решил пойти другим путем — я взял нужный код из предлагаемого модуля для Drupal. Он пестрел кучей всяких преобразований вроде urldecode и htmlentities, которых не было в тексте примера в руководстве. И опять — мимо!
В конце концов я решил взять набор $_POST данных и попробовать на нем разные способы вычисления цифровой подписи. Оказалось, что к присланным $_POST данным не следует вообще применять каких либо операций (менять кодировку, исправлять спец. символы и т.п.). Так какого же, господа, рожна вы их насовали в ваши примеры?
Вот мой рабочий пример, переделанный в заготовку для интеграции :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
/* прием запроса о результатах транзакции c единого кошелька WALLET ONE */ function walletone_transaction_result() { // Проверка наличия необходимых параметров в POST-запросе if (!isset($_POST["WMI_SIGNATURE"])) WMI_answer("Retry", "Отсутствует параметр WMI_SIGNATURE"); if (!isset($_POST["WMI_PAYMENT_NO"])) WMI_answer("Retry", "Отсутствует параметр WMI_PAYMENT_NO"); if (!isset($_POST["WMI_ORDER_STATE"])) WMI_answer("Retry", "Отсутствует параметр WMI_ORDER_STATE"); //TODO: проверить дополнительные параметры, если нужно //... //в коде модуля drupal было ограничение в 500 симв на вх. параметр //я посчитал это адекватным для последующих операций протоколирования, хотя и //не факт, что переменные можно "обрезать" для расчета подписи $post = array(); foreach ($_POST as $key => $value) { $post[$key] = $value; if (strlen($post[$key]) > 500) $post[$key] = substr($post[$key], 0, 500); } //копирование массива по элементно - тоже не верх изящества кода //но после долгих поисков - это уже не так существенно $res = array(); foreach ($post as $name => $value) if ($name !== "WMI_SIGNATURE") $res[$name] = $value; uksort($res, "strcasecmp"); $values = ""; foreach ($res as $name => $value) $values .= $value; $key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //ваш ключ $signature = base64_encode(pack("H*", md5($values . $key))); if ($signature == $post["WMI_SIGNATURE"]) { if (strtoupper($post["WMI_ORDER_STATE"]) == "ACCEPTED") { // TODO: Пометить заказ, как «Оплаченный» в системе учета магазина // и другие операции, необходимые для регистрации успешной оплаты // ... // платежной системе мы должны отправить код - OK, чтобы перестала //долбить сайт запросами WMI_answer("Ok", "Заказ #" . $_POST["WMI_PAYMENT_NO"] . " оплачен!"); } else { // Случилось что-то странное, пришло неизвестное состояние заказа WMI_answer("Retry", "Неверное состояние " . $_POST["WMI_ORDER_STATE"]); } } else // Подпись не совпадает, возможно вы поменяли настройки интернет-магазина WMI_answer("Retry", "Неверная подпись " . $_POST["WMI_SIGNATURE"] . " вместо {$signature}"); exit; } // Функция, которая возвращает результат в Единую кассу function WMI_answer($result, $description) { print "WMI_RESULT=" . strtoupper($result) . "&"; print "WMI_DESCRIPTION=" .urlencode($description); // TODO: здесь можно протоколировать ответы в единую кассу // ... exit(); } |
Надеюсь, кому то сэкономит время и нервы.