qiwi-pay 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +8 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +65 -0
- data/LICENSE +22 -0
- data/README.md +296 -0
- data/Rakefile +11 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/qiwi-pay.rb +42 -0
- data/lib/qiwi-pay/api/capture_operation.rb +44 -0
- data/lib/qiwi-pay/api/payment_operation.rb +29 -0
- data/lib/qiwi-pay/api/refund_operation.rb +47 -0
- data/lib/qiwi-pay/api/response.rb +35 -0
- data/lib/qiwi-pay/api/reversal_operation.rb +47 -0
- data/lib/qiwi-pay/api/status_operation.rb +83 -0
- data/lib/qiwi-pay/cheque.rb +103 -0
- data/lib/qiwi-pay/confirmation.rb +138 -0
- data/lib/qiwi-pay/credentials.rb +66 -0
- data/lib/qiwi-pay/messages_for_codes.rb +91 -0
- data/lib/qiwi-pay/payment_operation.rb +108 -0
- data/lib/qiwi-pay/signature.rb +41 -0
- data/lib/qiwi-pay/version.rb +5 -0
- data/lib/qiwi-pay/wpf/auth_operation.rb +31 -0
- data/lib/qiwi-pay/wpf/payment_operation.rb +64 -0
- data/lib/qiwi-pay/wpf/sale_operation.rb +29 -0
- data/qiwi-pay.gemspec +40 -0
- metadata +165 -0
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "qiwi-pay"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/qiwi-pay.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module QiwiPay
|
4
|
+
# Web Payment Form interface interaction implementation
|
5
|
+
# @see https://developer.qiwi.com/ru/qiwipay/index.html?php#qiwipay-wpf
|
6
|
+
module Wpf
|
7
|
+
# QiwiPay WPF host
|
8
|
+
ENDPOINT_HOST = 'pay.qiwi.com'
|
9
|
+
|
10
|
+
# QiwiPay WPF endpoint
|
11
|
+
ENDPOINT_PATH = '/paypage/initial'
|
12
|
+
end
|
13
|
+
|
14
|
+
# JSON API interaction implementation
|
15
|
+
# @see https://developer.qiwi.com/ru/qiwipay/index.html?json#section-6
|
16
|
+
module Api
|
17
|
+
# QiwiPay API host
|
18
|
+
ENDPOINT_HOST = 'acquiring.qiwi.com'
|
19
|
+
|
20
|
+
# QiwiPay API endpoint
|
21
|
+
ENDPOINT_PATH = '/merchant/direct'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require "qiwi-pay/version"
|
26
|
+
require "qiwi-pay/messages_for_codes"
|
27
|
+
require "qiwi-pay/payment_operation"
|
28
|
+
require "qiwi-pay/cheque"
|
29
|
+
require "qiwi-pay/credentials"
|
30
|
+
require "qiwi-pay/signature"
|
31
|
+
require "qiwi-pay/confirmation"
|
32
|
+
|
33
|
+
require "qiwi-pay/wpf/payment_operation"
|
34
|
+
require "qiwi-pay/wpf/sale_operation"
|
35
|
+
require "qiwi-pay/wpf/auth_operation"
|
36
|
+
|
37
|
+
require "qiwi-pay/api/payment_operation"
|
38
|
+
require "qiwi-pay/api/capture_operation"
|
39
|
+
require "qiwi-pay/api/refund_operation"
|
40
|
+
require "qiwi-pay/api/reversal_operation"
|
41
|
+
require "qiwi-pay/api/status_operation"
|
42
|
+
require "qiwi-pay/api/response"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module QiwiPay::Api
|
4
|
+
# Подтверждение авторизации в случае двухшагового сценария оплаты
|
5
|
+
#
|
6
|
+
# @note Параметры запроса
|
7
|
+
# merchant_site Обязательно integer Идентификатор сайта ТСП
|
8
|
+
# txn_id Обязательно integer Идентификатор транзакции
|
9
|
+
# cheque Опционально string Данные для кассового чека по 54-ФЗ
|
10
|
+
#
|
11
|
+
# @example Запрос
|
12
|
+
# {
|
13
|
+
# "opcode": 5,
|
14
|
+
# "merchant_site": 99,
|
15
|
+
# "txn_id": "172001",
|
16
|
+
# "sign": "bb5c48ea540035e6b7c03c8184f74f09d26e9286a9b8f34b236b1bf2587e4268"
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
# @example Ответ
|
20
|
+
# {
|
21
|
+
# "txn_id":172001,
|
22
|
+
# "txn_status":3,
|
23
|
+
# "txn_type":2,
|
24
|
+
# "txn_date": "2017-03-09T17:16:06+00:00",
|
25
|
+
# "error_code":0
|
26
|
+
# }
|
27
|
+
class CaptureOperation < PaymentOperation
|
28
|
+
# Код операции sale
|
29
|
+
def self.opcode
|
30
|
+
5
|
31
|
+
end
|
32
|
+
|
33
|
+
# Описание операции
|
34
|
+
def self.description
|
35
|
+
'Подтверждение авторизации в случае двухшагового сценария оплаты'
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def self.in_params
|
41
|
+
%i[merchant_site txn_id cheque].freeze
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rest_client'
|
4
|
+
|
5
|
+
module QiwiPay::Api
|
6
|
+
# General QiwiPay API payment operation request
|
7
|
+
class PaymentOperation < QiwiPay::PaymentOperation
|
8
|
+
# @return [Response]
|
9
|
+
def perform
|
10
|
+
res = RestClient::Resource.new(
|
11
|
+
url,
|
12
|
+
ssl_client_cert: credentials.certificate,
|
13
|
+
ssl_client_key: credentials.key,
|
14
|
+
verify_ssl: OpenSSL::SSL::VERIFY_PEER
|
15
|
+
).post(request_params.to_json)
|
16
|
+
|
17
|
+
Response.new res.code, res.body
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def url
|
23
|
+
URI::HTTPS.build(
|
24
|
+
host: ENDPOINT_HOST,
|
25
|
+
path: ENDPOINT_PATH
|
26
|
+
).to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module QiwiPay::Api
|
4
|
+
# Операция возврата платежа (средства возвращаются в течение 30 дней)
|
5
|
+
#
|
6
|
+
# @note Параметры запроса
|
7
|
+
# merchant_site Обязательно integer Идентификатор сайта ТСП
|
8
|
+
# txn_id Обязательно integer Идентификатор транзакции
|
9
|
+
# amount Опционально string(20) Сумма операции
|
10
|
+
# cheque Опционально string Данные для кассового чека по 54-ФЗ
|
11
|
+
#
|
12
|
+
# @example Запрос
|
13
|
+
# {
|
14
|
+
# "opcode":7,
|
15
|
+
# "merchant_site": 99,
|
16
|
+
# "txn_id": 181001,
|
17
|
+
# "amount": "700",
|
18
|
+
# "sign": "bb5c48ea540035e6b7c03c8184f74f09d26e9286a9b8f34b236b1bf2587e4268"
|
19
|
+
# }
|
20
|
+
#
|
21
|
+
# @example Ответ
|
22
|
+
# {
|
23
|
+
# "txn_id":182001,
|
24
|
+
# "txn_status":3,
|
25
|
+
# "txn_type":3,
|
26
|
+
# "txn_date": "2017-03-09T17:16:06+00:00",
|
27
|
+
# "error_code":0,
|
28
|
+
# "amount": 700
|
29
|
+
# }
|
30
|
+
class RefundOperation < PaymentOperation
|
31
|
+
# Код операции sale
|
32
|
+
def self.opcode
|
33
|
+
7
|
34
|
+
end
|
35
|
+
|
36
|
+
# Описание операции
|
37
|
+
def self.description
|
38
|
+
'Возврат платежа'
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def self.in_params
|
44
|
+
%i[merchant_site txn_id amount cheque].freeze
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
module QiwiPay::Api
|
7
|
+
# QiwiPay API response
|
8
|
+
class Response < OpenStruct
|
9
|
+
include QiwiPay::MessagesForCodes
|
10
|
+
|
11
|
+
# Parameters of integer type
|
12
|
+
INTEGER_PARAMS = %w[
|
13
|
+
txn_id
|
14
|
+
txn_status
|
15
|
+
txn_type
|
16
|
+
error_code
|
17
|
+
currency
|
18
|
+
]
|
19
|
+
|
20
|
+
# @param response_code [Integer] HTTP response status code
|
21
|
+
# @param response_body [String] Response body in JSON
|
22
|
+
def initialize(response_code, response_body)
|
23
|
+
params = JSON.parse(response_body)
|
24
|
+
(INTEGER_PARAMS & params.keys).each do |p|
|
25
|
+
params[p] = params[p] && params[p].to_i
|
26
|
+
end
|
27
|
+
super params
|
28
|
+
send(:http_code=, response_code)
|
29
|
+
end
|
30
|
+
|
31
|
+
def success?
|
32
|
+
http_code == 200 && error_code == 0
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module QiwiPay::Api
|
4
|
+
# Операция отмены платежа (средства расхолдируются практически сразу)
|
5
|
+
#
|
6
|
+
# @note Параметры запроса
|
7
|
+
# merchant_site Обязательно integer Идентификатор сайта ТСП
|
8
|
+
# txn_id Обязательно integer Идентификатор транзакции
|
9
|
+
# amount Опционально string(20) Сумма операции
|
10
|
+
# cheque Опционально string Данные для кассового чека по 54-ФЗ
|
11
|
+
#
|
12
|
+
# @example Запрос
|
13
|
+
# {
|
14
|
+
# "opcode":6,
|
15
|
+
# "merchant_site": 99,
|
16
|
+
# "txn_id": 181001,
|
17
|
+
# "amount": "700",
|
18
|
+
# "sign": "bb5c48ea540035e6b7c03c8184f74f09d26e9286a9b8f34b236b1bf2587e4268"
|
19
|
+
# }
|
20
|
+
#
|
21
|
+
# @example Ответ
|
22
|
+
# {
|
23
|
+
# "txn_id":182001,
|
24
|
+
# "txn_status":3,
|
25
|
+
# "txn_type":4,
|
26
|
+
# "txn_date": "2017-03-09T17:16:06+00:00",
|
27
|
+
# "error_code":0,
|
28
|
+
# "amount": 700
|
29
|
+
# }
|
30
|
+
class ReversalOperation < PaymentOperation
|
31
|
+
# Код операции sale
|
32
|
+
def self.opcode
|
33
|
+
6
|
34
|
+
end
|
35
|
+
|
36
|
+
# Описание операции
|
37
|
+
def self.description
|
38
|
+
'Отмена платежа'
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def self.in_params
|
44
|
+
%i[merchant_site txn_id amount cheque].freeze
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module QiwiPay::Api
|
4
|
+
# Запрос статуса операции
|
5
|
+
#
|
6
|
+
# @note Параметры запроса
|
7
|
+
# merchant_site Обязательно integer Идентификатор сайта ТСП
|
8
|
+
# txn_id Опционально integer Идентификатор транзакции
|
9
|
+
# order_id Опционально string(256) Уникальный номер заказа в системе ТСП
|
10
|
+
#
|
11
|
+
# @example Запрос
|
12
|
+
# {
|
13
|
+
# "opcode":30,
|
14
|
+
# "merchant_site": 99,
|
15
|
+
# "order_id": "41324123412342",
|
16
|
+
# "sign": "bb5c48ea540035e6b7c03c8184f74f09d26e9286a9b8f34b236b1bf2587e4268"
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
# @example Ответ
|
20
|
+
# {
|
21
|
+
# "transactions": [
|
22
|
+
# {
|
23
|
+
# "error_code": 0,
|
24
|
+
# "txn_id": 3666050,
|
25
|
+
# "txn_status": 2,
|
26
|
+
# "txn_type": 2,
|
27
|
+
# "txn_date": "2017-03-09T17:16:06+00:00",
|
28
|
+
# "pan": "400000******0002",
|
29
|
+
# "amount": 10000,
|
30
|
+
# "currency": 643,
|
31
|
+
# "auth_code": "181218",
|
32
|
+
# "merchant_site": 99,
|
33
|
+
# "card_name": "cardholder name",
|
34
|
+
# "card_bank": "",
|
35
|
+
# "order_id": "41324123412342"
|
36
|
+
# },
|
37
|
+
# {
|
38
|
+
# "error_code": 0,
|
39
|
+
# "txn_id": 3684050,
|
40
|
+
# "txn_status": 3,
|
41
|
+
# "txn_type": 4,
|
42
|
+
# "txn_date": "2017-03-09T17:16:09+00:00",
|
43
|
+
# "pan": "400000******0002",
|
44
|
+
# "amount": 100,
|
45
|
+
# "currency": 643,
|
46
|
+
# "merchant_site": 99,
|
47
|
+
# "card_name": "cardholder name",
|
48
|
+
# "card_bank": ""
|
49
|
+
# },
|
50
|
+
# {
|
51
|
+
# "error_code": 0,
|
52
|
+
# "txn_id": 3685050,
|
53
|
+
# "txn_status": 3,
|
54
|
+
# "txn_type": 4,
|
55
|
+
# "txn_date": "2017-03-19T17:16:06+00:00",
|
56
|
+
# "pan": "400000******0002",
|
57
|
+
# "amount": 100,
|
58
|
+
# "currency": 643,
|
59
|
+
# "merchant_site": 99,
|
60
|
+
# "card_name": "cardholder name",
|
61
|
+
# "card_bank": ""
|
62
|
+
# }
|
63
|
+
# ],
|
64
|
+
# "error_code": 0
|
65
|
+
# }
|
66
|
+
class StatusOperation < PaymentOperation
|
67
|
+
# Код операции sale
|
68
|
+
def self.opcode
|
69
|
+
30
|
70
|
+
end
|
71
|
+
|
72
|
+
# Описание операции
|
73
|
+
def self.description
|
74
|
+
'Запрос статуса операции'
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def self.in_params
|
80
|
+
%i[merchant_site txn_id order_id].freeze
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'base64'
|
3
|
+
require 'zlib'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module QiwiPay
|
7
|
+
# Чек 54-ФЗ
|
8
|
+
class Cheque
|
9
|
+
# Возможные значения НДС
|
10
|
+
module VAT
|
11
|
+
# не облагается НДС
|
12
|
+
NONE = 6
|
13
|
+
# облагается НДС по ставке 0%
|
14
|
+
VAT_0 = 5
|
15
|
+
# облагается НДС по ставке 10%
|
16
|
+
VAT_10 = 2
|
17
|
+
# облагается НДС по ставке 18%
|
18
|
+
VAT_18 = 1
|
19
|
+
# облагается НДС по ставке 10/110
|
20
|
+
VAT_110 = 4
|
21
|
+
# облагается НДС по ставке 18/118
|
22
|
+
VAT_118 = 3
|
23
|
+
end
|
24
|
+
|
25
|
+
# Возможные значения системы налогообложения
|
26
|
+
module TaxMode
|
27
|
+
# 0 — Общая система налогообложения
|
28
|
+
OSN = 0
|
29
|
+
# 1 — Упрощенная система налогообложения (Доход)
|
30
|
+
USN_D = 1
|
31
|
+
# 2 — Упрощенная СН (Доход минус Расход)
|
32
|
+
USN_DR = 2
|
33
|
+
# 3 — Единый налог на вмененный доход
|
34
|
+
ENVD = 3
|
35
|
+
# 4 — Единый сельскохозяйственный налог
|
36
|
+
ESHD = 4
|
37
|
+
# 5 — Патентная система налогообложения
|
38
|
+
PSN = 5
|
39
|
+
end
|
40
|
+
|
41
|
+
# Возможные значения типов чеков
|
42
|
+
module Type
|
43
|
+
# Приход
|
44
|
+
INFLOW = 1
|
45
|
+
# Возврат прихода
|
46
|
+
INFLOW_REVERSE = 2
|
47
|
+
# Расход
|
48
|
+
OUTFLOW = 3
|
49
|
+
# Возврат расхода
|
50
|
+
OUTFLOW_REVERSE = 4
|
51
|
+
end
|
52
|
+
|
53
|
+
# @option params seller_id [Integer] ИНН организации, для которой пробивается чек
|
54
|
+
# @option params cheque_type [Integer] Признак расчета (тэг 1054):
|
55
|
+
# 1. Приход
|
56
|
+
# 2. Возврат прихода
|
57
|
+
# 3. Расход
|
58
|
+
# 4. Возврат расхода
|
59
|
+
# @option params customer_contact [String] Телефон или электронный адрес покупателя (тэг 1008)
|
60
|
+
# @option params tax_system [Integer] Система налогообложения (тэг 1055):
|
61
|
+
# 0 – Общая, ОСН
|
62
|
+
# 1 – Упрощенная доход, УСН доход
|
63
|
+
# 2 – Упрощенная доход минус расход, УСН доход - расход
|
64
|
+
# 3 – Единый налог на вмененный доход, ЕНВД
|
65
|
+
# 4 – Единый сельскохозяйственный налог, ЕСН
|
66
|
+
# 5 – Патентная система налогообложения, Патент
|
67
|
+
# @option params positions [Array<Hash>] Массив товаров
|
68
|
+
def initialize(params)
|
69
|
+
@json = JSON.fast_generate params
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [String] cheque as JSON
|
73
|
+
# @example
|
74
|
+
# {
|
75
|
+
# "seller_id" : 3123011520,
|
76
|
+
# "cheque_type" : 1,
|
77
|
+
# "customer_contact" : "foo@domain.tld",
|
78
|
+
# "tax_system" : 1,
|
79
|
+
# "positions" : [
|
80
|
+
# {
|
81
|
+
# "quantity" : 2,
|
82
|
+
# "price" : 322.94,
|
83
|
+
# "tax" : 4,
|
84
|
+
# "description" : "Товар/Услуга 1"
|
85
|
+
# },
|
86
|
+
# {
|
87
|
+
# "quantity" : 1,
|
88
|
+
# "price" : 500,
|
89
|
+
# "tax" : 4,
|
90
|
+
# "description" : "Товар/Услуга 2"
|
91
|
+
# }
|
92
|
+
# ]
|
93
|
+
# }
|
94
|
+
def to_json
|
95
|
+
@json
|
96
|
+
end
|
97
|
+
|
98
|
+
# @return [String] Encoded cheque
|
99
|
+
def encode
|
100
|
+
Base64.strict_encode64(Zlib::Deflate.deflate(to_json))
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|