wirecardmapper 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -2,6 +2,44 @@
2
2
 
3
3
  A Ruby Object Mapper for Wirecard XML interface
4
4
 
5
+ == Compatibility
6
+
7
+ wirecardmapper is tested against Ruby 1.9.2 .
8
+
9
+ {<img src="http://travis-ci.org/aklaiber/wirecardmapper.png" />}[http://travis-ci.org/aklaiber/wirecardmapper]
10
+
11
+ == Install
12
+
13
+ $ gem install wirecardmapper
14
+
15
+ or add the following line to Gemfile:
16
+
17
+ gem 'wirecardmapper'
18
+
19
+ and run bundle install from your shell.
20
+
21
+ == Examples
22
+
23
+ === Config
24
+
25
+ WirecardMapper::Config.server_uri = "https://c3-test.wirecard.com/issuer/client"
26
+ WirecardMapper::Config.server_port = 443
27
+ WirecardMapper::Config.login = "login"
28
+ WirecardMapper::Config.password = "password"
29
+ WirecardMapper::Config.mode = "live"
30
+ WirecardMapper::Config.entity_id = "entity_id"
31
+ WirecardMapper::Config.product_id = 11
32
+
33
+ === How to use
34
+
35
+ WirecardMapper.create_card
36
+ WirecardMapper.card_info(:card_id => '47ae07020a010018157db66065da6e5c')
37
+ WirecardMapper.update_card_info(:card_id => '47ae07020a010018157db66065da6e5c')
38
+ WirecardMapper.submit_payment(:card_id => '47ae07020a010018157db66065da6e5c', :amount => 10, :payment_comment => "Test Comment")
39
+ WirecardMapper.submit_payment(:card_id => '47ae07020a010018157db66065da6e5c', :amount => -10, :payment_comment => "Test Comment")
40
+ WirecardMapper.payment_info(:card_id => '47ae07020a010018157db66065da6e5c', :from => Time.now - (24 * 3600), :to => Time.now)
41
+ WirecardMapper.change_card_status(:card_id => '47ae07020a010018157db66065da6e5c', :status_code => 'cancelled')
42
+
5
43
  == Note on Patches/Pull Requests
6
44
 
7
45
  * Fork the project.
@@ -10,14 +48,25 @@ A Ruby Object Mapper for Wirecard XML interface
10
48
  * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself in another branch so I can ignore when I pull)
11
49
  * Send me a pull request. Bonus points for topic branches.
12
50
 
13
- == Install
14
-
15
- $ gem install wirecardmapper
51
+ == Copyright
16
52
 
17
- == Port Tunnel
53
+ Copyright (c) 2010 Alexander Klaiber
18
54
 
19
- ssh tunnelserver1 -L localhost:8080:wirecardserver:443
55
+ Permission is hereby granted, free of charge, to any person obtaining
56
+ a copy of this software and associated documentation files (the
57
+ "Software"), to deal in the Software without restriction, including
58
+ without limitation the rights to use, copy, modify, merge, publish,
59
+ distribute, sublicense, and/or sell copies of the Software, and to
60
+ permit persons to whom the Software is furnished to do so, subject to
61
+ the following conditions:
20
62
 
21
- == Copyright
63
+ The above copyright notice and this permission notice shall be
64
+ included in all copies or substantial portions of the Software.
22
65
 
23
- See LICENSE for details.
66
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
67
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
69
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
70
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
71
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
72
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,24 +1,21 @@
1
- require 'rubygems'
2
-
3
- require 'rake'
4
- require 'rake/rdoctask'
5
-
1
+ require 'bundler'
6
2
  require "rspec"
7
- require "rspec/core/rake_task"
3
+ require 'rspec/core/rake_task'
8
4
 
9
- require File.expand_path('../lib/wirecardmapper/version', __FILE__)
5
+ Bundler::GemHelper.install_tasks
10
6
 
11
- Rake::RDocTask.new do |rdoc|
12
- files =['README.rdoc', 'LICENSE', 'lib/**/*.rb']
13
- rdoc.rdoc_files.add(files)
14
- rdoc.main = "README.rdoc" # page to start on
15
- rdoc.title = "wirecardmapper Docs"
16
- rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
17
- rdoc.options << '--line-numbers'
18
- end
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ namespace :spec do
10
+ desc "Run the code examples in spec/unit"
11
+ RSpec::Core::RakeTask.new('unit') do |t|
12
+ t.pattern = 'spec/unit/**/*_spec.rb'
13
+ end
19
14
 
20
- Rspec::Core::RakeTask.new(:spec) do |spec|
21
- spec.pattern = "spec/**/*_spec.rb"
15
+ desc "Run the code examples in spec/functional"
16
+ RSpec::Core::RakeTask.new('functional') do |t|
17
+ t.pattern = 'spec/functional/*_spec.rb'
18
+ end
22
19
  end
23
20
 
24
21
  namespace :wirecard do
@@ -27,16 +24,3 @@ namespace :wirecard do
27
24
  sh "ssh test.freecent.com -L localhost:8080:c3-test.wirecard.com:443"
28
25
  end
29
26
  end
30
-
31
- desc 'Builds the gem'
32
- task :build do
33
- sh "gem build wirecardmapper.gemspec"
34
- end
35
-
36
- desc 'Tags version, pushes to remote, and pushes gem'
37
- task :release => [:spec, :build] do
38
- sh "git tag v#{WirecardMapper::Version}"
39
- sh "git push origin master"
40
- sh "git push origin v#{WirecardMapper::Version}"
41
- sh "gem push wirecardmapper-#{WirecardMapper::Version}.gem"
42
- end
@@ -1,52 +1,111 @@
1
- require "rubygems"
2
1
  require "bundler/setup"
3
2
 
4
- require 'net/https'
3
+ require "active_support/core_ext"
4
+ require "net/https"
5
5
  require "base64"
6
- require 'nokogiri'
7
- require 'uuid'
6
+ require "nokogiri"
7
+ require "uuid"
8
+ require "time"
9
+ require "money"
8
10
 
9
- require 'wirecardmapper/net_http_monkeypatch'
11
+ require "wirecardmapper/railtie" if defined?(Rails)
12
+ require "wirecardmapper/exception"
13
+ require "wirecardmapper/config"
14
+ require "wirecardmapper/response"
15
+
16
+ require 'wirecardmapper/models/base'
17
+ require 'wirecardmapper/models/mongo_mapper'
10
18
 
11
19
  module WirecardMapper
12
- autoload :Config, 'wirecardmapper/config'
13
- autoload :Xml, 'wirecardmapper/xml'
14
- autoload :Response, 'wirecardmapper/response'
15
20
 
16
- extend Xml
21
+ private
22
+
23
+ def self.define_request(name, options = {:default => {}})
24
+ define_singleton_method("#{name}_request") do |params = {}|
25
+ build_request(options[:request_method].blank? ? name : options[:request_method], options[:default].blank? ? params : options[:default].deep_merge(params))
26
+ end
27
+ end
28
+
29
+ public
30
+
31
+ define_request :create_card, :default => {:product_data => {:product_id => lambda { Config.product_id }}, :card_data => nil}
17
32
 
18
33
  def self.create_card(params = {})
19
- request("create_card", params)
34
+ self.post(self.create_card_request(params))
20
35
  end
21
36
 
22
- def self.update_card_info(params = {})
23
- request("update_card_info", params)
37
+ define_request :card_info, :request_method => 'get_card_info'
38
+
39
+ def self.card_info(card_id, params = {})
40
+ self.post(self.card_info_request({:card_data => {:card_id => card_id}}.deep_merge(params)))
41
+ end
42
+
43
+ define_request :update_card_info
44
+
45
+ def self.update_card_info(card_id, params = {})
46
+ self.post(self.update_card_info_request({:card_data => {:card_id => card_id}}.deep_merge(params)))
24
47
  end
25
48
 
26
- def self.card_info(params = {})
27
- request("get_card_info", params)
49
+ define_request :payment_info, :request_method => 'get_payment_info'
50
+
51
+ def self.payment_info(card_id, params = {})
52
+ self.post(self.payment_info_request(params.deep_merge(:card_data => {:card_id => card_id})))
28
53
  end
29
54
 
30
- def self.submit_payment(params = {})
31
- request("submit_payment", params)
55
+ define_request :change_card_status
56
+
57
+ def self.change_card_status(card_id, params = {})
58
+ self.post(self.change_card_status_request(params.deep_merge(:card_data => {:card_id => card_id})))
32
59
  end
33
60
 
34
- def self.payment_info(params = {})
35
- request("get_payment_info", params)
61
+ define_request :submit_payment
62
+
63
+ def self.submit_payment(card_id, params = {})
64
+ self.post(self.submit_payment_request(params.deep_merge(:card_data => {:card_id => card_id})))
36
65
  end
37
66
 
38
- def self.change_card_status(params = {})
39
- request("change_card_status", params)
67
+ private
68
+
69
+ def self.build_request(method, params)
70
+ builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
71
+ xml.send('issuer-request', :mode => Config.mode, :version => '1.0') do
72
+ xml.application do
73
+ xml.send('request-id', UUID.generate)
74
+ if params[:entity_id].present?
75
+ xml.send('entity-id', params[:entity_id])
76
+ params.delete(:entity_id)
77
+ else
78
+ xml.send('entity-id', Config.entity_id)
79
+ end
80
+ end
81
+ xml.send(method.to_s.gsub(/_/, '-')) do
82
+ self.build_request_method_params(xml, params) unless params.blank?
83
+ end
84
+ end
85
+ end
86
+ builder.to_xml
40
87
  end
41
88
 
42
- def self.request(xml_request_name, params)
43
- main_xml = self.main_xml
44
- if main_xml
45
- sub_xml("#{xml_request_name}.xml", params) do |xml|
46
- main_xml.at_css('issuer-request').add_child(xml.at(xml_request_name.to_s.gsub(/_/,'-')))
89
+ def self.build_request_method_params(xml, params)
90
+ params.each do |key, value|
91
+ if value.kind_of?(Hash)
92
+ if value.include?(:text) || value.include?(:attributes)
93
+ xml.send(key.to_s.gsub(/_/, '-'), value[:attributes]) do
94
+ xml.text value[:text]
95
+ end
96
+ else
97
+ xml.send(key.to_s.gsub(/_/, '-')) do
98
+ self.build_request_method_params(xml, value)
99
+ end
100
+ end
101
+ else
102
+ if value.kind_of?(Proc)
103
+ xml.send(key.to_s.gsub(/_/, '-'), value.call)
104
+ else
105
+ xml.send(key.to_s.gsub(/_/, '-'), value)
106
+ end
47
107
  end
48
108
  end
49
- return post(main_xml.to_s)
50
109
  end
51
110
 
52
111
  def self.post(xml)
@@ -54,7 +113,9 @@ module WirecardMapper
54
113
  unless uri.nil?
55
114
  http = Net::HTTP.new(uri.host, Config.server_port)
56
115
  if http
116
+ http.read_timeout = 30
57
117
  http.use_ssl = true
118
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
58
119
  request = Net::HTTP::Post.new(uri.path)
59
120
  if request
60
121
  request.content_type = "text/xml"
@@ -63,10 +124,15 @@ module WirecardMapper
63
124
  request.body = xml
64
125
  response = http.request(request)
65
126
  if response
66
- return WirecardMapper::Response.new(response.body)
127
+ response = WirecardMapper::Response.new(response.body)
128
+ if response.return_message.eql?("System error.")
129
+ raise WirecardMapper::Exception, "Wirecard-System error (#{WirecardMapper::Config.server_uri}) post response : #{response.return_message}"
130
+ end
131
+ return response
67
132
  end
68
133
  end
69
134
  end
70
135
  end
71
136
  end
137
+
72
138
  end
@@ -2,10 +2,19 @@ module WirecardMapper
2
2
  module Config
3
3
 
4
4
  class << self
5
- attr_accessor :mode, :entity_id, :server_uri, :login, :password, :product_id
5
+ attr_accessor :mode, :entity_id, :server_uri, :login, :password, :product_id, :currency
6
+
6
7
  attr_writer :templates_path, :server_port
7
8
  end
8
-
9
+
10
+ def self.config=(config)
11
+ config.each { |method, value| self.send("#{method}=", value) if self.respond_to?(method) }
12
+ end
13
+
14
+ def self.config
15
+ yield self
16
+ end
17
+
9
18
  def self.templates_path
10
19
  @templates_path ||= "#{File.dirname(__FILE__)}/../../templates/"
11
20
  end
@@ -13,6 +22,6 @@ module WirecardMapper
13
22
  def self.server_port
14
23
  @server_port ||= 443
15
24
  end
16
-
25
+
17
26
  end
18
27
  end
@@ -0,0 +1,5 @@
1
+ module WirecardMapper
2
+ class Exception < RuntimeError
3
+
4
+ end
5
+ end
@@ -0,0 +1,117 @@
1
+ module WirecardMapper
2
+ module Model
3
+ module Base
4
+
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def product_id(product_id = nil)
9
+ if product_id.present?
10
+ @product_id = product_id
11
+ else
12
+ @product_id
13
+ end
14
+ end
15
+
16
+ def entity_id(entity_id = nil)
17
+ if entity_id.present?
18
+ @entity_id = entity_id
19
+ else
20
+ @entity_id
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.status_writer(*args)
26
+ args.each do |arg|
27
+ define_method("#{arg}!") do
28
+ response = WirecardMapper.change_card_status(self.card_id, {:entity_id => self.class.entity_id, :status_code => arg})
29
+ unless response.blank?
30
+ reload_card_info_cache
31
+ transaction_log("change_card_status", response)
32
+ raise WirecardMapper::Exception, "Wirecard-System[ERROR]: #{response.return_message}" unless response.ok?
33
+ end
34
+ return response
35
+ end
36
+ end
37
+ end
38
+
39
+ def self.status_reader(*args)
40
+ args.each do |arg|
41
+ define_method("#{arg}?") do
42
+ status.to_s.eql?(arg.to_s.gsub('_', '-'))
43
+ end
44
+ end
45
+ end
46
+
47
+ def self.card_attr_reader(*args)
48
+ args.each do |arg|
49
+ define_method(arg) do
50
+ card_info.send(arg)
51
+ end
52
+ end
53
+ end
54
+
55
+ public
56
+
57
+ attr_accessor :card_id
58
+
59
+ status_writer :activated, :blocked, :cancelled
60
+
61
+ status_reader :activated, :activation_pending, :activation_failed
62
+ status_reader :blocked, :block_requested, :block_pending, :block_failed
63
+ status_reader :cancelled, :cancellation_requested, :cancellation_pending, :cancellation_failed
64
+ status_reader :decline, :expired, :inactive, :referral
65
+
66
+ card_attr_reader :expiration_year, :expiration_month
67
+
68
+ public
69
+
70
+ def transaction_log(method_name, response)
71
+ end
72
+
73
+ def status
74
+ card_info.status_code
75
+ end
76
+
77
+ def balance
78
+ Money.euro(card_info.balance)
79
+ end
80
+
81
+ def load_amount(amount = self.amount.cents, comment = "load")
82
+ response = WirecardMapper.submit_payment(self.card_id, {:entity_id => self.class.entity_id, :payment_data => {:amount => {:text => amount, :attributes => {:currency => Config.currency}}, :payment_comment => comment}})
83
+ unless response.blank?
84
+ reload_card_info_cache
85
+ transaction_log("submit_payment - load_amount", response)
86
+ return response.ok?
87
+ end
88
+ return false
89
+ end
90
+
91
+ def unload_amount(amount = self.balance.cents, comment = "unload")
92
+ response = WirecardMapper.submit_payment(self.card_id, {:entity_id => self.class.entity_id,:payment_data => {:amount => {:text => -amount, :attributes => {:currency => Config.currency}}, :payment_comment => comment}})
93
+ unless response.blank?
94
+ reload_card_info_cache
95
+ transaction_log("submit_payment - unload_amount", response)
96
+ return response.ok?
97
+ end
98
+ return false
99
+ end
100
+
101
+ def amount
102
+ Money.euro(@amount)
103
+ end
104
+
105
+ private
106
+
107
+ def card_info
108
+ @card_info ||= WirecardMapper.card_info(self.card_id, {:entity_id => self.class.entity_id, :card_activity => 'no'})
109
+ end
110
+
111
+ def reload_card_info_cache
112
+ @card_info = nil
113
+ end
114
+
115
+ end
116
+ end
117
+ end