qiwi-pay 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|