judopay 1.0.2.pre → 2.0.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 +4 -4
- data/.travis.yml +6 -0
- data/CHANGELOG.md +3 -0
- data/README.md +2 -0
- data/Rakefile +17 -2
- data/judopay.gemspec +11 -10
- data/lib/faraday/raise_http_exception.rb +1 -18
- data/lib/judopay.rb +12 -9
- data/lib/judopay/connection.rb +28 -18
- data/lib/judopay/core_ext/string.rb +4 -3
- data/lib/judopay/error.rb +55 -97
- data/lib/judopay/model.rb +49 -40
- data/lib/judopay/models/card_payment.rb +5 -10
- data/lib/judopay/models/card_preauth.rb +1 -1
- data/lib/judopay/models/collection.rb +1 -1
- data/lib/judopay/models/refund.rb +1 -1
- data/lib/judopay/models/register_card.rb +28 -0
- data/lib/judopay/models/save_card.rb +26 -0
- data/lib/judopay/models/token_payment.rb +1 -0
- data/lib/judopay/models/void.rb +19 -0
- data/lib/judopay/models/web_payments/payment.rb +3 -0
- data/lib/judopay/models/web_payments/web_payment_operation.rb +8 -0
- data/lib/judopay/request.rb +1 -1
- data/lib/judopay/serializer.rb +1 -5
- data/lib/judopay/version.rb +2 -1
- data/spec/factories.rb +64 -19
- data/spec/faraday/response_spec.rb +10 -12
- data/spec/fixtures/card_payments/create_bad_request.json +11 -4
- data/spec/fixtures/transactions/register_card.json +29 -0
- data/spec/fixtures/transactions/save_card.json +28 -0
- data/spec/fixtures/transactions/void.json +27 -0
- data/spec/judopay/card_address_spec.rb +1 -1
- data/spec/judopay/card_payment_spec.rb +1 -2
- data/spec/judopay/collection_spec.rb +1 -1
- data/spec/judopay/error_spec.rb +36 -15
- data/spec/judopay/judopay_spec.rb +1 -1
- data/spec/judopay/market/collection_spec.rb +1 -1
- data/spec/judopay/market/payment_spec.rb +1 -1
- data/spec/judopay/market/preauth_spec.rb +1 -1
- data/spec/judopay/market/refund_spec.rb +1 -1
- data/spec/judopay/market/transaction_spec.rb +1 -1
- data/spec/judopay/payment_spec.rb +1 -1
- data/spec/judopay/preauth_spec.rb +1 -1
- data/spec/judopay/refund_spec.rb +1 -1
- data/spec/judopay/register_card_spec.rb +24 -0
- data/spec/judopay/save_card_spec.rb +23 -0
- data/spec/judopay/transaction_spec.rb +1 -1
- data/spec/judopay/void_spec.rb +24 -0
- data/spec/spec_helper.rb +6 -2
- data/test/authentication_test.rb +23 -0
- data/test/base/integration_base.rb +20 -0
- data/test/base/payments_tests.rb +40 -0
- data/test/base/token_payment_tests.rb +91 -0
- data/test/card_details_test.rb +21 -0
- data/test/configuration_test.rb +35 -0
- data/test/helper/assertion_helper.rb +29 -0
- data/test/payment_test.rb +10 -0
- data/test/preauth_test.rb +10 -0
- data/test/register_card_test.rb +37 -0
- data/test/token_payment_test.rb +10 -0
- data/test/token_preauth_test.rb +10 -0
- data/test/void_test.rb +44 -0
- metadata +107 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: adc77d2a9f1b25747948b90476f9b72610823d58
|
4
|
+
data.tar.gz: 3747bc655c3d24a90883970037ce3f746f9a115d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e75fa57d16570440e16117e37fb6a47fcb9b991c69970009f105efe0224ce225369eb5bcaaeff9f34b37777fe87ac742eba66c40653644385d5a4ab39abdea12
|
7
|
+
data.tar.gz: af7d3f3ce3d06e1cd7942c28fdcfa257f61a9bb759de1be709a15b9e985db30974f86b314d736e6a09c75d607e49bb971f25d4df0b82091dbc0876f82ffbc9d2
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -1,7 +1,22 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rspec/core/rake_task'
|
3
|
+
require 'rake/testtask'
|
3
4
|
|
4
5
|
RSpec::Core::RakeTask.new
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
Rake::TestTask.new do |t|
|
8
|
+
raise 'Please setup JUDO_* environment vars' unless ENV['JUDO_API_ID'] && ENV['JUDO_API_TOKEN'] && ENV['JUDO_API_SECRET']
|
9
|
+
t.libs << 'test'
|
10
|
+
t.test_files = FileList['test/*_test.rb']
|
11
|
+
t.verbose = true
|
12
|
+
end
|
13
|
+
|
14
|
+
task :code_check do
|
15
|
+
sh 'rubocop'
|
16
|
+
Rake::Task['spec'].invoke
|
17
|
+
Rake::Task['test'].invoke
|
18
|
+
end
|
19
|
+
|
20
|
+
# check code before build
|
21
|
+
task :build => :code_check
|
22
|
+
task :default => :build
|
data/judopay.gemspec
CHANGED
@@ -5,7 +5,7 @@ require 'judopay/version'
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'judopay'
|
8
|
-
spec.version = Judopay::
|
8
|
+
spec.version = Judopay::SDK_VERSION
|
9
9
|
spec.authors = ['judoPay']
|
10
10
|
spec.email = ['developersupport@judopay.com']
|
11
11
|
spec.summary = 'Ruby SDK wrapper for the Judopay REST API'
|
@@ -19,19 +19,20 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
21
|
spec.required_ruby_version = '>= 1.9.3'
|
22
|
-
spec.add_development_dependency 'bundler'
|
23
|
-
spec.add_development_dependency 'rake'
|
24
22
|
spec.add_development_dependency 'rspec'
|
25
23
|
spec.add_development_dependency 'yard'
|
24
|
+
spec.add_development_dependency 'test-unit'
|
26
25
|
spec.add_development_dependency 'yard-xml'
|
27
26
|
spec.add_development_dependency 'factory_girl'
|
28
27
|
spec.add_development_dependency 'rubocop'
|
29
28
|
spec.add_development_dependency 'webmock'
|
30
|
-
spec.add_dependency '
|
31
|
-
spec.add_dependency '
|
32
|
-
spec.add_dependency '
|
33
|
-
spec.add_dependency '
|
34
|
-
spec.add_dependency '
|
35
|
-
spec.add_dependency '
|
36
|
-
spec.add_dependency '
|
29
|
+
spec.add_dependency 'bundler'
|
30
|
+
spec.add_dependency 'rake'
|
31
|
+
spec.add_dependency 'virtus', '~> 1.0.2'
|
32
|
+
spec.add_dependency 'httpclient', '~> 2.4.0'
|
33
|
+
spec.add_dependency 'activemodel', '~> 4.1.1'
|
34
|
+
spec.add_dependency 'faraday', '~> 0.9.0'
|
35
|
+
spec.add_dependency 'faraday_middleware', '~> 0.9.1'
|
36
|
+
spec.add_dependency 'rash', '~> 0.4.0'
|
37
|
+
spec.add_dependency 'addressable', '~> 2.3.6'
|
37
38
|
end
|
@@ -7,24 +7,7 @@ module FaradayMiddleware
|
|
7
7
|
class RaiseHttpException < Faraday::Middleware
|
8
8
|
def call(env)
|
9
9
|
@app.call(env).on_complete do |response|
|
10
|
-
|
11
|
-
when 400
|
12
|
-
fail Judopay::BadRequest, response
|
13
|
-
when 401, 403
|
14
|
-
fail Judopay::NotAuthorized, response
|
15
|
-
when 404
|
16
|
-
fail Judopay::NotFound, response
|
17
|
-
when 409
|
18
|
-
fail Judopay::Conflict, response
|
19
|
-
when 500
|
20
|
-
fail Judopay::InternalServerError, response
|
21
|
-
when 502
|
22
|
-
fail Judopay::BadGateway, response
|
23
|
-
when 503
|
24
|
-
fail Judopay::ServiceUnavailable, response
|
25
|
-
when 504
|
26
|
-
fail Judopay::GatewayTimeout, response
|
27
|
-
end
|
10
|
+
raise Judopay::APIError.factory(response) unless response.status.to_i == 200
|
28
11
|
end
|
29
12
|
end
|
30
13
|
|
data/lib/judopay.rb
CHANGED
@@ -25,15 +25,13 @@ module Judopay
|
|
25
25
|
logger.add(log_level) { message }
|
26
26
|
end
|
27
27
|
|
28
|
-
protected
|
29
|
-
|
30
28
|
# Based on the use_production flag, which endpoint should we use?
|
31
29
|
def self.configure_endpoint_for_environment
|
32
|
-
if self.configuration.use_production
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
30
|
+
self.configuration.endpoint_url = if self.configuration.use_production
|
31
|
+
self.configuration.api_endpoints[:production]
|
32
|
+
else
|
33
|
+
self.configuration.api_endpoints[:sandbox]
|
34
|
+
end
|
37
35
|
end
|
38
36
|
|
39
37
|
class Configuration
|
@@ -52,10 +50,10 @@ module Judopay
|
|
52
50
|
|
53
51
|
# Set sensible configuration defaults
|
54
52
|
def initialize
|
55
|
-
@api_version =
|
53
|
+
@api_version = Judopay::API_VERSION
|
56
54
|
@format = 'json'
|
57
55
|
@use_production = false
|
58
|
-
@user_agent =
|
56
|
+
@user_agent = "Judopay Ruby (#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}) SDK gem v#{Judopay::SDK_VERSION}"
|
59
57
|
@logger = Judopay::NullLogger.new
|
60
58
|
@api_endpoints = {
|
61
59
|
:sandbox => 'https://partnerapi.judopay-sandbox.com',
|
@@ -63,5 +61,10 @@ module Judopay
|
|
63
61
|
}.freeze
|
64
62
|
@endpoint_url = @api_endpoints[:sandbox]
|
65
63
|
end
|
64
|
+
|
65
|
+
def validate
|
66
|
+
return true unless judo_id.to_s.empty? || api_token.to_s.empty? || api_secret.to_s.empty?
|
67
|
+
raise Judopay::ValidationError, 'SDK configuration variables missing'
|
68
|
+
end
|
66
69
|
end
|
67
70
|
end
|
data/lib/judopay/connection.rb
CHANGED
@@ -10,31 +10,29 @@ module Judopay
|
|
10
10
|
private
|
11
11
|
|
12
12
|
def connection(raw = false)
|
13
|
-
|
14
|
-
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:ca_file => File.dirname(File.dirname(__FILE__)) + '/certs/rapidssl_ca.crt',
|
18
|
-
:cert_store => false,
|
19
|
-
:verify => true
|
20
|
-
}
|
21
|
-
}
|
22
|
-
|
23
|
-
connection = Faraday::Connection.new(options) do |faraday|
|
24
|
-
faraday.adapter :httpclient
|
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
|
25
17
|
faraday.use Faraday::Request::UrlEncoded
|
26
18
|
faraday.use Faraday::Response::Logger, Judopay.configuration.logger
|
27
|
-
faraday
|
28
|
-
unless raw
|
29
|
-
case Judopay.configuration.format.to_s
|
30
|
-
when 'json' then faraday.use Faraday::Response::ParseJson
|
31
|
-
end
|
32
|
-
end
|
19
|
+
define_format(faraday, raw)
|
33
20
|
faraday.use FaradayMiddleware::RaiseHttpException
|
34
21
|
end
|
35
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)
|
36
33
|
# Authentication with basic auth if there is no OAuth2 access token
|
37
34
|
if Judopay.configuration.oauth_access_token.nil?
|
35
|
+
Judopay.configuration.validate
|
38
36
|
connection.basic_auth(
|
39
37
|
Judopay.configuration.api_token,
|
40
38
|
Judopay.configuration.api_secret
|
@@ -45,6 +43,18 @@ module Judopay
|
|
45
43
|
connection
|
46
44
|
end
|
47
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
|
+
|
48
58
|
def request_headers
|
49
59
|
format = Judopay.configuration.format
|
50
60
|
|
@@ -4,7 +4,7 @@ class String
|
|
4
4
|
# "foo_bar".camel_case #=> "fooBar"
|
5
5
|
def camel_case
|
6
6
|
return self if self !~ /_/ && self =~ /[A-Z]+.*/
|
7
|
-
split('_').map
|
7
|
+
split('_').map(&:capitalize).join.uncapitalize
|
8
8
|
end
|
9
9
|
|
10
10
|
# Convert first letter to lower case
|
@@ -19,8 +19,9 @@ class String
|
|
19
19
|
#
|
20
20
|
# "BananaMan".underscore #=> "banana_man"
|
21
21
|
def underscore
|
22
|
-
to_s
|
23
|
-
.
|
22
|
+
to_s
|
23
|
+
.strip
|
24
|
+
.tr(' ', '_')
|
24
25
|
.gsub(/::/, '/')
|
25
26
|
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
26
27
|
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
data/lib/judopay/error.rb
CHANGED
@@ -1,133 +1,91 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
3
|
module Judopay
|
4
|
-
#
|
5
|
-
class
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(message
|
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
|
9
12
|
@message = message
|
10
13
|
end
|
11
14
|
|
12
|
-
def message
|
13
|
-
@message || self.class.name
|
14
|
-
end
|
15
|
-
|
16
15
|
def to_s
|
17
|
-
@message
|
16
|
+
"Field \"#{@field_name}\" (code #{@code}): #{@message}"
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
20
|
# Custom error class for rescuing from all API errors
|
22
21
|
class APIError < StandardError
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
30
43
|
|
31
|
-
|
32
|
-
return if parsed_body.nil?
|
44
|
+
protected
|
33
45
|
|
34
|
-
|
35
|
-
|
36
|
-
api_model_errors = body_attribute('modelErrors')
|
37
|
-
return if api_model_errors.nil?
|
46
|
+
def extract_field_errors(field_errors)
|
47
|
+
result = []
|
38
48
|
|
39
|
-
|
40
|
-
|
49
|
+
field_errors.to_a.each do |field_error|
|
50
|
+
result << FieldError.new(field_error['message'], field_error['code'], field_error['fieldName'], field_error['detail'])
|
51
|
+
end
|
41
52
|
|
42
|
-
|
43
|
-
|
53
|
+
result
|
54
|
+
end
|
44
55
|
end
|
45
56
|
|
46
|
-
def
|
47
|
-
@
|
57
|
+
def initialize(message, error_code = 0, status_code = 0, category = CATEGORY_UNKNOWN, field_errors = [])
|
58
|
+
@message = message
|
59
|
+
@error_code = error_code
|
60
|
+
@status_code = status_code
|
61
|
+
@category = category
|
62
|
+
@field_errors = field_errors
|
48
63
|
end
|
49
64
|
|
50
65
|
def to_s
|
51
|
-
|
52
|
-
|
53
|
-
summary = []
|
54
|
-
model_errors.each do |_key, value|
|
55
|
-
summary.push(value.join('; '))
|
56
|
-
end
|
57
|
-
|
58
|
-
@message + ' (' + summary.join('; ') + ')'
|
66
|
+
"JudoPay ApiException (status code #{@status_code}, error code #{@error_code}, category #{@category}) #{message}"
|
59
67
|
end
|
60
68
|
|
61
69
|
def message
|
62
|
-
@message || self.class.name
|
63
|
-
end
|
64
|
-
|
65
|
-
def parsed_body
|
66
|
-
@parsed_body ||= parse_body
|
70
|
+
(@message || self.class.name) + field_errors_message
|
67
71
|
end
|
68
72
|
|
69
73
|
protected
|
70
74
|
|
71
|
-
def
|
72
|
-
return
|
73
|
-
|
74
|
-
return unless @response.response_headers['Content-Type'].include?('application/json')
|
75
|
-
|
76
|
-
::JSON.parse(@response.body)
|
77
|
-
end
|
78
|
-
|
79
|
-
def body_attribute(attribute)
|
80
|
-
return nil if parsed_body.nil? || !parsed_body.include?(attribute)
|
81
|
-
parsed_body[attribute]
|
82
|
-
end
|
83
|
-
|
84
|
-
# Turn API model errors into a more ActiveRecord-like format
|
85
|
-
def process_api_model_errors(api_model_errors)
|
86
|
-
@model_errors = {}
|
87
|
-
api_model_errors.each do |api_model_error|
|
88
|
-
next unless api_model_error.is_a?(Hash)
|
89
|
-
field_name = api_model_error['fieldName'].underscore.to_sym
|
90
|
-
@model_errors[field_name] = [] if @model_errors[field_name].nil?
|
91
|
-
@model_errors[field_name].push(api_model_error['errorMessage'])
|
92
|
-
end
|
75
|
+
def field_errors_message
|
76
|
+
return '' if @field_errors.empty?
|
77
|
+
"\nFields errors:\n#{@field_errors.join("\n")}"
|
93
78
|
end
|
94
79
|
end
|
95
80
|
|
96
|
-
# Raised when API returns the HTTP status code 400
|
97
|
-
class BadRequest < APIError; end
|
98
|
-
|
99
|
-
# Raised when API returns the HTTP status code 401/403
|
100
|
-
class NotAuthorized < APIError
|
101
|
-
def message
|
102
|
-
'Authorization has been denied for this request'
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# Raised when API returns the HTTP status code 404
|
107
|
-
class NotFound < APIError; end
|
108
|
-
|
109
|
-
# Raised when API returns the HTTP status code 409
|
110
|
-
class Conflict < APIError; end
|
111
|
-
|
112
|
-
# Raised when API returns the HTTP status code 500
|
113
|
-
class InternalServerError < APIError; end
|
114
|
-
|
115
|
-
# Raised when API returns the HTTP status code 502
|
116
|
-
class BadGateway < APIError; end
|
117
|
-
|
118
|
-
# Raised when API returns the HTTP status code 503
|
119
|
-
class ServiceUnavailable < APIError; end
|
120
|
-
|
121
|
-
# Raised when API returns the HTTP status code 504
|
122
|
-
class GatewayTimeout < APIError; end
|
123
|
-
|
124
81
|
# A validation error that hasn't reached the API
|
125
82
|
class ValidationError < StandardError
|
126
83
|
attr_accessor :errors, :message
|
127
84
|
|
128
|
-
def initialize(errors)
|
85
|
+
def initialize(message, errors = nil)
|
129
86
|
@errors = errors
|
130
|
-
@message =
|
87
|
+
@message = message
|
88
|
+
@message += model_errors_summary unless @errors.nil?
|
131
89
|
end
|
132
90
|
|
133
91
|
def to_s
|
@@ -142,12 +100,12 @@ module Judopay
|
|
142
100
|
protected
|
143
101
|
|
144
102
|
def model_errors_summary
|
145
|
-
summary = []
|
103
|
+
summary = ["\nField errors:"]
|
146
104
|
model_errors.each do |key, value|
|
147
|
-
summary.push(key
|
105
|
+
summary.push("#{key}: #{value.join('; ')}")
|
148
106
|
end
|
149
107
|
|
150
|
-
|
108
|
+
summary.join("\n")
|
151
109
|
end
|
152
110
|
end
|
153
111
|
end
|