realex 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.md +52 -0
- data/Rakefile +34 -0
- data/lib/real_ex/address.rb +15 -0
- data/lib/real_ex/card.rb +23 -0
- data/lib/real_ex/client.rb +35 -0
- data/lib/real_ex/config.rb +7 -0
- data/lib/real_ex/initializer.rb +24 -0
- data/lib/real_ex/recurring.rb +151 -0
- data/lib/real_ex/response.rb +38 -0
- data/lib/real_ex/transaction.rb +171 -0
- data/lib/realex.rb +20 -0
- data/realex.gemspec +68 -0
- data/spec/address_spec.rb +26 -0
- data/spec/card_spec.rb +27 -0
- data/spec/config_spec.rb +11 -0
- data/spec/real_ex_spec.rb +23 -0
- data/spec/recurring_spec.rb +52 -0
- data/spec/response_spec.rb +70 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/transaction_spec.rb +132 -0
- metadata +83 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg/*
|
data/README.md
ADDED
@@ -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!
|
data/Rakefile
ADDED
@@ -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
|
data/lib/real_ex/card.rb
ADDED
@@ -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,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
|
data/lib/realex.rb
ADDED
@@ -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
|
data/realex.gemspec
ADDED
@@ -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
|
data/spec/card_spec.rb
ADDED
@@ -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
|
data/spec/config_spec.rb
ADDED
@@ -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
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
@@ -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
|