wvanbergen-adyen 0.0.1

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