ipizza 2.0.1 → 2.2.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 +5 -5
- data/Gemfile.lock +4 -1
- data/ipizza.gemspec +1 -1
- data/lib/ipizza/authentication.rb +2 -2
- data/lib/ipizza/authentication_response.rb +4 -4
- data/lib/ipizza/config.rb +11 -11
- data/lib/ipizza/payment.rb +2 -2
- data/lib/ipizza/payment_response.rb +3 -3
- data/lib/ipizza/provider/base.rb +22 -3
- data/lib/ipizza/provider/luminor.rb +4 -0
- data/lib/ipizza/provider/nordea.rb +1 -74
- data/lib/ipizza/provider.rb +2 -2
- data/lib/ipizza/request.rb +2 -2
- data/lib/ipizza/response.rb +5 -5
- data/lib/ipizza/util.rb +27 -8
- data/lib/ipizza/version.rb +1 -1
- data/lib/ipizza.rb +1 -0
- data/spec/certificates/pangalink_luminor_bank.cert.pem +18 -0
- data/spec/certificates/pangalink_luminor_bank_cert.pem +17 -0
- data/spec/config/config.yml +13 -0
- data/spec/config/plain_config.yml +2 -0
- data/spec/ipizza/config_spec.rb +2 -0
- data/spec/ipizza/provider/luminor_spec.rb +89 -0
- data/spec/ipizza/provider/seb_spec.rb +12 -2
- data/spec/ipizza/provider_spec.rb +11 -7
- metadata +13 -15
- data/spec/ipizza/provider/nordea/authentication_response_spec.rb +0 -33
- data/spec/ipizza/provider/nordea/payment_request_spec.rb +0 -4
- data/spec/ipizza/provider/nordea/payment_response_spec.rb +0 -4
- data/spec/ipizza/provider/nordea_spec.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5ed9393a3cf761d93af6cacfe5ab9f5290bd9f9fa07df805eba6e8923c302b80
|
4
|
+
data.tar.gz: 8543fd69e9b7c1c523bdbed2f20ac511b8fef3f3661987d4a960c27df9827bab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9172fb1cbe9b620439a73b41b12d53f0e6bfd5f4ce2d219f0398ab6c4136716200463885ba692cf34b70675e4151f3536398c10a4bf59e9817b09f2c3b52eb69
|
7
|
+
data.tar.gz: 01010f397f8c724adcf89e9db463f7ba6ba9277501ef243957e58b8a7e2eb863c840d9a533e921ec4f953dd10d76479676b0ade0b7bf24da69891bc8fc6cfd7e
|
data/Gemfile.lock
CHANGED
data/ipizza.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.homepage = 'https://github.com/Voog/ipizza'
|
12
12
|
s.summary = 'Implements iPizza protocol to communicate with Estonian Banks'
|
13
13
|
s.description = 'Simplifies generating payment requests and parsing responses from banks when using iPizza protocol.'
|
14
|
-
|
14
|
+
|
15
15
|
s.add_development_dependency 'rspec', '~> 2.9.0'
|
16
16
|
s.add_development_dependency 'guard-rspec'
|
17
17
|
s.add_development_dependency 'rb-fsevent'
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Ipizza
|
2
2
|
class Authentication
|
3
|
-
|
3
|
+
|
4
4
|
attr_accessor :provider, :user, :message_time, :sender_id, :receiver_id, :user_name, :user_id, :country, :other, :authentication_identifier, :request_identifier
|
5
|
-
|
5
|
+
|
6
6
|
def initialize(attribs = {})
|
7
7
|
attribs.each do |key, value|
|
8
8
|
if self.respond_to?("#{key.to_s}=".to_sym)
|
@@ -1,18 +1,18 @@
|
|
1
1
|
module Ipizza
|
2
2
|
class AuthenticationResponse < Ipizza::Response
|
3
|
-
|
3
|
+
|
4
4
|
def success?
|
5
5
|
%w(3012 3013).include?(@params['VK_SERVICE'])
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def valid?
|
9
9
|
@valid
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def info_social_security_id
|
13
13
|
authentication_info.user_id
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def info_name
|
17
17
|
authentication_info.user_name
|
18
18
|
end
|
data/lib/ipizza/config.rb
CHANGED
@@ -8,10 +8,10 @@ module Ipizza
|
|
8
8
|
|
9
9
|
def load_from_file(yaml_path)
|
10
10
|
@certs_root = File.dirname(yaml_path)
|
11
|
-
|
11
|
+
|
12
12
|
load_from_hash(YAML::load_file(yaml_path))
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def load_from_hash(config)
|
16
16
|
config.each do |bank, params|
|
17
17
|
params.each do |param, value|
|
@@ -21,19 +21,19 @@ module Ipizza
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def configure
|
26
26
|
yield self
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def method_missing(m, *args)
|
30
|
-
if /^(lhv|swedbank|seb|sampo|krediidipank|nordea)_(.*)=$/ =~ m.to_s
|
30
|
+
if /^(lhv|swedbank|seb|sampo|krediidipank|nordea|luminor)_(.*)=$/ =~ m.to_s
|
31
31
|
clz = Ipizza::Provider.const_get($1.capitalize)
|
32
32
|
key = $2
|
33
33
|
value = args.first
|
34
|
-
|
34
|
+
|
35
35
|
value = load_certificate(value) if /^file_(cert|key)/ =~ key
|
36
|
-
|
36
|
+
|
37
37
|
if clz.respond_to?(:"#{key}=")
|
38
38
|
return clz.send(:"#{key}=", *[value])
|
39
39
|
end
|
@@ -41,23 +41,23 @@ module Ipizza
|
|
41
41
|
|
42
42
|
super
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
private
|
46
|
-
|
46
|
+
|
47
47
|
def load_certificate(file_path)
|
48
48
|
if File.exist?(file_path)
|
49
49
|
file_path
|
50
50
|
else
|
51
51
|
file_path = File.expand_path(File.join(certs_root, file_path))
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
if File.exist?(file_path)
|
55
55
|
file_path
|
56
56
|
else
|
57
57
|
raise "Could not load certificate from file '#{file_path}'"
|
58
58
|
end
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
data/lib/ipizza/payment.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Ipizza
|
2
2
|
class Payment
|
3
|
-
|
3
|
+
|
4
4
|
attr_accessor :provider, :stamp, :amount, :currency, :refnum, :receiver_account, :receiver_name, :sender_account, :sender_name, :message, :transaction_id, :transaction_time
|
5
|
-
|
5
|
+
|
6
6
|
def initialize(attribs = {})
|
7
7
|
attribs.each do |key, value|
|
8
8
|
if self.respond_to?("#{key.to_s}=".to_sym)
|
@@ -3,15 +3,15 @@ class Ipizza::PaymentResponse < Ipizza::Response
|
|
3
3
|
def success?
|
4
4
|
%w(1111).include?(@params['VK_SERVICE'])
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def valid?
|
8
8
|
@valid
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def automatic_message?
|
12
12
|
@params['VK_AUTO'] == 'Y'
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def payment_info
|
16
16
|
@payment_info ||= Ipizza::Payment.new(
|
17
17
|
provider: @params['VK_SND_ID'],
|
data/lib/ipizza/provider/base.rb
CHANGED
@@ -4,7 +4,20 @@ module Ipizza::Provider
|
|
4
4
|
SUPPORTED_ENCODINGS = %w(UTF-8 ISO-8859-1 WINDOWS-1257)
|
5
5
|
|
6
6
|
class << self
|
7
|
-
attr_accessor :service_url,
|
7
|
+
attr_accessor :service_url,
|
8
|
+
:return_url,
|
9
|
+
:cancel_url,
|
10
|
+
:file_key,
|
11
|
+
:key_secret,
|
12
|
+
:file_cert,
|
13
|
+
:sign_algorithm,
|
14
|
+
:verification_algorithm,
|
15
|
+
:snd_id,
|
16
|
+
:rec_id,
|
17
|
+
:rec_acc,
|
18
|
+
:rec_name,
|
19
|
+
:encoding,
|
20
|
+
:lang
|
8
21
|
end
|
9
22
|
|
10
23
|
def payment_request(payment, service_no = 1012)
|
@@ -40,7 +53,10 @@ module Ipizza::Provider
|
|
40
53
|
|
41
54
|
def payment_response(params)
|
42
55
|
response = Ipizza::PaymentResponse.new(params)
|
43
|
-
response.verify(
|
56
|
+
response.verify(
|
57
|
+
self.class.file_cert,
|
58
|
+
self.class.verification_algorithm || Ipizza::Util::DEFAULT_HASH_ALGORITHM
|
59
|
+
)
|
44
60
|
response
|
45
61
|
end
|
46
62
|
|
@@ -77,7 +93,10 @@ module Ipizza::Provider
|
|
77
93
|
|
78
94
|
def authentication_response(params)
|
79
95
|
response = Ipizza::AuthenticationResponse.new(params)
|
80
|
-
response.verify(
|
96
|
+
response.verify(
|
97
|
+
self.class.file_cert,
|
98
|
+
self.class.verification_algorithm || Ipizza::Util::DEFAULT_HASH_ALGORITHM
|
99
|
+
)
|
81
100
|
response
|
82
101
|
end
|
83
102
|
|
@@ -1,77 +1,4 @@
|
|
1
1
|
module Ipizza::Provider
|
2
|
-
|
3
|
-
# TODO: configure whether use sha-1 or md5 for signing and verification
|
4
|
-
class Nordea
|
5
|
-
|
6
|
-
require 'ipizza/provider/nordea/payment_request'
|
7
|
-
require 'ipizza/provider/nordea/payment_response'
|
8
|
-
require 'ipizza/provider/nordea/authentication_request'
|
9
|
-
require 'ipizza/provider/nordea/authentication_response'
|
10
|
-
|
11
|
-
class << self
|
12
|
-
attr_accessor :payments_service_url, :payments_return_url, :payments_reject_url, :payments_cancel_url
|
13
|
-
attr_accessor :payments_rcv_id, :payments_language
|
14
|
-
attr_accessor :auth_service_url, :auth_return_url, :auth_reject_url, :auth_cancel_url, :auth_language
|
15
|
-
attr_accessor :auth_rcv_id
|
16
|
-
attr_accessor :file_key, :rcv_account, :rcv_name, :confirm, :keyvers
|
17
|
-
end
|
18
|
-
|
19
|
-
def payment_request(payment, service = 1002)
|
20
|
-
req = Ipizza::Provider::Nordea::PaymentRequest.new
|
21
|
-
req.service_url = self.class.payments_service_url
|
22
|
-
req.params = {
|
23
|
-
'VERSION' => '0003',
|
24
|
-
'STAMP' => payment.stamp,
|
25
|
-
'RCV_ID' => self.class.payments_rcv_id,
|
26
|
-
# 'RCV_ACCOUNT' => self.rcv_account,
|
27
|
-
# 'RCV_NAME' => self.rcv_name,
|
28
|
-
'LANGUAGE' => self.class.payments_language,
|
29
|
-
'AMOUNT' => sprintf('%.2f', payment.amount),
|
30
|
-
'REF' => Ipizza::Util.sign_731(payment.refnum),
|
31
|
-
'DATE' => 'EXPRESS',
|
32
|
-
'MSG' => payment.message,
|
33
|
-
'CONFIRM' => self.class.confirm,
|
34
|
-
'CUR' => payment.currency,
|
35
|
-
'KEYVERS' => self.class.keyvers,
|
36
|
-
'REJECT' => self.class.payments_reject_url,
|
37
|
-
'RETURN' => self.class.payments_return_url,
|
38
|
-
'CANCEL' => self.class.payments_cancel_url
|
39
|
-
}
|
40
|
-
|
41
|
-
req.sign(self.class.file_key)
|
42
|
-
req
|
43
|
-
end
|
44
|
-
|
45
|
-
def payment_response(params)
|
46
|
-
response = Ipizza::Provider::Nordea::PaymentResponse.new(params)
|
47
|
-
response.verify(self.class.file_key)
|
48
|
-
return response
|
49
|
-
end
|
50
|
-
|
51
|
-
def authentication_request
|
52
|
-
req = Ipizza::Provider::Nordea::AuthenticationRequest.new
|
53
|
-
req.service_url = self.class.auth_service_url
|
54
|
-
req.params = {
|
55
|
-
'ACTION_ID' => '701',
|
56
|
-
'VERS' => '0002',
|
57
|
-
'RCVID' => self.class.auth_rcv_id,
|
58
|
-
'LANGCODE' => self.class.auth_language,
|
59
|
-
'STAMP' => Time.now.strftime('%Y%m%d%H%M%S'),
|
60
|
-
'IDTYPE' => '02',
|
61
|
-
'KEYVERS' => self.class.keyvers,
|
62
|
-
'RETLINK' => self.class.auth_return_url,
|
63
|
-
'CANLINK' => self.class.auth_cancel_url,
|
64
|
-
'REJLINK' => self.class.auth_reject_url,
|
65
|
-
'ALG' => '01'
|
66
|
-
}
|
67
|
-
req.sign(self.class.file_key)
|
68
|
-
req
|
69
|
-
end
|
70
|
-
|
71
|
-
def authentication_response(params)
|
72
|
-
response = Ipizza::Provider::Nordea::AuthenticationResponse.new(params)
|
73
|
-
response.verify(self.class.file_key)
|
74
|
-
return response
|
75
|
-
end
|
2
|
+
class Nordea < Ipizza::Provider::Base
|
76
3
|
end
|
77
4
|
end
|
data/lib/ipizza/provider.rb
CHANGED
data/lib/ipizza/request.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Ipizza
|
2
2
|
class Request
|
3
|
-
|
3
|
+
|
4
4
|
attr_accessor :extra_params
|
5
5
|
attr_accessor :sign_params
|
6
6
|
attr_accessor :service_url
|
@@ -16,7 +16,7 @@ module Ipizza
|
|
16
16
|
signature = Ipizza::Util.sign(privkey_path, privkey_secret, Ipizza::Util.mac_data_string(sign_params, order))
|
17
17
|
self.sign_params[mac_param] = signature
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def request_params
|
21
21
|
sign_params.merge(extra_params)
|
22
22
|
end
|
data/lib/ipizza/response.rb
CHANGED
@@ -2,21 +2,21 @@ class Ipizza::Response
|
|
2
2
|
|
3
3
|
attr_accessor :verify_params
|
4
4
|
attr_accessor :verify_params_order
|
5
|
-
|
5
|
+
|
6
6
|
PARAM_ORDER = {
|
7
7
|
'1111' => %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_T_NO VK_AMOUNT VK_CURR VK_REC_ACC VK_REC_NAME VK_SND_ACC VK_SND_NAME VK_REF VK_MSG VK_T_DATETIME),
|
8
8
|
'3012' => %w(VK_SERVICE VK_VERSION VK_USER VK_DATETIME VK_SND_ID VK_REC_ID VK_USER_NAME VK_USER_ID VK_COUNTRY VK_OTHER VK_TOKEN VK_RID),
|
9
9
|
'3013' => %w(VK_SERVICE VK_VERSION VK_DATETIME VK_SND_ID VK_REC_ID VK_NONCE VK_USER_NAME VK_USER_ID VK_COUNTRY VK_OTHER VK_TOKEN VK_RID),
|
10
10
|
'1911' => %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_REF VK_MSG)
|
11
|
-
}
|
12
|
-
|
11
|
+
}
|
12
|
+
|
13
13
|
def initialize(params)
|
14
14
|
@params = params
|
15
15
|
end
|
16
16
|
|
17
|
-
def verify(certificate_path)
|
17
|
+
def verify(certificate_path, hash_algorithm = Ipizza::Util::DEFAULT_HASH_ALGORITHM)
|
18
18
|
mac_string = Ipizza::Util.mac_data_string(@params, PARAM_ORDER[@params['VK_SERVICE']])
|
19
19
|
|
20
|
-
@valid = Ipizza::Util.verify_signature(certificate_path, @params['VK_MAC'], mac_string)
|
20
|
+
@valid = Ipizza::Util.verify_signature(certificate_path, @params['VK_MAC'], mac_string, hash_algorithm)
|
21
21
|
end
|
22
22
|
end
|
data/lib/ipizza/util.rb
CHANGED
@@ -3,24 +3,33 @@ require 'openssl'
|
|
3
3
|
|
4
4
|
module Ipizza
|
5
5
|
class Util
|
6
|
-
|
6
|
+
|
7
|
+
DEFAULT_HASH_ALGORITHM = 'sha1'
|
8
|
+
|
7
9
|
class << self
|
8
|
-
|
9
|
-
def verify_signature(certificate_path, signature, data)
|
10
|
+
|
11
|
+
def verify_signature(certificate_path, signature, data, hash_algorithm = DEFAULT_HASH_ALGORITHM)
|
10
12
|
if !certificate_path.to_s.empty? && !signature.to_s.empty? && File.file?(certificate_path)
|
11
13
|
certificate = OpenSSL::X509::Certificate.new(File.read(certificate_path).gsub(/ /, '')).public_key
|
12
|
-
certificate.verify(
|
14
|
+
certificate.verify(
|
15
|
+
digest_class(hash_algorithm).new,
|
16
|
+
Base64.decode64(signature),
|
17
|
+
data
|
18
|
+
)
|
13
19
|
else
|
14
20
|
false
|
15
21
|
end
|
16
22
|
end
|
17
|
-
|
18
|
-
def sign(privkey_path, privkey_secret, data)
|
23
|
+
|
24
|
+
def sign(privkey_path, privkey_secret, data, hash_algorithm = DEFAULT_HASH_ALGORITHM)
|
19
25
|
privkey = File.open(privkey_path, 'r') { |f| f.read }
|
20
26
|
privkey = OpenSSL::PKey::RSA.new(privkey.gsub(/ /, ''), privkey_secret)
|
21
27
|
|
22
|
-
signature = privkey.sign(
|
23
|
-
|
28
|
+
signature = privkey.sign(
|
29
|
+
digest_class(hash_algorithm).new,
|
30
|
+
data
|
31
|
+
)
|
32
|
+
Base64.encode64(signature).gsub(/\n/, '')
|
24
33
|
end
|
25
34
|
|
26
35
|
# Calculates and adds control number using 7-3-1 algoritm for Estonian banking account and reference numbers.
|
@@ -74,6 +83,16 @@ module Ipizza
|
|
74
83
|
sprintf('%03i', val.bytesize)
|
75
84
|
end
|
76
85
|
end
|
86
|
+
|
87
|
+
def digest_class(hash_algorithm)
|
88
|
+
algorithm = (hash_algorithm || '').upcase
|
89
|
+
|
90
|
+
if OpenSSL::Digest.const_defined?(algorithm)
|
91
|
+
OpenSSL::Digest.const_get(algorithm)
|
92
|
+
else
|
93
|
+
raise ArgumentError, "Unknown hash algorithm OpenSSL::Digest::#{algorithm}"
|
94
|
+
end
|
95
|
+
end
|
77
96
|
end
|
78
97
|
end
|
79
98
|
end
|
data/lib/ipizza/version.rb
CHANGED
data/lib/ipizza.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIC+jCCAeICCQDuCELf8TcV7DANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJF
|
3
|
+
RTEOMAwGA1UECAwFVGFydHUxDjAMBgNVBAcMBVRhcnR1MRAwDgYDVQQKDAdNaWxl
|
4
|
+
ZWRpMB4XDTIwMTIwMzA5NDkxMloXDTI1MTIwMTA5NDkxMlowPzELMAkGA1UEBhMC
|
5
|
+
RUUxDjAMBgNVBAgMBVRhcnR1MQ4wDAYDVQQHDAVUYXJ0dTEQMA4GA1UECgwHTWls
|
6
|
+
ZWVkaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALmozE2DIZyCddrW
|
7
|
+
AVoVkNWYRYDytAi5lefa5+PEAQLGFzzfTBRnClla/Qerfe4NBGjyiwu8W6VeLGQ9
|
8
|
+
+GGDw5uEQumII2t0f1vpKWiauyfM+MlSOB6cobf9bwlgs9gBss/PEAa8E4MhpS60
|
9
|
+
p7KNfR1qcq3AWgxpjE9ns7KheARW1q0vNZFzPkONyleZ4HJIC8rlta38/VMvbPnp
|
10
|
+
PLbMnVOvrOsxeDMCgGpD9hupxVsFnhsv/Y4F14W7f4XHl36FhDjP8dkrgrkQE4E1
|
11
|
+
dRnxx6GC4Lv71rQDu+gmgyKtZWmsym1b1Tzw3aCF27J1EReHvCxtkDfMH1VzQSad
|
12
|
+
FGF4yXsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAQfs7p7MLZqtm9QxBkGcYALDw
|
13
|
+
q/f+5b+n1uPdFcXu8K26hG6RiVZTXUJrIqR71kGLG0mBJ3V6+vAM9gjsUJs20uiZ
|
14
|
+
qvdV2xQglTpJlNTG4Je3Sq4Lbyz4w+8e9VVrE3atfARHxA5FIewCviJNdXS+xeuh
|
15
|
+
GqKaGqLSf4sJlbe3hE69hzlDXmzUE+/OhoaSPS3zFAzcp9m50o7InhYy80eKDRFS
|
16
|
+
hBIDbLnyzb+97If9BMOhqQ/nfCrsX6TiTiqhIFB+qNSIZt733fx9AD3AwSxM51RC
|
17
|
+
V232swdtXx9d39S/DskhMkXkOiqpr+0P87Qyy8Y0/FoWO57i/jXb0uCccPatdw==
|
18
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,17 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICnzCCAYegAwIBAgIBATANBgkqhkiG9w0BAQUFADATMREwDwYDVQQDDAhCYW5r
|
3
|
+
bGluazAeFw0yMDEyMDMxMDUwNDJaFw0yMjEyMDMxMDUwNDJaMBMxETAPBgNVBAMM
|
4
|
+
CEJhbmtsaW5rMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgI7m13+Z
|
5
|
+
2B3aBtXE4/2YmsG9koPpD7RHj5B7uEozBCNM1MhfYoE7R7vP1tPm7lD/oJxKk0G3
|
6
|
+
gpODtGDqo+kMfI+TlJ/w2KzwS5YPEop7aliEQ1bbwjjjY2tXYwsBYa0uRvkbwizH
|
7
|
+
lp3PHmr4DBl+JxyETIWGX623nZxZcHAvwcM6VpTtd9+KEpgToQ2gPHHj4/svQfwm
|
8
|
+
mzhdEwFZjwjCaOEHssaUcLsyvKVoJ5OJqBWS1e0mVqWsuJJJnkeG7NVXY2LWDDfP
|
9
|
+
iGogVz9hqqxfNKhCTLGMCG8k8VDQdLTaR+vvmXSUBLh+4TbFA7ZPLSvgbRu3995F
|
10
|
+
CCY/wADRophRVQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAcTtcH4m//FyGrNC2h
|
11
|
+
rcry6wt843xclEkLQSSNGz9wVCQW/D8I0VNjFPk4PgoUh4bTr+mKrZ6UrrIwBuO6
|
12
|
+
oFj2Nh+Y1wgkpd3LMKae5DvWLE4taZ4ylBGSUXOpQ062+pOtUldZQxBiczaUJWm4
|
13
|
+
4Ns+27Zi5oGyTNnlZXfguEnt54KA+63S4aiHWUSaaXkRN62LeNuyrX0ZdITEfTaz
|
14
|
+
0ZvVcn6FbL6OnsqoZn2MF9+xZfMqlu/K5HfGl928v0fzY8/jQygxUoGFIBfxhn46
|
15
|
+
NniPM9xtnPSu11ut1n0PQPP8K94+MUJz7GDw9o9z3X0zgy8SOFSpY8HNp0MEjN7l
|
16
|
+
MT8n
|
17
|
+
-----END CERTIFICATE-----
|
data/spec/config/config.yml
CHANGED
@@ -41,6 +41,19 @@ seb:
|
|
41
41
|
key_secret: foobar
|
42
42
|
encoding: UTF-8
|
43
43
|
snd_id: sender
|
44
|
+
sign_algorithm: 'sha256'
|
45
|
+
verification_algorithm: 'sha256'
|
46
|
+
|
47
|
+
luminor:
|
48
|
+
service_url: https://banklink.luminor.ee/test
|
49
|
+
return_url: http://test.local/seb
|
50
|
+
cancel_url: http://test.local/seb
|
51
|
+
login: dealer
|
52
|
+
file_cert: ../certificates/pangalink_seb_bank_cert.pem
|
53
|
+
file_key: ../certificates/pangalink_seb_user_key.pem
|
54
|
+
key_secret: foobar
|
55
|
+
encoding: UTF-8
|
56
|
+
snd_id: sender
|
44
57
|
|
45
58
|
nordea:
|
46
59
|
payments_service_url: https://netbank.nordea.com/pnbepaytest/epayn.jsp
|
data/spec/ipizza/config_spec.rb
CHANGED
@@ -16,6 +16,8 @@ describe Ipizza::Config do
|
|
16
16
|
Ipizza::Provider::Swedbank.encoding.should == 'UTF-8'
|
17
17
|
|
18
18
|
Ipizza::Provider::Seb.service_url.should == 'https://www.seb.ee/banklink'
|
19
|
+
Ipizza::Provider::Seb.sign_algorithm.should == 'sha256'
|
20
|
+
Ipizza::Provider::Seb.verification_algorithm.should == 'sha1'
|
19
21
|
end
|
20
22
|
|
21
23
|
it 'should load certificates from path relative to configuration file' do
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Ipizza::Provider::Luminor do
|
4
|
+
let(:response_time) { Ipizza::Util.time_to_iso8601(Time.now) }
|
5
|
+
let(:bank_key) { File.expand_path('../../../certificates/pangalink_seb_bank_key.pem', __FILE__) }
|
6
|
+
|
7
|
+
describe '#payment_request' do
|
8
|
+
let(:payment) { Ipizza::Payment.new(stamp: 1, amount: '123.34', refnum: 1, message: 'Payment message', currency: 'EUR') }
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
req_time = Time.now
|
12
|
+
Time.stub!(:now).and_return(req_time)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should sign the request' do
|
16
|
+
req = Ipizza::Provider::Luminor.new.payment_request(payment)
|
17
|
+
params = {
|
18
|
+
'VK_SERVICE' => '1012',
|
19
|
+
'VK_VERSION' => '008',
|
20
|
+
'VK_SND_ID' => Ipizza::Provider::Luminor.snd_id,
|
21
|
+
'VK_STAMP' => payment.stamp,
|
22
|
+
'VK_AMOUNT' => sprintf('%.2f', payment.amount),
|
23
|
+
'VK_CURR' => payment.currency,
|
24
|
+
'VK_REF' => Ipizza::Util.sign_731(payment.refnum),
|
25
|
+
'VK_MSG' => payment.message,
|
26
|
+
'VK_RETURN' => Ipizza::Provider::Luminor.return_url,
|
27
|
+
'VK_CANCEL' => Ipizza::Provider::Luminor.cancel_url,
|
28
|
+
'VK_DATETIME' => Ipizza::Util.time_to_iso8601(Time.now)
|
29
|
+
}
|
30
|
+
signature = Ipizza::Util.sign(Ipizza::Provider::Luminor.file_key, Ipizza::Provider::Luminor.key_secret, Ipizza::Util.mac_data_string(params, Ipizza::Request::PARAM_ORDER['1012']))
|
31
|
+
req.sign_params['VK_MAC'].should == signature
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#payment_response' do
|
36
|
+
let(:params) {
|
37
|
+
{
|
38
|
+
'VK_SERVICE' => '1111', 'VK_VERSION' => '008', 'VK_SND_ID' => 'LUMINOR', 'VK_REC_ID' => 'sender',
|
39
|
+
'VK_STAMP' => '20150111000004', 'VK_T_NO' => '1143', 'VK_AMOUNT' => '.17', 'VK_CURR' => 'EUR',
|
40
|
+
'VK_REC_ACC' => 'EE411010002050618003', 'VK_REC_NAME' => 'ÕILIS OÜ',
|
41
|
+
'VK_SND_ACC' => 'EE541010010046155012', 'VK_SND_NAME' => 'TÕÄGER Leõpäöld¸´¨¦',
|
42
|
+
'VK_REF' => '201501110000048', 'VK_MSG' => 'Invoice #20150111000004', 'VK_T_DATETIME' => response_time,
|
43
|
+
'VK_ENCODING' => 'UTF-8', 'VK_LANG' => 'EST', 'VK_AUTO' => 'N'
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
it 'should parse and verify the payment response from bank' do
|
48
|
+
signature = Ipizza::Util.sign(bank_key, nil, Ipizza::Util.mac_data_string(params, Ipizza::Response::PARAM_ORDER['1111']))
|
49
|
+
Ipizza::Provider::Luminor.new.payment_response(params.merge('VK_MAC' => signature)).should be_valid
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#authentication_request' do
|
54
|
+
before(:each) do
|
55
|
+
req_time = Time.now
|
56
|
+
Time.stub!(:now).and_return(req_time)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should sign the request' do
|
60
|
+
req = Ipizza::Provider::Luminor.new.authentication_request
|
61
|
+
params = {
|
62
|
+
'VK_SERVICE' => '4011',
|
63
|
+
'VK_VERSION' => '008',
|
64
|
+
'VK_SND_ID' => Ipizza::Provider::Luminor.snd_id,
|
65
|
+
'VK_RETURN' => Ipizza::Provider::Luminor.return_url,
|
66
|
+
'VK_DATETIME' => Ipizza::Util.time_to_iso8601(Time.now),
|
67
|
+
'VK_RID' => '',
|
68
|
+
'VK_REPLY' => '3012'
|
69
|
+
}
|
70
|
+
signature = Ipizza::Util.sign(Ipizza::Provider::Luminor.file_key, Ipizza::Provider::Luminor.key_secret, Ipizza::Util.mac_data_string(params, Ipizza::Request::PARAM_ORDER['4011']))
|
71
|
+
req.sign_params['VK_MAC'].should == signature
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#authentication_response' do
|
76
|
+
let(:params) {
|
77
|
+
{
|
78
|
+
'VK_SERVICE' => '3012', 'VK_VERSION' => '008', 'VK_USER' => 'dealer', 'VK_DATETIME' => response_time,
|
79
|
+
'VK_SND_ID' => 'LUMINOR', 'VK_REC_ID' => 'sender', 'VK_USER_NAME' => 'TÕÄGER Leõpäöld¸´¨¦', 'VK_USER_ID' => '35511280268',
|
80
|
+
'VK_COUNTRY' => 'EE', 'VK_OTHER' => '', 'VK_TOKEN' => '7', 'VK_RID' => ''
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
it 'should parse and verify the authentication response from bank' do
|
85
|
+
signature = Ipizza::Util.sign(bank_key, nil, Ipizza::Util.mac_data_string(params, Ipizza::Response::PARAM_ORDER['3012']))
|
86
|
+
Ipizza::Provider::Luminor.new.authentication_response(params.merge('VK_MAC' => signature)).should be_valid
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -45,7 +45,12 @@ describe Ipizza::Provider::Seb do
|
|
45
45
|
}
|
46
46
|
|
47
47
|
it 'should parse and verify the payment response from bank' do
|
48
|
-
signature = Ipizza::Util.sign(
|
48
|
+
signature = Ipizza::Util.sign(
|
49
|
+
bank_key,
|
50
|
+
nil,
|
51
|
+
Ipizza::Util.mac_data_string(params, Ipizza::Response::PARAM_ORDER['1111']),
|
52
|
+
Ipizza::Provider::Seb.sign_algorithm
|
53
|
+
)
|
49
54
|
Ipizza::Provider::Seb.new.payment_response(params.merge('VK_MAC' => signature)).should be_valid
|
50
55
|
end
|
51
56
|
end
|
@@ -82,7 +87,12 @@ describe Ipizza::Provider::Seb do
|
|
82
87
|
}
|
83
88
|
|
84
89
|
it 'should parse and verify the authentication response from bank' do
|
85
|
-
signature = Ipizza::Util.sign(
|
90
|
+
signature = Ipizza::Util.sign(
|
91
|
+
bank_key,
|
92
|
+
nil,
|
93
|
+
Ipizza::Util.mac_data_string(params, Ipizza::Response::PARAM_ORDER['3012']),
|
94
|
+
Ipizza::Provider::Seb.sign_algorithm
|
95
|
+
)
|
86
96
|
Ipizza::Provider::Seb.new.authentication_response(params.merge('VK_MAC' => signature)).should be_valid
|
87
97
|
end
|
88
98
|
end
|
@@ -9,11 +9,11 @@ describe Ipizza::Provider do
|
|
9
9
|
it 'returns swedbank provider for "swedbank" attribute' do
|
10
10
|
Ipizza::Provider.get('swedbank').should be_a(Ipizza::Provider::Swedbank)
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
it 'returns swedbank provider for "hp" attribute' do
|
14
14
|
Ipizza::Provider.get('hp').should be_a(Ipizza::Provider::Swedbank)
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
it 'returns seb provider for "eyp" attribute' do
|
18
18
|
Ipizza::Provider.get('eyp').should be_a(Ipizza::Provider::Seb)
|
19
19
|
end
|
@@ -22,6 +22,14 @@ describe Ipizza::Provider do
|
|
22
22
|
Ipizza::Provider.get('seb').should be_a(Ipizza::Provider::Seb)
|
23
23
|
end
|
24
24
|
|
25
|
+
it 'returns luminor provider for "luminor" attribute' do
|
26
|
+
Ipizza::Provider.get('luminor').should be_a(Ipizza::Provider::Luminor)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns luminor provider for "testluminor" attribute' do
|
30
|
+
Ipizza::Provider.get('luminor').should be_a(Ipizza::Provider::Luminor)
|
31
|
+
end
|
32
|
+
|
25
33
|
it 'returns sampo provider for "sampo" attribute' do
|
26
34
|
Ipizza::Provider.get('sampo').should be_a(Ipizza::Provider::Sampo)
|
27
35
|
end
|
@@ -33,14 +41,10 @@ describe Ipizza::Provider do
|
|
33
41
|
it 'returns krediidipank provider for "krep" attribute' do
|
34
42
|
Ipizza::Provider.get('krep').should be_a(Ipizza::Provider::Krediidipank)
|
35
43
|
end
|
36
|
-
|
44
|
+
|
37
45
|
it 'returns krediidipank provider for "krediidipank" attribute' do
|
38
46
|
Ipizza::Provider.get('krediidipank').should be_a(Ipizza::Provider::Krediidipank)
|
39
47
|
end
|
40
|
-
|
41
|
-
it 'returns nordea provider for "nordea" attribute' do
|
42
|
-
Ipizza::Provider.get('nordea').should be_a(Ipizza::Provider::Nordea)
|
43
|
-
end
|
44
48
|
|
45
49
|
it 'returns nothing for "unkn" attribute' do
|
46
50
|
Ipizza::Provider.get('unkn').should be_nil
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ipizza
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Priit Haamer
|
8
8
|
- Tanel Jakobsoo
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2023-09-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -98,6 +98,7 @@ files:
|
|
98
98
|
- lib/ipizza/provider/base.rb
|
99
99
|
- lib/ipizza/provider/krediidipank.rb
|
100
100
|
- lib/ipizza/provider/lhv.rb
|
101
|
+
- lib/ipizza/provider/luminor.rb
|
101
102
|
- lib/ipizza/provider/nordea.rb
|
102
103
|
- lib/ipizza/provider/nordea/authentication_request.rb
|
103
104
|
- lib/ipizza/provider/nordea/authentication_response.rb
|
@@ -120,6 +121,8 @@ files:
|
|
120
121
|
- spec/certificates/pangalink_lhv_bank_cert.pem
|
121
122
|
- spec/certificates/pangalink_lhv_bank_key.pem
|
122
123
|
- spec/certificates/pangalink_lhv_user_key.pem
|
124
|
+
- spec/certificates/pangalink_luminor_bank.cert.pem
|
125
|
+
- spec/certificates/pangalink_luminor_bank_cert.pem
|
123
126
|
- spec/certificates/pangalink_seb_bank_cert.pem
|
124
127
|
- spec/certificates/pangalink_seb_bank_key.pem
|
125
128
|
- spec/certificates/pangalink_seb_user_key.pem
|
@@ -132,10 +135,7 @@ files:
|
|
132
135
|
- spec/ipizza/config_spec.rb
|
133
136
|
- spec/ipizza/provider/krediidipank_spec.rb
|
134
137
|
- spec/ipizza/provider/lhv_spec.rb
|
135
|
-
- spec/ipizza/provider/
|
136
|
-
- spec/ipizza/provider/nordea/payment_request_spec.rb
|
137
|
-
- spec/ipizza/provider/nordea/payment_response_spec.rb
|
138
|
-
- spec/ipizza/provider/nordea_spec.rb
|
138
|
+
- spec/ipizza/provider/luminor_spec.rb
|
139
139
|
- spec/ipizza/provider/sampo_spec.rb
|
140
140
|
- spec/ipizza/provider/seb_spec.rb
|
141
141
|
- spec/ipizza/provider/swedbank_spec.rb
|
@@ -146,7 +146,7 @@ files:
|
|
146
146
|
homepage: https://github.com/Voog/ipizza
|
147
147
|
licenses: []
|
148
148
|
metadata: {}
|
149
|
-
post_install_message:
|
149
|
+
post_install_message:
|
150
150
|
rdoc_options: []
|
151
151
|
require_paths:
|
152
152
|
- lib
|
@@ -161,9 +161,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
161
|
- !ruby/object:Gem::Version
|
162
162
|
version: '0'
|
163
163
|
requirements: []
|
164
|
-
|
165
|
-
|
166
|
-
signing_key:
|
164
|
+
rubygems_version: 3.0.8
|
165
|
+
signing_key:
|
167
166
|
specification_version: 4
|
168
167
|
summary: Implements iPizza protocol to communicate with Estonian Banks
|
169
168
|
test_files:
|
@@ -177,6 +176,8 @@ test_files:
|
|
177
176
|
- spec/certificates/pangalink_lhv_bank_cert.pem
|
178
177
|
- spec/certificates/pangalink_lhv_bank_key.pem
|
179
178
|
- spec/certificates/pangalink_lhv_user_key.pem
|
179
|
+
- spec/certificates/pangalink_luminor_bank.cert.pem
|
180
|
+
- spec/certificates/pangalink_luminor_bank_cert.pem
|
180
181
|
- spec/certificates/pangalink_seb_bank_cert.pem
|
181
182
|
- spec/certificates/pangalink_seb_bank_key.pem
|
182
183
|
- spec/certificates/pangalink_seb_user_key.pem
|
@@ -189,10 +190,7 @@ test_files:
|
|
189
190
|
- spec/ipizza/config_spec.rb
|
190
191
|
- spec/ipizza/provider/krediidipank_spec.rb
|
191
192
|
- spec/ipizza/provider/lhv_spec.rb
|
192
|
-
- spec/ipizza/provider/
|
193
|
-
- spec/ipizza/provider/nordea/payment_request_spec.rb
|
194
|
-
- spec/ipizza/provider/nordea/payment_response_spec.rb
|
195
|
-
- spec/ipizza/provider/nordea_spec.rb
|
193
|
+
- spec/ipizza/provider/luminor_spec.rb
|
196
194
|
- spec/ipizza/provider/sampo_spec.rb
|
197
195
|
- spec/ipizza/provider/seb_spec.rb
|
198
196
|
- spec/ipizza/provider/swedbank_spec.rb
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
-
|
3
|
-
describe Ipizza::Provider::Nordea::AuthenticationResponse do
|
4
|
-
before(:each) do
|
5
|
-
@valid_params = {
|
6
|
-
'B02K_CUSTNAME' => 'Demo kasutaja', 'B02K_IDNBR' => '87654321', 'B02K_TIMESTMP' => '20020101204145428720',
|
7
|
-
'B02K_STAMP' => '20101204155339', 'B02K_KEYVERS' => '0001', 'B02K_MAC' => 'A061E22312D7D63FDC2B0B52E16BC971',
|
8
|
-
'B02K_CUSTTYPE' => '01', 'B02K_ALG' => '01', 'B02K_CUSTID' => '37404280367', 'B02K_VERS' => '0002'
|
9
|
-
}
|
10
|
-
@response = Ipizza::Provider::Nordea::AuthenticationResponse.new(@valid_params)
|
11
|
-
@response.verify(Ipizza::Provider::Nordea.file_key)
|
12
|
-
end
|
13
|
-
|
14
|
-
describe '#valid?' do
|
15
|
-
context 'given valid parameters' do
|
16
|
-
it 'returns true' do
|
17
|
-
@response.valid?.should be_true
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
describe '#info_social_security_id' do
|
23
|
-
it 'should get user social security id from the response' do
|
24
|
-
@response.info_social_security_id.should == '37404280367'
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe '#info_name' do
|
29
|
-
it 'should get user name from the response' do
|
30
|
-
@response.info_name.should == 'Demo kasutaja'
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
-
|
3
|
-
describe Ipizza::Provider::Nordea do
|
4
|
-
describe '#authentication_request' do
|
5
|
-
before(:each) do
|
6
|
-
@req = Ipizza::Provider::Nordea.new.authentication_request
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'returns signed authentication request object' do
|
10
|
-
@req.request_params.fetch('A01Y_MAC').should be
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'adds service url to request' do
|
14
|
-
@req.service_url.should == Ipizza::Provider::Nordea.auth_service_url
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'adds return url from configuration to request' do
|
18
|
-
@req.request_params.fetch('A01Y_RETLINK').should == Ipizza::Provider::Nordea.auth_return_url
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'adds cancel url from configuration to request' do
|
22
|
-
@req.request_params.fetch('A01Y_CANLINK').should == Ipizza::Provider::Nordea.auth_cancel_url
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'adds reject url from configuration to request' do
|
26
|
-
@req.request_params.fetch('A01Y_REJLINK').should == Ipizza::Provider::Nordea.auth_reject_url
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|