activemerchant_banklink 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in activemerchant_banklink.gemspec
4
+ gemspec
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
@@ -0,0 +1,3 @@
1
+ module ActivemerchantBanklink
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'active_merchant'
2
+ require 'active_merchant/billing/integrations/pizza'
3
+ require 'active_merchant/billing/integrations/swedbank_est'
4
+ require 'active_merchant/billing/integrations/seb_est'
5
+ require 'active_merchant/billing/integrations/sampo_est'
@@ -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
+