wvanbergen-adyen 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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Willem van Bergen and Michel Barbosa
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,100 @@
1
+ = Adyen
2
+
3
+ Package to simplify including the Adyen payments services into a Ruby on Rails application.
4
+ Currently, the package contains functions to easily generate the required hidden fields and
5
+ matchers to easily check your views using rspec.
6
+
7
+ * For more information about Adyen, see http://www.adyen.com
8
+ * For more information about integrating Adyen, see their manuals at
9
+ http://support.adyen.com/links/documentation
10
+
11
+ == Skins
12
+
13
+ Adyen using the notion of "skins" to determine what payment methods should be available
14
+ and what the payment environment should look like. At least one skin is required, which
15
+ can be created in the merchant area of Adyen. For every key, a shared secret is generated
16
+ that is required to sign payment forms. You will need to provide this secret as the
17
+ :shared_secret field to the hidden_fields method (see below).
18
+
19
+ == Building payment forms
20
+
21
+ <% form_tag(:url => Adyen::Form.url) do %>
22
+ <%= Adyen::Form.hidden_fields(:merchant_account => 'myaccount', ... ,
23
+ :skin_code => 'myperfectskin', :shared_secret => 'youllneverguess')
24
+ ...
25
+ <%= submit_tag('pay') %>
26
+ <% end %>
27
+
28
+ Please refer to the Adyen integration manual for all the
29
+
30
+ <tt>Adyen::Form.url</tt> will return the URL to the live environment of Adyen in production
31
+ mode, otherwise it will return the testing environment. To override this behavior, use:
32
+
33
+ <% form_tag(:url => Adyen::Form.url('live')) do %>
34
+ ...
35
+ <% end %>
36
+
37
+ <tt>Adyen::Form.hidden_fields</tt> will generate the hidden fields for the key/value pairs
38
+ you provide to the function. The keys will be camelized automatically. Some notes:
39
+
40
+ * <tt>:recurring => true</tt> will be translated to <tt>:recurringContract => 'DEFAULT'</tt>.
41
+ * <tt>:order_data</tt> will be encoded using gzip/base64.
42
+ * <tt>:shared_secret</tt> must be provided to calculate the merchant signature.
43
+ * <tt>:merchant_sig</tt> will be computed automatically using this secret.
44
+
45
+ == Testing payment forms using rspec matchers
46
+
47
+ First, make sure that the Adyen matchers are available in your view specs:
48
+
49
+ Spec::Runner.configure do |config|
50
+ ...
51
+ config.include Adyen::Matchers, :type => :views
52
+ ...
53
+ end
54
+
55
+ To check the response in a view spec, use the <tt>have_adyen_payment_form</tt>,
56
+ <tt>have_adyen_recurrent_payment_form</tt> and <tt>have_adyen_single_payment_form matchers</tt>.
57
+ By passing a hash, you can check the values of the hidden fields. By passing :anything
58
+ as value, the matcher will simply check if the hidden field exists and ignore its value.
59
+
60
+ Some example specs:
61
+
62
+ before(:each) do
63
+ render 'payments/new.html.erb'
64
+ end
65
+
66
+ it "should contain an Adyen payment form" do
67
+ # either single or recurring
68
+ response.should have_adyen_payment_form(:currency_code => 'EUR', :payment_amount => 1000)
69
+ end
70
+
71
+ it "should contain an Adyen recurrent payment form" do
72
+ response.should have_adyen_recurrent_payment_form
73
+ end
74
+
75
+ it "should contain an Adyen recurrent payment form" do
76
+ response.should have_adyen_single_payment_form(:merchant_reference => :anything)
77
+ end
78
+
79
+ == Testing payment forms using assertions
80
+
81
+ To use the assertions in unit tests, first include the matchers module in your test class:
82
+
83
+ class PaymentControllerTest < Test::Unit
84
+ include Adyen::Matchers
85
+ ...
86
+
87
+ Use the assertion methods <tt>assert_adyen_payment_form</tt>, <tt>assert_adyen_single_payment_form</tt>
88
+ and <tt>assert_adyen_recurring_payment_form</tt>. They work similarly to the RSpec matcher methods
89
+ described above. An example:
90
+
91
+ def test_payment_form
92
+ get new_payment_path
93
+ assert_adyen_payment_form(@response, :currency_code => 'EUR', :payment_amount => 1000)
94
+ end
95
+
96
+ == About
97
+
98
+ This package is written by Michel Barbosa and Willem van Bergen for Floorplanner.com,
99
+ and made public under the MIT license (see LICENSE). It comes without warranty of any kind,
100
+ so use at your own risk.
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ Dir['tasks/*.rake'].each { |file| load(file) }
2
+
3
+ task :default => [:spec]
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'adyen'
data/lib/adyen.rb ADDED
@@ -0,0 +1,31 @@
1
+ module Adyen
2
+ LIVE_RAILS_ENVIRONMENTS = ['production']
3
+
4
+ # Setter voor the current Adyen environment.
5
+ # Must be either 'test' or 'live'
6
+ def self.environment=(env)
7
+ @environment = env
8
+ end
9
+
10
+ # Returns the current Adyen environment.
11
+ # Returns either 'test' or 'live'.
12
+ def self.environment(override = nil)
13
+ override || @environment || Adyen.autodetect_environment
14
+ end
15
+
16
+ # Autodetects the Adyen environment based on the RAILS_ENV constant
17
+ def self.autodetect_environment
18
+ (defined?(RAILS_ENV) && Adyen::LIVE_RAILS_ENVIRONMENTS.include?(RAILS_ENV.to_s.downcase)) ? 'live' : 'test'
19
+ end
20
+
21
+ # Loads submodules on demand, so that dependencies are not required.
22
+ def self.const_missing(sym)
23
+ require "adyen/#{sym.to_s.downcase}"
24
+ return Adyen.const_get(sym)
25
+ rescue
26
+ super(sym)
27
+ end
28
+ end
29
+
30
+ require 'adyen/encoding'
31
+ require 'adyen/formatter'
data/lib/adyen/form.rb ADDED
@@ -0,0 +1,58 @@
1
+ require 'action_view'
2
+
3
+ module Adyen
4
+ module Form
5
+
6
+ extend ActionView::Helpers::TagHelper
7
+
8
+ ACTION_URL = "https://%s.adyen.com/hpp/select.shtml"
9
+
10
+ def self.url(environment = nil)
11
+ environment ||= Adyen.environment(environment)
12
+ Adyen::Form::ACTION_URL % environment.to_s
13
+ end
14
+
15
+ def self.calculate_signature_string(attributes)
16
+ merchant_sig_string = ""
17
+ merchant_sig_string << attributes[:payment_amount].to_s << attributes[:currency_code].to_s <<
18
+ attributes[:ship_before_date].to_s << attributes[:merchant_reference].to_s <<
19
+ attributes[:skin_code].to_s << attributes[:merchant_account].to_s <<
20
+ attributes[:session_validity].to_s << attributes[:shopper_email].to_s <<
21
+ attributes[:shopper_reference].to_s << attributes[:recurring_contract].to_s <<
22
+ attributes[:allowed_methods].to_s << attributes[:blocked_methods].to_s <<
23
+ attributes[:shopper_statement].to_s << attributes[:billing_address_type].to_s
24
+ end
25
+
26
+ def self.calculate_signature(attributes)
27
+ Adyen::Encoding.hmac_base64(attributes.delete(:shared_secret), calculate_signature_string(attributes))
28
+ end
29
+
30
+ def self.do_attribute_transformations!(attributes = {})
31
+ raise "YENs are not yet supported!" if attributes[:currency_code] == 'JPY' # TODO: fixme
32
+
33
+ attributes[:recurring_contract] = 'DEFAULT' if attributes.delete(:recurring) == true
34
+ attributes[:order_data] = Adyen::Encoding.gzip_base64(attributes.delete(:order_data_raw)) if attributes[:order_data_raw]
35
+ attributes[:ship_before_date] = Adyen::Formatter::DateTime.fmt_date(attributes[:ship_before_date])
36
+ attributes[:session_validity] = Adyen::Formatter::DateTime.fmt_time(attributes[:session_validity])
37
+ end
38
+
39
+ def self.hidden_fields(attributes = {})
40
+ do_attribute_transformations!(attributes)
41
+
42
+ raise "Cannot generate form: :currency code attribute not found!" unless attributes[:currency_code]
43
+ raise "Cannot generate form: :payment_amount code attribute not found!" unless attributes[:payment_amount]
44
+ raise "Cannot generate form: :merchant_account attribute not found!" unless attributes[:merchant_account]
45
+ raise "Cannot generate form: :skin_code attribute not found!" unless attributes[:skin_code]
46
+ raise "Cannot generate form: :shared_secret signing secret not provided!" unless attributes[:shared_secret]
47
+
48
+ # Merchant signature
49
+ attributes[:merchant_sig] = calculate_signature(attributes)
50
+
51
+ # Generate hidden input tags
52
+ attributes.map { |key, value|
53
+ self.tag(:input, :type => 'hidden', :name => key.to_s.camelize(:lower), :value => value)
54
+ }.join("\n")
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,105 @@
1
+ require 'xml'
2
+
3
+ module Adyen
4
+ module Matchers
5
+
6
+ module XPathPaymentFormCheck
7
+
8
+ def self.build_xpath_query(checks)
9
+ # Start by finding the check for the Adyen form tag
10
+ xpath_query = "//form[@action='#{Adyen::Form.url}']"
11
+
12
+ # Add recurring/single check if specified
13
+ recurring = checks.delete(:recurring)
14
+ unless recurring.nil?
15
+ if recurring
16
+ xpath_query << "[descendant::input[@type='hidden'][@name='recurringContract']]"
17
+ else
18
+ xpath_query << "[not(descendant::input[@type='hidden'][@name='recurringContract'])]"
19
+ end
20
+ end
21
+
22
+ # Add a check for all the other fields specified
23
+ checks.each do |key, value|
24
+ condition = "descendant::input[@type='hidden'][@name='#{key.to_s.camelize(:lower)}']"
25
+ condition << "[@value='#{value}']" unless value == :anything
26
+ xpath_query << "[#{condition}]"
27
+ end
28
+
29
+ return xpath_query
30
+ end
31
+
32
+ def self.document(subject)
33
+ if String === subject
34
+ XML::HTMLParser.string(subject).parse
35
+ elsif subject.respond_to?(:body)
36
+ XML::HTMLParser.string(subject.body).parse
37
+ elsif XML::Node === subject
38
+ subject
39
+ elsif XML::Document === subject
40
+ subject
41
+ else
42
+ raise "Cannot handle this XML input type"
43
+ end
44
+ end
45
+
46
+ def self.check(subject, checks = {})
47
+ document(subject).find_first(build_xpath_query(checks))
48
+ end
49
+ end
50
+
51
+ class HaveAdyenPaymentForm
52
+
53
+ def initialize(checks)
54
+ @checks = checks
55
+ end
56
+
57
+ def matches?(document)
58
+ Adyen::Matchers::XPathPaymentFormCheck.check(document, @checks)
59
+ end
60
+
61
+ def description
62
+ "have an adyen payment form"
63
+ end
64
+
65
+ def failure_message
66
+ "expected to find a valid Adyen form on this page"
67
+ end
68
+
69
+ def negative_failure_message
70
+ "expected not to find a valid Adyen form on this page"
71
+ end
72
+ end
73
+
74
+ def have_adyen_payment_form(checks = {})
75
+ default_checks = {:merchant_sig => :anything, :payment_amount => :anything, :currency_code => :anything, :skin_code => :anything }
76
+ HaveAdyenPaymentForm.new(default_checks.merge(checks))
77
+ end
78
+
79
+ def have_adyen_recurring_payment_form(checks = {})
80
+ recurring_checks = { :recurring => true, :shopper_email => :anything, :shopper_reference => :anything }
81
+ have_adyen_payment_form(recurring_checks.merge(checks))
82
+ end
83
+
84
+ def have_adyen_single_payment_form(checks = {})
85
+ recurring_checks = { :recurring => false }
86
+ have_adyen_payment_form(recurring_checks.merge(checks))
87
+ end
88
+
89
+ def assert_adyen_payment_form(subject, checks = {})
90
+ default_checks = {:merchant_sig => :anything, :payment_amount => :anything, :currency_code => :anything, :skin_code => :anything }
91
+ assert Adyen::Matchers::XPathPaymentFormCheck.check(subject, default_checks.merge(checks)), 'No Adyen payment form found'
92
+ end
93
+
94
+ def assert_adyen_recurring_payment_form(subject, checks = {})
95
+ recurring_checks = { :recurring => true, :shopper_email => :anything, :shopper_reference => :anything }
96
+ assert_adyen_payment_form(subject, recurring_checks.merge(checks))
97
+ end
98
+
99
+ def assert_adyen_single_payment_form(subject, checks = {})
100
+ recurring_checks = { :recurring => false }
101
+ assert_adyen_payment_form(subject, recurring_checks.merge(checks))
102
+ end
103
+
104
+ end
105
+ end
data/spec/form_spec.rb ADDED
@@ -0,0 +1,88 @@
1
+ require "#{File.dirname(__FILE__)}/spec_helper.rb"
2
+
3
+ describe Adyen::Form do
4
+
5
+ describe 'Action URLs' do
6
+
7
+ before(:each) do
8
+ # Use autodetection for the environment unless otherwise specified
9
+ Adyen.environment = nil
10
+ end
11
+
12
+ it "should generate correct the testing url" do
13
+ Adyen::Form.url.should eql('https://test.adyen.com/hpp/select.shtml')
14
+ end
15
+
16
+ it "should generate a live url if the environemtn is set top live" do
17
+ Adyen.environment = :live
18
+ Adyen::Form.url.should eql('https://live.adyen.com/hpp/select.shtml')
19
+ end
20
+
21
+ it "should generate correct live url in a production environment" do
22
+ Adyen.stub!(:autodetect_environment).and_return('live')
23
+ Adyen::Form.url.should eql('https://live.adyen.com/hpp/select.shtml')
24
+ end
25
+
26
+ it "should generate correct live url if explicitely asked for" do
27
+ Adyen::Form.url(:live).should eql('https://live.adyen.com/hpp/select.shtml')
28
+ end
29
+ end
30
+
31
+ describe 'hidden fields generation' do
32
+
33
+ include ActionView::Helpers::TagHelper
34
+
35
+ before(:each) do
36
+ @attributes = { :currency_code => 'GBP', :payment_amount => 10000, :ship_before_date => Date.today,
37
+ :merchant_reference => 'Internet Order 12345', :skin_code => '4aD37dJA',
38
+ :merchant_account => 'TestMerchant', :session_validity => 1.hour.from_now }
39
+ end
40
+
41
+ it "should generate a valid payment form" do
42
+ content_tag(:form, Adyen::Form.hidden_fields(@attributes.merge(:shared_secret => 'secret')),
43
+ :action => Adyen::Form.url, :method => :post).should have_adyen_payment_form
44
+ end
45
+ end
46
+
47
+ describe 'signature calculation' do
48
+
49
+ # This example is taken from the Adyen integration manual
50
+
51
+ before(:each) do
52
+ @attributes = { :currency_code => 'GBP', :payment_amount => 10000,
53
+ :ship_before_date => '2007-10-20', :merchant_reference => 'Internet Order 12345',
54
+ :skin_code => '4aD37dJA', :merchant_account => 'TestMerchant',
55
+ :session_validity => '2007-10-11T11:00:00Z' }
56
+
57
+ Adyen::Form.do_attribute_transformations!(@attributes)
58
+ end
59
+
60
+ it "should construct the signature string correctly" do
61
+ signature_string = Adyen::Form.calculate_signature_string(@attributes)
62
+ signature_string.should eql("10000GBP2007-10-20Internet Order 123454aD37dJATestMerchant2007-10-11T11:00:00Z")
63
+ end
64
+
65
+ it "should calculate the signature correctly" do
66
+ signature = Adyen::Form.calculate_signature(@attributes.merge(:shared_secret => 'Kah942*$7sdp0)'))
67
+ signature.should eql('x58ZcRVL1H6y+XSeBGrySJ9ACVo=')
68
+ end
69
+
70
+ it "should calculate the signature correctly for a recurring payment" do
71
+ # Add the required recurrent payment attributes
72
+ @attributes.merge!(:recurring_contract => 'DEFAULT', :shopper_reference => 'grasshopper52', :shopper_email => 'gras.shopper@somewhere.org')
73
+
74
+ signature_string = Adyen::Form.calculate_signature_string(@attributes)
75
+ signature_string.should eql("10000GBP2007-10-20Internet Order 123454aD37dJATestMerchant2007-10-11T11:00:00Zgras.shopper@somewhere.orggrasshopper52DEFAULT")
76
+ end
77
+
78
+ it "should calculate the signature correctly for a recurring payment" do
79
+ # Add the required recurrent payment attributes
80
+ @attributes.merge!(:recurring_contract => 'DEFAULT', :shopper_reference => 'grasshopper52', :shopper_email => 'gras.shopper@somewhere.org')
81
+
82
+ signature = Adyen::Form.calculate_signature(@attributes.merge(:shared_secret => 'Kah942*$7sdp0)'))
83
+ signature.should eql('F2BQEYbE+EUhiRGuPtcD16Gm7JY=')
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -0,0 +1,11 @@
1
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'rubygems'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ require 'adyen'
8
+
9
+ Spec::Runner.configure do |config|
10
+ config.include Adyen::Matchers
11
+ end
@@ -0,0 +1,255 @@
1
+ require 'rubygems'
2
+ require 'rubyforge'
3
+ require 'rake'
4
+ require 'rake/tasklib'
5
+ require 'date'
6
+
7
+ module Rake
8
+
9
+ class GithubGem < TaskLib
10
+
11
+ attr_accessor :name
12
+ attr_accessor :specification
13
+
14
+ def self.define_tasks!
15
+ gem_task_builder = Rake::GithubGem.new
16
+ gem_task_builder.register_all_tasks!
17
+ end
18
+
19
+
20
+ def initialize
21
+ reload_gemspec!
22
+ end
23
+
24
+ def register_all_tasks!
25
+ namespace(:gem) do
26
+ desc "Updates the file lists for this gem"
27
+ task(:manifest) { manifest_task }
28
+
29
+ desc "Releases a new version of #{@name}"
30
+ task(:build => [:manifest]) { build_task }
31
+
32
+
33
+ release_dependencies = [:check_clean_master_branch, :version, :build, :create_tag]
34
+ release_dependencies.push 'doc:publish' if generate_rdoc?
35
+ release_dependencies.unshift 'test' if has_tests?
36
+ release_dependencies.unshift 'spec' if has_specs?
37
+
38
+ desc "Releases a new version of #{@name}"
39
+ task(:release => release_dependencies) { release_task }
40
+
41
+ # helper task for releasing
42
+ task(:check_clean_master_branch) { verify_clean_status('master') }
43
+ task(:check_version) { verify_version(ENV['VERSION'] || @specification.version) }
44
+ task(:version => [:check_version]) { set_gem_version! }
45
+ task(:create_tag) { create_version_tag! }
46
+ end
47
+
48
+ # Register RDoc tasks
49
+ if generate_rdoc?
50
+ require 'rake/rdoctask'
51
+
52
+ namespace(:doc) do
53
+ desc 'Generate documentation for request-log-analyzer'
54
+ Rake::RDocTask.new(:compile) do |rdoc|
55
+ rdoc.rdoc_dir = 'doc'
56
+ rdoc.title = @name
57
+ rdoc.options += @specification.rdoc_options
58
+ rdoc.rdoc_files.include(@specification.extra_rdoc_files)
59
+ rdoc.rdoc_files.include('lib/**/*.rb')
60
+ end
61
+
62
+ desc "Publish RDoc files for #{@name} to Github"
63
+ task(:publish => :compile) do
64
+ sh 'git checkout gh-pages'
65
+ sh 'git pull origin gh-pages'
66
+ sh 'cp -rf doc/* .'
67
+ sh "git commit -am \"Publishing newest RDoc documentation for #{@name}\""
68
+ sh "git push origin gh-pages"
69
+ sh "git checkout master"
70
+ end
71
+ end
72
+ end
73
+
74
+ # Setup :spec task if RSpec files exist
75
+ if has_specs?
76
+ require 'spec/rake/spectask'
77
+
78
+ desc "Run all specs for #{@name}"
79
+ Spec::Rake::SpecTask.new(:spec) do |t|
80
+ t.spec_files = FileList[File.dirname(__FILE__) + '/../spec/**/*_spec.rb']
81
+ end
82
+ end
83
+
84
+ # Setup :test task if unit test files exist
85
+ if has_tests?
86
+ require 'rake/testtask'
87
+
88
+ desc "Run all unit tests for #{@name}"
89
+ Rake::TestTask.new(:test) do |t|
90
+ t.pattern = File.dirname(__FILE__) + '/../test/**/*_test.rb'
91
+ t.verbose = true
92
+ t.libs << 'test'
93
+ end
94
+ end
95
+ end
96
+
97
+ protected
98
+
99
+ def generate_rdoc?
100
+ git_branch_exists?('gh-pages')
101
+ end
102
+
103
+ def has_specs?
104
+ Dir[File.dirname(__FILE__) + '/../spec/**/*_spec.rb'].any?
105
+ end
106
+
107
+ def has_tests?
108
+ Dir[File.dirname(__FILE__) + '/../test/**/*_test.rb'].any?
109
+ end
110
+
111
+ def reload_gemspec!
112
+ raise "No gemspec file found!" if gemspec_file.nil?
113
+ spec = File.read(gemspec_file)
114
+ @specification = eval(spec)
115
+ @name = specification.name
116
+ end
117
+
118
+ def run_command(command)
119
+ lines = []
120
+ IO.popen(command) { |f| lines = f.readlines }
121
+ return lines
122
+ end
123
+
124
+ def git_modified?(file)
125
+ return !run_command('git status').detect { |line| Regexp.new(Regexp.quote(file)) =~ line }.nil?
126
+ end
127
+
128
+ def git_commit_file(file, message, branch = nil)
129
+ verify_current_branch(branch) unless branch.nil?
130
+ if git_modified?(file)
131
+ sh "git add #{file}"
132
+ sh "git commit -m \"#{message}\""
133
+ else
134
+ raise "#{file} is not modified and cannot be committed!"
135
+ end
136
+ end
137
+
138
+ def git_create_tag(tag_name, message)
139
+ sh "git tag -a \"#{tag_name}\" -m \"#{message}\""
140
+ end
141
+
142
+ def git_push(remote = 'origin', branch = 'master', options = [])
143
+ verify_clean_status(branch)
144
+ options_str = options.map { |o| "--#{o}"}.join(' ')
145
+ sh "git push #{options_str} #{remote} #{branch}"
146
+ end
147
+
148
+ def gemspec_version=(new_version)
149
+ spec = File.read(gemspec_file)
150
+ spec.gsub!(/^(\s*s\.version\s*=\s*)('|")(.+)('|")(\s*)$/) { "#{$1}'#{new_version}'#{$5}" }
151
+ spec.gsub!(/^(\s*s\.date\s*=\s*)('|")(.+)('|")(\s*)$/) { "#{$1}'#{Date.today.strftime('%Y-%m-%d')}'#{$5}" }
152
+ File.open(gemspec_file, 'w') { |f| f << spec }
153
+ reload_gemspec!
154
+ end
155
+
156
+ def gemspec_date=(new_date)
157
+ spec = File.read(gemspec_file)
158
+ spec.gsub!(/^(\s*s\.date\s*=\s*)('|")(.+)('|")(\s*)$/) { "#{$1}'#{new_date.strftime('%Y-%m-%d')}'#{$5}" }
159
+ File.open(gemspec_file, 'w') { |f| f << spec }
160
+ reload_gemspec!
161
+ end
162
+
163
+ def gemspec_file
164
+ @gemspec_file ||= Dir[File.dirname(__FILE__) + '/../*.gemspec'].first
165
+ end
166
+
167
+ def git_branch_exists?(branch_name)
168
+ branches = run_command('git branch').map { |line| /^\*?\s+(\w+)/ =~ line; $1 }
169
+ branches.include?(branch_name.to_s)
170
+ end
171
+
172
+ def verify_current_branch(branch)
173
+ run_command('git branch').detect { |line| /^\* (.+)/ =~ line }
174
+ raise "You are currently not working in the master branch!" unless branch == $1
175
+ end
176
+
177
+ def verify_clean_status(on_branch = nil)
178
+ sh "git fetch"
179
+ lines = run_command('git status')
180
+ raise "You don't have the most recent version available. Run git pull first." if /^\# Your branch is behind/ =~ lines[1]
181
+ raise "You are currently not working in the #{on_branch} branch!" unless on_branch.nil? || (/^\# On branch (.+)/ =~ lines.first && $1 == on_branch)
182
+ raise "Your master branch contains modifications!" unless /^nothing to commit \(working directory clean\)/ =~ lines.last
183
+ end
184
+
185
+ def verify_version(new_version)
186
+ newest_version = run_command('git tag').map { |tag| tag.split(name + '-').last }.compact.map { |v| Gem::Version.new(v) }.max
187
+ raise "This version number (#{new_version}) is not higher than the highest tagged version (#{newest_version})" if !newest_version.nil? && newest_version >= Gem::Version.new(new_version.to_s)
188
+ end
189
+
190
+ def set_gem_version!
191
+ # update gemspec file
192
+ self.gemspec_version = ENV['VERSION'] if Gem::Version.correct?(ENV['VERSION'])
193
+ self.gemspec_date = Date.today
194
+ end
195
+
196
+ def manifest_task
197
+ verify_current_branch('master')
198
+
199
+ list = Dir['**/*'].sort
200
+ list -= [gemspec_file]
201
+
202
+ if File.exist?('.gitignore')
203
+ File.read('.gitignore').each_line do |glob|
204
+ glob = glob.chomp.sub(/^\//, '')
205
+ list -= Dir[glob]
206
+ list -= Dir["#{glob}/**/*"] if File.directory?(glob) and !File.symlink?(glob)
207
+ end
208
+ end
209
+
210
+ # update the spec file
211
+ spec = File.read(gemspec_file)
212
+ spec.gsub! /^(\s* s.(test_)?files \s* = \s* )( \[ [^\]]* \] | %w\( [^)]* \) )/mx do
213
+ assignment = $1
214
+ bunch = $2 ? list.grep(/^(test.*_test\.rb|spec.*_spec.rb)$/) : list
215
+ '%s%%w(%s)' % [assignment, bunch.join(' ')]
216
+ end
217
+
218
+ File.open(gemspec_file, 'w') { |f| f << spec }
219
+ reload_gemspec!
220
+ end
221
+
222
+ def build_task
223
+ sh "gem build #{gemspec_file}"
224
+ Dir.mkdir('pkg') unless File.exist?('pkg')
225
+ sh "mv #{name}-#{specification.version}.gem pkg/#{name}-#{specification.version}.gem"
226
+ end
227
+
228
+ def install_task
229
+ raise "#{name} .gem file not found" unless File.exist?("pkg/#{name}-#{specification.version}.gem")
230
+ sh "gem install pkg/#{name}-#{specification.version}.gem"
231
+ end
232
+
233
+ def uninstall_task
234
+ raise "#{name} .gem file not found" unless File.exist?("pkg/#{name}-#{specification.version}.gem")
235
+ sh "gem uninstall #{name}"
236
+ end
237
+
238
+ def create_version_tag!
239
+ # commit the gemspec file
240
+ git_commit_file(gemspec_file, "Updated #{gemspec_file} for release of version #{@specification.version}") if git_modified?(gemspec_file)
241
+
242
+ # create tag and push changes
243
+ git_create_tag("#{@name}-#{@specification.version}", "Tagged version #{@specification.version}")
244
+ git_push('origin', 'master', [:tags])
245
+ end
246
+
247
+ def release_task
248
+ puts
249
+ puts '------------------------------------------------------------'
250
+ puts "Released #{@name} - version #{@specification.version}"
251
+ end
252
+ end
253
+ end
254
+
255
+ Rake::GithubGem.define_tasks!
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wvanbergen-adyen
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Willem van Bergen
8
+ - Michel Barbosa
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-08-06 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ type: :development
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ description: Package to simplify including the Adyen payments services into a Ruby on Rails application.
27
+ email:
28
+ - willem@vanbergen.org
29
+ - cicaboo@gmail.com
30
+ executables: []
31
+
32
+ extensions: []
33
+
34
+ extra_rdoc_files:
35
+ - README.rdoc
36
+ files:
37
+ - LICENSE
38
+ - README.rdoc
39
+ - Rakefile
40
+ - init.rb
41
+ - lib
42
+ - lib/adyen
43
+ - lib/adyen.rb
44
+ - lib/adyen/form.rb
45
+ - lib/adyen/matchers.rb
46
+ - spec
47
+ - spec/form_spec.rb
48
+ - spec/spec_helper.rb
49
+ - tasks
50
+ - tasks/github-gem.rake
51
+ has_rdoc: false
52
+ homepage: http://www.adyen.com
53
+ licenses:
54
+ post_install_message:
55
+ rdoc_options:
56
+ - --title
57
+ - adyen
58
+ - --main
59
+ - README.rdoc
60
+ - --line-numbers
61
+ - --inline-source
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.5
80
+ signing_key:
81
+ specification_version: 2
82
+ summary: Integrate Adyen payment services in you Ruby on Rails application
83
+ test_files:
84
+ - spec/form_spec.rb