judopay 2.1.0 → 2.1.3

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 (122) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +24 -23
  3. data/.rspec +1 -1
  4. data/.rubocop.yml +54 -51
  5. data/.travis.yml +6 -6
  6. data/CHANGELOG.md +17 -17
  7. data/Gemfile +4 -4
  8. data/LICENSE +21 -21
  9. data/README.md +96 -94
  10. data/Rakefile +22 -22
  11. data/judopay.gemspec +38 -38
  12. data/lib/certs/digicert_sha256_ca.pem +49 -49
  13. data/lib/certs/rapidssl_ca.crt +63 -63
  14. data/lib/faraday/judo_mashify.rb +11 -11
  15. data/lib/faraday/raise_http_exception.rb +19 -19
  16. data/lib/judopay.rb +70 -70
  17. data/lib/judopay/api.rb +10 -10
  18. data/lib/judopay/connection.rb +77 -77
  19. data/lib/judopay/core_ext/hash.rb +29 -29
  20. data/lib/judopay/core_ext/string.rb +32 -32
  21. data/lib/judopay/error.rb +117 -115
  22. data/lib/judopay/mash.rb +11 -11
  23. data/lib/judopay/model.rb +134 -134
  24. data/lib/judopay/models/android_payment.rb +26 -26
  25. data/lib/judopay/models/android_preauth.rb +8 -8
  26. data/lib/judopay/models/apple_payment.rb +26 -26
  27. data/lib/judopay/models/apple_preauth.rb +9 -9
  28. data/lib/judopay/models/card_address.rb +11 -11
  29. data/lib/judopay/models/card_payment.rb +33 -33
  30. data/lib/judopay/models/card_preauth.rb +11 -11
  31. data/lib/judopay/models/collection.rb +16 -16
  32. data/lib/judopay/models/encrypt_details.rb +18 -0
  33. data/lib/judopay/models/inner/pk_payment.rb +17 -17
  34. data/lib/judopay/models/inner/pk_payment_token.rb +13 -13
  35. data/lib/judopay/models/inner/transmitted_field.rb +39 -39
  36. data/lib/judopay/models/inner/wallet.rb +30 -30
  37. data/lib/judopay/models/market/collection.rb +10 -10
  38. data/lib/judopay/models/market/payment.rb +10 -10
  39. data/lib/judopay/models/market/preauth.rb +10 -10
  40. data/lib/judopay/models/market/refund.rb +10 -10
  41. data/lib/judopay/models/market/transaction.rb +10 -10
  42. data/lib/judopay/models/one_use_token_payment.rb +29 -0
  43. data/lib/judopay/models/payment.rb +8 -8
  44. data/lib/judopay/models/preauth.rb +8 -8
  45. data/lib/judopay/models/refund.rb +16 -16
  46. data/lib/judopay/models/register_card.rb +27 -27
  47. data/lib/judopay/models/save_card.rb +24 -25
  48. data/lib/judopay/models/token_payment.rb +30 -30
  49. data/lib/judopay/models/token_preauth.rb +10 -10
  50. data/lib/judopay/models/transaction.rb +8 -8
  51. data/lib/judopay/models/void.rb +19 -19
  52. data/lib/judopay/models/web_payments/payment.rb +28 -28
  53. data/lib/judopay/models/web_payments/preauth.rb +10 -10
  54. data/lib/judopay/models/web_payments/transaction.rb +19 -19
  55. data/lib/judopay/models/web_payments/web_payment_operation.rb +8 -8
  56. data/lib/judopay/null_logger.rb +9 -11
  57. data/lib/judopay/request.rb +50 -50
  58. data/lib/judopay/response.rb +7 -7
  59. data/lib/judopay/serializer.rb +27 -27
  60. data/lib/judopay/version.rb +4 -4
  61. data/spec/factories.rb +227 -208
  62. data/spec/faraday/response_spec.rb +27 -27
  63. data/spec/fixtures/card_payments/create.json +21 -21
  64. data/spec/fixtures/card_payments/create_3dsecure.json +7 -7
  65. data/spec/fixtures/card_payments/create_bad_request.json +12 -12
  66. data/spec/fixtures/card_payments/create_declined.json +23 -23
  67. data/spec/fixtures/card_payments/validate.json +4 -4
  68. data/spec/fixtures/token_payments/create.json +21 -21
  69. data/spec/fixtures/transactions/all.json +237 -237
  70. data/spec/fixtures/transactions/android_payment.json +26 -26
  71. data/spec/fixtures/transactions/apple_payment.json +26 -26
  72. data/spec/fixtures/transactions/find.json +22 -22
  73. data/spec/fixtures/transactions/find_not_found.json +4 -4
  74. data/spec/fixtures/transactions/register_card.json +28 -28
  75. data/spec/fixtures/transactions/save_card.json +27 -27
  76. data/spec/fixtures/transactions/void.json +26 -26
  77. data/spec/fixtures/web_payments/payments/create.json +3 -3
  78. data/spec/fixtures/web_payments/payments/find.json +38 -38
  79. data/spec/judopay/android_payment_spec.rb +74 -74
  80. data/spec/judopay/apple_payment_spec.rb +80 -80
  81. data/spec/judopay/card_address_spec.rb +10 -10
  82. data/spec/judopay/card_payment_spec.rb +51 -63
  83. data/spec/judopay/card_preauth_spec.rb +35 -35
  84. data/spec/judopay/collection_spec.rb +26 -26
  85. data/spec/judopay/core_ext/hash_spec.rb +24 -24
  86. data/spec/judopay/core_ext/string_spec.rb +16 -16
  87. data/spec/judopay/error_spec.rb +70 -70
  88. data/spec/judopay/judopay_spec.rb +19 -19
  89. data/spec/judopay/market/collection_spec.rb +26 -26
  90. data/spec/judopay/market/payment_spec.rb +14 -14
  91. data/spec/judopay/market/preauth_spec.rb +14 -14
  92. data/spec/judopay/market/refund_spec.rb +26 -26
  93. data/spec/judopay/market/transaction_spec.rb +14 -14
  94. data/spec/judopay/payment_spec.rb +14 -14
  95. data/spec/judopay/preauth_spec.rb +14 -14
  96. data/spec/judopay/refund_spec.rb +26 -26
  97. data/spec/judopay/register_card_spec.rb +24 -24
  98. data/spec/judopay/save_card_spec.rb +23 -23
  99. data/spec/judopay/token_payment_spec.rb +22 -22
  100. data/spec/judopay/token_preauth_spec.rb +22 -22
  101. data/spec/judopay/transaction_spec.rb +51 -51
  102. data/spec/judopay/void_spec.rb +24 -24
  103. data/spec/judopay/web_payments/payment_spec.rb +16 -16
  104. data/spec/judopay/web_payments/preauth_spec.rb +16 -16
  105. data/spec/judopay/web_payments/transaction_spec.rb +15 -15
  106. data/spec/spec_helper.rb +41 -41
  107. data/test/additions_payment_test.rb +30 -0
  108. data/test/authentication_test.rb +23 -23
  109. data/test/base/integration_base.rb +20 -20
  110. data/test/base/payments_tests.rb +47 -47
  111. data/test/base/token_payment_tests.rb +98 -98
  112. data/test/card_details_test.rb +21 -21
  113. data/test/configuration_test.rb +35 -35
  114. data/test/helper/assertion_helper.rb +29 -29
  115. data/test/payment_test.rb +10 -10
  116. data/test/preauth_test.rb +10 -10
  117. data/test/register_card_test.rb +42 -42
  118. data/test/save_card_test.rb +23 -0
  119. data/test/token_payment_test.rb +10 -10
  120. data/test/token_preauth_test.rb +10 -10
  121. data/test/void_test.rb +45 -45
  122. metadata +18 -12
@@ -1,10 +1,10 @@
1
- require File.expand_path('../connection', __FILE__)
2
- require File.expand_path('../request', __FILE__)
3
-
4
- module Judopay
5
- # @private
6
- class API
7
- include Connection
8
- include Request
9
- end
10
- end
1
+ require File.expand_path('../connection', __FILE__)
2
+ require File.expand_path('../request', __FILE__)
3
+
4
+ module Judopay
5
+ # @private
6
+ class API
7
+ include Connection
8
+ include Request
9
+ end
10
+ end
@@ -1,77 +1,77 @@
1
- require 'faraday'
2
- require 'faraday_middleware'
3
- require 'openssl'
4
- require_relative '../faraday/raise_http_exception'
5
- require_relative '../faraday/judo_mashify'
6
-
7
- module Judopay
8
- # @private
9
- module Connection
10
- private
11
-
12
- def connection(raw = false)
13
- connection = Faraday::Connection.new(default_connection_options) do |faraday|
14
- # When adapter set to "httpclient" SSL error emerges after bunch of requests:
15
- # "Faraday::SSLError: SSL_connect SYSCALL returned=5 errno=0 state=SSLv2/v3 read server hello A"
16
- faraday.adapter :net_http
17
- faraday.use Faraday::Request::UrlEncoded
18
- faraday.use Faraday::Response::Logger, Judopay.configuration.logger
19
- define_format(faraday, raw)
20
- faraday.use FaradayMiddleware::RaiseHttpException
21
- end
22
-
23
- define_auth(connection)
24
- end
25
-
26
- def define_format(faraday, raw)
27
- return if raw
28
- faraday.use FaradayMiddleware::JudoMashify
29
- faraday.use Faraday::Response::ParseJson if Judopay.configuration.format.to_s == 'json'
30
- end
31
-
32
- def define_auth(connection)
33
- # Authentication with basic auth if there is no OAuth2 access token
34
- if Judopay.configuration.oauth_access_token.nil?
35
- Judopay.configuration.validate
36
- connection.basic_auth(
37
- Judopay.configuration.api_token,
38
- Judopay.configuration.api_secret
39
- )
40
- Judopay.log(Logger::DEBUG, 'Using HTTP basic auth')
41
- end
42
-
43
- connection
44
- end
45
-
46
- def default_connection_options
47
- {
48
- :headers => request_headers,
49
- :url => Judopay.configuration.endpoint_url,
50
- :ssl => {
51
- :ca_file => File.dirname(File.dirname(__FILE__)) + '/certs/rapidssl_ca.crt',
52
- :cert_store => false,
53
- :verify => true
54
- }
55
- }
56
- end
57
-
58
- def request_headers
59
- format = Judopay.configuration.format
60
-
61
- headers = {
62
- 'Accept' => "application/#{format}; charset=utf-8",
63
- 'User-Agent' => Judopay.configuration.user_agent,
64
- 'API-Version' => Judopay.configuration.api_version,
65
- 'Content-Type' => 'application/json'
66
- }
67
-
68
- # Do we have an OAuth2 access token?
69
- unless Judopay.configuration.oauth_access_token.nil?
70
- headers['Authorization'] = 'Bearer ' + Judopay.configuration.oauth_access_token
71
- Judopay.log(Logger::DEBUG, 'Using OAuth2 access token')
72
- end
73
-
74
- headers
75
- end
76
- end
77
- end
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+ require 'openssl'
4
+ require_relative '../faraday/raise_http_exception'
5
+ require_relative '../faraday/judo_mashify'
6
+
7
+ module Judopay
8
+ # @private
9
+ module Connection
10
+ private
11
+
12
+ def connection(raw = false)
13
+ connection = Faraday.new(default_connection_options) do |faraday|
14
+ faraday.use Faraday::Request::UrlEncoded
15
+ faraday.use Faraday::Response::Logger, Judopay.configuration.logger
16
+ define_format(faraday, raw)
17
+ faraday.use FaradayMiddleware::RaiseHttpException
18
+ # When adapter set to "httpclient" SSL error emerges after bunch of requests:
19
+ # "Faraday::SSLError: SSL_connect SYSCALL returned=5 errno=0 state=SSLv2/v3 read server hello A"
20
+ faraday.adapter :net_http
21
+ end
22
+
23
+ define_auth(connection)
24
+ end
25
+
26
+ def define_format(faraday, raw)
27
+ return if raw
28
+ faraday.use FaradayMiddleware::JudoMashify
29
+ faraday.use Faraday::Response::ParseJson if Judopay.configuration.format.to_s == 'json'
30
+ end
31
+
32
+ def define_auth(connection)
33
+ # Authentication with basic auth if there is no OAuth2 access token
34
+ if Judopay.configuration.oauth_access_token.nil?
35
+ Judopay.configuration.validate
36
+ connection.basic_auth(
37
+ Judopay.configuration.api_token,
38
+ Judopay.configuration.api_secret
39
+ )
40
+ Judopay.log(Logger::DEBUG, 'Using HTTP basic auth')
41
+ end
42
+
43
+ connection
44
+ end
45
+
46
+ def default_connection_options
47
+ {
48
+ :headers => request_headers,
49
+ :url => Judopay.configuration.endpoint_url,
50
+ :ssl => {
51
+ :ca_file => File.dirname(File.dirname(__FILE__)) + '/certs/rapidssl_ca.crt',
52
+ :cert_store => false,
53
+ :verify => true
54
+ }
55
+ }
56
+ end
57
+
58
+ def request_headers
59
+ format = Judopay.configuration.format
60
+
61
+ headers = {
62
+ 'Accept' => "application/#{format}; charset=utf-8",
63
+ 'User-Agent' => Judopay.configuration.user_agent,
64
+ 'API-Version' => Judopay.configuration.api_version,
65
+ 'Content-Type' => 'application/json'
66
+ }
67
+
68
+ # Do we have an OAuth2 access token?
69
+ unless Judopay.configuration.oauth_access_token.nil?
70
+ headers['Authorization'] = 'Bearer ' + Judopay.configuration.oauth_access_token
71
+ Judopay.log(Logger::DEBUG, 'Using OAuth2 access token')
72
+ end
73
+
74
+ headers
75
+ end
76
+ end
77
+ end
@@ -1,29 +1,29 @@
1
- require 'addressable/uri'
2
- require_relative 'string'
3
-
4
- class Hash
5
- # Convert hash keys to camelcase
6
- #
7
- # {'this_key' => 1}.camel_case_keys! #=> { 'thisKey' => 1 }
8
- def camel_case_keys!
9
- output_hash = {}
10
- each do |key, value|
11
- camel_case_key = key.to_s.camel_case
12
- if value.is_a?(Hash)
13
- output_hash[camel_case_key] = value.camel_case_keys!
14
- else
15
- output_hash[key.to_s.camel_case] = value
16
- end
17
- end
18
- replace(output_hash)
19
- end
20
-
21
- # Produce a URL query string from the hash
22
- #
23
- # {'this_key' => 1}.to_query_string #=> this_key=1
24
- def to_query_string
25
- uri = Addressable::URI.new
26
- uri.query_values = self
27
- uri.query
28
- end
29
- end
1
+ require 'addressable/uri'
2
+ require_relative 'string'
3
+
4
+ class Hash
5
+ # Convert hash keys to camelcase
6
+ #
7
+ # {'this_key' => 1}.camel_case_keys! #=> { 'thisKey' => 1 }
8
+ def camel_case_keys!
9
+ output_hash = {}
10
+ each do |key, value|
11
+ camel_case_key = key.to_s.camel_case
12
+ if value.is_a?(Hash)
13
+ output_hash[camel_case_key] = value.camel_case_keys!
14
+ else
15
+ output_hash[key.to_s.camel_case] = value
16
+ end
17
+ end
18
+ replace(output_hash)
19
+ end
20
+
21
+ # Produce a URL query string from the hash
22
+ #
23
+ # {'this_key' => 1}.to_query_string #=> this_key=1
24
+ def to_query_string
25
+ uri = Addressable::URI.new
26
+ uri.query_values = self
27
+ uri.query
28
+ end
29
+ end
@@ -1,32 +1,32 @@
1
- class String
2
- # Convert to camel case
3
- #
4
- # "foo_bar".camel_case #=> "fooBar"
5
- def camel_case
6
- return self if self !~ /_/ && self =~ /[A-Z]+.*/
7
- split('_').map(&:capitalize).join.uncapitalize
8
- end
9
-
10
- # Convert first letter to lower case
11
- #
12
- # "BananaMan".uncapitalize #=> "bananaMan"
13
- def uncapitalize
14
- self[0, 1].downcase + self[1..-1]
15
- end
16
-
17
- # Converts a camel_cased string to a underscored string
18
- # Replaces spaces with underscores, and strips whitespace
19
- #
20
- # "BananaMan".underscore #=> "banana_man"
21
- def underscore
22
- to_s
23
- .strip
24
- .tr(' ', '_')
25
- .gsub(/::/, '/')
26
- .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
27
- .gsub(/([a-z\d])([A-Z])/, '\1_\2')
28
- .tr('-', '_')
29
- .squeeze('_')
30
- .downcase
31
- end
32
- end
1
+ class String
2
+ # Convert to camel case
3
+ #
4
+ # "foo_bar".camel_case #=> "fooBar"
5
+ def camel_case
6
+ return self if self !~ /_/ && self =~ /[A-Z]+.*/
7
+ split('_').map(&:capitalize).join.uncapitalize
8
+ end
9
+
10
+ # Convert first letter to lower case
11
+ #
12
+ # "BananaMan".uncapitalize #=> "bananaMan"
13
+ def uncapitalize
14
+ self[0, 1].downcase + self[1..-1]
15
+ end
16
+
17
+ # Converts a camel_cased string to a underscored string
18
+ # Replaces spaces with underscores, and strips whitespace
19
+ #
20
+ # "BananaMan".underscore #=> "banana_man"
21
+ def underscore
22
+ to_s
23
+ .strip
24
+ .tr(' ', '_')
25
+ .gsub(/::/, '/')
26
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
27
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
28
+ .tr('-', '_')
29
+ .squeeze('_')
30
+ .downcase
31
+ end
32
+ end
@@ -1,115 +1,117 @@
1
- require 'json'
2
-
3
- module Judopay
4
- # Single field error model
5
- class FieldError
6
- attr_accessor :message, :code, :field_name, :detail
7
-
8
- def initialize(message, code, field_name, detail)
9
- @detail = detail
10
- @field_name = field_name
11
- @code = code
12
- @message = message
13
- end
14
-
15
- def to_s
16
- "Field \"#{@field_name}\" (code #{@code}): #{@message}"
17
- end
18
- end
19
-
20
- # Custom error class for rescuing from all API errors
21
- class APIError < StandardError
22
- CATEGORY_UNKNOWN = 0
23
- CATEGORY_REQUEST = 1
24
- CATEGORY_MODEL = 2
25
- CATEGORY_CONFIG = 3
26
- CATEGORY_PROCESSING = 4
27
- CATEGORY_EXCEPTION = 5
28
-
29
- attr_accessor :message, :error_code, :status_code, :category, :field_errors
30
-
31
- class << self
32
- def factory(response)
33
- parsed_body = JSON.parse(response.body)
34
-
35
- new(
36
- parsed_body['message'],
37
- parsed_body['code'],
38
- response.status.to_i,
39
- parsed_body['category'],
40
- extract_field_errors(parsed_body['details'])
41
- )
42
- end
43
-
44
- protected
45
-
46
- def extract_field_errors(field_errors)
47
- result = []
48
-
49
- if field_errors.is_a?(Hash) && field_errors.key?('receiptId')
50
- result << 'Duplicate transaction. Receipt id: ' + field_errors['receiptId'].to_s
51
- else
52
- field_errors.to_a.each do |field_error|
53
- result << FieldError.new(field_error['message'], field_error['code'], field_error['fieldName'], field_error['detail'])
54
- end
55
- end
56
-
57
- result
58
- end
59
- end
60
-
61
- def initialize(message, error_code = 0, status_code = 0, category = CATEGORY_UNKNOWN, field_errors = [])
62
- @message = message
63
- @error_code = error_code
64
- @status_code = status_code
65
- @category = category
66
- @field_errors = field_errors
67
- end
68
-
69
- def to_s
70
- "JudoPay ApiException (status code #{@status_code}, error code #{@error_code}, category #{@category}) #{message}"
71
- end
72
-
73
- def message
74
- (@message || self.class.name) + field_errors_message
75
- end
76
-
77
- protected
78
-
79
- def field_errors_message
80
- return '' if @field_errors.empty?
81
- "\nFields errors:\n#{@field_errors.join("\n")}"
82
- end
83
- end
84
-
85
- # A validation error that hasn't reached the API
86
- class ValidationError < StandardError
87
- attr_accessor :errors, :message
88
-
89
- def initialize(message, errors = nil)
90
- @errors = errors
91
- @message = message
92
- @message += model_errors_summary unless @errors.nil?
93
- end
94
-
95
- def to_s
96
- @message
97
- end
98
-
99
- def model_errors
100
- return if @errors.nil?
101
- @errors.messages
102
- end
103
-
104
- protected
105
-
106
- def model_errors_summary
107
- summary = ["\nField errors:"]
108
- model_errors.each do |key, value|
109
- summary.push("#{key}: #{value.join('; ')}")
110
- end
111
-
112
- summary.join("\n")
113
- end
114
- end
115
- end
1
+ require 'json'
2
+
3
+ module Judopay
4
+ # Single field error model
5
+ class FieldError
6
+ attr_accessor :message, :code, :field_name, :detail
7
+
8
+ def initialize(message, code, field_name, detail)
9
+ @detail = detail
10
+ @field_name = field_name
11
+ @code = code
12
+ @message = message
13
+ end
14
+
15
+ def to_s
16
+ "Field \"#{@field_name}\" (code #{@code}): #{@message}"
17
+ end
18
+ end
19
+
20
+ # Custom error class for rescuing from all API errors
21
+ class APIError < StandardError
22
+ CATEGORY_UNKNOWN = 0
23
+ CATEGORY_REQUEST = 1
24
+ CATEGORY_MODEL = 2
25
+ CATEGORY_CONFIG = 3
26
+ CATEGORY_PROCESSING = 4
27
+ CATEGORY_EXCEPTION = 5
28
+
29
+ attr_accessor :error_code, :status_code, :category, :field_errors
30
+
31
+ attr_writer :message
32
+
33
+ class << self
34
+ def factory(response)
35
+ parsed_body = JSON.parse(response.body)
36
+
37
+ new(
38
+ parsed_body['message'],
39
+ parsed_body['code'],
40
+ response.status.to_i,
41
+ parsed_body['category'],
42
+ extract_field_errors(parsed_body['details'])
43
+ )
44
+ end
45
+
46
+ protected
47
+
48
+ def extract_field_errors(field_errors)
49
+ result = []
50
+
51
+ if field_errors.is_a?(Hash) && field_errors.key?('receiptId')
52
+ result << 'Duplicate transaction. Receipt id: ' + field_errors['receiptId'].to_s
53
+ else
54
+ field_errors.to_a.each do |field_error|
55
+ result << FieldError.new(field_error['message'], field_error['code'], field_error['fieldName'], field_error['detail'])
56
+ end
57
+ end
58
+
59
+ result
60
+ end
61
+ end
62
+
63
+ def initialize(message, error_code = 0, status_code = 0, category = CATEGORY_UNKNOWN, field_errors = [])
64
+ @message = message
65
+ @error_code = error_code
66
+ @status_code = status_code
67
+ @category = category
68
+ @field_errors = field_errors
69
+ end
70
+
71
+ def to_s
72
+ "JudoPay ApiException (status code #{@status_code}, error code #{@error_code}, category #{@category}) #{message}"
73
+ end
74
+
75
+ def message
76
+ (@message || self.class.name) + field_errors_message
77
+ end
78
+
79
+ protected
80
+
81
+ def field_errors_message
82
+ return '' if @field_errors.empty?
83
+ "\nFields errors:\n#{@field_errors.join("\n")}"
84
+ end
85
+ end
86
+
87
+ # A validation error that hasn't reached the API
88
+ class ValidationError < StandardError
89
+ attr_accessor :errors, :message
90
+
91
+ def initialize(message, errors = nil)
92
+ @errors = errors
93
+ @message = message
94
+ @message += model_errors_summary unless @errors.nil?
95
+ end
96
+
97
+ def to_s
98
+ @message
99
+ end
100
+
101
+ def model_errors
102
+ return if @errors.nil?
103
+ @errors.messages
104
+ end
105
+
106
+ protected
107
+
108
+ def model_errors_summary
109
+ summary = ["\nField errors:"]
110
+ model_errors.each do |key, value|
111
+ summary.push("#{key}: #{value.join('; ')}")
112
+ end
113
+
114
+ summary.join("\n")
115
+ end
116
+ end
117
+ end