wirecardmapper 0.8.0 → 0.9.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.
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