activemerchant_banklink 0.0.1
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.
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +32 -0
- data/Rakefile +26 -0
- data/activemerchant_banklink.gemspec +21 -0
- data/init.rb +1 -0
- data/lib/active_merchant/billing/integrations/pizza/helper.rb +117 -0
- data/lib/active_merchant/billing/integrations/pizza/notification.rb +101 -0
- data/lib/active_merchant/billing/integrations/pizza.rb +116 -0
- data/lib/active_merchant/billing/integrations/sampo_est/helper.rb +17 -0
- data/lib/active_merchant/billing/integrations/sampo_est/notification.rb +12 -0
- data/lib/active_merchant/billing/integrations/sampo_est.rb +101 -0
- data/lib/active_merchant/billing/integrations/seb_est/helper.rb +16 -0
- data/lib/active_merchant/billing/integrations/seb_est/notification.rb +12 -0
- data/lib/active_merchant/billing/integrations/seb_est.rb +100 -0
- data/lib/active_merchant/billing/integrations/swedbank_est/helper.rb +20 -0
- data/lib/active_merchant/billing/integrations/swedbank_est/notification.rb +12 -0
- data/lib/active_merchant/billing/integrations/swedbank_est.rb +99 -0
- data/lib/activemerchant_banklink/version.rb +3 -0
- data/lib/activemerchant_banklink.rb +5 -0
- data/test/test_helper.rb +182 -0
- data/test/unit/integrations/notifications/seb_est_notification_test.rb +87 -0
- data/test/unit/integrations/sampo_est_module_test.rb +9 -0
- data/test/unit/integrations/seb_est_module_test.rb +9 -0
- data/test/unit/integrations/swedbank_est_module_test.rb +9 -0
- metadata +94 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2005-2010 Tobias Luetke
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
= Active Merchant Banklink
|
2
|
+
|
3
|
+
WARNING: this is an early release. THINGS WILL CHANGE.
|
4
|
+
|
5
|
+
This library adds Banklink payment integration support to {ActiveMerchant}[http://activemerchant.org].
|
6
|
+
|
7
|
+
Gem is originally based on ActiveMerchant {fork}[https://github.com/indrekj/active_merchant] by Indrek Juhkam.
|
8
|
+
|
9
|
+
== Installation
|
10
|
+
|
11
|
+
=== From Ruby Gems
|
12
|
+
|
13
|
+
Installation from RubyGems
|
14
|
+
|
15
|
+
> gem install activemerchant_banklink
|
16
|
+
|
17
|
+
=== From Git
|
18
|
+
|
19
|
+
You can check out the latest source from git:
|
20
|
+
|
21
|
+
> git pull git://github.com/laurynas/activemerchant_banklink.git
|
22
|
+
|
23
|
+
== Testing
|
24
|
+
|
25
|
+
You can run the tests from this gem with (inside the activemerchant_banklink directory):
|
26
|
+
|
27
|
+
> rake test
|
28
|
+
|
29
|
+
== Maintainer
|
30
|
+
|
31
|
+
This gem is maintained by {Laurynas Butkus}[mailto:laurynas.butkus@gmail.com]
|
32
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
desc "Run the unit test suite"
|
7
|
+
task :default => 'test:units'
|
8
|
+
|
9
|
+
namespace :test do
|
10
|
+
|
11
|
+
Rake::TestTask.new(:units) do |t|
|
12
|
+
t.pattern = 'test/unit/**/*_test.rb'
|
13
|
+
t.ruby_opts << '-rubygems'
|
14
|
+
t.libs << 'test'
|
15
|
+
t.verbose = true
|
16
|
+
end
|
17
|
+
|
18
|
+
Rake::TestTask.new(:remote) do |t|
|
19
|
+
t.pattern = 'test/remote/**/*_test.rb'
|
20
|
+
t.ruby_opts << '-rubygems'
|
21
|
+
t.libs << 'test'
|
22
|
+
t.verbose = true
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "activemerchant_banklink/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "activemerchant_banklink"
|
7
|
+
s.version = ActivemerchantBanklink::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Indrek Juhkam", "Laurynas Butkus"]
|
10
|
+
s.email = ["laurynas.butkus@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/laurynas/activemerchant_banklink"
|
12
|
+
s.summary = %q{ActiveMerchant Banklink add-on (alpha version)}
|
13
|
+
s.description = %q{Adds Banklink support to ActiveMerchant library. Banklink is provided by major banks in the Baltic states.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "activemerchant_banklink"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'activemerchant_banklink'
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module Pizza #:nodoc:
|
5
|
+
module Helper #:nodoc:
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.class_eval do
|
9
|
+
mapping :account, 'VK_SND_ID'
|
10
|
+
# Amount paid, for example, "33.00"
|
11
|
+
mapping :amount, 'VK_AMOUNT'
|
12
|
+
# Unique order id
|
13
|
+
mapping :order, 'VK_STAMP'
|
14
|
+
# Currency used, 3-letter ISO 4217 code
|
15
|
+
mapping :currency, 'VK_CURR'
|
16
|
+
mapping :notify_url, 'VK_RETURN'
|
17
|
+
mapping :return_url, 'VK_RETURN'
|
18
|
+
mapping :cancel_return_url, 'VK_CANCEL'
|
19
|
+
|
20
|
+
mapping :reference, 'VK_REF'
|
21
|
+
mapping :description, 'VK_MSG'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(order, account, options = {})
|
26
|
+
old_valid_keys = [:amount, :currency, :test]
|
27
|
+
new_valid_keys = [:description, :reference]
|
28
|
+
valid_keys = (old_valid_keys + new_valid_keys + Pizza.required_service_params.values << :service_msg_number).uniq
|
29
|
+
options.assert_valid_keys(valid_keys)
|
30
|
+
|
31
|
+
@options = options
|
32
|
+
@fields = {}
|
33
|
+
self.order = order
|
34
|
+
self.account = account
|
35
|
+
self.amount = options[:amount]
|
36
|
+
self.currency = options[:currency]
|
37
|
+
self.description = options[:description]
|
38
|
+
self.reference = options[:reference]
|
39
|
+
|
40
|
+
if options[:service_msg_number]
|
41
|
+
@service_msg_number = options.delete(:service_msg_number)
|
42
|
+
else
|
43
|
+
@service_msg_number = default_service_msg_number
|
44
|
+
end
|
45
|
+
|
46
|
+
add_required_params
|
47
|
+
add_charset_field
|
48
|
+
add_vk_mac
|
49
|
+
end
|
50
|
+
|
51
|
+
# Amount can be supplied with a optional dot separator for cents.
|
52
|
+
def amount=(amount)
|
53
|
+
# TODO check this, sooner or later someone will get a wrong amount.
|
54
|
+
|
55
|
+
# If a string is passed to us, don't do anything.
|
56
|
+
# If a Money object is passed to us, don't do anything.
|
57
|
+
# Otherwise delegate the handling to the money object
|
58
|
+
# and free ourself from the responsibility, yay.
|
59
|
+
if amount.is_a?(String) || amount.is_a?(Money)
|
60
|
+
add_field('VK_AMOUNT', amount)
|
61
|
+
else
|
62
|
+
add_field('VK_AMOUNT', Money.new(amount).to_s)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_vk_mac
|
67
|
+
# Signature used to validate previous parameters
|
68
|
+
add_field('VK_MAC', generate_mac(@service_msg_number, form_fields))
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_charset_field
|
72
|
+
add_field vk_charset_param, vk_charset
|
73
|
+
end
|
74
|
+
|
75
|
+
def add_required_params
|
76
|
+
required_params = Pizza.required_service_params[@service_msg_number]
|
77
|
+
required_params.each do |param|
|
78
|
+
param_value = (@options.delete(param) || send(param.to_s.downcase)).to_s
|
79
|
+
add_field param, iconv.iconv(param_value)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Default parameters
|
84
|
+
def vk_charset
|
85
|
+
'ISO-8859-1'
|
86
|
+
end
|
87
|
+
|
88
|
+
def vk_charset_param
|
89
|
+
'VK_CHARSET'
|
90
|
+
end
|
91
|
+
|
92
|
+
def vk_service
|
93
|
+
@service_msg_number
|
94
|
+
end
|
95
|
+
|
96
|
+
def vk_version
|
97
|
+
'008'
|
98
|
+
end
|
99
|
+
|
100
|
+
# Default service message number.
|
101
|
+
# Use '1002' because it requires the least amount of parameters.
|
102
|
+
def default_service_msg_number
|
103
|
+
1002
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
# Iconv converter to convert from utf8 to
|
108
|
+
# the charset the bank api expects.
|
109
|
+
def iconv
|
110
|
+
@iconv ||= Iconv.new(vk_charset, 'UTF-8')
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module Pizza
|
5
|
+
module Notification
|
6
|
+
|
7
|
+
# A helper method to parse the raw post of the request & return
|
8
|
+
# the right Notification subclass based on the sender id.
|
9
|
+
def self.get_notification(http_raw_data)
|
10
|
+
params = ActiveMerchant::Billing::Integrations::Notification.new(http_raw_data).params
|
11
|
+
Pizza.get_class(params['VK_SND_ID'])::Notification.new(params)
|
12
|
+
end
|
13
|
+
|
14
|
+
def bank_signature_valid?(bank_signature, service_msg_number, sigparams)
|
15
|
+
self.class.parent.get_bank_public_key.verify(OpenSSL::Digest::SHA1.new, bank_signature, generate_data_string(service_msg_number, sigparams))
|
16
|
+
end
|
17
|
+
|
18
|
+
def complete?
|
19
|
+
params['VK_SERVICE'] == '1101'
|
20
|
+
end
|
21
|
+
|
22
|
+
def currency
|
23
|
+
params['VK_CURR']
|
24
|
+
end
|
25
|
+
|
26
|
+
# The order id we passed to the form helper.
|
27
|
+
def item_id
|
28
|
+
params['VK_STAMP']
|
29
|
+
end
|
30
|
+
|
31
|
+
def transaction_id
|
32
|
+
params['VK_T_NO']
|
33
|
+
end
|
34
|
+
|
35
|
+
# When was this payment received by the client.
|
36
|
+
# We're expecting a dd.mm.yyyy format.
|
37
|
+
def received_at
|
38
|
+
date = params['VK_T_DATE']
|
39
|
+
return nil unless date
|
40
|
+
day, month, year = *date.split('.').map(&:to_i)
|
41
|
+
Date.civil(year, month, day)
|
42
|
+
end
|
43
|
+
|
44
|
+
def signature
|
45
|
+
Base64.decode64(params['VK_MAC'])
|
46
|
+
end
|
47
|
+
|
48
|
+
# The money amount we received, string.
|
49
|
+
def gross
|
50
|
+
params['VK_AMOUNT']
|
51
|
+
end
|
52
|
+
|
53
|
+
# Was this a test transaction?
|
54
|
+
def test?
|
55
|
+
params['VK_REC_ID'] == 'testvpos'
|
56
|
+
end
|
57
|
+
|
58
|
+
# TODO what should be here?
|
59
|
+
def status
|
60
|
+
complete? ? 'Completed' : 'Failed'
|
61
|
+
end
|
62
|
+
|
63
|
+
# If our request was sent automatically by the bank (true) or manually
|
64
|
+
# by the user triggering the callback by pressing a "return" button (false).
|
65
|
+
def automatic?
|
66
|
+
params['VK_AUTO'].upcase == 'Y'
|
67
|
+
end
|
68
|
+
|
69
|
+
def success?
|
70
|
+
acknowledge && complete?
|
71
|
+
end
|
72
|
+
|
73
|
+
# We don't actually acknowledge the notification by making another request ourself,
|
74
|
+
# instead, we check the notification by checking the signature that came with the notification.
|
75
|
+
# This method has to be called when handling the notification & deciding whether to process the order.
|
76
|
+
# Example:
|
77
|
+
#
|
78
|
+
# def notify
|
79
|
+
# notify = Notification.new(params)
|
80
|
+
#
|
81
|
+
# if notify.acknowledge
|
82
|
+
# ... process order ... if notify.complete?
|
83
|
+
# else
|
84
|
+
# ... log possible hacking attempt ...
|
85
|
+
# end
|
86
|
+
def acknowledge
|
87
|
+
bank_signature_valid?(signature, params['VK_SERVICE'], params)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
# Take the posted data and move the relevant data into a hash
|
92
|
+
# No parsing since we're already expecting a hash.
|
93
|
+
def parse(params)
|
94
|
+
raise(ArgumentError, 'Need a hash') unless params.is_a?(Hash)
|
95
|
+
@params = params
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'active_merchant/billing/integrations/pizza/helper.rb'
|
2
|
+
require 'active_merchant/billing/integrations/pizza/notification.rb'
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
module Integrations #:nodoc:
|
6
|
+
module Pizza
|
7
|
+
|
8
|
+
# Define sender id (VK_SND_ID) to bank module mappings.
|
9
|
+
def self.get_class(vk_snd_id)
|
10
|
+
case vk_snd_id
|
11
|
+
when 'EYP' then SebEst
|
12
|
+
when 'SAMPOPANK' then SampoEst
|
13
|
+
when 'HP' then SwedbankEst
|
14
|
+
else raise(ArgumentError, "unknown sender id: #{vk_snd_id}")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Define required fields for each service message.
|
19
|
+
# We need to know this in order to calculate VK_MAC
|
20
|
+
# from a given hash of parameters.
|
21
|
+
# Order of the parameters is important.
|
22
|
+
mattr_accessor :required_service_params
|
23
|
+
self.required_service_params = {
|
24
|
+
1001 => [
|
25
|
+
'VK_SERVICE',
|
26
|
+
'VK_VERSION',
|
27
|
+
'VK_SND_ID',
|
28
|
+
'VK_STAMP',
|
29
|
+
'VK_AMOUNT',
|
30
|
+
'VK_CURR',
|
31
|
+
'VK_ACC',
|
32
|
+
'VK_NAME',
|
33
|
+
'VK_REF',
|
34
|
+
'VK_MSG'],
|
35
|
+
1002 => [
|
36
|
+
'VK_SERVICE',
|
37
|
+
'VK_VERSION',
|
38
|
+
'VK_SND_ID',
|
39
|
+
'VK_STAMP',
|
40
|
+
'VK_AMOUNT',
|
41
|
+
'VK_CURR',
|
42
|
+
'VK_REF',
|
43
|
+
'VK_MSG' ],
|
44
|
+
1101 => [
|
45
|
+
'VK_SERVICE',
|
46
|
+
'VK_VERSION',
|
47
|
+
'VK_SND_ID',
|
48
|
+
'VK_REC_ID',
|
49
|
+
'VK_STAMP',
|
50
|
+
'VK_T_NO',
|
51
|
+
'VK_AMOUNT',
|
52
|
+
'VK_CURR',
|
53
|
+
'VK_REC_ACC',
|
54
|
+
'VK_REC_NAME',
|
55
|
+
'VK_SND_ACC',
|
56
|
+
'VK_SND_NAME',
|
57
|
+
'VK_REF',
|
58
|
+
'VK_MSG',
|
59
|
+
'VK_T_DATE'],
|
60
|
+
1901 => [
|
61
|
+
'VK_SERVICE',
|
62
|
+
'VK_VERSION',
|
63
|
+
'VK_SND_ID',
|
64
|
+
'VK_REC_ID',
|
65
|
+
'VK_STAMP',
|
66
|
+
'VK_REF',
|
67
|
+
'VK_MSG']
|
68
|
+
}
|
69
|
+
|
70
|
+
# Calculation using method VK_VERSION=008:
|
71
|
+
# VK_MAC is RSA signature of the request fields coded into BASE64.
|
72
|
+
# VK_MAC will be calculated using secret key of the sender using RSA. Signature will
|
73
|
+
# be calculated for string that consists of all field lengths and contents in the query. Also
|
74
|
+
# empty fields are used in calculation – lenght “000”. Unnumbered (optional) fields are
|
75
|
+
# not used in calculation.
|
76
|
+
# MAC(x1,x2,...,xn) := RSA( SHA-1(p(x1 )|| x1|| p(x2 )|| x2 || ... ||p( xn )||xn),d,n)
|
77
|
+
# where:
|
78
|
+
# || is string concatenation mark
|
79
|
+
# x1, x2, ..., xn are parameters of the query
|
80
|
+
# p(x) is length of the field x represented by three digits
|
81
|
+
# d is RSA secret exponent
|
82
|
+
# n is RSA modulus
|
83
|
+
module Common
|
84
|
+
# p(x) is length of the field x represented by three digits
|
85
|
+
def func_p(val)
|
86
|
+
sprintf("%03i", val.size)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Generate a string to be signed out of service message parameters.
|
90
|
+
# p(x1 )|| x1|| p(x2 )|| x2 || ... ||p( xn )||xn
|
91
|
+
# || is string concatenation mark
|
92
|
+
# p(x) is length of the field x represented by three digits
|
93
|
+
# Parameters val1, val2, value3 would be turned into:
|
94
|
+
# '003val1003val2006value3'
|
95
|
+
def generate_data_string(service_msg_number, sigparams)
|
96
|
+
str = ''
|
97
|
+
Pizza.required_service_params[Integer(service_msg_number)].each do |param|
|
98
|
+
val = sigparams[param].to_s # nil goes to ''
|
99
|
+
str << func_p(val) << val
|
100
|
+
end
|
101
|
+
str
|
102
|
+
end
|
103
|
+
|
104
|
+
def generate_signature(service_msg_number, sigparams)
|
105
|
+
privkey = self.class.parent.get_private_key
|
106
|
+
privkey.sign(OpenSSL::Digest::SHA1.new, generate_data_string(service_msg_number, sigparams))
|
107
|
+
end
|
108
|
+
|
109
|
+
def generate_mac(service_msg_number, sigparams)
|
110
|
+
Base64.encode64(generate_signature(service_msg_number, sigparams)).gsub(/\n/,'')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module SampoEst #:nodoc:
|
5
|
+
class Helper < ActiveMerchant::Billing::Integrations::Helper #:nodoc:
|
6
|
+
include Pizza::Common
|
7
|
+
include Pizza::Helper
|
8
|
+
|
9
|
+
def vk_charset
|
10
|
+
'ISO-8859-4'
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module SampoEst #:nodoc:
|
5
|
+
class Notification < ActiveMerchant::Billing::Integrations::Notification #:nodoc:
|
6
|
+
include Pizza::Common
|
7
|
+
include Pizza::Notification
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/sampo_est/helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/sampo_est/notification.rb'
|
3
|
+
|
4
|
+
module ActiveMerchant #:nodoc:
|
5
|
+
module Billing #:nodoc:
|
6
|
+
module Integrations #:nodoc:
|
7
|
+
|
8
|
+
# This module implements bank payments through
|
9
|
+
# AS Sampo Pank (http://www.sampopank.ee/en/index.html) using
|
10
|
+
# their bank link service (see http://www.sampopank.ee/en/25672.html).
|
11
|
+
#
|
12
|
+
# Configuration:
|
13
|
+
# ActiveMerchant::Billing::Integrations::SampoEst.bank_certificate = File.read('cert')
|
14
|
+
# ActiveMerchant::Billing::Integrations::SampoEst.test_bank_certificate = File.read('cert')
|
15
|
+
# ActiveMerchant::Billing::Integrations::SampoEst.private_key = File.read('keyfile')
|
16
|
+
# ActiveMerchant::Billing::Integrations::SampoEst.test_private_key = File.read('keyfile')
|
17
|
+
# ActiveMerchant::Billing::Integrations::SampoEst.test_url = 'https://test-gateway.tld/gw'
|
18
|
+
# ActiveMerchant::Billing::Integrations::SampoEst.production_url = 'https://production-gateway.tld/gw/'
|
19
|
+
#
|
20
|
+
# The syntax of the helper is as follows:
|
21
|
+
# <% payment_service_for order_id, account_id,
|
22
|
+
# :amount => 50.00,
|
23
|
+
# :service => :sampo_est do |service| %>
|
24
|
+
#
|
25
|
+
# <% service.notify_url url_for(:action => 'notify', :only_path => false) %>
|
26
|
+
# <% service.cancel_return_url 'http://mystore.com' %>
|
27
|
+
# <% end %>
|
28
|
+
#
|
29
|
+
# The order_id parameter is a random id referencing the transaction (VK_STAMP)
|
30
|
+
# The account_id parameter is a id given to you from the bank (VK_SND_ID)
|
31
|
+
# The notify_url is the URL that the bank will send its responses.
|
32
|
+
#
|
33
|
+
# You can handle the notification in
|
34
|
+
# your controller action as follows:
|
35
|
+
#
|
36
|
+
# class NotificationController < ApplicationController
|
37
|
+
# include ActiveMerchant::Billing::Integrations
|
38
|
+
#
|
39
|
+
# def notify
|
40
|
+
# # Notification class is automatically fetched based on the request parameters.
|
41
|
+
# notify = Pizza::Notification.get_notification(params)
|
42
|
+
#
|
43
|
+
# if notify.acknowledge
|
44
|
+
# ... process order ... if notify.complete?
|
45
|
+
# else
|
46
|
+
# ... log possible hacking attempt ...
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
|
51
|
+
module SampoEst
|
52
|
+
|
53
|
+
# Raw X509 certificate of the bank, string format.
|
54
|
+
mattr_accessor :bank_certificate
|
55
|
+
mattr_accessor :test_bank_certificate
|
56
|
+
# RSA public key of the bank, taken from the X509 certificate of the bank. OpenSSL container.
|
57
|
+
def self.get_bank_public_key
|
58
|
+
if ActiveMerchant::Billing::Base.integration_mode == :production
|
59
|
+
cert = self.bank_certificate
|
60
|
+
else
|
61
|
+
cert = self.test_bank_certificate
|
62
|
+
end
|
63
|
+
OpenSSL::X509::Certificate.new(cert.gsub(/ /, '')).public_key
|
64
|
+
end
|
65
|
+
|
66
|
+
# Our raw RSA private key, string format.
|
67
|
+
mattr_accessor :private_key
|
68
|
+
mattr_accessor :test_private_key
|
69
|
+
# Our RSA private key. OpenSSL container.
|
70
|
+
def self.get_private_key
|
71
|
+
if ActiveMerchant::Billing::Base.integration_mode == :production
|
72
|
+
private_key = self.private_key
|
73
|
+
else
|
74
|
+
private_key = self.test_private_key
|
75
|
+
end
|
76
|
+
OpenSSL::PKey::RSA.new(private_key.gsub(/ /, ''))
|
77
|
+
end
|
78
|
+
|
79
|
+
# Bank gateway
|
80
|
+
mattr_accessor :test_url
|
81
|
+
mattr_accessor :production_url
|
82
|
+
def self.service_url
|
83
|
+
mode = ActiveMerchant::Billing::Base.integration_mode
|
84
|
+
case mode
|
85
|
+
when :production
|
86
|
+
self.production_url
|
87
|
+
when :test
|
88
|
+
self.test_url
|
89
|
+
else
|
90
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.notification(post)
|
95
|
+
Notification.new(post)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module SebEst #:nodoc:
|
5
|
+
class Helper < ActiveMerchant::Billing::Integrations::Helper #:nodoc:
|
6
|
+
include Pizza::Common
|
7
|
+
include Pizza::Helper
|
8
|
+
|
9
|
+
def vk_charset
|
10
|
+
'UTF-8'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module SebEst #:nodoc:
|
5
|
+
class Notification < ActiveMerchant::Billing::Integrations::Notification #:nodoc:
|
6
|
+
include Pizza::Common
|
7
|
+
include Pizza::Notification
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/seb_est/helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/seb_est/notification.rb'
|
3
|
+
|
4
|
+
module ActiveMerchant #:nodoc:
|
5
|
+
module Billing #:nodoc:
|
6
|
+
module Integrations #:nodoc:
|
7
|
+
|
8
|
+
# This module implements bank payments through
|
9
|
+
# SEB Eesti Ühispank (http://www.seb.ee/index/1305) using
|
10
|
+
# their bank link service (see http://www.seb.ee/page/130212050205).
|
11
|
+
#
|
12
|
+
# Configuration:
|
13
|
+
# ActiveMerchant::Billing::Integrations::SebEst.bank_certificate = File.read('cert')
|
14
|
+
# ActiveMerchant::Billing::Integrations::SebEst.test_bank_certificate = File.read('cert')
|
15
|
+
# ActiveMerchant::Billing::Integrations::SebEst.private_key = File.read('keyfile')
|
16
|
+
# ActiveMerchant::Billing::Integrations::SebEst.test_private_key = File.read('keyfile')
|
17
|
+
# ActiveMerchant::Billing::Integrations::SebEst.test_url = 'https://test-gateway.tld/gw'
|
18
|
+
# ActiveMerchant::Billing::Integrations::SebEst.production_url = 'https://production-gateway.tld/gw/'
|
19
|
+
#
|
20
|
+
# The syntax of the helper is as follows:
|
21
|
+
# <% payment_service_for order_id, account_id,
|
22
|
+
# :amount => 50.00,
|
23
|
+
# :service => :seb_est do |service| %>
|
24
|
+
#
|
25
|
+
# <% service.notify_url url_for(:action => 'notify', :only_path => false) %>
|
26
|
+
# <% service.cancel_return_url 'http://mystore.com' %>
|
27
|
+
# <% end %>
|
28
|
+
#
|
29
|
+
# The order_id parameter is a random id referencing the transaction (VK_STAMP)
|
30
|
+
# The account_id parameter is a id given to you from the bank (VK_SND_ID)
|
31
|
+
# The notify_url is the URL that the bank will send its responses.
|
32
|
+
#
|
33
|
+
# You can handle the notification in
|
34
|
+
# your controller action as follows:
|
35
|
+
#
|
36
|
+
# class NotificationController < ApplicationController
|
37
|
+
# include ActiveMerchant::Billing::Integrations
|
38
|
+
#
|
39
|
+
# def notify
|
40
|
+
# # Notification class is automatically fetched based on the request parameters.
|
41
|
+
# notify = Pizza::Notification.get_notification(params)
|
42
|
+
#
|
43
|
+
# if notify.acknowledge
|
44
|
+
# ... process order ... if notify.complete?
|
45
|
+
# else
|
46
|
+
# ... log possible hacking attempt ...
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
|
51
|
+
module SebEst
|
52
|
+
|
53
|
+
# Raw X509 certificate of the bank, string format.
|
54
|
+
mattr_accessor :bank_certificate
|
55
|
+
mattr_accessor :test_bank_certificate
|
56
|
+
# RSA public key of the bank, taken from the X509 certificate of the bank. OpenSSL container.
|
57
|
+
def self.get_bank_public_key
|
58
|
+
if ActiveMerchant::Billing::Base.integration_mode == :production
|
59
|
+
cert = self.bank_certificate
|
60
|
+
else
|
61
|
+
cert = self.test_bank_certificate
|
62
|
+
end
|
63
|
+
OpenSSL::X509::Certificate.new(cert.gsub(/ /, '')).public_key
|
64
|
+
end
|
65
|
+
|
66
|
+
# Our raw RSA private key, string format.
|
67
|
+
mattr_accessor :private_key
|
68
|
+
mattr_accessor :test_private_key
|
69
|
+
# Our RSA private key. OpenSSL container.
|
70
|
+
def self.get_private_key
|
71
|
+
if ActiveMerchant::Billing::Base.integration_mode == :production
|
72
|
+
private_key = self.private_key
|
73
|
+
else
|
74
|
+
private_key = self.test_private_key
|
75
|
+
end
|
76
|
+
OpenSSL::PKey::RSA.new(private_key.gsub(/ /, ''))
|
77
|
+
end
|
78
|
+
|
79
|
+
mattr_accessor :test_url
|
80
|
+
mattr_accessor :production_url
|
81
|
+
def self.service_url
|
82
|
+
mode = ActiveMerchant::Billing::Base.integration_mode
|
83
|
+
case mode
|
84
|
+
when :production
|
85
|
+
self.production_url
|
86
|
+
when :test
|
87
|
+
self.test_url
|
88
|
+
else
|
89
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.notification(post)
|
94
|
+
Notification.new(post)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module SwedbankEst #:nodoc:
|
5
|
+
class Helper < ActiveMerchant::Billing::Integrations::Helper #:nodoc:
|
6
|
+
include Pizza::Common
|
7
|
+
include Pizza::Helper
|
8
|
+
|
9
|
+
def vk_charset
|
10
|
+
'ISO-8859-1'
|
11
|
+
end
|
12
|
+
|
13
|
+
def vk_charset_param
|
14
|
+
'VK_ENCODING'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module SwedbankEst #:nodoc:
|
5
|
+
class Notification < ActiveMerchant::Billing::Integrations::Notification #:nodoc:
|
6
|
+
include Pizza::Common
|
7
|
+
include Pizza::Notification
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/swedbank_est/helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/swedbank_est/notification.rb'
|
3
|
+
|
4
|
+
module ActiveMerchant #:nodoc:
|
5
|
+
module Billing #:nodoc:
|
6
|
+
module Integrations #:nodoc:
|
7
|
+
|
8
|
+
# This module implements bank payments through
|
9
|
+
# Aktsiaselts Hansapank using their bank link service
|
10
|
+
# (http://w.hansa.ee/eng/arikliendile_teenusedkaupmehele_makselahendusedinternetis_tehnilinekirjeldus.html).
|
11
|
+
#
|
12
|
+
# Configuration:
|
13
|
+
# ActiveMerchant::Billing::Integrations::SwedbankEst.bank_certificate = File.read('cert')
|
14
|
+
# ActiveMerchant::Billing::Integrations::SwedbankEst.test_bank_certificate = File.read('cert')
|
15
|
+
# ActiveMerchant::Billing::Integrations::SwedbankEst.private_key = File.read('keyfile')
|
16
|
+
# ActiveMerchant::Billing::Integrations::SwedbankEst.test_private_key = File.read('keyfile')
|
17
|
+
# ActiveMerchant::Billing::Integrations::SwedbankEst.production_url = 'https://production-gateway.tld/gw/'
|
18
|
+
#
|
19
|
+
#
|
20
|
+
# The syntax of the helper is as follows:
|
21
|
+
# <% payment_service_for order_id, account_id,
|
22
|
+
# :amount => 50.00,
|
23
|
+
# :service => :swedbank_est do |service| %>
|
24
|
+
#
|
25
|
+
# <% service.notify_url url_for(:action => 'notify', :only_path => false) %>
|
26
|
+
# <% service.cancel_return_url 'http://mystore.com' %>
|
27
|
+
# <% end %>
|
28
|
+
#
|
29
|
+
# The order_id parameter is a random id referencing the transaction (VK_STAMP)
|
30
|
+
# The account_id parameter is a id given to you from the bank (VK_SND_ID)
|
31
|
+
# The notify_url is the URL that the bank will send its responses.
|
32
|
+
#
|
33
|
+
# You can handle the notification in
|
34
|
+
# your controller action as follows:
|
35
|
+
#
|
36
|
+
# class NotificationController < ApplicationController
|
37
|
+
# include ActiveMerchant::Billing::Integrations
|
38
|
+
#
|
39
|
+
# def notify
|
40
|
+
# # Notification class is automatically fetched based on the request parameters.
|
41
|
+
# notify = Pizza::Notification.get_notification(params)
|
42
|
+
#
|
43
|
+
# if notify.acknowledge
|
44
|
+
# ... process order ... if notify.complete?
|
45
|
+
# else
|
46
|
+
# ... log possible hacking attempt ...
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
|
51
|
+
module SwedbankEst
|
52
|
+
|
53
|
+
# Raw X509 certificate of the bank, string format.
|
54
|
+
mattr_accessor :bank_certificate
|
55
|
+
mattr_accessor :test_bank_certificate
|
56
|
+
# RSA public key of the bank, taken from the X509 certificate of the bank. OpenSSL container.
|
57
|
+
def self.get_bank_public_key
|
58
|
+
if ActiveMerchant::Billing::Base.integration_mode == :production
|
59
|
+
cert = self.bank_certificate
|
60
|
+
else
|
61
|
+
cert = self.test_bank_certificate
|
62
|
+
end
|
63
|
+
OpenSSL::X509::Certificate.new(cert.gsub(/ /, '')).public_key
|
64
|
+
end
|
65
|
+
|
66
|
+
mattr_accessor :private_key
|
67
|
+
mattr_accessor :test_private_key
|
68
|
+
# Our RSA private key. OpenSSL container.
|
69
|
+
def self.get_private_key
|
70
|
+
if ActiveMerchant::Billing::Base.integration_mode == :production
|
71
|
+
private_key = self.private_key
|
72
|
+
else
|
73
|
+
private_key = self.test_private_key
|
74
|
+
end
|
75
|
+
OpenSSL::PKey::RSA.new(private_key.gsub(/ /, ''))
|
76
|
+
end
|
77
|
+
|
78
|
+
mattr_accessor :test_url
|
79
|
+
mattr_accessor :production_url
|
80
|
+
def self.service_url
|
81
|
+
mode = ActiveMerchant::Billing::Base.integration_mode
|
82
|
+
case mode
|
83
|
+
when :production
|
84
|
+
self.production_url
|
85
|
+
when :test
|
86
|
+
self.test_url
|
87
|
+
else
|
88
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.notification(post)
|
93
|
+
Notification.new(post)
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
3
|
+
|
4
|
+
require 'activemerchant_banklink'
|
5
|
+
require 'rubygems'
|
6
|
+
require 'money'
|
7
|
+
require 'test/unit'
|
8
|
+
require 'mocha'
|
9
|
+
require 'yaml'
|
10
|
+
|
11
|
+
begin
|
12
|
+
gem 'actionpack'
|
13
|
+
rescue LoadError
|
14
|
+
raise StandardError, "The view tests need ActionPack installed as gem to run"
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'action_controller'
|
18
|
+
require 'action_controller/test_process'
|
19
|
+
require 'active_merchant/billing/integrations/action_view_helper'
|
20
|
+
|
21
|
+
ActiveMerchant::Billing::Base.mode = :test
|
22
|
+
|
23
|
+
# Test gateways
|
24
|
+
class SimpleTestGateway < ActiveMerchant::Billing::Gateway
|
25
|
+
end
|
26
|
+
|
27
|
+
class SubclassGateway < SimpleTestGateway
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
module ActiveMerchant
|
32
|
+
module Assertions
|
33
|
+
def assert_field(field, value)
|
34
|
+
clean_backtrace do
|
35
|
+
assert_equal value, @helper.fields[field]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Allows the testing of you to check for negative assertions:
|
40
|
+
#
|
41
|
+
# # Instead of
|
42
|
+
# assert !something_that_is_false
|
43
|
+
#
|
44
|
+
# # Do this
|
45
|
+
# assert_false something_that_should_be_false
|
46
|
+
#
|
47
|
+
# An optional +msg+ parameter is available to help you debug.
|
48
|
+
def assert_false(boolean, message = nil)
|
49
|
+
message = build_message message, '<?> is not false or nil.', boolean
|
50
|
+
|
51
|
+
clean_backtrace do
|
52
|
+
assert_block message do
|
53
|
+
not boolean
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# A handy little assertion to check for a successful response:
|
59
|
+
#
|
60
|
+
# # Instead of
|
61
|
+
# assert_success response
|
62
|
+
#
|
63
|
+
# # DRY that up with
|
64
|
+
# assert_success response
|
65
|
+
#
|
66
|
+
# A message will automatically show the inspection of the response
|
67
|
+
# object if things go afoul.
|
68
|
+
def assert_success(response)
|
69
|
+
clean_backtrace do
|
70
|
+
assert response.success?, "Response failed: #{response.inspect}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# The negative of +assert_success+
|
75
|
+
def assert_failure(response)
|
76
|
+
clean_backtrace do
|
77
|
+
assert_false response.success?, "Response expected to fail: #{response.inspect}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def assert_valid(validateable)
|
82
|
+
clean_backtrace do
|
83
|
+
assert validateable.valid?, "Expected to be valid"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def assert_not_valid(validateable)
|
88
|
+
clean_backtrace do
|
89
|
+
assert_false validateable.valid?, "Expected to not be valid"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
def clean_backtrace(&block)
|
95
|
+
yield
|
96
|
+
rescue Test::Unit::AssertionFailedError => e
|
97
|
+
path = File.expand_path(__FILE__)
|
98
|
+
raise Test::Unit::AssertionFailedError, e.message, e.backtrace.reject { |line| File.expand_path(line) =~ /#{path}/ }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
module Fixtures
|
103
|
+
HOME_DIR = RUBY_PLATFORM =~ /mswin32/ ? ENV['HOMEPATH'] : ENV['HOME'] unless defined?(HOME_DIR)
|
104
|
+
LOCAL_CREDENTIALS = File.join(HOME_DIR.to_s, '.active_merchant/fixtures.yml') unless defined?(LOCAL_CREDENTIALS)
|
105
|
+
DEFAULT_CREDENTIALS = File.join(File.dirname(__FILE__), 'fixtures.yml') unless defined?(DEFAULT_CREDENTIALS)
|
106
|
+
|
107
|
+
private
|
108
|
+
def credit_card(number = '4242424242424242', options = {})
|
109
|
+
defaults = {
|
110
|
+
:number => number,
|
111
|
+
:month => 9,
|
112
|
+
:year => Time.now.year + 1,
|
113
|
+
:first_name => 'Longbob',
|
114
|
+
:last_name => 'Longsen',
|
115
|
+
:verification_value => '123',
|
116
|
+
:type => 'visa'
|
117
|
+
}.update(options)
|
118
|
+
|
119
|
+
Billing::CreditCard.new(defaults)
|
120
|
+
end
|
121
|
+
|
122
|
+
def check(options = {})
|
123
|
+
defaults = {
|
124
|
+
:name => 'Jim Smith',
|
125
|
+
:routing_number => '244183602',
|
126
|
+
:account_number => '15378535',
|
127
|
+
:account_holder_type => 'personal',
|
128
|
+
:account_type => 'checking',
|
129
|
+
:number => '1'
|
130
|
+
}.update(options)
|
131
|
+
|
132
|
+
Billing::Check.new(defaults)
|
133
|
+
end
|
134
|
+
|
135
|
+
def address(options = {})
|
136
|
+
{
|
137
|
+
:name => 'Jim Smith',
|
138
|
+
:address1 => '1234 My Street',
|
139
|
+
:address2 => 'Apt 1',
|
140
|
+
:company => 'Widgets Inc',
|
141
|
+
:city => 'Ottawa',
|
142
|
+
:state => 'ON',
|
143
|
+
:zip => 'K1C2N6',
|
144
|
+
:country => 'CA',
|
145
|
+
:phone => '(555)555-5555',
|
146
|
+
:fax => '(555)555-6666'
|
147
|
+
}.update(options)
|
148
|
+
end
|
149
|
+
|
150
|
+
def all_fixtures
|
151
|
+
@@fixtures ||= load_fixtures
|
152
|
+
end
|
153
|
+
|
154
|
+
def fixtures(key)
|
155
|
+
data = all_fixtures[key] || raise(StandardError, "No fixture data was found for '#{key}'")
|
156
|
+
|
157
|
+
data.dup
|
158
|
+
end
|
159
|
+
|
160
|
+
def load_fixtures
|
161
|
+
file = File.exists?(LOCAL_CREDENTIALS) ? LOCAL_CREDENTIALS : DEFAULT_CREDENTIALS
|
162
|
+
yaml_data = YAML.load(File.read(file))
|
163
|
+
symbolize_keys(yaml_data)
|
164
|
+
|
165
|
+
yaml_data
|
166
|
+
end
|
167
|
+
|
168
|
+
def symbolize_keys(hash)
|
169
|
+
return unless hash.is_a?(Hash)
|
170
|
+
|
171
|
+
hash.symbolize_keys!
|
172
|
+
hash.each{|k,v| symbolize_keys(v)}
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
Test::Unit::TestCase.class_eval do
|
178
|
+
include ActiveMerchant::Billing
|
179
|
+
include ActiveMerchant::Assertions
|
180
|
+
include ActiveMerchant::Utils
|
181
|
+
include ActiveMerchant::Fixtures
|
182
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../test_helper'
|
2
|
+
|
3
|
+
# setup test rsa private key
|
4
|
+
ActiveMerchant::Billing::Integrations::SebEst.test_private_key = <<EOF
|
5
|
+
-----BEGIN RSA PRIVATE KEY-----
|
6
|
+
MIICXAIBAAKBgQC+AROlXiRvi1T7Q9fAh0Lw73szAn26mqfKDqd6Bdplq3v+gVWC
|
7
|
+
3v0+bgtfNakRE/UVYOxEA0z0viqRpKzPuNy8OstTMe8fFKs19NW8lBYik6NzJ4Bk
|
8
|
+
+B6VmovOm0nJLQJytXKiJyuHP9DqPOVmP8S+azzX7Uqzov1nxo9fvH7y2QIDAQAB
|
9
|
+
AoGAFhbD9O6r57fYCloJxB01gBMnTHfWrBH8vbXUbJAvorA7+wuIKG3KHS7n7Yqs
|
10
|
+
fArI7FJXRVTo5m8RPdtaJ9ADAT9rjAi3A17TaEueyJl+B/hjHYhsd8MeFhTb2fh0
|
11
|
+
rY3F6diL8U/YDbiAIegnKO0zcc6ynJrsQZvzb6DlY/CLPe0CQQD3KXJzw1ZfJ1ts
|
12
|
+
c370b/ZC1YrRURw41Q0I8ljYJ8EJw/ngVxrnCIsd43bRnOVp9guJrjTQRkhDC3Gn
|
13
|
+
J2Y0+42LAkEAxMxmh7QY4nItBTS0fe1KCat4VDxhyxYEhZKlGDhxW75vNROrripB
|
14
|
+
1ZfBsq5xkY2MM9R7WKmL7SpStrUPIvEVqwJBAOXA4ISd61cupbytrDEbNscv7Afh
|
15
|
+
pyNpYOGVLmNYqQgj5c7WCcsD1RYmkRgPCe8y6czFZJDLFHdGVxLz+/16bTsCQC9J
|
16
|
+
Ob2TnYMTkhO1JUU4tdh69e+vjoPgp3d80+Rs83fq2wey0UaI6saqryUC21Dw5OYz
|
17
|
+
QOv92RxEVhmGibuIl/8CQCiYrzwlZJDlsKrWPZT0E8rzNmLZkhNHzYJP9S7x+FKk
|
18
|
+
m3gFeXEBgzGn9UOd6xIAp0p7A1XVBN8XzDMa09gSOks=
|
19
|
+
-----END RSA PRIVATE KEY-----
|
20
|
+
EOF
|
21
|
+
|
22
|
+
# setup bank public certificate, used for checking response params
|
23
|
+
ActiveMerchant::Billing::Integrations::SebEst.test_bank_certificate = <<EOF
|
24
|
+
-----BEGIN CERTIFICATE-----
|
25
|
+
MIIDRTCCAq6gAwIBAgIBADANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJFRTEO
|
26
|
+
MAwGA1UECBMFSGFyanUxEDAOBgNVBAcTB1RhbGxpbm4xDDAKBgNVBAoTA0VZUDEL
|
27
|
+
MAkGA1UECxMCSVQxDDAKBgNVBAMTA2EuYTEhMB8GCSqGSIb3DQEJARYSYWxsYXIu
|
28
|
+
YWxsYXNAZXlwLmVlMB4XDTk5MTExNTA4MTAzM1oXDTk5MTIxNTA4MTAzM1owezEL
|
29
|
+
MAkGA1UEBhMCRUUxDjAMBgNVBAgTBUhhcmp1MRAwDgYDVQQHEwdUYWxsaW5uMQww
|
30
|
+
CgYDVQQKEwNFWVAxCzAJBgNVBAsTAklUMQwwCgYDVQQDEwNhLmExITAfBgkqhkiG
|
31
|
+
9w0BCQEWEmFsbGFyLmFsbGFzQGV5cC5lZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
|
32
|
+
gYkCgYEAvgETpV4kb4tU+0PXwIdC8O97MwJ9upqnyg6negXaZat7/oFVgt79Pm4L
|
33
|
+
XzWpERP1FWDsRANM9L4qkaSsz7jcvDrLUzHvHxSrNfTVvJQWIpOjcyeAZPgelZqL
|
34
|
+
zptJyS0CcrVyoicrhz/Q6jzlZj/Evms81+1Ks6L9Z8aPX7x+8tkCAwEAAaOB2DCB
|
35
|
+
1TAdBgNVHQ4EFgQUFivCzZNmegEoOxYtg20YMMRB98gwgaUGA1UdIwSBnTCBmoAU
|
36
|
+
FivCzZNmegEoOxYtg20YMMRB98ihf6R9MHsxCzAJBgNVBAYTAkVFMQ4wDAYDVQQI
|
37
|
+
EwVIYXJqdTEQMA4GA1UEBxMHVGFsbGlubjEMMAoGA1UEChMDRVlQMQswCQYDVQQL
|
38
|
+
EwJJVDEMMAoGA1UEAxMDYS5hMSEwHwYJKoZIhvcNAQkBFhJhbGxhci5hbGxhc0Bl
|
39
|
+
eXAuZWWCAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBfkayuot+e
|
40
|
+
fwW8QmPwpWF5AY3oMT/fTncjCljDBOg39IQv4PjnpTdDfwwl3lUIZHHTLM2i0L/c
|
41
|
+
eD4D1UFM1qdp2VZzhBd1eeMjxYjCP8qL2v2MfLkCYcP30Sl6ISSkFjFc5qbGXZOc
|
42
|
+
C82uR/wUZJDw9kj+R1O46/byG8yA+S9FVw==
|
43
|
+
-----END CERTIFICATE-----
|
44
|
+
EOF
|
45
|
+
|
46
|
+
class SebEstNotificationTest < Test::Unit::TestCase
|
47
|
+
include ActiveMerchant::Billing::Integrations
|
48
|
+
|
49
|
+
def setup
|
50
|
+
@seb_est = Pizza::Notification.get_notification(http_raw_data)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_get_notification_class_from_pizza
|
54
|
+
notify_class = Pizza::Notification.get_notification(http_raw_data)
|
55
|
+
assert notify_class.is_a?(ActiveMerchant::Billing::Integrations::SebEst::Notification)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_accessors
|
59
|
+
assert_equal true, @seb_est.complete?
|
60
|
+
assert_equal 'Completed', @seb_est.status
|
61
|
+
assert_equal "88", @seb_est.item_id
|
62
|
+
assert_equal "2774", @seb_est.transaction_id
|
63
|
+
assert_equal '33', @seb_est.gross
|
64
|
+
assert_equal "EEK", @seb_est.currency
|
65
|
+
assert_equal '26.11.2007', @seb_est.received_at.strftime("%d.%m.%Y")
|
66
|
+
assert_equal true, @seb_est.test?
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_compositions
|
70
|
+
assert_equal Money.new(3300, 'EEK'), @seb_est.amount
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_acknowledgement
|
74
|
+
assert_equal true, @seb_est.acknowledge
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_acknowledgement_fail_with_params_changed
|
78
|
+
@seb_est_wrong = Pizza::Notification.get_notification(http_raw_data.gsub('VK_AMOUNT=33', 'VK_AMOUNT=100'))
|
79
|
+
assert_equal false, @seb_est_wrong.acknowledge
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def http_raw_data
|
85
|
+
"VK_SERVICE=1101&VK_VERSION=008&VK_SND_ID=EYP&VK_REC_ID=testvpos&VK_STAMP=88&VK_T_NO=2774&VK_AMOUNT=33&VK_CURR=EEK&VK_REC_ACC=10002050618003&VK_REC_NAME=ALLAS+ALLAR&VK_SND_ACC=10010046155012&VK_SND_NAME=t%C3%B5%C3%B5ger+%2C+Le%C3%B5p%C3%A4%C3%B6ld%C5%BE%C5%BD%C5%A1%C5%A0&VK_REF=123&VK_MSG=Porgandid&VK_T_DATE=26.11.2007&VK_MAC=LyCZRncu%2F%2BOi5nwzOkI6C9UMFohN6tSl3tLFyIJyNp2lGKBrDKZ2H8b%2BadU3XalzS7MwnAj8r%2FRhLpbsGNE5ysNyM4CKkSrsVzxoXbt9%2BB1foH9Rlp9LCeoR2H774f8UcMe9RVsE%2B%2BZfrEZzzXYyR1PXDCVOShQOAxlD9pbh8nk%3D&VK_LANG=EST&VK_RETURN=http%3A%2F%2F90.190.110.154%2Fseb_est%2Fnotify&VK_AUTO=N&VK_CHARSET=UTF-8&keel=EST&appname=UN3MIN&act=UPOSTEST2"
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper'
|
2
|
+
|
3
|
+
class SampoEstModuleTest < Test::Unit::TestCase
|
4
|
+
include ActiveMerchant::Billing::Integrations
|
5
|
+
|
6
|
+
def test_notification_method
|
7
|
+
assert_instance_of SampoEst::Notification, SampoEst.notification({'name' => 'cody'})
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper'
|
2
|
+
|
3
|
+
class SebEstModuleTest < Test::Unit::TestCase
|
4
|
+
include ActiveMerchant::Billing::Integrations
|
5
|
+
|
6
|
+
def test_notification_method
|
7
|
+
assert_instance_of SebEst::Notification, SebEst.notification({'name' => 'cody'})
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper'
|
2
|
+
|
3
|
+
class SwedbankEstModuleTest < Test::Unit::TestCase
|
4
|
+
include ActiveMerchant::Billing::Integrations
|
5
|
+
|
6
|
+
def test_notification_method
|
7
|
+
assert_instance_of SwedbankEst::Notification, SwedbankEst.notification({'name' => 'cody'})
|
8
|
+
end
|
9
|
+
end
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activemerchant_banklink
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Indrek Juhkam
|
14
|
+
- Laurynas Butkus
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2011-01-29 00:00:00 +02:00
|
20
|
+
default_executable:
|
21
|
+
dependencies: []
|
22
|
+
|
23
|
+
description: Adds Banklink support to ActiveMerchant library. Banklink is provided by major banks in the Baltic states.
|
24
|
+
email:
|
25
|
+
- laurynas.butkus@gmail.com
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- .gitignore
|
34
|
+
- Gemfile
|
35
|
+
- MIT-LICENSE
|
36
|
+
- README.rdoc
|
37
|
+
- Rakefile
|
38
|
+
- activemerchant_banklink.gemspec
|
39
|
+
- init.rb
|
40
|
+
- lib/active_merchant/billing/integrations/pizza.rb
|
41
|
+
- lib/active_merchant/billing/integrations/pizza/helper.rb
|
42
|
+
- lib/active_merchant/billing/integrations/pizza/notification.rb
|
43
|
+
- lib/active_merchant/billing/integrations/sampo_est.rb
|
44
|
+
- lib/active_merchant/billing/integrations/sampo_est/helper.rb
|
45
|
+
- lib/active_merchant/billing/integrations/sampo_est/notification.rb
|
46
|
+
- lib/active_merchant/billing/integrations/seb_est.rb
|
47
|
+
- lib/active_merchant/billing/integrations/seb_est/helper.rb
|
48
|
+
- lib/active_merchant/billing/integrations/seb_est/notification.rb
|
49
|
+
- lib/active_merchant/billing/integrations/swedbank_est.rb
|
50
|
+
- lib/active_merchant/billing/integrations/swedbank_est/helper.rb
|
51
|
+
- lib/active_merchant/billing/integrations/swedbank_est/notification.rb
|
52
|
+
- lib/activemerchant_banklink.rb
|
53
|
+
- lib/activemerchant_banklink/version.rb
|
54
|
+
- test/test_helper.rb
|
55
|
+
- test/unit/integrations/notifications/seb_est_notification_test.rb
|
56
|
+
- test/unit/integrations/sampo_est_module_test.rb
|
57
|
+
- test/unit/integrations/seb_est_module_test.rb
|
58
|
+
- test/unit/integrations/swedbank_est_module_test.rb
|
59
|
+
has_rdoc: true
|
60
|
+
homepage: http://github.com/laurynas/activemerchant_banklink
|
61
|
+
licenses: []
|
62
|
+
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
hash: 3
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
version: "0"
|
86
|
+
requirements: []
|
87
|
+
|
88
|
+
rubyforge_project: activemerchant_banklink
|
89
|
+
rubygems_version: 1.3.7
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: ActiveMerchant Banklink add-on (alpha version)
|
93
|
+
test_files: []
|
94
|
+
|