В данном примере рассматривается процесс формирования ссылки на оплату, исходя из предоставленных параметров. При переходе по данной ссылке плательщик будет перенаправлен на страницу оплаты для завершения транзакции.
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
#!/usr/bin/perl use strict; use warnings; use LWP::UserAgent; use JSON; use MIME::Base64; use URI::Escape; use DBI; use open ':std', ':encoding(UTF-8)'; binmode STDERR, ':encoding(UTF-8)'; # Доступы к Paykeeper my $server = 'https://xxxxxxxxxx.server.paykeeper.ru'; my $user = 'admin'; my $password = 'xxxxxxx'; # Данные клиента my $email = ''; my $phone = ''; # Номер заказа my $order_id = 9999; # Массив товаров в заказе my @basket = ( { name => 'Тортилья, 20 см, 756 г', count => 5, price => 381.00, } ); # Собираем массив товаров для paykeeper my $total = 0; my @prods; foreach my $row (@basket) { push @prods, { name => $row->{name}, price => $row->{price}, quantity => $row->{count}, sum => $row->{price} * $row->{count}, tax => 'none', item_type => 'goods', }; $total += $row->{price} * $row->{count}; } # Доставка push @prods, { name => 'Доставка', price => 300, quantity => 1, sum => 300, tax => 'none', item_type => 'service', }; $total += 300; # Авторизация в Paykeeper с отключенной проверкой SSL my $ua = LWP::UserAgent->new( ssl_opts => { SSL_verify_mode => 0, verify_hostname => 0, } ); my $auth = encode_base64("$user:$password", ''); my $headers = [ 'Content-Type' => 'application/x-www-form-urlencoded', 'Authorization' => "Basic $auth", ]; my $response = $ua->get("$server/info/settings/token/", @$headers); # Проверяем ответ if (!$response->is_success) { die "Ошибка авторизации: " . $response->decoded_content; } my $token_data = decode_json($response->decoded_content); if (!$token_data->{token}) { die "Ошибка получения токена: " . $response->decoded_content; } my $token = $token_data->{token}; # Готовим запрос 3.4 JSON API на получение счёта my $payment_data = { pay_amount => $total, orderid => $order_id, service_name => ';PKC|' . encode_json(\@prods) . '|', client_email => $email, client_phone => $phone, token => $token, }; $response = $ua->post( "$server/change/invoice/preview/", Content => $payment_data, Content_Type => 'application/x-www-form-urlencoded', @$headers ); # Проверяем ответ на создание счёта if (!$response->is_success) { die "Ошибка создания счёта: " . $response->decoded_content; } my $invoice_data = decode_json($response->decoded_content); if (!$invoice_data->{invoice_id}) { die "Ошибка создания счёта: " . $invoice_data->{msg}; } my $invoice_id = $invoice_data->{invoice_id}; # Сохранение invoice_id в заказе (DBI) my $dbh = DBI->connect("DBI:mysql:database=your_db;host=localhost", "username", "password"); my $sth = $dbh->prepare("UPDATE `orders` SET `invoice_id` = ? WHERE `id` = ?"); $sth->execute($invoice_id, $order_id); # Редирект на форму оплаты my $link = "$server/bill/$invoice_id/"; print "Content-type: text/html\n\n"; print qq{<script>window.location.replace("$link");</script>}; print qq{Перейдите по <a href="$link">ссылке</a>.}; exit; |
После перехода по ссылке $link пользователь будет направлен на страницу оплаты.
На языке Perl обработку запросов от PayKeeper об успешных платежах можно реализовать следующим образом:
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 |
#!/usr/bin/perl use strict; use warnings; use CGI::Carp qw(fatalsToBrowser); use CGI qw(:standard); use POSIX qw(strftime); use Digest::MD5 qw(md5_hex); # Конфигурация my $log_file = '/tmp/paykeeperlog.txt'; my $secret = 'ПАРОЛЬ'; # Получение данных my $cgi = CGI->new; my $time = strftime("%Y-%m-%d %H:%M:%S", localtime); # Данные из POST-запроса my %params = map { $_ => $cgi->param($_) // '' } qw( id sum clientid orderid key service_name client_email client_phone ps_id batch_date fop_receipt_key bank_id card_number card_holder card_expiry ); # Проверка обязательных параметров foreach my $param (qw(id sum clientid orderid key)) { if (!$params{$param}) { print "Content-type: text/html\n\n"; print "Error: Missing parameter $param\n"; exit; } } # Генерация и проверка MD5-хеша my $md5hash = md5_hex($params{id} . $params{sum} . $params{clientid} . $params{orderid} . $secret); # Установка заголовка print "Content-type: text/html\n\n"; if ($params{key} eq $md5hash) { # Хеш совпал, формируем ответ my $response_hash = md5_hex($params{id} . $secret); my $ret = "OK $response_hash"; print "$ret\n"; # Запись лога if (open my $log_fh, '>>', $log_file) { print $log_fh "$time Ret=$ret id=$params{id} sum=$params{sum} key=$params{key}, calculated key=$md5hash\n"; close $log_fh; } } else { # Ошибка проверки print "Error: Invalid key\n"; } exit; |
Полный перечень параметров в POST-оповещении можно посмотреть здесь.
В ответ на данный запрос должна быть отправлена строка вида:
Важно отметить, что ответ данного скрипта должен быть исключительно в указанном формате и ни байтом больше, в противном случае PayKeeper будет считать, что ваш сайт неправильно обработал оповещение об успешном платеже.
В PayKeeper возможен полный возврат платежа с помощью метода /change/payment/reverse/. Возврат могут делать только пользователи с включённой функцией возврата. Подробнее можно ознакомиться в документации JSON API. Пример запроса на полный возврат:
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 66 67 68 69 70 71 72 73 74 75 |
#!/usr/bin/perl use strict; use warnings; use CGI qw(:standard); use Encode qw(encode_utf8); use LWP::UserAgent; use HTTP::Request; use MIME::Base64; use JSON; use URI::Escape; use open ':std', ':encoding(UTF-8)'; binmode STDERR, ':encoding(UTF-8)'; # Номер платежа my $invoice_id = '1234567890'; # Доступы к Paykeeper my $server = 'https://xxxxxxxxxx.server.paykeeper.ru'; my $user = 'admin'; my $password = 'xxxxxxxxxx'; # Авторизация в Paykeeper my $base64 = encode_base64("$user:$password", ''); my @headers = ( 'Content-Type' => 'application/x-www-form-urlencoded', 'Authorization' => 'Basic ' . $base64, ); # Создание объекта для выполнения HTTP-запросов my $ua = LWP::UserAgent->new( ssl_opts => { SSL_verify_mode => 0, verify_hostname => 0, } ); # Запрос к PayKeeper для получения информации о счете my $url = $server . '/info/invoice/byid/?id=' . uri_escape($invoice_id); my $request = HTTP::Request->new(GET => $url, \@headers); my $response = $ua->request($request); # Обработка ответа my $info = decode_json($response->decoded_content); if ($info->{paymentid}) { # Получаем токен $url = $server . '/info/settings/token/'; $request = HTTP::Request->new(GET => $url, \@headers); $response = $ua->request($request); my $response_data = decode_json($response->decoded_content); # В ответе должен быть token if ($response_data->{token}) { # Строим запрос my $payment_parameters = "id=" . uri_escape($info->{paymentid}) . "&amount=" . uri_escape(500) . "&partial=false" . "&token=" . uri_escape($response_data->{token}); # Отправка запроса на отмену платежа $url = $server . '/change/payment/reverse/'; $request = HTTP::Request->new(POST => $url, \@headers, $payment_parameters); $response = $ua->request($request); # Проверка успешности запроса if ($response->is_success) { my $result = decode_json($response->decoded_content); # Печать ответа use Data::Dumper; print Dumper($result); } else { print "Ошибка: " . $response->status_line; } exit; } } |
Менеджер перезвонит вам и расскажет про детали подключения