payneteasy-payneteasyapi 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.
Files changed (87) hide show
  1. data/.gemtest +0 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +18 -0
  4. data/README.md +54 -0
  5. data/Rakefile +8 -0
  6. data/doc/00-basic-tutorial.md +254 -0
  7. data/doc/01-library-internals.md +6 -0
  8. data/doc/02-payment-scenarios.md +9 -0
  9. data/doc/library-internals/00-payment-data.md +162 -0
  10. data/doc/library-internals/01-payment-processor.md +163 -0
  11. data/doc/library-internals/02-validator.md +55 -0
  12. data/doc/library-internals/03-property-accessor.md +76 -0
  13. data/doc/payment-scenarios/00-sale-transactions.md +90 -0
  14. data/doc/payment-scenarios/01-preauth-capture-transactions.md +105 -0
  15. data/doc/payment-scenarios/02-transfer-transactions.md +89 -0
  16. data/doc/payment-scenarios/03-return-transactions.md +52 -0
  17. data/doc/payment-scenarios/04-recurrent-transactions.md +110 -0
  18. data/doc/payment-scenarios/05-payment-form-integration.md +59 -0
  19. data/doc/payment-scenarios/06-merchant-callbacks.md +29 -0
  20. data/example/capture.rb +12 -0
  21. data/example/common/functions.rb +56 -0
  22. data/lib/paynet_easy/paynet_easy_api/callback/callback_factory.rb +47 -0
  23. data/lib/paynet_easy/paynet_easy_api/callback/callback_prototype.rb +186 -0
  24. data/lib/paynet_easy/paynet_easy_api/callback/customer_return_callback.rb +28 -0
  25. data/lib/paynet_easy/paynet_easy_api/callback/paynet_easy_callback.rb +44 -0
  26. data/lib/paynet_easy/paynet_easy_api/error/paynet_error.rb +4 -0
  27. data/lib/paynet_easy/paynet_easy_api/error/request_error.rb +6 -0
  28. data/lib/paynet_easy/paynet_easy_api/error/response_error.rb +6 -0
  29. data/lib/paynet_easy/paynet_easy_api/error/validation_error.rb +6 -0
  30. data/lib/paynet_easy/paynet_easy_api/payment_data/billing_address.rb +41 -0
  31. data/lib/paynet_easy/paynet_easy_api/payment_data/credit_card.rb +32 -0
  32. data/lib/paynet_easy/paynet_easy_api/payment_data/customer.rb +35 -0
  33. data/lib/paynet_easy/paynet_easy_api/payment_data/data.rb +13 -0
  34. data/lib/paynet_easy/paynet_easy_api/payment_data/payment.rb +190 -0
  35. data/lib/paynet_easy/paynet_easy_api/payment_data/payment_transaction.rb +188 -0
  36. data/lib/paynet_easy/paynet_easy_api/payment_data/query_config.rb +95 -0
  37. data/lib/paynet_easy/paynet_easy_api/payment_data/recurrent_card.rb +40 -0
  38. data/lib/paynet_easy/paynet_easy_api/payment_processor.rb +251 -0
  39. data/lib/paynet_easy/paynet_easy_api/paynet_easy_api.rb +26 -0
  40. data/lib/paynet_easy/paynet_easy_api/query/capture_query.rb +30 -0
  41. data/lib/paynet_easy/paynet_easy_api/query/create_card_ref_query.rb +78 -0
  42. data/lib/paynet_easy/paynet_easy_api/query/get_card_info_query.rb +49 -0
  43. data/lib/paynet_easy/paynet_easy_api/query/make_rebill_query.rb +37 -0
  44. data/lib/paynet_easy/paynet_easy_api/query/preauth_form_query.rb +10 -0
  45. data/lib/paynet_easy/paynet_easy_api/query/preauth_query.rb +10 -0
  46. data/lib/paynet_easy/paynet_easy_api/query/prototype/payment_form_query.rb +69 -0
  47. data/lib/paynet_easy/paynet_easy_api/query/prototype/payment_query.rb +71 -0
  48. data/lib/paynet_easy/paynet_easy_api/query/prototype/query.rb +302 -0
  49. data/lib/paynet_easy/paynet_easy_api/query/query_factory.rb +19 -0
  50. data/lib/paynet_easy/paynet_easy_api/query/return_query.rb +46 -0
  51. data/lib/paynet_easy/paynet_easy_api/query/sale_form_query.rb +10 -0
  52. data/lib/paynet_easy/paynet_easy_api/query/sale_query.rb +53 -0
  53. data/lib/paynet_easy/paynet_easy_api/query/status_query.rb +50 -0
  54. data/lib/paynet_easy/paynet_easy_api/query/transfer_by_ref_query.rb +41 -0
  55. data/lib/paynet_easy/paynet_easy_api/query/transfer_form_query.rb +10 -0
  56. data/lib/paynet_easy/paynet_easy_api/transport/callback_response.rb +21 -0
  57. data/lib/paynet_easy/paynet_easy_api/transport/gateway_client.rb +91 -0
  58. data/lib/paynet_easy/paynet_easy_api/transport/request.rb +20 -0
  59. data/lib/paynet_easy/paynet_easy_api/transport/response.rb +136 -0
  60. data/lib/paynet_easy/paynet_easy_api/util/property_accessor.rb +60 -0
  61. data/lib/paynet_easy/paynet_easy_api/util/string.rb +9 -0
  62. data/lib/paynet_easy/paynet_easy_api/util/validator.rb +110 -0
  63. data/payneteasy-payneteasyapi.gemspec +16 -0
  64. data/test/paynet_easy/paynet_easy_api/callback/callback_factory_test.rb +22 -0
  65. data/test/paynet_easy/paynet_easy_api/callback/callback_test_prototype.rb +168 -0
  66. data/test/paynet_easy/paynet_easy_api/callback/customer_return_callback_test.rb +95 -0
  67. data/test/paynet_easy/paynet_easy_api/callback/paynet_easy_callback_test.rb +101 -0
  68. data/test/paynet_easy/paynet_easy_api/fake.rb +71 -0
  69. data/test/paynet_easy/paynet_easy_api/payment_processor_test.rb +255 -0
  70. data/test/paynet_easy/paynet_easy_api/query/capture_query_test.rb +48 -0
  71. data/test/paynet_easy/paynet_easy_api/query/create_card_ref_query_test.rb +116 -0
  72. data/test/paynet_easy/paynet_easy_api/query/get_card_info_query_test.rb +116 -0
  73. data/test/paynet_easy/paynet_easy_api/query/make_rebill_query_test.rb +59 -0
  74. data/test/paynet_easy/paynet_easy_api/query/prototype/payment_query_test_prototype.rb +117 -0
  75. data/test/paynet_easy/paynet_easy_api/query/prototype/query_test_prototype.rb +190 -0
  76. data/test/paynet_easy/paynet_easy_api/query/prototype/sync_query_test_prototype.rb +88 -0
  77. data/test/paynet_easy/paynet_easy_api/query/query_factory_test.rb +21 -0
  78. data/test/paynet_easy/paynet_easy_api/query/return_query_test.rb +58 -0
  79. data/test/paynet_easy/paynet_easy_api/query/sale_form_query_test.rb +96 -0
  80. data/test/paynet_easy/paynet_easy_api/query/sale_query_test.rb +78 -0
  81. data/test/paynet_easy/paynet_easy_api/query/status_query_test.rb +81 -0
  82. data/test/paynet_easy/paynet_easy_api/query/transfer_by_ref_query_test.rb +63 -0
  83. data/test/paynet_easy/paynet_easy_api/transport/gateway_client_test.rb +22 -0
  84. data/test/paynet_easy/paynet_easy_api/transport/response_test.rb +26 -0
  85. data/test/paynet_easy/paynet_easy_api/util/property_accessor_test.rb +52 -0
  86. data/test/paynet_easy/paynet_easy_api/util/validator_test.rb +42 -0
  87. metadata +204 -0
@@ -0,0 +1,136 @@
1
+ require 'error/paynet_error'
2
+
3
+ module PaynetEasy::PaynetEasyApi::Transport
4
+ class Response
5
+ include PaynetEasy::PaynetEasyApi::Error
6
+
7
+ # Need to update payment status
8
+ NEEDED_STATUS_UPDATE = 'status_update'
9
+
10
+ # Need to show html from response
11
+ NEEDED_SHOW_HTML = 'show_html'
12
+
13
+ # Need redirect to response url
14
+ NEEDED_REDIRECT = 'redirect'
15
+
16
+ @@allowed_needed_actions =
17
+ [
18
+ NEEDED_STATUS_UPDATE,
19
+ NEEDED_SHOW_HTML,
20
+ NEEDED_REDIRECT
21
+ ]
22
+
23
+ attr_accessor :needed_action
24
+
25
+ def initialize(response = {})
26
+ @data = Hash[response.map {|key, value| [key, value.to_s.strip]}]
27
+ end
28
+
29
+ def needed_action=(needed_action)
30
+ unless @@allowed_needed_actions.include? needed_action
31
+ raise ArgumentError, "Unknown needed action: '#{needed_action}'"
32
+ end
33
+
34
+ @needed_action = needed_action
35
+ end
36
+
37
+ def status_update_needed?
38
+ needed_action == NEEDED_STATUS_UPDATE
39
+ end
40
+
41
+ def show_html_needed?
42
+ needed_action == NEEDED_SHOW_HTML
43
+ end
44
+
45
+ def redirect_needed?
46
+ needed_action == NEEDED_REDIRECT
47
+ end
48
+
49
+ def html
50
+ fetch 'html', nil
51
+ end
52
+
53
+ def has_html?
54
+ !html.nil?
55
+ end
56
+
57
+ def type
58
+ fetch('type').downcase if key? 'type'
59
+ end
60
+
61
+ def status
62
+ if !fetch('status', nil) && !%w(validation-error error).include?(type)
63
+ store 'status', 'processing'
64
+ end
65
+
66
+ fetch('status').downcase if key? 'status'
67
+ end
68
+
69
+ def approved?
70
+ status == 'approved'
71
+ end
72
+
73
+ def processing?
74
+ status == 'processing'
75
+ end
76
+
77
+ def declined?
78
+ %w(filtered declined).include? status
79
+ end
80
+
81
+ def payment_client_id
82
+ any_key %w(merchant-order-id client_orderid merchant_order)
83
+ end
84
+
85
+ def payment_paynet_id
86
+ any_key %w(orderid paynet-order-id)
87
+ end
88
+
89
+ def card_paynet_id
90
+ fetch 'card-ref-id', nil
91
+ end
92
+
93
+ def redirect_url
94
+ fetch 'redirect-url', nil
95
+ end
96
+
97
+ def has_redirect_url?
98
+ !redirect_url.nil?
99
+ end
100
+
101
+ def control_code
102
+ any_key %w(control merchant_control)
103
+ end
104
+
105
+ def error_message
106
+ any_key %w(error_message error-message)
107
+ end
108
+
109
+ def error_code
110
+ any_key %w(error_code error-code)
111
+ end
112
+
113
+ def error?
114
+ %w(validation-error error).include?(type) || status == 'error'
115
+ end
116
+
117
+ def error
118
+ if error? || declined?
119
+ PaynetError.new error_message
120
+ else
121
+ raise RuntimeError, 'Response has no error'
122
+ end
123
+ end
124
+
125
+ def method_missing(name, *args, &block)
126
+ @data.send name, *args, &block
127
+ end
128
+
129
+ protected
130
+
131
+ def any_key(keys)
132
+ keys.each {|key| return fetch key if key? key}
133
+ nil # if all keys missed in data
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,60 @@
1
+ module PaynetEasy::PaynetEasyApi::Util
2
+ module PropertyAccessor
3
+ # Get property value by property path.
4
+ #
5
+ # @param object [Object] Object with data
6
+ # @param property_path [String] Path to property
7
+ # @param fail_on_error [TrueClass|FalseClass] Throw exception if error occurred or not
8
+ #
9
+ # @return [Object|NilClass]
10
+ def self.get_value(object, property_path, fail_on_error = true)
11
+ if !property_path.include? '.'
12
+ if object.respond_to? property_path
13
+ return object.send property_path
14
+ elsif fail_on_error
15
+ raise RuntimeError, "Expected object with method '#{property_path}'"
16
+ else
17
+ return
18
+ end
19
+ end
20
+
21
+ first_property, path_rest = property_path.split '.', 2
22
+ first_object = object.send first_property
23
+
24
+ if first_object
25
+ return self.get_value first_object, path_rest, fail_on_error
26
+ elsif fail_on_error
27
+ raise RuntimeError, "Object expected for property path '#{first_property}'"
28
+ end
29
+ end
30
+
31
+ # Set property value by property path.
32
+ #
33
+ # @param object [Object] Object with data
34
+ # @param property_path [String] Path to property
35
+ # @param value [Object] Value to set
36
+ # @param fail_on_error [TrueClass|FalseClass] Throw exception if error occurred or not
37
+ #
38
+ # @return [Object|NilClass]
39
+ def self.set_value(object, property_path, value, fail_on_error = true)
40
+ if !property_path.include? '.'
41
+ if object.respond_to? "#{property_path}="
42
+ return object.send "#{property_path}=", value
43
+ elsif fail_on_error
44
+ raise RuntimeError, "Expected object with method '#{property_path}='"
45
+ else
46
+ return
47
+ end
48
+ end
49
+
50
+ first_property, path_rest = property_path.split '.', 2
51
+ first_object = object.send(first_property)
52
+
53
+ if first_object
54
+ return self.set_value first_object, path_rest, value, fail_on_error
55
+ elsif fail_on_error
56
+ raise RuntimeError, "Object expected for property path '#{first_property}'"
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,9 @@
1
+ class String
2
+ # Convert string from format <this_is_the_string> or
3
+ # <this-is-the-string> to format <ThisIsTheString>
4
+ #
5
+ # @return [String] New string, converted to camel-case format
6
+ def camelize
7
+ split(/_|-/).map(&:capitalize).join('')
8
+ end
9
+ end
@@ -0,0 +1,110 @@
1
+ require 'uri'
2
+ require 'ipaddr'
3
+ require 'error/validation_error'
4
+
5
+ module PaynetEasy::PaynetEasyApi::Util
6
+ module Validator
7
+ include PaynetEasy::PaynetEasyApi::Error
8
+
9
+ # Validate value as email
10
+ EMAIL = 'email'
11
+
12
+ # Validate value as IP address
13
+ IP = 'ip'
14
+
15
+ # Validate value as URL
16
+ URL = 'url'
17
+
18
+ # Validate value as month
19
+ MONTH = 'month'
20
+
21
+ # Validate value as year
22
+ YEAR = 'year'
23
+
24
+ # Validate value as phone number
25
+ PHONE = 'phone'
26
+
27
+ # Validate value as payment amount
28
+ AMOUNT = 'amount'
29
+
30
+ # Validate value as currency
31
+ CURRENCY = 'currency'
32
+
33
+ # Validate value as card verification value
34
+ CVV2 = 'cvv2'
35
+
36
+ # Validate value as zip code
37
+ ZIP_CODE = 'zip_code'
38
+
39
+ # Validate value as two-letter country or state code
40
+ COUNTRY = 'country'
41
+
42
+ # Validate value as date in format MMDDYY
43
+ DATE = 'date'
44
+
45
+ # Validate value as last four digits of social security number
46
+ SSN = 'ssn'
47
+
48
+ # Validate value as credit card number
49
+ CREDIT_CARD_NUMBER = 'credit_card_number'
50
+
51
+ # Validate value as different IDs (client, paynet, card-ref)
52
+ ID = 'id'
53
+
54
+ # Validate value as medium string
55
+ MEDIUM_STRING = 'medium_string'
56
+
57
+ # Validate value as long string
58
+ LONG_STRING = 'long_string'
59
+
60
+ # Regular expressions for some validation rules
61
+ @@rule_regexps =
62
+ {
63
+ EMAIL => /@+/,
64
+ PHONE => /^[0-9\-\+\(\)\s]{6,15}$/i,
65
+ AMOUNT => /^[0-9\.]{1,11}$/i,
66
+ CURRENCY => /^[A-Z]{1,3}$/i,
67
+ CVV2 => /^[\S\s]{3,4}$/i,
68
+ ZIP_CODE => /^[\S\s]{1,10}$/i,
69
+ COUNTRY => /^[A-Z]{1,2}$/i,
70
+ YEAR => /^[0-9]{1,2}$/i,
71
+ DATE => /^[0-9]{6}$/i,
72
+ SSN => /^[0-9]{1,4}$/i,
73
+ CREDIT_CARD_NUMBER => /^[0-9]{1,20}$/i,
74
+ ID => /^[\S\s]{1,20}$/i,
75
+ MEDIUM_STRING => /^[\S\s]{1,50}$/i,
76
+ LONG_STRING => /^[\S\s]{1,128}$/i
77
+ }
78
+
79
+ # Validates value by given rule.
80
+ # Rule can be one of Validator constants or regExp.
81
+ #
82
+ # @param value [Object] Value for validation
83
+ # @param rule [String|Regexp] Rule for validation
84
+ # @param fail_on_error [TrueClass|FalseClass] Throw exception on invalid value or not
85
+ #
86
+ # @return [TrueClass|FalseClass] Validation result
87
+ def self.validate_by_rule(value, rule, fail_on_error = true)
88
+ begin
89
+ valid = case rule
90
+ when URL then URI::ABS_URI === value
91
+ when IP then IPAddr.new value
92
+ when MONTH then (1..12).include? value.to_i
93
+ else
94
+ regexp = @@rule_regexps.key?(rule) ? @@rule_regexps[rule] : rule
95
+ regexp === value.to_s
96
+ end
97
+ rescue Exception
98
+ valid = false
99
+ end
100
+
101
+ if valid
102
+ true
103
+ elsif fail_on_error
104
+ raise ValidationError, "Value '#{value}' does not match rule '#{rule}'"
105
+ else
106
+ false
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,16 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'payneteasy-payneteasyapi'
3
+ s.version = '0.1.0'
4
+ s.summary = 'Ruby library for PaynetEasy payment API.'
5
+ s.author = 'Artem Ponomarenko'
6
+ s.email = 'imenem@inbox.ru'
7
+ s.require_paths = ['lib', 'lib/paynet_easy/paynet_easy_api']
8
+
9
+ s.files = Dir['lib/**/*.rb'] + %w(.gemtest Gemfile Gemfile.lock Rakefile payneteasy-payneteasyapi.gemspec)
10
+ s.test_files = Dir['test/**/*.rb']
11
+ s.extra_rdoc_files = Dir['example/**/*.rb'] + Dir['doc/**/*.md'] << 'README.md'
12
+
13
+ s.required_ruby_version = '>= 1.9.3'
14
+ s.add_development_dependency 'test-unit'
15
+ s.add_development_dependency 'rake'
16
+ end
@@ -0,0 +1,22 @@
1
+ require 'test/unit'
2
+ require 'paynet_easy_api'
3
+ require 'callback/callback_factory'
4
+ require 'callback/customer_return_callback'
5
+ require 'callback/paynet_easy_callback'
6
+
7
+ module PaynetEasy::PaynetEasyApi::Callback
8
+ class CallbackFactoryTest < Test::Unit::TestCase
9
+ def setup
10
+ @object = CallbackFactory.new
11
+ end
12
+
13
+ def test_callback
14
+ callback = @object.callback 'customer_return'
15
+ assert_instance_of CustomerReturnCallback, callback
16
+
17
+ callback = @object.callback 'sale'
18
+ assert_instance_of PaynetEasyCallback, callback
19
+ assert_equal 'sale', callback.instance_variable_get(:@callback_type)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,168 @@
1
+ require 'test/unit'
2
+ require 'digest/sha1'
3
+ require 'paynet_easy_api'
4
+ require 'callback/callback_prototype'
5
+ require 'payment_data/payment_transaction'
6
+ require 'payment_data/payment'
7
+ require 'payment_data/query_config'
8
+ require 'transport/callback_response'
9
+ require 'error/validation_error'
10
+ require 'error/paynet_error'
11
+
12
+ module PaynetEasy::PaynetEasyApi::Callback
13
+ module CallbackTestPrototype
14
+ include PaynetEasy::PaynetEasyApi::PaymentData
15
+ include PaynetEasy::PaynetEasyApi::Transport
16
+ include PaynetEasy::PaynetEasyApi::Error
17
+
18
+ SIGNING_KEY = 'D5F82EC1-8575-4482-AD89-97X6X0X20X22'
19
+ CLIENT_ID = 'CLIENT-112233'
20
+ PAYNET_ID = 'PAYNET-112233'
21
+
22
+ def test_process_callback_approved
23
+ raise NotImplementedError
24
+ end
25
+
26
+ def assert_process_callback_approved(callback)
27
+ payment_transaction = payment_transaction()
28
+ callback_response = CallbackResponse.new callback
29
+ sign_callback callback_response
30
+
31
+ callback_processor.process_callback payment_transaction, callback_response
32
+
33
+ assert_true payment_transaction.approved?
34
+ assert_true payment_transaction.finished?
35
+ assert_false payment_transaction.has_errors?
36
+
37
+ [payment_transaction, callback_response]
38
+ end
39
+
40
+ def test_process_callback_declined
41
+ raise NotImplementedError
42
+ end
43
+
44
+ def assert_process_callback_declined(callback)
45
+ payment_transaction = payment_transaction()
46
+ callback_response = CallbackResponse.new callback
47
+ sign_callback callback_response
48
+
49
+ callback_processor.process_callback payment_transaction, callback_response
50
+
51
+ assert_true payment_transaction.declined?
52
+ assert_true payment_transaction.finished?
53
+ assert_true payment_transaction.has_errors?
54
+ end
55
+
56
+ def test_process_callback_error
57
+ raise NotImplementedError
58
+ end
59
+
60
+ def assert_process_callback_error(callback)
61
+ payment_transaction = payment_transaction()
62
+ callback_response = CallbackResponse.new callback
63
+ sign_callback callback_response
64
+
65
+ begin
66
+ callback_processor.process_callback payment_transaction, callback_response
67
+ rescue PaynetError => error
68
+ assert_true payment_transaction.error?
69
+ assert_true payment_transaction.finished?
70
+ assert_true payment_transaction.has_errors?
71
+ assert_equal callback_response.error_message, error.message
72
+
73
+ [payment_transaction, callback_response]
74
+ else
75
+ flunk 'Exception must be raised'
76
+ end
77
+ end
78
+
79
+ def test_process_callback_with_empty_control
80
+ assert_raise ValidationError, "Actual control code '' does not equal expected" do
81
+ callback_processor.process_callback payment_transaction, Response.new
82
+ end
83
+ end
84
+
85
+ def test_process_callback_with_empty_fields
86
+ callback_response = CallbackResponse.new(
87
+ [
88
+ 'status' => 'approved',
89
+ 'orderid' => '_',
90
+ 'client_orderid' => '_'
91
+ ])
92
+
93
+ sign_callback callback_response
94
+
95
+ assert_raise ValidationError, 'Some required fields missed or empty in CallbackResponse' do
96
+ callback_processor.process_callback payment_transaction, callback_response
97
+ end
98
+ end
99
+
100
+ def test_process_callback_with_unequal_fields
101
+ callback_response = CallbackResponse.new(
102
+ [
103
+ 'status' => 'approved',
104
+ 'orderid' => 'unequal',
105
+ 'merchant_order' => 'unequal',
106
+ 'client_orderid' => 'unequal'
107
+ ])
108
+
109
+ sign_callback callback_response
110
+
111
+ assert_raise ValidationError, 'Some fields from CallbackResponse unequal properties from Payment' do
112
+ callback_processor.process_callback payment_transaction, callback_response
113
+ end
114
+ end
115
+
116
+ def test_process_callback_with_invalid_status
117
+ callback_response = CallbackResponse.new(
118
+ [
119
+ 'status' => 'processing',
120
+ 'amount' => 0.99,
121
+ 'orderid' => PAYNET_ID,
122
+ 'merchant_order' => CLIENT_ID,
123
+ 'client_orderid' => CLIENT_ID,
124
+ ])
125
+
126
+ sign_callback callback_response
127
+
128
+ assert_raise ValidationError, "Invalid callback status: 'processing'" do
129
+ callback_processor.process_callback payment_transaction, callback_response
130
+ end
131
+ end
132
+
133
+ protected
134
+
135
+ # @return [CallbackPrototype]
136
+ def callback_processor
137
+ raise NotImplementedError
138
+ end
139
+
140
+ # @return [PaymentTransaction]
141
+ def payment_transaction
142
+ PaymentTransaction.new(
143
+ {
144
+ 'payment' => Payment.new(
145
+ {
146
+ 'client_id' => CLIENT_ID,
147
+ 'paynet_id' => PAYNET_ID,
148
+ 'amount' => 0.99,
149
+ 'currency' => 'USD',
150
+ }),
151
+ 'query_config' => QueryConfig.new(
152
+ {
153
+ 'signing_key' => SIGNING_KEY
154
+ })
155
+ })
156
+ end
157
+
158
+ # @param callback_response [CallbackResponse]
159
+ def sign_callback(callback_response)
160
+ callback_response['control'] = Digest::SHA1.hexdigest(
161
+ callback_response.status +
162
+ callback_response.payment_paynet_id.to_s +
163
+ callback_response.payment_client_id.to_s +
164
+ SIGNING_KEY
165
+ )
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,95 @@
1
+ require_relative './callback_test_prototype'
2
+ require 'callback/customer_return_callback'
3
+
4
+ module PaynetEasy::PaynetEasyApi::Callback
5
+ class CustomerReturnCallbackTest < Test::Unit::TestCase
6
+ include CallbackTestPrototype
7
+
8
+ def test_process_callback_approved
9
+ [
10
+ {
11
+ 'status' => 'approved',
12
+ 'amount' => 0.99,
13
+ 'orderid' => PAYNET_ID,
14
+ 'merchant_order' => CLIENT_ID,
15
+ 'client_orderid' => CLIENT_ID,
16
+ }
17
+ ].each do |callback|
18
+ assert_process_callback_approved callback
19
+ end
20
+ end
21
+
22
+ def test_process_callback_declined
23
+ [
24
+ {
25
+ 'status' => 'declined',
26
+ 'amount' => 0.99,
27
+ 'orderid' => PAYNET_ID,
28
+ 'merchant_order' => CLIENT_ID,
29
+ 'client_orderid' => CLIENT_ID,
30
+ },
31
+ {
32
+ 'status' => 'filtered',
33
+ 'amount' => 0.99,
34
+ 'orderid' => PAYNET_ID,
35
+ 'merchant_order' => CLIENT_ID,
36
+ 'client_orderid' => CLIENT_ID,
37
+ }
38
+ ].each do |callback|
39
+ assert_process_callback_declined callback
40
+ end
41
+ end
42
+
43
+ def test_process_callback_error
44
+ [
45
+ {
46
+ 'status' => 'error',
47
+ 'amount' => 0.99,
48
+ 'orderid' => PAYNET_ID,
49
+ 'merchant_order' => CLIENT_ID,
50
+ 'client_orderid' => CLIENT_ID,
51
+ 'error_message' => 'test type error message',
52
+ 'error_code' => 5
53
+ }
54
+ ].each do |callback|
55
+ assert_process_callback_error callback
56
+ end
57
+ end
58
+
59
+ def test_process_callback_with_not_processing_transaction
60
+ payment_transaction = payment_transaction()
61
+ payment_transaction.status = PaymentTransaction::STATUS_APPROVED
62
+
63
+ callback_response = CallbackResponse.new(
64
+ [
65
+ 'status' => 'processing',
66
+ 'amount' => 0.99,
67
+ 'orderid' => PAYNET_ID,
68
+ 'merchant_order' => CLIENT_ID,
69
+ 'client_orderid' => CLIENT_ID,
70
+ ])
71
+
72
+ sign_callback callback_response
73
+
74
+ assert_raise ValidationError, 'Only processing payment transaction can be processed' do
75
+ callback_processor.process_callback payment_transaction, callback_response
76
+ end
77
+ end
78
+
79
+ protected
80
+
81
+ alias :callback_test_prototype_payment_transaction :payment_transaction
82
+
83
+ # @return [PaymentTransaction]
84
+ def payment_transaction
85
+ payment_transaction = callback_test_prototype_payment_transaction
86
+ payment_transaction.status = PaymentTransaction::STATUS_PROCESSING
87
+ payment_transaction
88
+ end
89
+
90
+ # @return [CustomerReturnCallback]
91
+ def callback_processor
92
+ CustomerReturnCallback.new 'customer_return'
93
+ end
94
+ end
95
+ end