seb_elink 0.9.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 +7 -0
- data/.circleci/config.yml +24 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +66 -0
- data/LICENSE.txt +28 -0
- data/README.md +136 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/seb_elink.rb +38 -0
- data/lib/seb_elink/communications.rb +19 -0
- data/lib/seb_elink/gateway.rb +106 -0
- data/lib/seb_elink/message.rb +59 -0
- data/lib/seb_elink/message_specs.rb +96 -0
- data/lib/seb_elink/response.rb +67 -0
- data/lib/seb_elink/version.rb +3 -0
- data/seb_elink.gemspec +31 -0
- metadata +148 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 4754ac20b5f8fb96fa6f5da401ad7a743eb9f0bc
|
|
4
|
+
data.tar.gz: 35fd08333c236cc5e4b3fca833cf178880b81f4c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e91e10a2ecfe7bc6a1dc525ca931f2111af3c38356c8866a8c82e58cfc3a5fdc0df4de4c99552b77a62fb0b540b746d2c31c558c41913027110714147f571185
|
|
7
|
+
data.tar.gz: 2bae5422c88af83cd9b16c07af01efa1501044b482b4167b41c896f024d16d7c49fb6b3d15eb0753e4f496b60856436df5b2b731acfd7ac46186cd2fad1cc7b5
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
jobs:
|
|
3
|
+
build:
|
|
4
|
+
working_directory: ~/seb_elink
|
|
5
|
+
docker:
|
|
6
|
+
# ruby:2-node
|
|
7
|
+
- image: circleci/ruby@sha256:382aa3816e4a1447f56dfa5c70751a727eb276bb0d1617f1989e3ca28bb251f5
|
|
8
|
+
|
|
9
|
+
steps:
|
|
10
|
+
- checkout
|
|
11
|
+
|
|
12
|
+
- run: gem install bundler -v 1.16.0 --no-doc
|
|
13
|
+
|
|
14
|
+
- restore_cache:
|
|
15
|
+
key: seb_elink-v1-{{ checksum "Gemfile.lock" }}
|
|
16
|
+
|
|
17
|
+
- run: bundle install --path vendor/bundle
|
|
18
|
+
|
|
19
|
+
- save_cache:
|
|
20
|
+
key: seb_elink-v1-{{ checksum "Gemfile.lock" }}
|
|
21
|
+
paths:
|
|
22
|
+
- vendor/bundle
|
|
23
|
+
|
|
24
|
+
- run: bundle exec rspec
|
data/.gitignore
ADDED
data/.rspec
ADDED
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 cto@creative.gs. 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/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
seb_elink (0.9.0)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
coderay (1.1.2)
|
|
10
|
+
coveralls (0.7.2)
|
|
11
|
+
multi_json (~> 1.3)
|
|
12
|
+
rest-client (= 1.6.7)
|
|
13
|
+
simplecov (>= 0.7)
|
|
14
|
+
term-ansicolor (= 1.2.2)
|
|
15
|
+
thor (= 0.18.1)
|
|
16
|
+
diff-lcs (1.3)
|
|
17
|
+
docile (1.1.5)
|
|
18
|
+
json (2.1.0)
|
|
19
|
+
method_source (0.9.0)
|
|
20
|
+
mime-types (3.1)
|
|
21
|
+
mime-types-data (~> 3.2015)
|
|
22
|
+
mime-types-data (3.2016.0521)
|
|
23
|
+
multi_json (1.12.2)
|
|
24
|
+
pry (0.11.3)
|
|
25
|
+
coderay (~> 1.1.0)
|
|
26
|
+
method_source (~> 0.9.0)
|
|
27
|
+
rake (10.5.0)
|
|
28
|
+
rest-client (1.6.7)
|
|
29
|
+
mime-types (>= 1.16)
|
|
30
|
+
rspec (3.7.0)
|
|
31
|
+
rspec-core (~> 3.7.0)
|
|
32
|
+
rspec-expectations (~> 3.7.0)
|
|
33
|
+
rspec-mocks (~> 3.7.0)
|
|
34
|
+
rspec-core (3.7.0)
|
|
35
|
+
rspec-support (~> 3.7.0)
|
|
36
|
+
rspec-expectations (3.7.0)
|
|
37
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
38
|
+
rspec-support (~> 3.7.0)
|
|
39
|
+
rspec-mocks (3.7.0)
|
|
40
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
41
|
+
rspec-support (~> 3.7.0)
|
|
42
|
+
rspec-support (3.7.0)
|
|
43
|
+
simplecov (0.15.1)
|
|
44
|
+
docile (~> 1.1.0)
|
|
45
|
+
json (>= 1.8, < 3)
|
|
46
|
+
simplecov-html (~> 0.10.0)
|
|
47
|
+
simplecov-html (0.10.2)
|
|
48
|
+
term-ansicolor (1.2.2)
|
|
49
|
+
tins (~> 0.8)
|
|
50
|
+
thor (0.18.1)
|
|
51
|
+
tins (0.13.2)
|
|
52
|
+
|
|
53
|
+
PLATFORMS
|
|
54
|
+
ruby
|
|
55
|
+
|
|
56
|
+
DEPENDENCIES
|
|
57
|
+
bundler (~> 1.16)
|
|
58
|
+
coveralls
|
|
59
|
+
pry (~> 0.11.3)
|
|
60
|
+
rake (~> 10.0)
|
|
61
|
+
rspec (~> 3.7)
|
|
62
|
+
seb_elink!
|
|
63
|
+
simplecov (~> 0.15.1)
|
|
64
|
+
|
|
65
|
+
BUNDLED WITH
|
|
66
|
+
1.16.0
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-clause "New" or "Revised" License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 Creative.gs . All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
6
|
+
are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
9
|
+
this list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation and/or
|
|
13
|
+
other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of Creative.gs nor the names of its contributors
|
|
16
|
+
may be used to endorse or promote products derived from this software without
|
|
17
|
+
specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY Creative.gs AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
21
|
+
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
22
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
23
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
25
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
26
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
[](https://badge.fury.io/rb/seb_elink)
|
|
2
|
+
[](https://circleci.com/gh/CreativeGS/seb_elink/tree/master)
|
|
3
|
+
[](https://coveralls.io/github/CreativeGS/seb_elink?branch=master)
|
|
4
|
+
|
|
5
|
+
# SebElink
|
|
6
|
+
Lightweight Ruby wrapper for communicating with SEB.lv i-bank payment API.
|
|
7
|
+
Solves the cryptographic requirements for you.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
Bundle or manually install the latest version of the gem:
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
gem 'seb_elink'
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
Please note that for consistency in this gem all hash keys are constant-case __symbols__.
|
|
18
|
+
|
|
19
|
+
The gem has three elements represented as Ruby classes:
|
|
20
|
+
|
|
21
|
+
__1. SebElink::Gateway__
|
|
22
|
+
Think of this as the communication adapter. Initialize it with a base64-encoded private key string (the human-readable .pem format). You can store the instance in a constant to reduce processing overhead.
|
|
23
|
+
|
|
24
|
+
You can pass an optional options hash as the second argument that will specify default values for communications processed by that gateway instance. Useful for setting company-related data just once.
|
|
25
|
+
|
|
26
|
+
```rb
|
|
27
|
+
SebElink::Gateway.new(
|
|
28
|
+
<privkey string>,
|
|
29
|
+
{
|
|
30
|
+
IB_SND_ID: "TESTCOMPANY",
|
|
31
|
+
IB_NAME: "Test Inc."
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Additionally, you can rewrite values used by the gem pertaining to SEB.lv i-bank, such as their public key, API uri etc. Here's a complete list:
|
|
37
|
+
|
|
38
|
+
```rb
|
|
39
|
+
{
|
|
40
|
+
IB_VERSION: "001", # which API version to use
|
|
41
|
+
IBANK_CERT: "-----BEGIN CERTIFICATE-----..." # public key/cer of SEB.lv, changes rarely
|
|
42
|
+
IBANK_API_URI: "https://ibanka.seb.lv/ipc/epakindex.jsp" # where to POST users
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Instances of `SebElink::Gateway` have one method for public use:
|
|
47
|
+
|
|
48
|
+
```rb
|
|
49
|
+
gateway.ibank_api_uri #=> uri for POSTing intial message to.
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
__2. SebElink::Message__
|
|
53
|
+
Instances represent requests to i-bank, generally for payment.
|
|
54
|
+
|
|
55
|
+
Initialize these with `SebElink::Message.new(gateway_instance, message_code, data_hash)`
|
|
56
|
+
|
|
57
|
+
```rb
|
|
58
|
+
SEB_LV_GATEWAY = SebElink::Gateway.new(<privkey string>)
|
|
59
|
+
message_instance = SebElink::Message.new(SEB_LV_GATEWAY, "0002", {IB_SND_ID: ...})
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Please consult `message_specs.rb` for the full list of data_hash keys.
|
|
63
|
+
|
|
64
|
+
Instances of `SebElink::Message` have two methods:
|
|
65
|
+
|
|
66
|
+
```rb
|
|
67
|
+
message_instance.to_h
|
|
68
|
+
#=> hash of all fields you need to POST to i-bank API uri.
|
|
69
|
+
|
|
70
|
+
message_instance.digital_signature
|
|
71
|
+
#=> outputs the value of :IB_CRC key, the base64-encoded digital signature of the message
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
__3. SebElink::Response__
|
|
75
|
+
Instances represent responses from SEB.lv i-bank server.
|
|
76
|
+
Well-formedness is not validated since if digital signature is OK, one would think that the bank adheres to it's own spec.
|
|
77
|
+
|
|
78
|
+
Initialize these with `SebElink::Response.new(gateway_instance, response_body)`
|
|
79
|
+
|
|
80
|
+
Please note that the method name `#response` is reserved in Rails, use something else for response variable names!
|
|
81
|
+
|
|
82
|
+
```rb
|
|
83
|
+
SEB_LV_GATEWAY = SebElink::Gateway.new(<privkey string>)
|
|
84
|
+
|
|
85
|
+
# in a Rails controller context you can obtain the response_body with:
|
|
86
|
+
response_body =
|
|
87
|
+
if request.get?
|
|
88
|
+
request.query_string
|
|
89
|
+
else
|
|
90
|
+
request.raw_post
|
|
91
|
+
end #=> "IB_SND_ID=TEST..."
|
|
92
|
+
|
|
93
|
+
response_instance = SebElink::Response.new(SEB_LV_GATEWAY, response_body)
|
|
94
|
+
|
|
95
|
+
# Please note that the :IB_CRC signature values will often end with "==\n" which, when uri-escaped will be "%3D%3D%0A", pass the response just like that into the initializer
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Instances of `SebElink::Response` have two methods:
|
|
99
|
+
|
|
100
|
+
```rb
|
|
101
|
+
response_instance.valid?
|
|
102
|
+
#=> true, if the digital signature is OK.
|
|
103
|
+
# DO NOT process responses that are invalid, someone has tampered with the values!
|
|
104
|
+
|
|
105
|
+
response_instance.to_h
|
|
106
|
+
#=> {IB_SND_ID: "TEST", ...}
|
|
107
|
+
# Will raise if called on an invalid response_instance
|
|
108
|
+
# to override this default safety setting, call with to_h(:insecure)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Tests have been written in a documenting manner, so, please,
|
|
112
|
+
have a look at the contents of `spec/` directory to get a feel of what the gem can do.
|
|
113
|
+
|
|
114
|
+
Version 001 (current) uses the deprecated SHA-1 hashing algorithm. Let SEB.lv know that v2 that uses SHA-256 is needed.
|
|
115
|
+
|
|
116
|
+
## Contributing
|
|
117
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/CreativeGS/seb_elink. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
|
118
|
+
|
|
119
|
+
The project uses TDD approach to software development, follow these steps to set up:
|
|
120
|
+
1. fork and clone the repo on github
|
|
121
|
+
2. Install appropriate Ruby and Bundler
|
|
122
|
+
3. `bundle`
|
|
123
|
+
4. See if all specs are green with `rspec`
|
|
124
|
+
5. TDD new features
|
|
125
|
+
6. Make a Pull Request in github
|
|
126
|
+
|
|
127
|
+
## Releasing a new version
|
|
128
|
+
TODO
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
The gem is available as open source under the terms of the [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause).
|
|
133
|
+
|
|
134
|
+
## Code of Conduct
|
|
135
|
+
|
|
136
|
+
Everyone interacting in the SebElink project’s codebases and issue trackers is expected to follow the [code of conduct](https://github.com/CreativeGS/seb_elink/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "seb_elink"
|
|
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
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require "irb"
|
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/seb_elink.rb
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require "base64"
|
|
2
|
+
require "openssl"
|
|
3
|
+
|
|
4
|
+
require "seb_elink/message_specs"
|
|
5
|
+
require "seb_elink/communications"
|
|
6
|
+
require "seb_elink/gateway"
|
|
7
|
+
require "seb_elink/message"
|
|
8
|
+
require "seb_elink/response"
|
|
9
|
+
require "seb_elink/version"
|
|
10
|
+
|
|
11
|
+
module SebElink
|
|
12
|
+
extend self
|
|
13
|
+
|
|
14
|
+
def root
|
|
15
|
+
@@root ||= Pathname.new(Gem::Specification.find_by_name("seb_elink").gem_dir)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
DEFAULTS = {
|
|
19
|
+
IB_VERSION: "001",
|
|
20
|
+
IBANK_API_URI: "https://ibanka.seb.lv/ipc/epakindex.jsp",
|
|
21
|
+
IBANK_CERT: <<-HEREDOC
|
|
22
|
+
-----BEGIN CERTIFICATE-----
|
|
23
|
+
MIIB9TCCAV4CCQC7RlKZ7y4JPTANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQGEwJM
|
|
24
|
+
VjENMAsGA1UEBwwEUmlnYTERMA8GA1UECgwIU0VCIGJhbmsxDjAMBgNVBAMMBVNF
|
|
25
|
+
QlVCMB4XDTE2MDcxODA4NTQxM1oXDTIxMDYyMjA4NTQxM1owPzELMAkGA1UEBhMC
|
|
26
|
+
TFYxDTALBgNVBAcMBFJpZ2ExETAPBgNVBAoMCFNFQiBiYW5rMQ4wDAYDVQQDDAVT
|
|
27
|
+
RUJVQjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3gfAFe64YIu21x2UOTby
|
|
28
|
+
stFPMo7TFRWd7oW1L1YQWLHQuNVOh1kjrQWehECyK8cyX1hdHXPoAY3B2Virgj8U
|
|
29
|
+
g70ZfO6QQx9zifhlN0gbxRdPjq5jM7Ni5RMWsIayErAhk8IjbPSINLe5l/CpVAhp
|
|
30
|
+
yGJWRW8CYH9c/HLsUeg0sKUCAwEAATANBgkqhkiG9w0BAQUFAAOBgQDY9hRVOZkK
|
|
31
|
+
957h2Ij8iwV7fIR3Nw8l+248D09xuknBrDOSYMXEDvEPKAW+CS0sQ64MOFybAFRx
|
|
32
|
+
YICfpu2DQkcmMM5APo79YzwMCjElRn5BsNyX7oDe4SZHbdUVqF4/mrFI3FU1KdN2
|
|
33
|
+
MJizE92BjvgQlJocLJePUi6jbO5YrmICkw==
|
|
34
|
+
-----END CERTIFICATE-----
|
|
35
|
+
HEREDOC
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SebElink::Communications
|
|
2
|
+
private
|
|
3
|
+
|
|
4
|
+
def validate_message_code
|
|
5
|
+
message_codes = send(:class)::SUPPORTED_MESSAGES
|
|
6
|
+
|
|
7
|
+
raise ArgumentError.new(
|
|
8
|
+
"'#{message_code}' is not a supported message code. Supported ones are: #{message_codes}"
|
|
9
|
+
) unless message_codes.include?(message_code)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def validate_version
|
|
13
|
+
versions = send(:class)::SUPPORTED_VERSIONS
|
|
14
|
+
|
|
15
|
+
raise ArgumentError.new(
|
|
16
|
+
"'#{version}' is not a supported version. Supported ones are: #{versions}"
|
|
17
|
+
) unless versions.include?(version)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
class SebElink::Gateway
|
|
2
|
+
include SebElink::MessageSpecs
|
|
3
|
+
|
|
4
|
+
attr_reader :privkey, :defaults
|
|
5
|
+
|
|
6
|
+
def initialize(privkey, defaults={})
|
|
7
|
+
@privkey = privkey
|
|
8
|
+
@defaults = SebElink::DEFAULTS.merge(defaults)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def ibank_api_uri
|
|
12
|
+
@ibank_api_uri ||= defaults[:IBANK_API_URI]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# options: {
|
|
16
|
+
# message_code: "000x",
|
|
17
|
+
# version: "00x"
|
|
18
|
+
# skip_validation: false, # true for from-SEB messages like 0003 and 0004
|
|
19
|
+
# data: {
|
|
20
|
+
# IB_SND_ID: "TESTACC",
|
|
21
|
+
# ...
|
|
22
|
+
# }
|
|
23
|
+
# }
|
|
24
|
+
def produce_footprint(options)
|
|
25
|
+
data_hash = options[:data]
|
|
26
|
+
spec_set = spec_for(version: options[:version], message_code: options[:message_code])
|
|
27
|
+
|
|
28
|
+
footprint_string = spec_set.map do |field, spec|
|
|
29
|
+
next unless spec[:in_signature]
|
|
30
|
+
|
|
31
|
+
unless options[:skip_validation]
|
|
32
|
+
# 1. validate each field's length in .bytesize and format
|
|
33
|
+
raise_nil_error(field) if data_hash[field] == nil
|
|
34
|
+
raise_length_error(field) if data_hash[field].to_s.bytesize > spec[:max_length]
|
|
35
|
+
raise_format_error(field) if !data_hash[field].to_s[spec[:format]]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# 2. build the 'len(p1)||p1..' string
|
|
39
|
+
"#{data_hash[field].to_s.bytesize.to_s.rjust(3, "0")}#{data_hash[field]}"
|
|
40
|
+
end.join("")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# options: {
|
|
44
|
+
# version: "00x",
|
|
45
|
+
# message_code: "000x"
|
|
46
|
+
# }
|
|
47
|
+
def spec_for(options)
|
|
48
|
+
send(:class).const_get("V#{options[:version]}_MESSAGE#{options[:message_code]}_SPEC")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# options: {
|
|
52
|
+
# version: "00x",
|
|
53
|
+
# message_footprint: "001a.."
|
|
54
|
+
# }
|
|
55
|
+
def sign(options)
|
|
56
|
+
Base64.encode64(
|
|
57
|
+
privkey_rsa.sign(
|
|
58
|
+
send("v#{options[:version]}_digest"), #=> digest algorythm, SHA1
|
|
59
|
+
options[:message_footprint]
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# options: {
|
|
65
|
+
# version: "00x",
|
|
66
|
+
# message:,
|
|
67
|
+
# base64_signature:
|
|
68
|
+
# # OR
|
|
69
|
+
# signature:
|
|
70
|
+
# }
|
|
71
|
+
def verify(options)
|
|
72
|
+
received_binary_signature = options[:signature] ||
|
|
73
|
+
Base64.decode64(options[:base64_signature])
|
|
74
|
+
|
|
75
|
+
ibank_pubkey_rsa.verify(
|
|
76
|
+
send("v#{options[:version]}_digest"),
|
|
77
|
+
received_binary_signature,
|
|
78
|
+
options[:message]
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
def v001_digest
|
|
84
|
+
OpenSSL::Digest::SHA1.new
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def privkey_rsa
|
|
88
|
+
@privkey_rsa ||= OpenSSL::PKey::RSA.new(privkey)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def ibank_pubkey_rsa
|
|
92
|
+
@ibank_pubkey_rsa ||= OpenSSL::X509::Certificate.new(defaults[:IBANK_CERT]).public_key
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def raise_length_error(field)
|
|
96
|
+
raise ArgumentError.new("#{field} value is too long")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def raise_format_error(field)
|
|
100
|
+
raise ArgumentError.new("#{field} value format does not match the spec")
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def raise_nil_error(field)
|
|
104
|
+
raise ArgumentError.new("#{field} key is absent")
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
class SebElink::Message
|
|
2
|
+
include SebElink::Communications
|
|
3
|
+
|
|
4
|
+
SUPPORTED_VERSIONS = ["001"].freeze
|
|
5
|
+
SUPPORTED_MESSAGES = ["0002"].freeze
|
|
6
|
+
|
|
7
|
+
attr_reader :gateway_instance, :message_code, :data_hash
|
|
8
|
+
|
|
9
|
+
def initialize(gateway_instance, message_code, data_hash)
|
|
10
|
+
@gateway_instance = gateway_instance
|
|
11
|
+
|
|
12
|
+
@message_code = message_code
|
|
13
|
+
|
|
14
|
+
validate_message_code
|
|
15
|
+
|
|
16
|
+
@data_hash = gateway_instance.defaults.
|
|
17
|
+
merge(IB_SERVICE: @message_code).merge(data_hash)
|
|
18
|
+
|
|
19
|
+
validate_version
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def digital_signature
|
|
23
|
+
@digital_signature ||= to_h[:IB_CRC]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_h
|
|
27
|
+
@to_h ||= send("message_#{message_code}")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def message_0002
|
|
33
|
+
footprint_string = gateway_instance.produce_footprint({
|
|
34
|
+
message_code: message_code,
|
|
35
|
+
version: version,
|
|
36
|
+
skip_validation: false,
|
|
37
|
+
data: data_hash
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
# 3. Hash-sign the footprint string => obtain "digital signature" of the message
|
|
41
|
+
digital_signature = gateway_instance.sign({
|
|
42
|
+
version: version,
|
|
43
|
+
message_footprint: footprint_string
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
# 4. Append IB_CRC key with the "digital signature" and return the hash
|
|
47
|
+
gateway_instance.spec_for(version: version, message_code: message_code).
|
|
48
|
+
keys.each_with_object({}) do |k, hash|
|
|
49
|
+
hash[k] = data_hash[k] if data_hash.has_key?(k)
|
|
50
|
+
end.merge(IB_CRC: digital_signature)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def version
|
|
54
|
+
return @version if defined?(@version)
|
|
55
|
+
|
|
56
|
+
@version = data_hash[:IB_VERSION]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module SebElink::MessageSpecs
|
|
2
|
+
# Storing SEB-defined specs for messages here
|
|
3
|
+
|
|
4
|
+
# AKA P.MU.1
|
|
5
|
+
# Sequence, Parameter title, Max length, Example of value, Description
|
|
6
|
+
# 1, IB_SND_ID, 10, SOMENAME, AAA Request sender (E-system)
|
|
7
|
+
# 2, IB_SERVICE, 4, 0002, Code of the Internet bank request type. Constant 0002
|
|
8
|
+
# 3, IB_VERSION, 3, 001, ID of used digital signature algorithm. Constant 001.
|
|
9
|
+
# 4, IB_AMOUNT, 17, 1234.56, Payment amount
|
|
10
|
+
# 5, IB_CURR, 3, EUR, Payment currency (EUR)
|
|
11
|
+
# 6, IB_NAME, 30, Company Beneficiary’s name, (in this case: Company)
|
|
12
|
+
# 7, IB_PAYMENT_ID, 20, UB0000000000015, Payment order reference number
|
|
13
|
+
# 8, IB_PAYMENT_DESC, 100, Your invoice No. 1234 is paid, Payment order description
|
|
14
|
+
# 9, IB_CRC, 500, abs51ajksa..., Request digital signature
|
|
15
|
+
# 10, IB_FEEDBACK, 150, URL to which the Bank will send the message of acceptance
|
|
16
|
+
# of the payment order for processing, execution, cancellation.
|
|
17
|
+
# 11, IB_LANG, 3, LAT, Preferable language (LAT, ENG, RUS)
|
|
18
|
+
V001_MESSAGE0002_SPEC = {
|
|
19
|
+
IB_SND_ID: {no: 1, in_signature: true, max_length: 10, format: %r'\A.{1,}\z'},
|
|
20
|
+
IB_SERVICE: {no: 2, in_signature: true, max_length: 4, format: %r'\A0002\z'},
|
|
21
|
+
IB_VERSION: {no: 3, in_signature: true, max_length: 3, format: %r'\A001\z'},
|
|
22
|
+
IB_AMOUNT: {no: 4, in_signature: true, max_length: 17, format: %r'\A\d+([.,]\d{,2})?\z'},
|
|
23
|
+
IB_CURR: {no: 5, in_signature: true, max_length: 3, format: %r'\A[A-Z]{3}\z'},
|
|
24
|
+
IB_NAME: {no: 6, in_signature: true, max_length: 30, format: %r'\A.{1,}\z'},
|
|
25
|
+
IB_PAYMENT_ID: {no: 7, in_signature: true, max_length: 20, format: %r'\A[0-9a-zA-Z]{1,20}\z'},
|
|
26
|
+
IB_PAYMENT_DESC: {no: 8, in_signature: true, max_length: 100, format: %r'\A.{1,}\z'},
|
|
27
|
+
# IB_CRC: {no: 9, in_signature: false, max_length: 500, format: %r'\A.*\z'},
|
|
28
|
+
IB_FEEDBACK: {no: 10, in_signature: false, max_length: 150, format: %r'\A.*\z'},
|
|
29
|
+
IB_LANG: {no: 11, in_signature: false, max_length: 3, format: %r'\A(?:LAT)|(?:ENG)|(?:RUS)\z'},
|
|
30
|
+
}.freeze
|
|
31
|
+
|
|
32
|
+
# # 4.2 Message 0003 - Payment order acceptance for processing (P.MU.3 and P.MU.4 parameters):
|
|
33
|
+
# Sequence Parameter title Max length Example of value Description
|
|
34
|
+
# 1. IB_SND_ID 10 B1 Request sender (Banks ID)
|
|
35
|
+
# 2. IB_SERVICE 4 0003 Code of the Internet bank request type
|
|
36
|
+
# 3. IB_VERSION 3 001 ID of used digital signature algorithm
|
|
37
|
+
# 4. IB_PAYMENT_ID 20 UB0000000000015 Payment order reference number
|
|
38
|
+
# 5. IB_AMOUNT 17 1234.56 Payment amount
|
|
39
|
+
# 6. IB_CURR 3 EUR Payment currency (EUR)
|
|
40
|
+
# 7. IB_REC_ID 10 AAA Beneficiary’s identifier (in this case: AAA)
|
|
41
|
+
# 8. IB_REC_ACC 21 Beneficiary’s account (IBAN).
|
|
42
|
+
# 9. IB_REC_NAME 30 Company Beneficiary’s name (in this case: Company)
|
|
43
|
+
# 10. IB_PAYER_ACC 21 Payer’s account (IBAN)
|
|
44
|
+
# 11. IB_PAYER_NAME 110 Jānis Ozols Payer’s name
|
|
45
|
+
# 12. IB_PAYMENT_DESC 100 Your invoice No.1234 is paid Payment order description
|
|
46
|
+
# 13. IB_PAYMENT_DATE 10 12.12.2005 Payment confirmation date (DD.MM.YYYY)
|
|
47
|
+
# 14. IB_PAYMENT_TIME 8 21:12:34 Payment confirmation time (HH:MM:SS)
|
|
48
|
+
# 15. IB_CRC 500 Request digital signature
|
|
49
|
+
# 16. IB_LANG 3 LAT Language (possible values: LAT, ENG, RUS)
|
|
50
|
+
# 17. IB_FROM_SERVER 1 Y / N In case of P.MU.2: Y, P.MU.3: N
|
|
51
|
+
V001_MESSAGE0003_SPEC = {
|
|
52
|
+
IB_SND_ID: {no: 1, in_signature: true},
|
|
53
|
+
IB_SERVICE: {no: 2, in_signature: true},
|
|
54
|
+
IB_VERSION: {no: 3, in_signature: true},
|
|
55
|
+
IB_PAYMENT_ID: {no: 4, in_signature: true},
|
|
56
|
+
IB_AMOUNT: {no: 5, in_signature: true},
|
|
57
|
+
IB_CURR: {no: 6, in_signature: true},
|
|
58
|
+
IB_REC_ID: {no: 7, in_signature: true},
|
|
59
|
+
IB_REC_ACC: {no: 8, in_signature: true},
|
|
60
|
+
IB_REC_NAME: {no: 9, in_signature: true},
|
|
61
|
+
IB_PAYER_ACC: {no: 10, in_signature: true},
|
|
62
|
+
IB_PAYER_NAME: {no: 11, in_signature: true},
|
|
63
|
+
IB_PAYMENT_DESC: {no: 12, in_signature: true},
|
|
64
|
+
IB_PAYMENT_DATE: {no: 13, in_signature: true},
|
|
65
|
+
IB_PAYMENT_TIME: {no: 14, in_signature: true},
|
|
66
|
+
IB_PAYMENT_TIME: {no: 15, in_signature: true}
|
|
67
|
+
}.freeze
|
|
68
|
+
|
|
69
|
+
# # 4.3 Message 0004 - Payment order execution or cancellation (P.MU.2 and P.MU.5 parameters):
|
|
70
|
+
# Sequence, Parameter title, Max length, Example of value, Description
|
|
71
|
+
# 1. IB_SND_ID 10 B1 Request sender (Banks ID)
|
|
72
|
+
# 2. IB_SERVICE 4 0004 Code of the Internet bank request type
|
|
73
|
+
# 3. IB_VERSION 3 001 ID of used digital signature algorithm
|
|
74
|
+
# 4. IB_REC_ID 10 AAA Beneficiary’s identifier (in this case: “AAA”)
|
|
75
|
+
# 5. IB_PAYMENT_ID 20 UB0000000000015 Payment order reference number
|
|
76
|
+
# 6. IB_PAYMENT_DESC 100 Your invoice No. 1234 is paid Payment order description
|
|
77
|
+
# 7. IB_FROM_SERVER 1 Y/ N In case of P.MU.4: “Y”, P.MU.5: “N”
|
|
78
|
+
# 8. IB_STATUS 12 ACCOMPLISHED Payment order status
|
|
79
|
+
# 9. IB_CRC 300 Message digital signature
|
|
80
|
+
# 10. IB_LANG 3 LAT Language (possible values: “LAT”, “ENG”, “RUS”)
|
|
81
|
+
V001_MESSAGE0004_SPEC = {
|
|
82
|
+
IB_SND_ID: {no: 1, in_signature: true},
|
|
83
|
+
IB_SERVICE: {no: 2, in_signature: true},
|
|
84
|
+
IB_VERSION: {no: 3, in_signature: true},
|
|
85
|
+
IB_REC_ID: {no: 4, in_signature: true},
|
|
86
|
+
IB_PAYMENT_ID: {no: 5, in_signature: true},
|
|
87
|
+
IB_PAYMENT_DESC: {no: 6, in_signature: true},
|
|
88
|
+
# -- IB_FROM_SERVER {no: 7, in_signature: true},
|
|
89
|
+
IB_STATUS: {no: 7, in_signature: true},
|
|
90
|
+
}.freeze
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
class SebElink::Response
|
|
2
|
+
include SebElink::Communications
|
|
3
|
+
|
|
4
|
+
SUPPORTED_VERSIONS = ["001"].freeze
|
|
5
|
+
SUPPORTED_MESSAGES = ["0003", "0004"].freeze
|
|
6
|
+
|
|
7
|
+
attr_reader :gateway_instance, :body
|
|
8
|
+
|
|
9
|
+
def initialize(gateway_instance, body)
|
|
10
|
+
@gateway_instance = gateway_instance
|
|
11
|
+
@body = body
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def valid?
|
|
15
|
+
return @valid if defined?(@valid)
|
|
16
|
+
|
|
17
|
+
validate_message_code
|
|
18
|
+
validate_version
|
|
19
|
+
|
|
20
|
+
footprint = gateway_instance.produce_footprint({
|
|
21
|
+
message_code: message_code,
|
|
22
|
+
version: version,
|
|
23
|
+
skip_validation: true,
|
|
24
|
+
data: body_hash
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
@valid = gateway_instance.verify({
|
|
28
|
+
version: version,
|
|
29
|
+
message_footprint: footprint,
|
|
30
|
+
message_signature: body_hash[:IB_CRC]
|
|
31
|
+
})
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_h(mode=:secure)
|
|
35
|
+
raise SebElink::InvalidResponseError.new(
|
|
36
|
+
"The response with body '#{body}' is invalid"
|
|
37
|
+
) if mode != :insecure && !valid?
|
|
38
|
+
|
|
39
|
+
@to_h ||= body_hash
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
def body_hash
|
|
44
|
+
@body_hash ||= body.split("&").each_with_object({}) do |q_pair, hash|
|
|
45
|
+
pair = q_pair # CGI.unescape(q_pair)
|
|
46
|
+
split_index = CGI.unescape(pair).index("=")
|
|
47
|
+
key, value = pair[0..(split_index - 1)], pair[split_index.next..-1]
|
|
48
|
+
hash[key.to_sym] = value.to_s
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def message_code
|
|
53
|
+
return @message_code if defined?(@message_code)
|
|
54
|
+
|
|
55
|
+
@message_code = body_hash[:IB_SERVICE]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def version
|
|
59
|
+
return @version if defined?(@version)
|
|
60
|
+
|
|
61
|
+
@version = body_hash[:IB_VERSION]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class SebElink::InvalidResponseError < RuntimeError
|
|
67
|
+
end
|
data/seb_elink.gemspec
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require "seb_elink/version"
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |gem|
|
|
7
|
+
gem.name = "seb_elink"
|
|
8
|
+
gem.required_ruby_version = '>= 2'
|
|
9
|
+
gem.date = "2017-12-14"
|
|
10
|
+
gem.version = SebElink::VERSION
|
|
11
|
+
gem.authors = ["Epigene"]
|
|
12
|
+
gem.email = ["cto@creative.gs", "augusts.bautra@gmail.com"]
|
|
13
|
+
|
|
14
|
+
gem.summary = "Ruby wrapper for communicating with SEB.lv i-bank payment API."
|
|
15
|
+
gem.homepage = "https://github.com/CreativeGS/seb_elink"
|
|
16
|
+
gem.license = "BSD-3-Clause"
|
|
17
|
+
|
|
18
|
+
gem.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
19
|
+
f.match(%r{^(test|spec|features)/})
|
|
20
|
+
end
|
|
21
|
+
gem.bindir = "exe"
|
|
22
|
+
gem.executables = gem.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
23
|
+
gem.require_paths = ["lib"]
|
|
24
|
+
|
|
25
|
+
gem.add_development_dependency "bundler", "~> 1.16"
|
|
26
|
+
gem.add_development_dependency "rake", "~> 10.0"
|
|
27
|
+
gem.add_development_dependency "rspec", "~> 3.7"
|
|
28
|
+
gem.add_development_dependency "pry", "~> 0.11.3"
|
|
29
|
+
gem.add_development_dependency "simplecov", "~> 0.15.1"
|
|
30
|
+
gem.add_development_dependency "coveralls"
|
|
31
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: seb_elink
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.9.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Epigene
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2017-12-14 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ~>
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.16'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ~>
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.16'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ~>
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '10.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ~>
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '10.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ~>
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.7'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ~>
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.7'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: pry
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ~>
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 0.11.3
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ~>
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 0.11.3
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: simplecov
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ~>
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 0.15.1
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ~>
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 0.15.1
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: coveralls
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - '>='
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - '>='
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
description:
|
|
98
|
+
email:
|
|
99
|
+
- cto@creative.gs
|
|
100
|
+
- augusts.bautra@gmail.com
|
|
101
|
+
executables: []
|
|
102
|
+
extensions: []
|
|
103
|
+
extra_rdoc_files: []
|
|
104
|
+
files:
|
|
105
|
+
- .circleci/config.yml
|
|
106
|
+
- .gitignore
|
|
107
|
+
- .rspec
|
|
108
|
+
- CODE_OF_CONDUCT.md
|
|
109
|
+
- Gemfile
|
|
110
|
+
- Gemfile.lock
|
|
111
|
+
- LICENSE.txt
|
|
112
|
+
- README.md
|
|
113
|
+
- Rakefile
|
|
114
|
+
- bin/console
|
|
115
|
+
- bin/setup
|
|
116
|
+
- lib/seb_elink.rb
|
|
117
|
+
- lib/seb_elink/communications.rb
|
|
118
|
+
- lib/seb_elink/gateway.rb
|
|
119
|
+
- lib/seb_elink/message.rb
|
|
120
|
+
- lib/seb_elink/message_specs.rb
|
|
121
|
+
- lib/seb_elink/response.rb
|
|
122
|
+
- lib/seb_elink/version.rb
|
|
123
|
+
- seb_elink.gemspec
|
|
124
|
+
homepage: https://github.com/CreativeGS/seb_elink
|
|
125
|
+
licenses:
|
|
126
|
+
- BSD-3-Clause
|
|
127
|
+
metadata: {}
|
|
128
|
+
post_install_message:
|
|
129
|
+
rdoc_options: []
|
|
130
|
+
require_paths:
|
|
131
|
+
- lib
|
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
133
|
+
requirements:
|
|
134
|
+
- - '>='
|
|
135
|
+
- !ruby/object:Gem::Version
|
|
136
|
+
version: '2'
|
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
|
+
requirements:
|
|
139
|
+
- - '>='
|
|
140
|
+
- !ruby/object:Gem::Version
|
|
141
|
+
version: '0'
|
|
142
|
+
requirements: []
|
|
143
|
+
rubyforge_project:
|
|
144
|
+
rubygems_version: 2.4.8
|
|
145
|
+
signing_key:
|
|
146
|
+
specification_version: 4
|
|
147
|
+
summary: Ruby wrapper for communicating with SEB.lv i-bank payment API.
|
|
148
|
+
test_files: []
|