mollie-ideal 0.1.0

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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Peter Berkenbosch
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.
@@ -0,0 +1,18 @@
1
+ = mollie-ideal
2
+
3
+ Ruby API for accessing the ideal interface for mollie.
4
+
5
+
6
+ == Note on Patches/Pull Requests
7
+
8
+ * Fork the project.
9
+ * Make your feature addition or bug fix.
10
+ * Add tests for it. This is important so I don't break it in a
11
+ future version unintentionally.
12
+ * Commit, do not mess with rakefile, version, or history.
13
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
14
+ * Send me a pull request. Bonus points for topic branches.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2010 Peter Berkenbosch. See LICENSE for details.
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "mollie-ideal"
8
+ gem.summary = %Q{Ruby API for iDEAL with Mollie}
9
+ gem.description = %Q{Ruby API for iDEAL with Mollie}
10
+ gem.email = "peter@pero-ict.nl"
11
+ gem.homepage = "http://github.com/pero-ict/mollie-ideal"
12
+ gem.authors = ["PeRo ICT Solutions"]
13
+ gem.add_dependency 'crack', '>= 0.1.4'
14
+ gem.add_dependency 'httparty', '>= 0.4.5'
15
+ gem.add_dependency 'mash', '>= 0.1.1'
16
+ gem.add_development_dependency 'fakeweb'
17
+ gem.add_development_dependency "rspec", ">= 1.2.9"
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
+ end
24
+
25
+ require 'spec/rake/spectask'
26
+ Spec::Rake::SpecTask.new(:spec) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.spec_files = FileList['spec/**/*_spec.rb']
29
+ end
30
+
31
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
32
+ spec.libs << 'lib' << 'spec'
33
+ spec.pattern = 'spec/**/*_spec.rb'
34
+ spec.rcov = true
35
+ end
36
+
37
+ task :spec => :check_dependencies
38
+
39
+ task :default => :spec
40
+
41
+ require 'rake/rdoctask'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "mollie-ideal #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,17 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+
3
+ begin; require 'rubygems'; rescue LoadError; end
4
+ require 'httparty'
5
+ require 'mash'
6
+
7
+ module Mollie
8
+
9
+ autoload :Ideal, 'mollie/ideal'
10
+ autoload :IdealResponse, 'mollie/ideal_response'
11
+ autoload :IdealException, 'mollie/ideal_exception'
12
+
13
+ class << self
14
+ attr_accessor :partner_id
15
+ end
16
+
17
+ end
@@ -0,0 +1,61 @@
1
+ module Mollie
2
+ class Ideal
3
+ include HTTParty
4
+ format :xml
5
+ base_uri "https://secure.mollie.nl"
6
+
7
+ class << self
8
+
9
+ attr_accessor :testmode
10
+
11
+ def banklist
12
+ options = {:a => "banklist"}
13
+ options.merge!({:testmode=>true}) if testmode
14
+ payload = send_command(options).payload
15
+
16
+ if payload.bank.class.name == "Mash"
17
+ #in testmode there is only 1 bank. This is not wrapped in an Array.
18
+ return [payload.bank]
19
+ elsif payload.bank.class.name == "Array"
20
+ #in production mode the list is an Array.
21
+ payload.bank
22
+ end
23
+ end
24
+
25
+ def prepare_payment(bank_id,amount,description,return_url,callback_url)
26
+
27
+ #callback_url is being called by mollie in the background. They add an GET parameter :transaction_id
28
+ #return_url is used after the payment is done. The redirection also adds the :transaction_id as an GET parameter
29
+ options = {
30
+ :a => "fetch",
31
+ :bank_id=>bank_id,
32
+ :description=>description,
33
+ :amount=>amount,
34
+ :reporturl=>callback_url,
35
+ :returnurl=>return_url,
36
+ :partnerid=>Mollie.partner_id
37
+ }
38
+
39
+ options.merge!({:testmode=>true}) if testmode
40
+ send_command(options).payload.order
41
+ end
42
+
43
+ def check_order(transaction_id)
44
+ options = {
45
+ :a => "check",
46
+ :partnerid=>Mollie.partner_id,
47
+ :transaction_id => transaction_id
48
+ }
49
+ options.merge!({:testmode=>true}) if testmode
50
+ send_command(options).payload.order
51
+ end
52
+
53
+
54
+ def send_command(options)
55
+ IdealResponse.new(Mash.new( get("/xml/ideal", :query=> options, :format=>:xml) ))
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,9 @@
1
+ module Mollie
2
+ class IdealException < Exception
3
+ attr_accessor :errorcode, :message
4
+ def initialize(errorcode, message="")
5
+ self.errorcode = errorcode
6
+ self.message = message
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ module Mollie
2
+ class IdealResponse
3
+
4
+ attr_accessor :payload
5
+
6
+ def initialize(xml_response)
7
+ self.payload = xml_response.response
8
+ raise Mollie::IdealException.new(errorcode, errormessage) if error_occured?
9
+ end
10
+
11
+ private
12
+ def error_occured?
13
+ payload.key?(:item) and payload.item.key?(:errorcode)
14
+ end
15
+
16
+ def errorcode
17
+ payload.item.errorcode.to_i if error_occured?
18
+ end
19
+
20
+ def errormessage
21
+ payload.item.message if error_occured?
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1 @@
1
+ irb -r rubygems -r lib/mollie.rb
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0"?>
2
+ <response>
3
+ <order>
4
+ <transaction_id>482d599bbcc7795727650330ad65fe9b</transaction_id>
5
+ <amount>1000</amount>
6
+ <currency>EUR</currency>
7
+ <payed>true</payed>
8
+ <consumer>
9
+ <consumerName>Hr J Janssen</consumerName>
10
+ <consumerAccount>P001234567</consumerAccount>
11
+ <consumerCity>Amsterdam</consumerCity>
12
+ </consumer>
13
+ <message>This iDEAL-order has successfuly been payed for, and this is the first time you check it.</message>
14
+ </order>
15
+ </response>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0"?>
2
+ <response>
3
+ <item type="error">
4
+ <errorcode>-1</errorcode>
5
+ <message>Did not receive a proper input value from you</message>
6
+ </item>
7
+ </response>
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0"?>
2
+ <response>
3
+ <order>
4
+ <transaction_id>482d599bbcc7795727650330ad65fe9b</transaction_id>
5
+ <amount>1000</amount>
6
+ <currency>EUR</currency>
7
+ <URL>https://mijn.postbank.nl/internetbankieren/SesamLoginServlet?sessie=ideal&trxid=003123456789123&random=123456789abcdefgh</URL>
8
+ <message>Your iDEAL-payment has succesfuly been setup. Your customer should visit the given URL to make the payment</message>
9
+ </order>
10
+ </response>
@@ -0,0 +1,5 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "MollieIdeal" do
4
+
5
+ end
@@ -0,0 +1,11 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Mollie::IdealResponse do
4
+
5
+ it "throws an IdealException when it receives an error response from mollie" do
6
+ file = File.read( File.expand_path(File.dirname(__FILE__) + '/../fixtures/errors/1.xml') )
7
+ response_mash = Mash.new( Crack::XML.parse(file) )
8
+ lambda {Mollie::IdealResponse.new(response_mash)}.should raise_error(Mollie::IdealException)
9
+ end
10
+
11
+ end
@@ -0,0 +1,99 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Mollie::Ideal do
4
+
5
+ it "is in live mode by default" do
6
+ Mollie::Ideal.testmode.should_not == true
7
+ end
8
+
9
+ it "send_command method returns an IdealResponse instance" do
10
+ options = {:a => "banklist", :testmode=>true}
11
+ options.merge!({:testmode=>true})
12
+ payload = Mollie::Ideal.send_command(options)
13
+ payload.class.name.should == "Mollie::IdealResponse"
14
+ end
15
+
16
+ describe "banklist command" do
17
+
18
+ it "returns an Array of available banks" do
19
+ Mollie::Ideal.testmode = true
20
+ banks = Mollie::Ideal.banklist
21
+ banks.class.name.should == "Array"
22
+ end
23
+
24
+ end
25
+
26
+ describe "prepare payment" do
27
+
28
+ before do
29
+ Mollie.partner_id = 123456
30
+ Mollie::Ideal.testmode = true
31
+ FakeWeb.allow_net_connect = false
32
+ FakeWeb.register_uri(
33
+ :get,
34
+ "https://secure.mollie.nl/xml/ideal?description=test%20payment&reporturl=http%3A%2F%2Fwww.postbin.org%2Fwyptsm&amount=1000&returnurl=http%3A%2F%2Fwww.postbin.org%2Fwyptsm&a=fetch&partnerid=123456&bank_id=9999&testmode=true",
35
+ :body => File.read( File.expand_path(File.dirname(__FILE__) + '/../fixtures/fetch_response.xml') )
36
+ )
37
+
38
+ end
39
+
40
+ after do
41
+ #to make sure the integration specs still work.
42
+ FakeWeb.allow_net_connect = true
43
+ end
44
+
45
+ it "returns order information" do
46
+
47
+ order_payload = Mollie::Ideal.prepare_payment(
48
+ 9999, #bank_id
49
+ 1000, #amount in cents, so this is 10.00
50
+ "test payment", #description
51
+ "http://www.postbin.org/wyptsm",
52
+ "http://www.postbin.org/wyptsm"
53
+ )
54
+
55
+ #save the transaction_id with the order that is payed.
56
+ order_payload.transaction_id.should == "482d599bbcc7795727650330ad65fe9b"
57
+ #redirect the user to the URL.
58
+ order_payload.URL.should == "https://mijn.postbank.nl/internetbankieren/SesamLoginServlet?sessie=ideal&trxid=003123456789123&random=123456789abcdefgh"
59
+ #this is for checking only..compare this with the order amount. When someone tries to fake an request with a lower amount.. raise an exception...for example.
60
+ order_payload.amount.should == "1000"
61
+ order_payload.currency.should == "EUR"
62
+
63
+ end
64
+
65
+
66
+ end
67
+
68
+ describe "check payment" do
69
+
70
+ before do
71
+ Mollie.partner_id = 123456
72
+ Mollie::Ideal.testmode = true
73
+ FakeWeb.allow_net_connect = false
74
+ FakeWeb.register_uri(
75
+ :get,
76
+ "https://secure.mollie.nl/xml/ideal?partnerid=123456&a=check&testmode=true&transaction_id=482d599bbcc7795727650330ad65fe9b",
77
+ :body => File.read( File.expand_path(File.dirname(__FILE__) + '/../fixtures/check_response.xml') )
78
+ )
79
+
80
+ end
81
+
82
+ after do
83
+ #to make sure the integration specs still work.
84
+ FakeWeb.allow_net_connect = true
85
+ end
86
+
87
+ it "returns the order with payed status" do
88
+
89
+ Mollie::Ideal.testmode = true
90
+ order_payload = Mollie::Ideal.check_order( "482d599bbcc7795727650330ad65fe9b" )
91
+
92
+ order_payload.transaction_id.should == "482d599bbcc7795727650330ad65fe9b"
93
+ order_payload.payed.should == "true"
94
+ order_payload.consumer.should_not be_nil
95
+
96
+ end
97
+
98
+ end
99
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'mollie-ideal'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+ require 'fakeweb'
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mollie-ideal
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - PeRo ICT Solutions
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-12 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: crack
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 1
30
+ - 4
31
+ version: 0.1.4
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: httparty
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 4
44
+ - 5
45
+ version: 0.4.5
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: mash
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ - 1
58
+ - 1
59
+ version: 0.1.1
60
+ type: :runtime
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: fakeweb
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ type: :development
73
+ version_requirements: *id004
74
+ - !ruby/object:Gem::Dependency
75
+ name: rspec
76
+ prerelease: false
77
+ requirement: &id005 !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ segments:
82
+ - 1
83
+ - 2
84
+ - 9
85
+ version: 1.2.9
86
+ type: :development
87
+ version_requirements: *id005
88
+ description: Ruby API for iDEAL with Mollie
89
+ email: peter@pero-ict.nl
90
+ executables: []
91
+
92
+ extensions: []
93
+
94
+ extra_rdoc_files:
95
+ - LICENSE
96
+ - README.rdoc
97
+ files:
98
+ - .document
99
+ - .gitignore
100
+ - LICENSE
101
+ - README.rdoc
102
+ - Rakefile
103
+ - VERSION
104
+ - lib/mollie-ideal.rb
105
+ - lib/mollie/ideal.rb
106
+ - lib/mollie/ideal_exception.rb
107
+ - lib/mollie/ideal_response.rb
108
+ - script/console
109
+ - spec/fixtures/check_response.xml
110
+ - spec/fixtures/errors/1.xml
111
+ - spec/fixtures/fetch_response.xml
112
+ - spec/mollie-ideal_spec.rb
113
+ - spec/mollie/ideal_response_spec.rb
114
+ - spec/mollie/ideal_spec.rb
115
+ - spec/spec.opts
116
+ - spec/spec_helper.rb
117
+ has_rdoc: true
118
+ homepage: http://github.com/pero-ict/mollie-ideal
119
+ licenses: []
120
+
121
+ post_install_message:
122
+ rdoc_options:
123
+ - --charset=UTF-8
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ segments:
131
+ - 0
132
+ version: "0"
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ segments:
138
+ - 0
139
+ version: "0"
140
+ requirements: []
141
+
142
+ rubyforge_project:
143
+ rubygems_version: 1.3.6
144
+ signing_key:
145
+ specification_version: 3
146
+ summary: Ruby API for iDEAL with Mollie
147
+ test_files:
148
+ - spec/mollie/ideal_response_spec.rb
149
+ - spec/mollie/ideal_spec.rb
150
+ - spec/mollie-ideal_spec.rb
151
+ - spec/spec_helper.rb