payanyway 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 257f313795dce5796dc66612f46fa949cdb20e0c
4
- data.tar.gz: f6fb7fdec9464461c7b33fa81a0857eead5f83f5
3
+ metadata.gz: a3820acaab28d06906f0eb283beda473a1d2f084
4
+ data.tar.gz: 0e8f58b5347aea043c3ee8a17fc346afbb078d43
5
5
  SHA512:
6
- metadata.gz: 9e0de6dff4b65949d18b709cd12e7ba6f1ebf78927736b224d4b818b81c96b1ff33558688dcd8bf8058a932f2cc6e01f4b8c7d101757c6f0f041befccc3f9274
7
- data.tar.gz: 4af175a8d83770dc55017f5866c3243ebe179a8bea4ce743beca6ab41841ef91f32e2403c2719cd2fb434c79e36a038bbcdcfaf480bbeed4e927f003952fb8ff
6
+ metadata.gz: dbb2e8812b3d2d95fb3cdc87d23ad119600c763fffc19891980a9e5c681aeabfffa8ed63921b1ca9cae8d00aa8a7b301276951a671819b116eb539de353cb542
7
+ data.tar.gz: 8b4c4f979d6adf934788cb5fbf542b9288615cffd32c720f5682022b4f6ef66d49c94bf51802865acc23973460c646b1648a78b931c2b062041171faa9dc3caf
data/README.md CHANGED
@@ -44,7 +44,7 @@ class PayanywayController
44
44
 
45
45
  def pay_implementation(params)
46
46
  # вызывается при оповещении магазина об
47
- # успешной оплате пользователем заказа.
47
+ # успешной оплате пользователем заказа. (Pay URL)
48
48
  #
49
49
  # params[ KEY ], где KEY ∈ [ :moneta_id, :order_id, :operation_id,
50
50
  # :amount, :currency, :subscriber_id, :test_mode, :user, :corraccount,
@@ -54,6 +54,23 @@ class PayanywayController
54
54
  def fail_implementation(order_id)
55
55
  # вызывается при отправки шлюзом пользователя на Fail URL.
56
56
  end
57
+
58
+ def return_implementation(order_id)
59
+ # Вызывается при добровольном отказе пользователем от оплаты (Return URL)
60
+ end
61
+
62
+ def in_progress_implementation(order_id)
63
+ # Вызывается после успешного запроса на авторизацию средств,
64
+ # до подтверждения списания и зачисления средств (InProgress URL)
65
+ #
66
+ # ВНИМАНИЕ: InProgress URL может быть использован в любом способе оплаты.
67
+ # Если к моменту, когда пользователя надо вернуть в магазин оплата
68
+ # по какой-либо причине не завершена, то его перекинет на InProgress, если он указан.
69
+ # Если InProgress URL не указан, то на Success URL.
70
+ # Если операция уже успешно выполнилась, то сразу на Success URL.
71
+ # К примеру, в случае с картами чаще всего получается так, что операция не успевает выполниться,
72
+ # поэтому InProgress будет использован с бОльшей вероятностью, чем Success URL.
73
+ end
57
74
  end
58
75
  ```
59
76
 
@@ -73,7 +90,12 @@ production: <<: *config
73
90
  ```
74
91
  ## Использование
75
92
 
76
- Что бы получить ссылку на платежный шлюз для оплаты заказа пользвателем, используйте `Payanyway::Gateway.payment_url(params, use_signature = true)`, где `params[ KEY ]` такой, что `KEY` ∈ `[:order_id, :amount, :test_mode, :description, :subscriber_id, :custom1, :custom2, :custom3]`
93
+ Что бы получить ссылку на платежный шлюз для оплаты заказа пользвателем,
94
+ используйте `Payanyway::Gateway.payment_url(params, use_signature = true)`, где `params[ KEY ]` такой, что `KEY` ∈
95
+ `[:order_id, :amount, :test_mode, :description, :subscriber_id, :custom1, :custom2, :custom3, :locale, :payment_system_unit_id, :payment_system_limit_ids]`
96
+
97
+ Если в настройках счета в системе **moneta.ru** выставлен флаг «Можно переопределять настройки в URL», то можно так же передавать
98
+ `[:success_url, :in_progress_url, :fail_url, :return_url]`.
77
99
 
78
100
  Пример:
79
101
  ```ruby
@@ -84,7 +106,9 @@ class OrdersController < AplicationController
84
106
  order = Order.create(params[:order])
85
107
  redirect_to Payanyway::Gateway.payment_url(
86
108
  order_id: order.id,
87
- amount: order.total_amount
109
+ amount: order.total_amount,
110
+ locale: 'ru',
111
+ description: "Оплата заказа № #{ order.number } на сумму #{ order.total_amount }руб."
88
112
  )
89
113
  end
90
114
  end
@@ -93,18 +117,26 @@ end
93
117
  ### Расшифровка параметров
94
118
 
95
119
  params[ KEY ], где KEY | Описание
96
- --------------------------|:-----------------------------------------------------------
97
- `:moneta_id` | Идентификатор магазина в системе MONETA.RU.
98
- `:order_id` | Внутренний идентификатор заказа, однозначно определяющий заказ в магазине.
99
- `:operation_id` | Номер операции в системе MONETA.RU.
100
- `:amount` | Фактическая сумма, полученная на оплату заказа.
101
- `:currency` | ISO код валюты, в которой произведена оплата заказа в магазине.
102
- `:test_mode` | Флаг оплаты в тестовом режиме (1 - да, 0 - нет).
103
- `description` | Описание оплаты.
104
- `:subscriber_id` | Внутренний идентификатор пользователя в системе магазина.
105
- `:corraccount` | Номер счета плательщика.
106
- `:custom[1|2|3]` | Поля произвольных параметров. Будут возращены магазину в параметрах отчета о проведенной оплате.
107
- `:user` | Номер счета пользователя, если оплата производилась с пользовательского счета в системе «MONETA.RU».MONETA.Assistant.
120
+ ---------------------------|:-----------------------------------------------------------
121
+ `:moneta_id` | Идентификатор магазина в системе MONETA.RU.
122
+ `:order_id` | Внутренний идентификатор заказа, однозначно определяющий заказ в магазине.
123
+ `:operation_id` | Номер операции в системе MONETA.RU.
124
+ `:amount` | Фактическая сумма, полученная на оплату заказа.
125
+ `:currency` | ISO код валюты, в которой произведена оплата заказа в магазине.
126
+ `:test_mode` | Флаг оплаты в тестовом режиме (1 - да, 0 - нет).
127
+ `:description` | Описание оплаты.
128
+ `:subscriber_id` | Внутренний идентификатор пользователя в системе магазина.
129
+ `:corraccount` | Номер счета плательщика.
130
+ `:custom[1|2|3]` | Поля произвольных параметров. Будут возращены магазину в параметрах отчета о проведенной оплате.
131
+ `:user` | Номер счета пользователя, если оплата производилась с пользовательского счета в системе «MONETA.RU».MONETA.Assistant.
132
+ `:locale` | (ru\|en) Язык пользовательского интерфейса.
133
+ `:payment_system_unit_id` | Предварительный выбор платежной системы. (https://www.moneta.ru/viewPaymentMethods.htm)
134
+ `:payment_system_limit_ids`| Список (разделенный запятыми) идентификаторов платежных систем, которые необходимо показывать пользователю.
135
+ `:success_url` | URL страницы магазина, куда должен попасть покупатель после успешно выполненных действий.
136
+ `:in_progress_url` | URL страницы магазина, куда должен попасть покупатель после успешного запроса на авторизацию средств, до подтверждения списания и зачисления средств.
137
+ `:fail_url` | URL страницы магазина, куда должен попасть покупатель после отмененной или неуспешной оплаты.
138
+ `:return_url` | URL страницы магазина, куда должен вернуться покупатель при добровольном отказе от оплаты.
139
+
108
140
 
109
141
  ## Contributing
110
142
 
data/config/routes.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  Payanyway::Engine.routes.draw do
2
- get 'success' => 'payanyway#success', as: :payanyway_on_success
3
- get 'pay' => 'payanyway#pay', as: :payanyway_pay
4
- get 'fail' => 'payanyway#fail', as: :payanyway_on_fail
5
- end
2
+ get 'success' => 'payanyway#success', as: :payanyway_on_success
3
+ get 'pay' => 'payanyway#pay', as: :payanyway_pay
4
+ get 'fail' => 'payanyway#fail', as: :payanyway_on_fail
5
+ get 'return' => 'payanyway#return', as: :payanyway_on_return
6
+ get 'in_progress' => 'payanyway#in_progress', as: :payanyway_in_progress
7
+ get 'check' => 'payanyway#check', as: :payanyway_on_check
8
+ end
data/lib/payanyway.rb CHANGED
@@ -4,6 +4,10 @@ require 'active_support/core_ext'
4
4
  require 'payanyway/helpers/settings'
5
5
  require 'payanyway/helpers/signature_generator'
6
6
 
7
+ require 'payanyway/request/payment_url'
8
+ require 'payanyway/response/base'
9
+ require 'payanyway/response/pay'
10
+
7
11
  require 'payanyway/gateway'
8
12
  require 'payanyway/engine'
9
13
  require 'payanyway/controller'
@@ -8,49 +8,84 @@ module Payanyway
8
8
 
9
9
  def pay
10
10
  service = Payanyway::Response::Pay.new(params)
11
- service.perform
12
11
  service.success? ?
13
12
  pay_implementation(service.pretty_params) :
14
- error_log(service.pretty_params)
13
+ Rails.logger.error(service.error_message)
15
14
 
16
15
  render text: service.result
17
16
  end
18
17
 
19
18
  def success
20
19
  service = Payanyway::Response::Base.new(params)
21
- Rails.logger.info("Called success payment url for order '#{ service.pretty_params[:order_id] }'")
22
20
 
23
21
  success_implementation(service.pretty_params)
24
22
  end
25
23
 
26
24
  def fail
27
25
  service = Payanyway::Response::Base.new(params)
28
- Rails.logger.error("Fail paid order '#{ service.pretty_params[:order_id] }'")
29
26
 
30
- fail_implementation(service.pretty_params)
27
+ fail_implementation(service.pretty_params[:order_id])
31
28
  end
32
29
 
33
- private
30
+ def return
31
+ service = Payanyway::Response::Base.new(params)
32
+
33
+ return_implementation(service.pretty_params[:order_id])
34
+ end
35
+
36
+ def in_progress
37
+ service = Payanyway::Response::Base.new(params)
34
38
 
35
- def error_log(params)
36
- Rails.logger.error("ERROR! Invalid signature for order #{ params[:order_id] }. Params: #{ params.inspect }")
39
+ in_progress_implementation(service.pretty_params[:order_id])
37
40
  end
38
41
 
42
+ def check
43
+ service = Payanyway::Response::Check.new(params)
44
+ raise service.error_message unless service.success?
45
+
46
+ render xml: service.result(check_implementation(service.pretty_params)).to_xml
47
+ end
48
+
49
+ private
50
+
39
51
  def pay_implementation(params)
40
52
  # Вызывается после успешного прохождения
41
53
  # запроса об оплате от payanyway.ru
42
54
 
43
- Rails.logger.info("Success paid order #{ params[:order_id] }")
55
+ Rails.logger.info("PAYANYWAY: Success paid order #{ params[:order_id] }")
44
56
  end
45
57
 
46
58
  def success_implementation(params)
47
59
  # Вызывается после успешной оплаты
60
+
61
+ Rails.logger.info("PAYANYWAY: Called success payment url for order '#{ params[:order_id] }'")
48
62
  render nothing: true
49
63
  end
50
64
 
51
- def fail_implementation(params)
65
+ def fail_implementation(order_id)
52
66
  # Вызывается после ошибки при оплате
67
+
68
+ Rails.logger.error("PAYANYWAY: Fail paid order '#{ order_id }'")
69
+ render nothing: true
70
+ end
71
+
72
+ def return_implementation(order_id)
73
+ # Вызывается при добровольном отказе пользователем от оплаты
74
+
75
+ Rails.logger.info("PAYANYWAY: Return from payanyway. Order '#{ order_id }'")
53
76
  render nothing: true
54
77
  end
78
+
79
+ def in_progress_implementation(order_id)
80
+ # Вызывается после успешного запроса на авторизацию средств, до подтверждения списания и зачисления средств
81
+
82
+ Rails.logger.info("PAYANYWAY: Order '#{ order_id }' in progress")
83
+ render nothing: true
84
+ end
85
+
86
+ def check_implementation(params)
87
+ # Ответ на запрос о проверке заказа
88
+ # { amount: AMOUNT, state: STATE, description: description, attributes: ATTRIBUTES }
89
+ end
55
90
  end
56
91
  end
@@ -35,8 +35,19 @@ module Payanyway
35
35
  # * _params[custom1]_ - Поля произвольных параметров.
36
36
  # * _params[custom2]_ - Поля произвольных параметров.
37
37
  # * _params[custom3]_ - Поля произвольных параметров.
38
+ # * _params[locale]_ - (ru|en) Язык пользовательского интерфейса.
38
39
 
39
- Payanyway::Helpers::PaymentUrl.build(params, use_signature)
40
+ # * _params[payment_system_unit_id ]_ - Предварительный выбор платежной системы. (https://www.moneta.ru/viewPaymentMethods.htm)
41
+ # * _params[payment_system_limit_ids ]_ - Список (разделенный запятыми) идентификаторов платежных систем, которые необходимо показывать пользователю. (https://www.moneta.ru/viewPaymentMethods.htm)
42
+
43
+ # Эти параметры используются только тогда, когда в настройках счета выставлен флаг «Можно переопределять настройки в URL»
44
+ # * _params[success_url]_ - URL страницы магазина, куда должен попасть покупатель после успешно выполненных действий.
45
+ # * _params[inprogress_url]_- URL страницы магазина, куда должен попасть покупатель после успешного запроса на авторизацию средств, до подтверждения списания и зачисления средств.
46
+ # * _params[fail_url]_ - URL страницы магазина, куда должен попасть покупатель после отмененной или неуспешной оплаты.
47
+ # * _params[return_url]_ - URL страницы магазина, куда должен вернуться покупатель при добровольном отказе от оплаты.
48
+
49
+
50
+ Payanyway::Request::PaymentUrl.build(params, use_signature)
40
51
  end
41
52
 
42
53
  class << self
@@ -3,27 +3,29 @@ require 'digest/md5'
3
3
  module Payanyway
4
4
  module Helpers
5
5
  class SignatureGenerate
6
- class << self
7
- PAY_KEYS = %w(
8
- MNT_TRANSACTION_ID
9
- MNT_OPERATION_ID
10
- MNT_AMOUNT
11
- MNT_CURRENCY_CODE
12
- MNT_SUBSCRIBER_ID
13
- MNT_TEST_MODE
14
- )
15
-
16
- URL_KEYS = PAY_KEYS - [ 'MNT_OPERATION_ID' ]
17
-
18
- def for_pay(params)
19
- generate_by(params, PAY_KEYS)
20
- end
21
-
22
-
23
- def for_url(params)
24
- generate_by(params, URL_KEYS)
6
+ BASE_KEYS = %w(
7
+ MNT_TRANSACTION_ID
8
+ MNT_OPERATION_ID
9
+ MNT_AMOUNT
10
+ MNT_CURRENCY_CODE
11
+ MNT_SUBSCRIBER_ID
12
+ MNT_TEST_MODE
13
+ )
14
+
15
+ KEYS = {
16
+ pay: BASE_KEYS,
17
+ url: BASE_KEYS - [ 'MNT_OPERATION_ID' ],
18
+ check: [ 'MNT_COMMAND' ] + BASE_KEYS,
19
+ check_response: %w(MNT_RESULT_CODE MNT_ID MNT_TRANSACTION_ID)
20
+ }
21
+
22
+ KEYS.each do |key_name, keys|
23
+ define_singleton_method("for_#{ key_name }") do |params|
24
+ generate_by(params, keys)
25
25
  end
26
+ end
26
27
 
28
+ class << self
27
29
  private
28
30
 
29
31
  def generate_by(params, keys)
@@ -33,7 +35,7 @@ module Payanyway
33
35
  end
34
36
 
35
37
  def get_value(params, key)
36
- (key == 'MNT_AMOUNT') ? '%.2f' % params[key] : params[key]
38
+ (key == 'MNT_AMOUNT' && params[key].present?) ? '%.2f' % params[key] : params[key]
37
39
  end
38
40
 
39
41
  def md5(str)
@@ -1,15 +1,25 @@
1
1
  module Payanyway
2
- module Helpers
2
+ module Request
3
3
  class PaymentUrl
4
4
  PARAMS = {
5
- 'MNT_TRANSACTION_ID' => :order_id,
6
- 'MNT_DESCRIPTION' => :description,
7
- 'MNT_SUBSCRIBER_ID' => :subscriber_id,
8
- 'MNT_AMOUNT' => :amount,
9
- 'MNT_CUSTOM1' => :custom1,
10
- 'MNT_CUSTOM2' => :custom2,
11
- 'MNT_CUSTOM3' => :custom3
12
- # 'MNT_SIGNATURE' => добавляется при use_signature == true
5
+ 'MNT_TRANSACTION_ID' => :order_id,
6
+ 'MNT_AMOUNT' => :amount,
7
+ 'MNT_DESCRIPTION' => :description,
8
+ 'MNT_SUBSCRIBER_ID' => :subscriber_id,
9
+
10
+ 'MNT_SUCCESS_URL' => :success_url,
11
+ 'MNT_INPROGRESS_URL' => :in_progress_url,
12
+ 'MNT_FAIL_URL' => :fail_url,
13
+ 'MNT_RETURN_URL' => :return_url,
14
+
15
+ 'MNT_CUSTOM1' => :custom1,
16
+ 'MNT_CUSTOM2' => :custom2,
17
+ 'MNT_CUSTOM3' => :custom3,
18
+
19
+ 'moneta.locale' => :locale,
20
+ 'paymentSystem.unitId' => :payment_system_unit_id,
21
+ 'paymentSystem.limitIds' => :payment_system_limit_ids
22
+ # 'MNT_SIGNATURE' => добавляется при use_signature == true
13
23
  }.to_settings
14
24
 
15
25
  class << self
@@ -9,6 +9,10 @@ module Payanyway
9
9
  @params = params
10
10
  @pretty_params = @@_params.configure_by(params)
11
11
  end
12
+
13
+ def error_message
14
+ "ERROR! Invalid signature for order #{ @pretty_params[:order_id] }. Params: #{ @params.inspect }"
15
+ end
12
16
  end
13
17
  end
14
- end
18
+ end
@@ -0,0 +1,113 @@
1
+ module Payanyway
2
+ module Response
3
+ class InvalidState < Exception; end
4
+
5
+ class Check < Base
6
+ RESPONSE_CODE = {
7
+ set_amount: 100,
8
+ paid: 200,
9
+ in_process: 302,
10
+ unpaid: 402,
11
+ canceled: 500
12
+ }
13
+
14
+ @@_params = {
15
+ 'MNT_COMMAND' => :command,
16
+ 'MNT_ID' => :moneta_id,
17
+ 'MNT_TRANSACTION_ID' => :order_id,
18
+ 'MNT_OPERATION_ID' => :operation_id,
19
+ 'MNT_AMOUNT' => :amount,
20
+ 'MNT_CURRENCY_CODE' => :currency,
21
+ 'MNT_SUBSCRIBER_ID' => :subscriber_id,
22
+ 'MNT_TEST_MODE' => :test_mode,
23
+ 'MNT_SIGNATURE' => :signature,
24
+ 'MNT_USER' => :user,
25
+ 'MNT_CORRACCOUNT' => :corraccount,
26
+ 'MNT_CUSTOM1' => :custom1,
27
+ 'MNT_CUSTOM2' => :custom2,
28
+ 'MNT_CUSTOM3' => :custom3,
29
+ 'paymentSystem.unitId' => :payment_system_unit_id
30
+ }.invert.to_settings
31
+
32
+ def initialize(params)
33
+ super
34
+ @valid_signature = (@pretty_params[:signature] == Payanyway::Helpers::SignatureGenerate.for_check(@params))
35
+ end
36
+
37
+ def success?
38
+ @valid_signature
39
+ end
40
+
41
+ def result(attr)
42
+ # Возвращает Nokogiri::XML документ
43
+ # * _attr[:amount] - сумма заказа
44
+ # * _attr[:state] - статус платежа(см. RESPONSE_CODE)
45
+ # * _attr[:description] - Произвольное описание заказа (необязятельно)
46
+ # * _attr[:attributes] - Произвольный атрибуты заказа (необязятельно)
47
+
48
+ validate_status!(attr[:state])
49
+
50
+ xml = base_xml(attr[:amount], attr[:state], attr[:description])
51
+ parent = xml.at_css('MNT_RESPONSE')
52
+
53
+ parent.add_child(signature_node(xml))
54
+ parent.add_child(attributes_node(attr[:attributes], xml)) if attr[:attributes].present?
55
+
56
+ xml
57
+ end
58
+
59
+ private
60
+
61
+ def validate_status!(status)
62
+ if RESPONSE_CODE.keys.exclude?(status.to_sym)
63
+ raise InvalidState.new("PAYANYWAY: Invalid response state! State must be eq #{ RESPONSE_CODE.keys }")
64
+ end
65
+ end
66
+
67
+ def base_xml(amount, state, description)
68
+ xml = <<-EOXML
69
+ <MNT_RESPONSE>
70
+ <MNT_ID>#{ Payanyway::Gateway.config['moneta_id'] }</MNT_ID>
71
+ <MNT_TRANSACTION_ID>#{ @pretty_params[:order_id] }</MNT_TRANSACTION_ID>
72
+ <MNT_RESULT_CODE>#{ result_code_of(amount, state) }</MNT_RESULT_CODE>
73
+ <MNT_DESCRIPTION>#{ description }</MNT_DESCRIPTION>
74
+ <MNT_AMOUNT>#{ amount }</MNT_AMOUNT>
75
+ </MNT_RESPONSE>
76
+ EOXML
77
+
78
+ Nokogiri::XML(xml, nil, 'UTF-8')
79
+ end
80
+
81
+ def signature_node(xml)
82
+ create_new_node('MNT_SIGNATURE',
83
+ Payanyway::Helpers::SignatureGenerate.for_check_response(Hash.from_xml(xml.to_s)['MNT_RESPONSE']),
84
+ xml
85
+ )
86
+ end
87
+
88
+ def result_code_of(amount, state)
89
+ if @pretty_params[:amount].blank? && amount.present?
90
+ RESPONSE_CODE[:set_amount]
91
+ else
92
+ RESPONSE_CODE[state.to_sym]
93
+ end
94
+ end
95
+
96
+ def attributes_node(attributes, xml)
97
+ Nokogiri::XML::Node.new('MNT_ATTRIBUTES', xml).tap do |node|
98
+ attributes.each do |key, value|
99
+ attr_node = Nokogiri::XML::Node.new('ATTRIBUTE', xml)
100
+ attr_node.add_child(create_new_node('KEY', key.to_s, xml))
101
+ attr_node.add_child(create_new_node('VALUE', value.to_s, xml))
102
+
103
+ node.add_child(attr_node)
104
+ end
105
+ end
106
+ end
107
+
108
+ def create_new_node(name, content, xml)
109
+ Nokogiri::XML::Node.new(name, xml).tap { |node| node.content = content }
110
+ end
111
+ end
112
+ end
113
+ end
@@ -17,8 +17,9 @@ module Payanyway
17
17
  'MNT_CUSTOM3' => :custom3
18
18
  }.invert.to_settings
19
19
 
20
- def perform
21
- @valid_signature = (@pretty_params[:signature] == signature)
20
+ def initialize(params)
21
+ super
22
+ @valid_signature = (@pretty_params[:signature] == Payanyway::Helpers::SignatureGenerate.for_pay(@params))
22
23
  end
23
24
 
24
25
  def success?
@@ -1,3 +1,3 @@
1
1
  module Payanyway
2
- VERSION = '1.0.0'
2
+ VERSION = '1.2.0'
3
3
  end
data/payanyway.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'rails', '>= 3.2.0'
22
+ spec.add_dependency 'nokogiri'
22
23
 
23
24
  spec.add_development_dependency 'bundler', '~> 1.7'
24
25
  spec.add_development_dependency 'rake', '~> 10.0'
@@ -16,5 +16,20 @@ describe Payanyway::Engine, type: :routing do
16
16
  controller: 'payanyway',
17
17
  action: 'fail'
18
18
  )}
19
+
20
+ specify { get('/return').should route_to(
21
+ controller: 'payanyway',
22
+ action: 'return'
23
+ )}
24
+
25
+ specify { get('/in_progress').should route_to(
26
+ controller: 'payanyway',
27
+ action: 'in_progress'
28
+ )}
29
+
30
+ specify { get('/check').should route_to(
31
+ controller: 'payanyway',
32
+ action: 'check'
33
+ )}
19
34
  end
20
35
  end
@@ -3,7 +3,7 @@ describe PayanywayController do
3
3
 
4
4
  describe 'GET #success' do
5
5
  it 'should and message to logger' do
6
- expect(Rails.logger).to receive(:info).with("Called success payment url for order '676'")
6
+ expect(Rails.logger).to receive(:info).with("PAYANYWAY: Called success payment url for order '676'")
7
7
 
8
8
  get :success, { 'MNT_TRANSACTION_ID' => 676 }
9
9
  end
@@ -11,9 +11,42 @@ describe PayanywayController do
11
11
 
12
12
  describe 'GET #fail' do
13
13
  it 'should and message to logger' do
14
- expect(Rails.logger).to receive(:error).with("Fail paid order '676'")
14
+ expect(Rails.logger).to receive(:error).with("PAYANYWAY: Fail paid order '676'")
15
15
 
16
16
  get :fail, { 'MNT_TRANSACTION_ID' => 676 }
17
17
  end
18
18
  end
19
- end
19
+
20
+ describe 'GET #return' do
21
+ it 'should and message to logger' do
22
+ expect(Rails.logger).to receive(:info).with("PAYANYWAY: Return from payanyway. Order '676'")
23
+
24
+ get :return, { 'MNT_TRANSACTION_ID' => 676 }
25
+ end
26
+ end
27
+
28
+ describe 'GET #in_progress' do
29
+ it 'should and message to logger' do
30
+ expect(Rails.logger).to receive(:info).with("PAYANYWAY: Order '676' in progress")
31
+
32
+ get :in_progress, { 'MNT_TRANSACTION_ID' => 676 }
33
+ end
34
+ end
35
+
36
+ describe 'GET #check' do
37
+ context 'when invalid signature' do
38
+ it 'should raise error' do
39
+ expect{ get :check }.to raise_error
40
+ end
41
+ end
42
+
43
+ context 'when valid signature' do
44
+ it 'should and message to logger' do
45
+ expect_any_instance_of(Payanyway::Controller).to receive(:check_implementation).and_return({amount: 12, state: :paid})
46
+ get :check, { 'MNT_TRANSACTION_ID' => 676, 'MNT_SIGNATURE' => '79c1c4f41a0a70bb107c976ebba25811' }
47
+
48
+ expect(Nokogiri::XML(response.body).at_css('MNT_RESPONSE')).to be_present
49
+ end
50
+ end
51
+ end
52
+ end
@@ -23,4 +23,4 @@ describe Payanyway::Gateway do
23
23
  it { is_expected.to be_include('MNT_SIGNATURE') }
24
24
  end
25
25
  end
26
- end
26
+ end
@@ -0,0 +1,43 @@
1
+ require 'uri'
2
+
3
+ describe Payanyway::Request::PaymentUrl do
4
+ subject do
5
+ parse_url = URI(described_class.build(params, false))
6
+
7
+ Hash[ URI.decode_www_form(parse_url.query) ]
8
+ end
9
+
10
+ context 'when reset urls' do
11
+ let(:params) {
12
+ {
13
+ amount: '120.25',
14
+ order_id: 'FF790ABCD',
15
+ success_url: 'success_url',
16
+ in_progress_url: 'in_progress_url',
17
+ fail_url: 'fail_url',
18
+ return_url: 'return_url'
19
+ }
20
+ }
21
+
22
+ its(['MNT_SUCCESS_URL']) { is_expected.to eq('success_url') }
23
+ its(['MNT_INPROGRESS_URL']) { is_expected.to eq('in_progress_url') }
24
+ its(['MNT_FAIL_URL']) { is_expected.to eq('fail_url') }
25
+ its(['MNT_RETURN_URL']) { is_expected.to eq('return_url') }
26
+ end
27
+
28
+ context 'when set payment params' do
29
+ let(:params) {
30
+ {
31
+ amount: '120.25',
32
+ order_id: 'FF790ABCD',
33
+ locale: 'ru',
34
+ payment_system_unit_id: '1015',
35
+ payment_system_limit_ids: '1015,1017'
36
+ }
37
+ }
38
+
39
+ its(['moneta.locale']) { is_expected.to eq('ru') }
40
+ its(['paymentSystem.unitId']) { is_expected.to eq('1015') }
41
+ its(['paymentSystem.limitIds']) { is_expected.to eq('1015,1017') }
42
+ end
43
+ end
@@ -0,0 +1,11 @@
1
+ describe Payanyway::Response::Base do
2
+ let(:service) { described_class.new(params) }
3
+ let(:params) { { 'MNT_ID' => 1, 'MNT_AMOUNT' => 10.20 } }
4
+
5
+ describe '#pretty_params' do
6
+ subject { service.pretty_params }
7
+
8
+ its([:moneta_id]) { is_expected.to eq(1) }
9
+ its([:amount]) { is_expected.to eq(10.20) }
10
+ end
11
+ end
@@ -0,0 +1,102 @@
1
+ describe Payanyway::Response::Check do
2
+ RSpec::Matchers.define :be_eq_node do |expected|
3
+ def value_of(node)
4
+ elements = node.children.select { |e| e.instance_of? Nokogiri::XML::Element }
5
+ elements.map { |el| [ el.name, el.children.many? ? value_of(el) : el.children.text ] }
6
+ end
7
+
8
+ match do |actual|
9
+ value_of(actual) == value_of(expected)
10
+ end
11
+ end
12
+
13
+ let(:service) { described_class.new(params) }
14
+ let(:request_amount) { 10.20 }
15
+ let(:params) do
16
+ {
17
+ 'MNT_TRANSACTION_ID' => 2,
18
+ 'MNT_OPERATION_ID' => 3,
19
+ 'MNT_AMOUNT' => request_amount,
20
+ 'MNT_CURRENCY_CODE' => 'RUB',
21
+ 'MNT_TEST_MODE' => 1
22
+ }
23
+ end
24
+
25
+ describe '#result' do
26
+ let(:xml) { service.result(amount: amount, state: state, description: description, attributes: attributes) }
27
+ let(:amount) { request_amount }
28
+ let(:state) { :unpaid }
29
+ let(:description) { 'Заказ создан, но не оплачен' }
30
+ let(:attributes) { {} }
31
+
32
+ context 'when code 402' do
33
+ it 'should valid xml' do
34
+ expected = <<-EOXML
35
+ <MNT_RESPONSE>
36
+ <MNT_ID>141290</MNT_ID>
37
+ <MNT_TRANSACTION_ID>2</MNT_TRANSACTION_ID>
38
+ <MNT_RESULT_CODE>402</MNT_RESULT_CODE>
39
+ <MNT_DESCRIPTION>Заказ создан, но не оплачен</MNT_DESCRIPTION>
40
+ <MNT_AMOUNT>10.2</MNT_AMOUNT>
41
+ <MNT_SIGNATURE>061c2b859c27c75db9e5bbef3aef90a0</MNT_SIGNATURE>
42
+ </MNT_RESPONSE>
43
+ EOXML
44
+ expected_xml = Nokogiri::XML(expected, nil, 'UTF-8')
45
+
46
+ expect(xml.at_css('MNT_RESPONSE')).to be_eq_node(expected_xml.at_css('MNT_RESPONSE'))
47
+ end
48
+ end
49
+
50
+ context 'when have attributes' do
51
+ let(:attributes) { { type: 'chocolate', brand: 'Mars' } }
52
+
53
+ it 'should generate attributes xml' do
54
+ expected = <<-EOXML
55
+ <MNT_RESPONSE>
56
+ <MNT_ATTRIBUTES>
57
+ <ATTRIBUTE>
58
+ <KEY>type</KEY>
59
+ <VALUE>chocolate</VALUE>
60
+ </ATTRIBUTE>
61
+ <ATTRIBUTE>
62
+ <KEY>brand</KEY>
63
+ <VALUE>Mars</VALUE>
64
+ </ATTRIBUTE>
65
+ </MNT_ATTRIBUTES>
66
+ </MNT_RESPONSE>
67
+ EOXML
68
+
69
+ expected_xml = Nokogiri::XML(expected, nil, 'UTF-8')
70
+ expect(xml.at_css('MNT_ATTRIBUTES')).to be_eq_node(expected_xml.at_css('MNT_ATTRIBUTES'))
71
+ end
72
+ end
73
+
74
+ describe 'response code' do
75
+ context 'when invalid status' do
76
+ let(:state) { 'foobar' }
77
+ it 'should raise error' do
78
+ expect { xml }.to raise_error(Payanyway::Response::InvalidState)
79
+ end
80
+ end
81
+
82
+ context 'when set amount' do
83
+ let(:request_amount) { nil }
84
+ let(:amount) { 10.10 }
85
+
86
+ it 'should eq 100' do
87
+ code_node = xml.at_css('MNT_RESULT_CODE')
88
+ expect(code_node.text).to eq('100')
89
+ end
90
+ end
91
+
92
+ context 'when valid status' do
93
+ let(:state) { :paid }
94
+
95
+ it 'should eq 200' do
96
+ code_node = xml.at_css('MNT_RESULT_CODE')
97
+ expect(code_node.text).to eq('200')
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -12,20 +12,9 @@ describe Payanyway::Response::Pay do
12
12
  }
13
13
  end
14
14
 
15
- describe '#pretty_params' do
16
- subject { service.pretty_params }
17
-
18
- its([:moneta_id]) { is_expected.to eq(1) }
19
- its([:amount]) { is_expected.to eq(10.20) }
20
- end
21
-
22
- describe '#perform' do
15
+ describe '#success?' do
23
16
  subject { service.success? }
24
17
 
25
- context 'when success' do
26
- before { service.perform }
27
-
28
- it { is_expected.to be_truthy }
29
- end
18
+ it { is_expected.to be_truthy }
30
19
  end
31
- end
20
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: payanyway
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ssnikolay
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-18 00:00:00.000000000 Z
11
+ date: 2015-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -156,10 +170,11 @@ files:
156
170
  - lib/payanyway/controller.rb
157
171
  - lib/payanyway/engine.rb
158
172
  - lib/payanyway/gateway.rb
159
- - lib/payanyway/helpers/payment_url.rb
160
173
  - lib/payanyway/helpers/settings.rb
161
174
  - lib/payanyway/helpers/signature_generator.rb
175
+ - lib/payanyway/request/payment_url.rb
162
176
  - lib/payanyway/response/base.rb
177
+ - lib/payanyway/response/check.rb
163
178
  - lib/payanyway/response/pay.rb
164
179
  - lib/payanyway/version.rb
165
180
  - payanyway.gemspec
@@ -170,6 +185,9 @@ files:
170
185
  - spec/internal/config/payanyway.yml
171
186
  - spec/lib/payanyway/gateway_spec.rb
172
187
  - spec/lib/payanyway/helpers/signature_generator_spec.rb
188
+ - spec/lib/payanyway/request/payment_url_spec.rb
189
+ - spec/lib/payanyway/response/base_spec.rb
190
+ - spec/lib/payanyway/response/check_spec.rb
173
191
  - spec/lib/payanyway/response/pay_spec.rb
174
192
  - spec/spec_helper.rb
175
193
  homepage: ''
@@ -204,5 +222,8 @@ test_files:
204
222
  - spec/internal/config/payanyway.yml
205
223
  - spec/lib/payanyway/gateway_spec.rb
206
224
  - spec/lib/payanyway/helpers/signature_generator_spec.rb
225
+ - spec/lib/payanyway/request/payment_url_spec.rb
226
+ - spec/lib/payanyway/response/base_spec.rb
227
+ - spec/lib/payanyway/response/check_spec.rb
207
228
  - spec/lib/payanyway/response/pay_spec.rb
208
229
  - spec/spec_helper.rb