В данном примере рассматривается процесс формирования ссылки на оплату, исходя из предоставленных параметров. При переходе по данной ссылке плательщик будет перенаправлен на страницу оплаты для завершения транзакции.
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 |
require 'net/http' require 'uri' require 'json' require 'base64' # Доступы к Paykeeper server = 'https://xxxxxxxxxx.server.paykeeper.ru' user = 'admin' password = 'xxxxxxxxxx' # Данные клиента email = '' phone = '' # Номер заказа order_id = 9999 # Массив товаров в заказе basket = [ { 'name' => 'Тортилья, 20 см, 756 г', 'count' => 5, 'price' => 381.00 } ] # Собираем массив товаров для Paykeeper # https://docs.paykeeper.ru/onlain-kassa-54-fz/tovary-v-cheke-54-fz-full/ total = 0 prods = basket.map do |row| sum = row['price'] * row['count'] total += sum { 'name' => row['name'], 'price' => row['price'], 'quantity' => row['count'], 'sum' => sum, 'tax' => 'none', 'item_type' => 'goods' } end # Добавляем доставку delivery = { 'name' => 'Доставка', 'price' => 300, 'quantity' => 1, 'sum' => 300, 'tax' => 'none', 'item_type' => 'service' } prods << delivery total += delivery['sum'] # Авторизация в Paykeeper base64_credentials = Base64.strict_encode64("#{user}:#{password}") headers = { 'Content-Type' => 'application/x-www-form-urlencoded', 'Authorization' => "Basic #{base64_credentials}" } # Получение токена uri = URI("#{server}/info/settings/token/") response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http| req = Net::HTTP::Get.new(uri, headers) http.request(req) end token_response = JSON.parse(response.body) if token_response['token'] token = token_response['token'] # Формируем данные для запроса payment_data = { 'pay_amount' => total, 'orderid' => order_id, 'service_name' => ";PKC|#{prods.to_json}|", 'client_email' => email, 'client_phone' => phone } # Отправка данных на создание счета uri = URI("#{server}/change/invoice/preview/") request_body = URI.encode_www_form(payment_data.merge('token' => token)) response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http| req = Net::HTTP::Post.new(uri, headers) req.body = request_body http.request(req) end invoice_response = JSON.parse(response.body) if invoice_response['invoice_id'] invoice_id = invoice_response['invoice_id'] # Редирект на оплату link = "#{server}/bill/#{invoice_id}/" puts "Перейдите по ссылке: #{link}" else puts "Ошибка при создании счета: #{invoice_response}" end else puts "Ошибка авторизации: #{token_response}" end |
После перехода по ссылке #{link} пользователь будет направлен на страницу оплаты.
На языке Ruby обработку запросов от 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 |
require 'digest' # Секретное слово SECRET_SEED = "verysecretseed" # Получение данных из запроса. В данном примере приходят через params. id = params["id"] # пример 12345 sum = params["sum"] # пример 100.00 clientid = params["clientid"] # пример Иван Иванов orderid = params["orderid"] # пример 67890 key = params["key"] # пример 2ba28d39e3836f4cc1bd96559417b4fb # Проверка цифровой подписи calculated_key = Digest::MD5.hexdigest("#{id}#{'%.2f' % sum.to_f}#{clientid}#{orderid}#{SECRET_SEED}") if key != calculated_key puts "Error! Hash mismatch" exit end # Рекомендуемая проверка заказа # Здесь необходимо добавить логику для проверки существования заказа в вашей системе # Например: # - Существует ли заказ с номером orderid? # - Принадлежит ли он клиенту clientid? # - Совпадает ли сумма заказа с sum? # Отметить заказ как оплаченный # Здесь должна быть логика обновления статуса заказа puts "OK #{Digest::MD5.hexdigest("#{id}#{SECRET_SEED}")}" |
Полный перечень параметров в 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 |
require 'net/http' require 'uri' require 'json' require 'base64' # Номер платежа invoice_id = '123456789' # Доступы к Paykeeper server = 'https://xxxxx.server.paykeeper.ru' user = 'admin' password = 'xxxxxxxxxx' # Авторизация в Paykeeper base64_credentials = Base64.strict_encode64("#{user}:#{password}") headers = { 'Content-Type' => 'application/x-www-form-urlencoded', 'Authorization' => "Basic #{base64_credentials}" } # Получение информации о платеже uri = URI("#{server}/info/invoice/byid/?id=#{invoice_id}") response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http| request = Net::HTTP::Get.new(uri, headers) http.request(request) end info = JSON.parse(response.body) if info['paymentid'] # Запрос токена uri = URI("#{server}/info/settings/token/") response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http| request = Net::HTTP::Get.new(uri, headers) http.request(request) end token_response = JSON.parse(response.body) if token_response['token'] # Запрос на возврат платежа uri = URI("#{server}/change/payment/reverse/") request_data = { id: info['paymentid'], amount: 500, partial: false, token: token_response['token'] } response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http| request = Net::HTTP::Post.new(uri, headers) request.set_form_data(request_data) http.request(request) end reverse_response = JSON.parse(response.body) puts reverse_response else puts 'Не удалось получить токен' end else puts 'Платеж не найден' end |
Менеджер перезвонит вам и расскажет про детали подключения