eml 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/README.md +6 -3
- data/Rakefile +6 -0
- data/bin/console +13 -0
- data/bin/setup +8 -0
- data/eml.gemspec +30 -26
- data/lib/eml.rb +19 -1
- data/lib/eml/error.rb +0 -9
- data/lib/eml/error/tns.rb +8 -0
- data/lib/eml/error/tns/authentication.rb +17 -0
- data/lib/eml/lib/basic_auth/generate.rb +42 -0
- data/lib/eml/lib/basic_auth/verify.rb +48 -0
- data/lib/eml/lib/constant_time_compare.rb +31 -0
- data/lib/eml/model.rb +35 -0
- data/lib/eml/parameters.rb +5 -2
- data/lib/eml/uk.rb +6 -3
- data/lib/eml/uk/api_resource.rb +14 -13
- data/lib/eml/uk/config.rb +10 -4
- data/lib/eml/uk/models/tns_card.rb +20 -0
- data/lib/eml/uk/models/tns_transaction.rb +49 -0
- data/lib/eml/uk/{model → models}/transaction.rb +9 -16
- data/lib/eml/uk/parameters.rb +0 -11
- data/lib/eml/uk/parameters/card/show.rb +4 -6
- data/lib/eml/uk/payload.rb +0 -11
- data/lib/eml/uk/payload/agreement/show.rb +6 -6
- data/lib/eml/uk/responses/card/transaction.rb +2 -2
- data/lib/eml/uk/tns/process_request.rb +64 -0
- data/lib/eml/uk/tns/response.rb +23 -0
- data/lib/eml/version.rb +1 -1
- metadata +45 -12
- data/lib/eml/uk/payload/contactentity.rb +0 -64
- data/spec/config_spec.rb +0 -26
- data/spec/helpers/config_helper.rb +0 -21
- data/spec/helpers/vcr_helper.rb +0 -19
- data/spec/spec_helper.rb +0 -120
- data/spec/uk/api_resource_spec.rb +0 -39
- data/spec/uk/resources/agreement_spec.rb +0 -23
- data/spec/uk/resources/card_spec.rb +0 -197
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e01fb29821c0e3e1bb2b2ba438e5dfc662162a398d187904adf1a52725a11936
|
4
|
+
data.tar.gz: a7d4d70f1ad4e28f01b60df90fb5937205985f36b32f8c0d7cbf73895d2e306e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: edd3ebfb85dd29364c3e1942f49aac8417feb5bb99f4c6e14ece9f014e6d77de656838c9158077cda051f4581cc18c3e47861f334aaf10b3ae6ca8c4dd631338
|
7
|
+
data.tar.gz: b2f96353fce3d485aa5663ec73fd36d11884e9db5c3848f0c2700dd15a9051f0e4f312a34dc51a46bdf5b2945599134a28b7b72fb760f182567382ad1e2cb5e2
|
data/.rubocop.yml
CHANGED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at development@hashnotadam.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@ You don't need this source code unless you want to modify the gem. If you just
|
|
13
13
|
want to use the package, just include the following in your Gemfile:
|
14
14
|
|
15
15
|
```sh
|
16
|
-
gem "eml"
|
16
|
+
gem "eml"
|
17
17
|
```
|
18
18
|
|
19
19
|
If you are debugging or developing this gem and wish to use it within the
|
@@ -36,10 +36,13 @@ with your supplied credentials.
|
|
36
36
|
require "eml"
|
37
37
|
|
38
38
|
EML::UK.configure do |config|
|
39
|
-
config.
|
40
|
-
config.
|
39
|
+
config.rest_username = "username"
|
40
|
+
config.rest_password = "password"
|
41
41
|
config.merchant_group = "merchant_id"
|
42
42
|
config.program = "program_id"
|
43
|
+
config.search_parameter = "program_id"
|
44
|
+
config.tns_username = "username"
|
45
|
+
config.tns_password = "password"
|
43
46
|
end
|
44
47
|
```
|
45
48
|
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "eml"
|
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
|
+
require "pry"
|
10
|
+
Pry.start
|
11
|
+
|
12
|
+
require "irb"
|
13
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/eml.gemspec
CHANGED
@@ -4,34 +4,38 @@ $LOAD_PATH.unshift(::File.join(::File.dirname(__FILE__), "lib"))
|
|
4
4
|
|
5
5
|
require "eml/version"
|
6
6
|
|
7
|
-
Gem::Specification.new do |
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "eml"
|
9
|
+
spec.version = EML::VERSION
|
10
|
+
spec.required_ruby_version = ">= 2.6.0"
|
11
|
+
spec.summary = "Ruby bindings for the EML API"
|
12
|
+
spec.description = "Connect to the EML payments APIs and " \
|
13
13
|
"Transaction Notification Serices"
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
spec.author = "Morning Coffee"
|
15
|
+
spec.email = "developers@morningcoffee.com.au"
|
16
|
+
spec.homepage = "https://github.com/MorningCoffeeDev/eml_ruby"
|
17
|
+
spec.license = "MIT"
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
20
|
+
`git ls-files -z`.split("\x0").
|
21
|
+
reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
|
+
end
|
23
|
+
spec.require_paths = ["lib"]
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
+
spec.add_dependency "http", "~> 4.0.0"
|
26
|
+
spec.add_dependency "sorbet-runtime"
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
28
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
29
|
+
spec.add_development_dependency "dotenv"
|
30
|
+
spec.add_development_dependency "faker"
|
31
|
+
spec.add_development_dependency "pry-byebug"
|
32
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
33
|
+
spec.add_development_dependency "rspec", "~> 3.8"
|
34
|
+
spec.add_development_dependency "rubocop", "~> 0.71"
|
35
|
+
spec.add_development_dependency "rubocop-performance"
|
36
|
+
spec.add_development_dependency "rubocop-rspec"
|
37
|
+
spec.add_development_dependency "simplecov"
|
38
|
+
spec.add_development_dependency "sorbet"
|
39
|
+
spec.add_development_dependency "vcr"
|
40
|
+
spec.add_development_dependency "webmock"
|
37
41
|
end
|
data/lib/eml.rb
CHANGED
@@ -13,10 +13,28 @@ require "eml/data/states"
|
|
13
13
|
|
14
14
|
require "eml/config"
|
15
15
|
require "eml/environment"
|
16
|
+
|
16
17
|
require "eml/error"
|
18
|
+
require "eml/error/rest"
|
19
|
+
require "eml/error/rest/authentication"
|
20
|
+
require "eml/error/rest/bad_request"
|
21
|
+
require "eml/error/rest/daily_funding_limit"
|
22
|
+
require "eml/error/rest/forbidden"
|
23
|
+
require "eml/error/rest/internal_server"
|
24
|
+
require "eml/error/rest/not_found"
|
25
|
+
require "eml/error/rest/unprocessable_entity"
|
26
|
+
require "eml/error/tns"
|
27
|
+
require "eml/error/tns/authentication"
|
28
|
+
|
29
|
+
require "eml/lib/basic_auth/generate"
|
30
|
+
require "eml/lib/basic_auth/verify"
|
31
|
+
require "eml/lib/constant_time_compare"
|
17
32
|
require "eml/lib/endpoint_class"
|
33
|
+
|
34
|
+
require "eml/model"
|
18
35
|
require "eml/parameters"
|
19
36
|
require "eml/payload"
|
20
37
|
require "eml/response"
|
21
|
-
require "eml/uk"
|
22
38
|
require "eml/version"
|
39
|
+
|
40
|
+
require "eml/uk"
|
data/lib/eml/error.rb
CHANGED
@@ -14,12 +14,3 @@ module EML
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
18
|
-
require "eml/error/rest"
|
19
|
-
require "eml/error/rest/authentication"
|
20
|
-
require "eml/error/rest/bad_request"
|
21
|
-
require "eml/error/rest/daily_funding_limit"
|
22
|
-
require "eml/error/rest/forbidden"
|
23
|
-
require "eml/error/rest/internal_server"
|
24
|
-
require "eml/error/rest/not_found"
|
25
|
-
require "eml/error/rest/unprocessable_entity"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module EML
|
5
|
+
module TNS
|
6
|
+
class AuthenticationError < ::EML::TNSError
|
7
|
+
sig { params(message: T.nilable(String)).void }
|
8
|
+
def initialize(message = nil)
|
9
|
+
message ||= "An unexpected authorization token was supplied in the " \
|
10
|
+
"request. Please check that you have set the correct tns_username " \
|
11
|
+
"and tns_password in your config and that EML is using the same " \
|
12
|
+
"credentials. Failing this, it is possible you are being attacked"
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "base64"
|
5
|
+
|
6
|
+
module EML
|
7
|
+
module BasicAuth
|
8
|
+
class Generate
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
sig do
|
12
|
+
params(
|
13
|
+
username: String,
|
14
|
+
password: String,
|
15
|
+
prefix: String
|
16
|
+
).returns(String)
|
17
|
+
end
|
18
|
+
def self.call(username, password, prefix: "")
|
19
|
+
new(username, password, prefix).call
|
20
|
+
end
|
21
|
+
|
22
|
+
sig do
|
23
|
+
params(
|
24
|
+
username: String,
|
25
|
+
password: String,
|
26
|
+
prefix: String
|
27
|
+
).void
|
28
|
+
end
|
29
|
+
def initialize(username, password, prefix)
|
30
|
+
@username = username
|
31
|
+
@password = password
|
32
|
+
@prefix = prefix
|
33
|
+
end
|
34
|
+
|
35
|
+
sig { returns(String) }
|
36
|
+
def call
|
37
|
+
token = Base64.encode64("#{@username}:#{@password}").tr("\n", "")
|
38
|
+
"#{@prefix}#{token}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module EML
|
5
|
+
module BasicAuth
|
6
|
+
class Verify
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig do
|
10
|
+
params(
|
11
|
+
auth_token: String,
|
12
|
+
username: String,
|
13
|
+
password: String
|
14
|
+
).returns(T::Boolean)
|
15
|
+
end
|
16
|
+
def self.call(auth_token, username, password)
|
17
|
+
new(auth_token, username, password).call
|
18
|
+
end
|
19
|
+
|
20
|
+
sig do
|
21
|
+
params(
|
22
|
+
auth_token: String,
|
23
|
+
username: String,
|
24
|
+
password: String
|
25
|
+
).void
|
26
|
+
end
|
27
|
+
def initialize(auth_token, username, password)
|
28
|
+
@auth_token = auth_token
|
29
|
+
@username = username
|
30
|
+
@password = password
|
31
|
+
end
|
32
|
+
|
33
|
+
sig { returns(T::Boolean) }
|
34
|
+
def call
|
35
|
+
request_token = parse_auth_token
|
36
|
+
expected_token = Generate.(@username, @password)
|
37
|
+
|
38
|
+
::EML::ConstantTimeCompare.(request_token, expected_token)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def parse_auth_token
|
44
|
+
@auth_token.sub(/^[^\s]+\s/, "")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module EML
|
5
|
+
class ConstantTimeCompare
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
sig { params(comparison: String, expected: String).returns(T::Boolean) }
|
9
|
+
def self.call(comparison, expected)
|
10
|
+
new(comparison, expected).call
|
11
|
+
end
|
12
|
+
|
13
|
+
sig { params(comparison: String, expected: String).void }
|
14
|
+
def initialize(comparison, expected)
|
15
|
+
@comparison = comparison
|
16
|
+
@expected = expected
|
17
|
+
end
|
18
|
+
|
19
|
+
sig { returns(T::Boolean) }
|
20
|
+
def call
|
21
|
+
return false if @comparison.length != @expected.length
|
22
|
+
|
23
|
+
result = 0
|
24
|
+
|
25
|
+
Hash[[@comparison.bytes, @expected.bytes].transpose].
|
26
|
+
each { |x, y| result |= x ^ y }
|
27
|
+
|
28
|
+
result.zero?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/eml/model.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module EML
|
5
|
+
class Model
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
def self.fields(fields)
|
9
|
+
const_set(:FIELDS, fields.freeze)
|
10
|
+
fields.each do |response_name, local_name|
|
11
|
+
local_name ||= response_name
|
12
|
+
__send__(:attr_reader, :"#{local_name}")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
sig { params(raw_values: T::Hash[String, T.untyped]).void }
|
17
|
+
def initialize(raw_values)
|
18
|
+
self.class::FIELDS.each do |response_name, local_name|
|
19
|
+
local_name ||= response_name
|
20
|
+
value = field_value(response_name, raw_values[response_name])
|
21
|
+
instance_variable_set(:"@#{local_name}", value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
sig { params(name: String, raw_value: T.untyped).returns(T.untyped) }
|
28
|
+
def field_value(name, raw_value)
|
29
|
+
return raw_value unless name.match?(/(Date|Time)$/)
|
30
|
+
return raw_value if raw_value.nil? || raw_value.empty?
|
31
|
+
|
32
|
+
Time.parse(raw_value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|