ipizza 2.0.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|