realex 0.1.1

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 @@
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