realex 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ pkg/*
@@ -0,0 +1,52 @@
1
+ # RealEx library for interfacing with www.realexpayments.com #
2
+
3
+ This is a Ruby library for interfacing with the RealEx API ( http://www.realexpayments.com )
4
+
5
+ ## Basic Usage ##
6
+
7
+ require 'realex'
8
+
9
+ RealEx::Config.shared_secret = 'YOUR SHARED SECRET'
10
+ RealEx::Config.merchant_id = 'YOUR MERCHANT ID'
11
+
12
+ card = RealEx::Card.new(:number => '4***************', :cvv => '509', :expiry_date => '0822', :cardholder_name => 'Paul Campbell', :type => 'VISA')
13
+
14
+ transaction = RealEx::Authorization.new(
15
+ :customer_number => 1234, :variable_reference => 1234,
16
+ :card => card, :amount => 500, :order_id => 12345, :currency => 'EUR', :autosettle => true)
17
+
18
+ transaction.comments << "Here's a comment"
19
+
20
+ transaction.to_xml
21
+
22
+ transaction.shipping_address = RealEx::Address.new(:type => 'shipping', :code => 'Postal Code', :country => 'Country')
23
+
24
+ transaction.billing_address = RealEx::Address.new(:type => 'billing', :code => 'Postal Code', :country => 'Country')
25
+
26
+ transaction.authorize!
27
+
28
+ ## Manual Request Type ##
29
+
30
+ transaction.manual = true
31
+ transaction.authcode = '12345'
32
+
33
+ transaction.authorize!
34
+
35
+
36
+ ## Recurring payments ##
37
+
38
+ payer = RealEx::Recurring::Payer.new(:type => 'Business', :reference => 'boom', :title => 'Mr.', :firstname => 'Paul', :lastname => 'Campbell', :company => 'Hyper Tiny')
39
+
40
+ payer.address = RealEx::Address.new(:street => '64 Dame Street', :city => 'Dublin', :county => 'Dublin', :post_code => 'Dublin 3', :country => 'Ireland', :country_code => 'IE', :phone_numbers => { :home => '1234', :work => '1234', :fax => '1234', :mobile => '1234'}, :email => 'paul@rslw.com')
41
+
42
+ payer.save!
43
+
44
+ recurring_card = RealEx::Recurring::Card.new(:payer => payer, :reference => 'paulcampbell')
45
+
46
+ recurring_card.card = card
47
+
48
+ recurring_card.save
49
+
50
+ transaction = RealEx::Recurring::Authorization.new(:amount => 500, :payer => payer, :order_id => order_id)
51
+
52
+ transaction.authorize!
@@ -0,0 +1,34 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ desc 'Default: run specs.'
5
+ task :default => :spec
6
+
7
+ desc 'Run the specs'
8
+ Spec::Rake::SpecTask.new(:spec) do |t|
9
+ t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
10
+ t.spec_files = FileList['spec/**/*_spec.rb']
11
+ end
12
+
13
+ PKG_FILES = FileList[
14
+ '[a-zA-Z]*',
15
+ 'lib/**/*',
16
+ 'rails/**/*'
17
+ ]
18
+
19
+ begin
20
+ require 'jeweler'
21
+ Jeweler::Tasks.new do |gemspec|
22
+ gemspec.name = "realex"
23
+ gemspec.summary = "Ruby interface to http://realexpayments.com"
24
+ gemspec.description = "A Ruby library to make use of the payments API at http://realexpayments.com"
25
+ gemspec.email = "paul@rslw.com"
26
+ gemspec.homepage = "http://github.com/paulca/realex"
27
+ gemspec.authors = ["Paul Campbell"]
28
+ gemspec.version = "0.1.1"
29
+ end
30
+ rescue LoadError
31
+ puts "Jeweler not available. Install it with: gem install jeweler"
32
+ end
33
+
34
+ Jeweler::GemcutterTasks.new
@@ -0,0 +1,15 @@
1
+ module RealEx
2
+ class Address
3
+ include Initializer
4
+ attributes :street, :city, :county
5
+ attributes :post_code, :country, :country_code, :phone_numbers, :email
6
+
7
+ [1,2,3].each do |line|
8
+ class_eval do
9
+ define_method("line#{line}") do
10
+ street.split("\n")[line - 1]
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ module RealEx
2
+ class Card
3
+ include Initializer
4
+
5
+ attributes :number, :cvv, :expiry_date, :cardholder_name, :type, :issue_number
6
+
7
+ # The luhn check is a check to see if a credit card
8
+ # is actually a credit card or not
9
+ def passes_luhn_check?
10
+ odd = true
11
+ luhn = number.to_s.gsub(/\D/,'').reverse.split('').collect { |d|
12
+ d = d.to_i
13
+ d *= 2 if odd = !odd
14
+ d > 9 ? d - 9 : d
15
+ }.inject(0) { |sum,number| sum + number }
16
+ luhn % 10 == 0
17
+ end
18
+
19
+ def clean_name
20
+ cardholder_name.gsub(/[^a-zA-Z0-9 ]/, '')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ module RealEx
2
+ class Client
3
+ class << self
4
+
5
+ def timestamp
6
+ Time.now.strftime('%Y%m%d%H%M%S')
7
+ end
8
+
9
+ def build_hash(hash_string_items)
10
+ first_hash = Digest::SHA1.hexdigest(hash_string_items.join('.'))
11
+ Digest::SHA1.hexdigest("#{first_hash}.#{RealEx::Config.shared_secret}")
12
+ end
13
+
14
+ def build_xml(type, &block)
15
+ xml = Builder::XmlMarkup.new(:indent => 2)
16
+ xml.instruct!
17
+ xml.request(:timestamp => timestamp, :type => type) { |r| block.call(r) }
18
+ xml.target!
19
+ end
20
+
21
+ def call(url,xml)
22
+ h = Net::HTTP.new('epage.payandshop.com', 443)
23
+ h.use_ssl = true
24
+ response = h.request_post(url, xml)
25
+ result = Hpricot.XML(response.body)
26
+ result
27
+ end
28
+
29
+ def parse(response)
30
+ status = (response/:result).inner_html
31
+ raise RealExError, "#{(response/:message).inner_html} (#{status})" unless status == "00"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,7 @@
1
+ module RealEx
2
+ class Config
3
+ class << self
4
+ attr_accessor :shared_secret, :merchant_id, :account, :refund_password, :currency
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,24 @@
1
+ module RealEx
2
+ module Initializer
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ # this blatantly ripped from jnunemaker's Twitter gem. Thanks John!
9
+ module ClassMethods
10
+ # creates the attributes class variable and creates each attribute's accessor methods
11
+ def attributes(*attrs)
12
+ @@attributes = attrs
13
+ @@attributes.each { |a| attr_accessor a }
14
+ end
15
+
16
+ # read method for attributes class variable
17
+ def self.attributes; @@attributes end
18
+ end
19
+
20
+ def initialize(setters = {})
21
+ setters.each { |k, v| send("#{k}=", v) } unless setters.nil?
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,151 @@
1
+ module RealEx
2
+ module Recurring
3
+
4
+ class Transaction < RealEx::Transaction
5
+ def authorize!
6
+ RealEx::Response.new_from_xml(RealEx::Client.call('/epage-remote-plugins.cgi', to_xml))
7
+ end
8
+ end
9
+
10
+ class Payer < Transaction
11
+ attributes :type, :reference, :title, :firstname, :lastname, :address, :company, :comments
12
+ attributes :update
13
+
14
+ def request_type
15
+ @request_type = update == true ? 'payer-edit' : 'payer-new'
16
+ end
17
+
18
+ def to_xml
19
+ super do |per|
20
+ per.payer(:type => type, :ref => reference) do |payer|
21
+ payer.title title
22
+ payer.firstname firstname
23
+ payer.lastname lastname
24
+ payer.company company
25
+ payer.address do |add|
26
+ add.line1 address.line1
27
+ add.line1 address.line2
28
+ add.line3 address.line3
29
+ add.city address.city
30
+ add.county address.county
31
+ add.postcode address.post_code
32
+ add.country(address.country, :country_code => address.country_code)
33
+ end
34
+ payer.phonenumbers do |numbers|
35
+ numbers.home address.phone_numbers[:home]
36
+ numbers.work address.phone_numbers[:work]
37
+ numbers.fax address.phone_numbers[:fax]
38
+ numbers.mobile address.phone_numbers[:mobile]
39
+ end
40
+ payer.email address.email
41
+ if !comments.empty?
42
+ payer.comments do |c|
43
+ comments.each_with_index do |i,comment|
44
+ c.comment(comment, :id => i + 1)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ # 20030516175919.yourmerchantid.uniqueid…smithj01
53
+ def hash
54
+ RealEx::Client.build_hash([RealEx::Client.timestamp, RealEx::Config.merchant_id, order_id, '', '', reference])
55
+ end
56
+
57
+ def save!
58
+ authorize!
59
+ end
60
+
61
+ def update!
62
+ self.update = true
63
+ authorize!
64
+ end
65
+
66
+ end
67
+
68
+ class Card < Transaction
69
+ attributes :card, :payer, :update, :reference
70
+
71
+ def request_type
72
+ @request_type = update == true ? 'eft-update-expiry-date' : 'card-new'
73
+ end
74
+
75
+ def to_xml
76
+ super do |per|
77
+ per.card do |c|
78
+ c.ref reference
79
+ c.payerref payer.reference
80
+ c.number card.number
81
+ c.expdate card.expiry_date
82
+ c.chname card.cardholder_name
83
+ c.type card.type
84
+ end
85
+ end
86
+ end
87
+
88
+ # 20030516181127.yourmerchantid.uniqueid…smithj01.John Smith.498843******9991
89
+ def hash
90
+ if update == true
91
+ RealEx::Client.build_hash([RealEx::Client.timestamp, RealEx::Config.merchant_id, payer.reference, reference,card.expiry_date])
92
+ else
93
+ RealEx::Client.build_hash([RealEx::Client.timestamp, RealEx::Config.merchant_id, order_id, '', '', payer.reference,card.cardholder_name,card.number])
94
+ end
95
+ end
96
+
97
+ def save!
98
+ authorize!
99
+ end
100
+
101
+ def update!
102
+ self.update = true
103
+ authorize!
104
+ end
105
+
106
+ end
107
+
108
+ class Authorization < Transaction
109
+ attributes :payer, :reference, :customer_number, :variable_reference, :product_id
110
+ attributes :billing_address, :shipping_address
111
+
112
+ def request_type
113
+ 'receipt-in'
114
+ end
115
+
116
+ def to_xml
117
+ super do |per|
118
+ per.amount(amount, :currency => currency)
119
+ per.payerref payer.reference
120
+ per.paymentmethod reference
121
+ if customer_number or variable_reference or billing_address or shipping_address
122
+ per.tssinfo do |t|
123
+ t.custnum customer_number if customer_number
124
+ t.varref variable_reference if variable_reference
125
+ t.prodid product_id if product_id
126
+ if billing_address
127
+ t.address :type => 'billing' do |a|
128
+ a.code billing_address.post_code
129
+ a.country billing_address.country
130
+ end
131
+ end
132
+ if shipping_address
133
+ t.address :type => 'shipping' do |a|
134
+ a.code shipping_address.post_code
135
+ a.country shipping_address.country
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ # timesttimestamp.merchantid.orderid.amount.currency.payerref
144
+ def hash
145
+ RealEx::Client.build_hash([RealEx::Client.timestamp, RealEx::Config.merchant_id, order_id, amount, currency, payer.reference])
146
+ end
147
+
148
+ end
149
+
150
+ end
151
+ end
@@ -0,0 +1,38 @@
1
+ module RealEx
2
+ class Response
3
+ class CardIssuer
4
+ include Initializer
5
+ attributes :bank, :country, :countrycode, :region
6
+ end
7
+
8
+ include Initializer
9
+
10
+ attributes :timestamp, :result, :message, :orderid, :merchantid, :account, :cvnresult, :avspostcoderesponse, :pasref, :timetaken, :authtimetaken, :batchid, :avsaddressresponse, :cardissuer
11
+
12
+ def self.new_from_xml(xml)
13
+ parsed_xml = xml.kind_of?(String) ? Hpricot.XML(xml) : xml
14
+ r = new
15
+ r.timestamp = (parsed_xml).at('response')['timestamp'] if (parsed_xml).at('response')
16
+ r.result = (parsed_xml).at('result').inner_html if (parsed_xml).at('result')
17
+ r.message = (parsed_xml).at('message').inner_html if (parsed_xml).at('message')
18
+ r.orderid = (parsed_xml).at('orderid').inner_html if (parsed_xml).at('orderid')
19
+ r.merchantid = (parsed_xml).at('merchantid').inner_html if (parsed_xml).at('merchantid')
20
+ r.account = (parsed_xml).at('account').inner_html if (parsed_xml).at('account')
21
+ r.cvnresult = (parsed_xml).at('cvnresult').inner_html if (parsed_xml).at('cvnresult')
22
+ r.avspostcoderesponse = (parsed_xml).at('avspostcoderesponse').inner_html if (parsed_xml).at('avspostcoderesponse')
23
+ r.avsaddressresponse = (parsed_xml).at('avsaddressresponse').inner_html if (parsed_xml).at('avsaddressresponse')
24
+ r.batchid = (parsed_xml).at('batchid').inner_html if (parsed_xml).at('batchid')
25
+ r.pasref = (parsed_xml).at('pasref').inner_html if (parsed_xml).at('pasref')
26
+ r.timetaken = (parsed_xml).at('timetaken').inner_html if (parsed_xml).at('timetaken')
27
+ r.authtimetaken = (parsed_xml).at('authtimetaken').inner_html if (parsed_xml).at('authtimetaken')
28
+ if cardissuer = (parsed_xml).at('cardissuer')
29
+ r.cardissuer = CardIssuer.new()
30
+ r.cardissuer.bank = cardissuer.at('bank').inner_html
31
+ r.cardissuer.country = cardissuer.at('country').inner_html
32
+ r.cardissuer.countrycode = cardissuer.at('countrycode').inner_html
33
+ r.cardissuer.region = cardissuer.at('region').inner_html
34
+ end
35
+ r
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,171 @@
1
+ module RealEx
2
+ class Transaction
3
+ include Initializer
4
+ attributes :card, :amount, :order_id, :currency, :autosettle, :variable_reference
5
+ attr_accessor :comments
6
+ attr_accessor :authcode, :pasref
7
+
8
+ REQUEST_TYPES = ['auth', 'manual', 'offline', 'tss', 'payer-new', 'payer-edit', 'card-new', 'eft-update-expiry-date']
9
+
10
+ def initialize(hash = {})
11
+ super(hash)
12
+ self.comments ||= []
13
+ self.autosettle ||= true
14
+ self.currency ||= RealEx::Config.currency || 'EUR'
15
+ end
16
+
17
+ def request_type
18
+ self.class.name.split('::').last.downcase
19
+ end
20
+
21
+ def autosettle?
22
+ autosettle
23
+ end
24
+
25
+ def to_xml(&block)
26
+ xml = RealEx::Client.build_xml(request_type) do |r|
27
+ r.merchantid RealEx::Config.merchant_id
28
+ r.orderid order_id
29
+ r.authcode authcode if authcode
30
+ r.pasref pasref if pasref
31
+ r.account RealEx::Config.account
32
+ if block_given?
33
+ block.call(r)
34
+ end
35
+ if !comments.empty?
36
+ r.comments do |c|
37
+ comments.each_with_index do |index,comment|
38
+ c.comment(comment, :id => index)
39
+ end
40
+ end
41
+ end
42
+ r.sha1hash hash
43
+ end
44
+ end
45
+
46
+ def hash
47
+ RealEx::Client.build_hash([RealEx::Client.timestamp, RealEx::Config.merchant_id, order_id, '', '', ''])
48
+ end
49
+
50
+ def authorize!
51
+ RealEx::Response.new_from_xml(RealEx::Client.call('/epage-remote.cgi', to_xml))
52
+ end
53
+
54
+ end
55
+
56
+ class Authorization < Transaction
57
+ attributes :shipping_address, :billing_address, :customer_number, :product_id, :customer_ip_address
58
+ attributes :offline, :manual
59
+
60
+ def initialize(hash = {})
61
+ super(hash)
62
+ self.manual ||= false
63
+ self.offline ||= false
64
+ end
65
+
66
+ REQUEST_TYPES.each do |type|
67
+ class_eval do
68
+ define_method("#{type}=") do |boolean| # def manual=(boolean)
69
+ self.request_type = type if boolean # self.request_type = 'manual' if boolean
70
+ end # end
71
+
72
+ define_method("#{type}?") do # def manual?
73
+ request_type == type # request_type == 'manual'
74
+ end # end
75
+ end
76
+ end
77
+
78
+ def request_type
79
+ @request_type ||= 'auth'
80
+ end
81
+
82
+ def request_type=(type)
83
+ @request_type = type if REQUEST_TYPES.include?(type)
84
+ end
85
+
86
+ def to_xml
87
+ super do |r|
88
+ r.amount(amount, :currency => currency) unless offline?
89
+ if !offline?
90
+ r.card do |c|
91
+ c.number card.number
92
+ c.expdate card.expiry_date
93
+ c.chname card.clean_name
94
+ c.type card.type
95
+ end
96
+ r.autosettle :flag => autosettle? ? '1' : '0'
97
+ r.tssinfo do |t|
98
+ t.custnum customer_number if customer_number
99
+ t.varref variable_reference if variable_reference
100
+ t.prodid product_id if product_id
101
+ t.custipaddress customer_ip_address if customer_ip_address
102
+ if billing_address
103
+ t.address :type => 'billing' do |a|
104
+ a.code billing_address.post_code
105
+ a.country billing_address.country
106
+ end
107
+ end
108
+ if shipping_address
109
+ t.address :type => 'shipping' do |a|
110
+ a.code shipping_address.post_code
111
+ a.country shipping_address.country
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ def hash
120
+ RealEx::Client.build_hash([RealEx::Client.timestamp, RealEx::Config.merchant_id, order_id, (amount unless offline?), (currency unless offline?), (card.number unless offline?)])
121
+ end
122
+
123
+ def rebate!
124
+
125
+ end
126
+
127
+ def void!
128
+
129
+ end
130
+
131
+ def settle!
132
+
133
+ end
134
+
135
+ end
136
+
137
+ class Void < Transaction
138
+ end
139
+
140
+ class Settle < Transaction
141
+ end
142
+
143
+ class Rebate < Transaction
144
+
145
+ attr_accessor :refund_password
146
+
147
+ def refund_hash
148
+ Digest::SHA1.hexdigest((refund_password || RealEx::Config.refund_password || ''))
149
+ end
150
+
151
+ def to_xml(&block)
152
+ super do |per|
153
+ per.amount(amount, :currency => currency)
154
+ per.autosettle :flag => autosettle? ? '1' : '0'
155
+ per.refundhash refund_hash
156
+ if !comments.empty?
157
+ per.comments do |c|
158
+ comments.each_with_index do |index,comment|
159
+ c.comment(comment, :id => index)
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+
167
+ def hash
168
+ RealEx::Client.build_hash([RealEx::Client.timestamp, RealEx::Config.merchant_id, order_id, amount, currency, ''])
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,20 @@
1
+ require 'rio'
2
+ require 'digest/sha1'
3
+ require 'hpricot'
4
+ require 'net/https'
5
+ require 'builder'
6
+
7
+ $:.unshift(File.dirname(__FILE__))
8
+ require 'real_ex/initializer'
9
+ require 'real_ex/config'
10
+ require 'real_ex/client'
11
+
12
+ require 'real_ex/address'
13
+ require 'real_ex/card'
14
+ require 'real_ex/transaction'
15
+ require 'real_ex/response'
16
+ require 'real_ex/recurring'
17
+
18
+ module RealEx
19
+ class UnknownError < StandardError; end
20
+ end
@@ -0,0 +1,68 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{realex}
8
+ s.version = "0.1.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Paul Campbell"]
12
+ s.date = %q{2010-02-24}
13
+ s.description = %q{A Ruby library to make use of the payments API at http://realexpayments.com}
14
+ s.email = %q{paul@rslw.com}
15
+ s.extra_rdoc_files = [
16
+ "README.md"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "README.md",
21
+ "Rakefile",
22
+ "lib/real_ex/address.rb",
23
+ "lib/real_ex/card.rb",
24
+ "lib/real_ex/client.rb",
25
+ "lib/real_ex/config.rb",
26
+ "lib/real_ex/initializer.rb",
27
+ "lib/real_ex/recurring.rb",
28
+ "lib/real_ex/response.rb",
29
+ "lib/real_ex/transaction.rb",
30
+ "lib/realex.rb",
31
+ "realex.gemspec",
32
+ "spec/address_spec.rb",
33
+ "spec/card_spec.rb",
34
+ "spec/config_spec.rb",
35
+ "spec/real_ex_spec.rb",
36
+ "spec/recurring_spec.rb",
37
+ "spec/response_spec.rb",
38
+ "spec/spec.opts",
39
+ "spec/spec_helper.rb",
40
+ "spec/transaction_spec.rb"
41
+ ]
42
+ s.homepage = %q{http://github.com/paulca/realex}
43
+ s.rdoc_options = ["--charset=UTF-8"]
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = %q{1.3.5}
46
+ s.summary = %q{Ruby interface to http://realexpayments.com}
47
+ s.test_files = [
48
+ "spec/address_spec.rb",
49
+ "spec/card_spec.rb",
50
+ "spec/config_spec.rb",
51
+ "spec/real_ex_spec.rb",
52
+ "spec/recurring_spec.rb",
53
+ "spec/response_spec.rb",
54
+ "spec/spec_helper.rb",
55
+ "spec/transaction_spec.rb"
56
+ ]
57
+
58
+ if s.respond_to? :specification_version then
59
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
60
+ s.specification_version = 3
61
+
62
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
63
+ else
64
+ end
65
+ else
66
+ end
67
+ end
68
+
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe "RealEx::Address" do
4
+ before do
5
+ @address = RealEx::Address.new(
6
+ :post_code => '1234',
7
+ :country => 'Ireland',
8
+ :street => "99 Street view,\nholleraino\npicksville"
9
+ )
10
+ end
11
+
12
+ it "should just save the attributes" do
13
+ @address.post_code.should == '1234'
14
+ end
15
+
16
+ it "should just save the attributes" do
17
+ @address.country.should == 'Ireland'
18
+ end
19
+
20
+ it "should have line1 line2 and line3" do
21
+ @address.line1.should == "99 Street view,"
22
+ @address.line2.should == "holleraino"
23
+ @address.line3.should == "picksville"
24
+ end
25
+
26
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe "RealEx::Card" do
4
+ before do
5
+ @card = RealEx::Card.new(
6
+ :number => '4111111111111111',
7
+ :cvv => '509',
8
+ :expiry_date => '0802',
9
+ :cardholder_name => 'Paul Campbell',
10
+ :type => 'VISA',
11
+ :issue_number => nil
12
+ )
13
+ end
14
+
15
+ it "should just save the attributes" do
16
+ @card.number.should == '4111111111111111'
17
+ end
18
+
19
+ it "should pass the luhn check" do
20
+ @card.passes_luhn_check?.should == true
21
+ end
22
+
23
+ it "should fail the luhn check if it's an invalid card" do
24
+ @card.number = '1234'
25
+ @card.passes_luhn_check?.should == false
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe "RealEx::Config" do
4
+ before do
5
+ RealEx::Config.shared_secret = "He's actually a woman"
6
+ end
7
+
8
+ it "should set the shared_secret" do
9
+ RealEx::Config.shared_secret.should == "He's actually a woman"
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe "RealEx" do
4
+
5
+ # before do
6
+ # @card = RealEx::Cart
7
+ #
8
+ # RealEx::Connection
9
+ # RealEx::Card
10
+ # RealEx::Transaction
11
+ # RealEx::Refund
12
+ # RealEx::Recurring::Payer
13
+ # RealEx::Recurring::Card
14
+ # end
15
+ #
16
+ # it "should set the shared secret" do
17
+ # RealEx.shared_secret.should == "He's a woman"
18
+ # end
19
+ #
20
+ # it "should set the merchant_id" do
21
+ # RealEx.merchant_id.should == '123456'
22
+ # end
23
+ end
@@ -0,0 +1,52 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe "RealEx::Recurring" do
4
+ before do
5
+ RealEx::Config.merchant_id = 'paul'
6
+ RealEx::Config.shared_secret = "He's not dead, he's just asleep!"
7
+ RealEx::Config.account = 'internet'
8
+
9
+ @card = RealEx::Card.new(
10
+ :number => '4111111111111111',
11
+ :cvv => '509',
12
+ :expiry_date => '0802',
13
+ :cardholder_name => 'Paul Campbell',
14
+ :type => 'VISA',
15
+ :issue_number => nil
16
+ )
17
+ @payer = RealEx::Recurring::Payer.new(:type => 'Business', :reference => 'boom', :title => 'Mr.', :firstname => 'Paul', :lastname => 'Campbell', :company => 'Contrast')
18
+ @payer.address = RealEx::Address.new(:street => 'My house', :city => 'Dublin', :county => 'Dublin', :post_code => 'Dublin 2', :country => 'Ireland', :country_code => 'IE',
19
+ :phone_numbers => { :home => '1', :work => '2', :fax => '3', :mobile => '4'}, :email => 'paul@contrast.ie')
20
+ @card = RealEx::Recurring::Card.new(:payer => @payer, :card => @card, :reference => 'billabong')
21
+ @transaction = RealEx::Recurring::Authorization.new(
22
+ :payer => @payer,
23
+ :amount => 500,
24
+ :order_id => 1234,
25
+ :currency => 'EUR',
26
+ :autosettle => true
27
+ )
28
+ RealEx::Client.stub!(:timestamp).and_return('20090326160218')
29
+ end
30
+
31
+ it "should create tasty XML for the payer" do
32
+ @payer.to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<request type=\"payer-new\" timestamp=\"20090326160218\">\n <merchantid>paul</merchantid>\n <orderid></orderid>\n <account>internet</account>\n <payer type=\"Business\" ref=\"boom\">\n <title>Mr.</title>\n <firstname>Paul</firstname>\n <lastname>Campbell</lastname>\n <company>Contrast</company>\n <address>\n <line1>My house</line1>\n <line1></line1>\n <line3></line3>\n <city>Dublin</city>\n <county>Dublin</county>\n <postcode>Dublin 2</postcode>\n <country country_code=\"IE\">Ireland</country>\n </address>\n <phonenumbers>\n <home>1</home>\n <work>2</work>\n <fax>3</fax>\n <mobile>4</mobile>\n </phonenumbers>\n <email>paul@contrast.ie</email>\n </payer>\n <sha1hash>7e97b1b743c2599b6c1fd0c5515d369d8372df15</sha1hash>\n</request>\n"
33
+ end
34
+
35
+ it "should create tasty XML for the payer update" do
36
+ @payer.update = true
37
+ @payer.to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<request type=\"payer-edit\" timestamp=\"20090326160218\">\n <merchantid>paul</merchantid>\n <orderid></orderid>\n <account>internet</account>\n <payer type=\"Business\" ref=\"boom\">\n <title>Mr.</title>\n <firstname>Paul</firstname>\n <lastname>Campbell</lastname>\n <company>Contrast</company>\n <address>\n <line1>My house</line1>\n <line1></line1>\n <line3></line3>\n <city>Dublin</city>\n <county>Dublin</county>\n <postcode>Dublin 2</postcode>\n <country country_code=\"IE\">Ireland</country>\n </address>\n <phonenumbers>\n <home>1</home>\n <work>2</work>\n <fax>3</fax>\n <mobile>4</mobile>\n </phonenumbers>\n <email>paul@contrast.ie</email>\n </payer>\n <sha1hash>7e97b1b743c2599b6c1fd0c5515d369d8372df15</sha1hash>\n</request>\n"
38
+ end
39
+
40
+ it "should create lovely XML for the card" do
41
+ @card.to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<request type=\"card-new\" timestamp=\"20090326160218\">\n <merchantid>paul</merchantid>\n <orderid></orderid>\n <account>internet</account>\n <card>\n <ref>billabong</ref>\n <payerref>boom</payerref>\n <number>4111111111111111</number>\n <expdate>0802</expdate>\n <chname>Paul Campbell</chname>\n <type>VISA</type>\n </card>\n <sha1hash>24dc62271ccaddc59082b4db45c80b0241f630f7</sha1hash>\n</request>\n"
42
+ end
43
+
44
+ it "should create lovely XML for the card update" do
45
+ @card.update = true
46
+ @card.to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<request type=\"eft-update-expiry-date\" timestamp=\"20090326160218\">\n <merchantid>paul</merchantid>\n <orderid></orderid>\n <account>internet</account>\n <card>\n <ref>billabong</ref>\n <payerref>boom</payerref>\n <number>4111111111111111</number>\n <expdate>0802</expdate>\n <chname>Paul Campbell</chname>\n <type>VISA</type>\n </card>\n <sha1hash>a97a52b7e5afa2980f4298251c2b8b836fd82331</sha1hash>\n</request>\n"
47
+ end
48
+
49
+ it "should create tasty XML for the authorization" do
50
+ @transaction.to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<request type=\"receipt-in\" timestamp=\"20090326160218\">\n <merchantid>paul</merchantid>\n <orderid>1234</orderid>\n <account>internet</account>\n <amount currency=\"EUR\">500</amount>\n <payerref>boom</payerref>\n <paymentmethod></paymentmethod>\n <sha1hash>ec3afd1714b4473210c2b1eda0c6675bd13c411b</sha1hash>\n</request>\n"
51
+ end
52
+ end
@@ -0,0 +1,70 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ # <?xml version="1.0" ?>
3
+ # <response timestamp="20090326164411">
4
+ # <result>501</result>
5
+ # <message>This transaction (1234) has already been processed! If you feel this is incorrect please contact the merchant!</message>
6
+ # <orderid>1234</orderid>
7
+ # </response>
8
+ describe "RealEx::Response" do
9
+ before do
10
+ @response = RealEx::Response.new_from_xml(%Q[<?xml version="1.0" ?>
11
+ <response timestamp="20090326164411">
12
+ <result>501</result>
13
+ <message>This transaction (1234) has already been processed! If you feel this is incorrect please contact the merchant!</message>
14
+ <orderid>1234</orderid>
15
+ </response>])
16
+ end
17
+
18
+ it "should build the object" do
19
+ @response.timestamp.should == '20090326164411'
20
+ @response.result.should == '501'
21
+ @response.message.should == 'This transaction (1234) has already been processed! If you feel this is incorrect please contact the merchant!'
22
+ @response.orderid.should == '1234'
23
+ end
24
+ end
25
+
26
+ describe "RealEx::Response" do
27
+ before do
28
+ @response = RealEx::Response.new_from_xml(%Q[<?xml version="1.0" encoding="UTF-8" ?>
29
+ <response timestamp="20090326171616">
30
+ <merchantid>test</merchantid>
31
+ <account>Realex</account>
32
+ <orderid>12345</orderid>
33
+ <authcode>171616</authcode>
34
+ <result>00</result>
35
+ <cvnresult>U</cvnresult>
36
+ <avspostcoderesponse>U</avspostcoderesponse>
37
+ <avsaddressresponse>U</avsaddressresponse>
38
+ <batchid>136</batchid>
39
+ <message>[ test system ] Authorised 171616</message>
40
+ <pasref>12380877763476</pasref>
41
+ <timetaken>1</timetaken>
42
+ <authtimetaken>0</authtimetaken>
43
+ <cardissuer>
44
+ <bank>AIB BANK</bank>
45
+ <country>IRELAND</country>
46
+ <countrycode>IE</countrycode>
47
+ <region>EUR</region>
48
+ </cardissuer>])
49
+ end
50
+
51
+ it "should build the object" do
52
+ @response.timestamp.should == '20090326171616'
53
+ @response.merchantid.should == 'test'
54
+ @response.account.should == 'Realex'
55
+ @response.orderid.should == '12345'
56
+ @response.cardissuer.bank.should == 'AIB BANK'
57
+ @response.cvnresult.should == 'U'
58
+ @response.cvnresult.should == 'U'
59
+ @response.avspostcoderesponse.should == 'U'
60
+ @response.avsaddressresponse.should == 'U'
61
+ @response.batchid.should == '136'
62
+ @response.message.should == '[ test system ] Authorised 171616'
63
+ @response.pasref.should == '12380877763476'
64
+ @response.timetaken.should == '1'
65
+ @response.authtimetaken.should == '0'
66
+ @response.cardissuer.country.should == 'IRELAND'
67
+ @response.cardissuer.countrycode.should == 'IE'
68
+ @response.cardissuer.region.should == 'EUR'
69
+ end
70
+ end
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,23 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ dir = File.dirname(__FILE__)
10
+
11
+ $:.unshift(File.join(dir, '/../lib/'))
12
+ require dir + '/../lib/real_ex'
13
+
14
+
15
+ def stdout_for(&block)
16
+ # Inspired by http://www.ruby-forum.com/topic/58647
17
+ old_stdout = $stdout
18
+ $stdout = StringIO.new
19
+ yield
20
+ output = $stdout.string
21
+ $stdout = old_stdout
22
+ output
23
+ end
@@ -0,0 +1,132 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe "RealEx::Transaction" do
4
+ before do
5
+ RealEx::Config.merchant_id = 'paul'
6
+ RealEx::Config.shared_secret = "She's a man!"
7
+ RealEx::Config.account = 'internet'
8
+
9
+ @card = RealEx::Card.new(
10
+ :number => '4111111111111111',
11
+ :cvv => '509',
12
+ :expiry_date => '0802',
13
+ :cardholder_name => 'Paul Campbell',
14
+ :type => 'VISA',
15
+ :issue_number => nil
16
+ )
17
+ @transaction = RealEx::Authorization.new(
18
+ :card => @card,
19
+ :amount => 500,
20
+ :order_id => 1234,
21
+ :currency => 'EUR',
22
+ :autosettle => true
23
+ )
24
+ RealEx::Client.stub!(:timestamp).and_return('20090326160218')
25
+ end
26
+
27
+ it "should set up the card" do
28
+ @transaction.card.should == @card
29
+ end
30
+
31
+ it "should allow setting comments" do
32
+ @transaction.comments << "This is a comment"
33
+ @transaction.comments.should == ["This is a comment"]
34
+ end
35
+
36
+ it "should build the xml" do
37
+ @transaction.to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<request type=\"auth\" timestamp=\"20090326160218\">\n <merchantid>paul</merchantid>\n <orderid>1234</orderid>\n <account>internet</account>\n <amount currency=\"EUR\">500</amount>\n <card>\n <number>4111111111111111</number>\n <expdate>0802</expdate>\n <chname>Paul Campbell</chname>\n <type>VISA</type>\n </card>\n <autosettle flag=\"1\"/>\n <tssinfo>\n </tssinfo>\n <sha1hash>d979885b0a296469d85ada0f08c5577d857142a0</sha1hash>\n</request>\n"
38
+ end
39
+
40
+ describe "with addresses" do
41
+ before do
42
+ @transaction.shipping_address = RealEx::Address.new(:post_code => 'Shipping Code', :country => 'Shipping Country')
43
+ @transaction.billing_address = RealEx::Address.new(:post_code => 'Biling Code', :country => 'Billing Country')
44
+ end
45
+
46
+ it "should add the addresses into the xml" do
47
+ @transaction.to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<request type=\"auth\" timestamp=\"20090326160218\">\n <merchantid>paul</merchantid>\n <orderid>1234</orderid>\n <account>internet</account>\n <amount currency=\"EUR\">500</amount>\n <card>\n <number>4111111111111111</number>\n <expdate>0802</expdate>\n <chname>Paul Campbell</chname>\n <type>VISA</type>\n </card>\n <autosettle flag=\"1\"/>\n <tssinfo>\n <address type=\"billing\">\n <code>Biling Code</code>\n <country>Billing Country</country>\n </address>\n <address type=\"shipping\">\n <code>Shipping Code</code>\n <country>Shipping Country</country>\n </address>\n </tssinfo>\n <sha1hash>d979885b0a296469d85ada0f08c5577d857142a0</sha1hash>\n</request>\n"
48
+ end
49
+ end
50
+
51
+ describe "actually going through" do
52
+
53
+ it "should parse the response" do
54
+ RealEx::Client.should_receive(:call).and_return(Hpricot.XML('yay'))
55
+ @transaction.authorize!
56
+ end
57
+ end
58
+
59
+ describe "a manual request type" do
60
+ before do
61
+ @transaction.manual = true
62
+ @transaction.authcode = '123456'
63
+ end
64
+
65
+ it "should allow a manual request" do
66
+ @transaction.to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<request type=\"manual\" timestamp=\"20090326160218\">\n <merchantid>paul</merchantid>\n <orderid>1234</orderid>\n <authcode>123456</authcode>\n <account>internet</account>\n <amount currency=\"EUR\">500</amount>\n <card>\n <number>4111111111111111</number>\n <expdate>0802</expdate>\n <chname>Paul Campbell</chname>\n <type>VISA</type>\n </card>\n <autosettle flag=\"1\"/>\n <tssinfo>\n </tssinfo>\n <sha1hash>d979885b0a296469d85ada0f08c5577d857142a0</sha1hash>\n</request>\n"
67
+ end
68
+ end
69
+
70
+ describe "an offline request type" do
71
+ before do
72
+ @transaction.offline = true
73
+ @transaction.authcode = '123456'
74
+ end
75
+
76
+ it "should allow an offline request" do
77
+ @transaction.to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<request type=\"offline\" timestamp=\"20090326160218\">\n <merchantid>paul</merchantid>\n <orderid>1234</orderid>\n <authcode>123456</authcode>\n <account>internet</account>\n <sha1hash>c01440492e678c7793cc7a221617384dec6d9ea1</sha1hash>\n</request>\n"
78
+ end
79
+ end
80
+
81
+ describe "a bit of meta" do
82
+ it "should allow setting and getting of manual= and manual?" do
83
+ @transaction.manual = true
84
+ @transaction.manual?.should == true
85
+ end
86
+
87
+ it "should allow setting and getting of offline= and offline?" do
88
+ @transaction.offline = true
89
+ @transaction.offline?.should == true
90
+ end
91
+ end
92
+
93
+ end
94
+
95
+ describe "RealEx::Rebate" do
96
+ before do
97
+ RealEx::Config.merchant_id = 'paul'
98
+ RealEx::Config.shared_secret = "She's a man!"
99
+ RealEx::Config.account = 'internet'
100
+ RealEx::Config.refund_password = ''
101
+ @rebate = RealEx::Rebate.new(
102
+ :order_id => '12345',
103
+ :pasref => '23455',
104
+ :authcode => '123123123',
105
+ :amount => 500
106
+ )
107
+ RealEx::Client.stub!(:timestamp).and_return('20090326160218')
108
+ end
109
+
110
+ it "should create some tasty xml" do
111
+ @rebate.to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<request type=\"rebate\" timestamp=\"20090326160218\">\n <merchantid>paul</merchantid>\n <orderid>12345</orderid>\n <authcode>123123123</authcode>\n <pasref>23455</pasref>\n <account>internet</account>\n <amount currency=\"EUR\">500</amount>\n <autosettle flag=\"1\"/>\n <refundhash>da39a3ee5e6b4b0d3255bfef95601890afd80709</refundhash>\n <sha1hash>be2f8fdc84c32d8d77ab6fae7896c10530d9d80c</sha1hash>\n</request>\n"
112
+ end
113
+ end
114
+
115
+ describe "RealEx::Void" do
116
+ before do
117
+ RealEx::Config.merchant_id = 'paul'
118
+ RealEx::Config.shared_secret = "She's a man!"
119
+ RealEx::Config.account = 'internet'
120
+ RealEx::Config.refund_password = ''
121
+ @void = RealEx::Void.new(
122
+ :order_id => '12345',
123
+ :pasref => '23455',
124
+ :authcode => '123123123'
125
+ )
126
+ RealEx::Client.stub!(:timestamp).and_return('20090326160218')
127
+ end
128
+
129
+ it "should create some tasty xml" do
130
+ @void.to_xml.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<request type=\"void\" timestamp=\"20090326160218\">\n <merchantid>paul</merchantid>\n <orderid>12345</orderid>\n <authcode>123123123</authcode>\n <pasref>23455</pasref>\n <account>internet</account>\n <sha1hash>16b04c4e989c413a54da8585266f6087cedccb0b</sha1hash>\n</request>\n"
131
+ end
132
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: realex
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Paul Campbell
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-24 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A Ruby library to make use of the payments API at http://realexpayments.com
17
+ email: paul@rslw.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.md
24
+ files:
25
+ - .gitignore
26
+ - README.md
27
+ - Rakefile
28
+ - lib/real_ex/address.rb
29
+ - lib/real_ex/card.rb
30
+ - lib/real_ex/client.rb
31
+ - lib/real_ex/config.rb
32
+ - lib/real_ex/initializer.rb
33
+ - lib/real_ex/recurring.rb
34
+ - lib/real_ex/response.rb
35
+ - lib/real_ex/transaction.rb
36
+ - lib/realex.rb
37
+ - realex.gemspec
38
+ - spec/address_spec.rb
39
+ - spec/card_spec.rb
40
+ - spec/config_spec.rb
41
+ - spec/real_ex_spec.rb
42
+ - spec/recurring_spec.rb
43
+ - spec/response_spec.rb
44
+ - spec/spec.opts
45
+ - spec/spec_helper.rb
46
+ - spec/transaction_spec.rb
47
+ has_rdoc: true
48
+ homepage: http://github.com/paulca/realex
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options:
53
+ - --charset=UTF-8
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project:
71
+ rubygems_version: 1.3.5
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Ruby interface to http://realexpayments.com
75
+ test_files:
76
+ - spec/address_spec.rb
77
+ - spec/card_spec.rb
78
+ - spec/config_spec.rb
79
+ - spec/real_ex_spec.rb
80
+ - spec/recurring_spec.rb
81
+ - spec/response_spec.rb
82
+ - spec/spec_helper.rb
83
+ - spec/transaction_spec.rb