xpay 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +4 -2
- data/Rakefile +1 -0
- data/UPGRADES +8 -0
- data/lib/xpay.rb +5 -0
- data/lib/xpay/core/creditcard.rb +5 -0
- data/lib/xpay/payment.rb +17 -24
- data/lib/xpay/transaction.rb +10 -9
- data/lib/xpay/transaction_query.rb +72 -0
- data/lib/xpay/version.rb +1 -1
- data/test/fixtures/config_load_test.xml +1 -0
- data/test/fixtures/creditcards.yml +1 -1
- data/test/fixtures/customer.xml +1 -1
- data/test/fixtures/default_config.xml +1 -0
- data/test/fixtures/operation.xml +1 -1
- data/test/fixtures/request_rewritten.xml +1 -1
- data/test/fixtures/root.xml +1 -1
- data/test/fixtures/transactionquery.xml +1 -0
- data/test/fixtures/transactionquery_response.xml +16 -0
- data/test/functional/transactionquery_functional_test.rb +28 -0
- data/test/test_helper.rb +8 -10
- data/test/xpay/core/customer_test.rb +1 -1
- data/test/xpay/core/operation_test.rb +1 -1
- data/test/xpay/payment_test.rb +5 -6
- data/test/xpay/transactionquery_test.rb +93 -0
- data/test/xpay_test.rb +16 -4
- metadata +11 -4
data/README.rdoc
CHANGED
@@ -11,6 +11,8 @@ http://www.securetrading.com/support/xpay.html for futher details, in depth spec
|
|
11
11
|
$ gem install xpay
|
12
12
|
|
13
13
|
* configure by either creating a yaml file at config/xpay.yml or call Xpay.set_config with a hash
|
14
|
+
* (make sure to use Xpay.set_config(options_hash) instead of setting the options direct as that would
|
15
|
+
* prevent the new xml from being generated)
|
14
16
|
* the following options can be set:
|
15
17
|
- merchant_name
|
16
18
|
- version
|
@@ -20,7 +22,7 @@ http://www.securetrading.com/support/xpay.html for futher details, in depth spec
|
|
20
22
|
- callback_url
|
21
23
|
|
22
24
|
== Usage
|
23
|
-
|
25
|
+
* An example of a 3D-Secure Transaction
|
24
26
|
|
25
27
|
-first: create the class instance for CreditCard, Customer and Operatioon
|
26
28
|
|
@@ -93,7 +95,7 @@ http://www.securetrading.com/support/xpay.html for futher details, in depth spec
|
|
93
95
|
|
94
96
|
The possible values of rt are as above.
|
95
97
|
|
96
|
-
|
98
|
+
* more examples to follow
|
97
99
|
|
98
100
|
|
99
101
|
== Copyright
|
data/Rakefile
CHANGED
data/UPGRADES
CHANGED
@@ -7,3 +7,11 @@
|
|
7
7
|
|
8
8
|
0.0.3 => 0.0.4
|
9
9
|
* bug fixed that prevents loading of MerchantName from config and create root xml
|
10
|
+
|
11
|
+
0.0.4 => 0.0.5
|
12
|
+
* bug fix that prevents having a return value on make_payment with non ST3DCARDQUERY as request
|
13
|
+
|
14
|
+
0.0.5 => 0.0.6
|
15
|
+
* bug fixed that prevents changing the config via hash
|
16
|
+
* added TransactionQuery as class that allows to query previous transactions
|
17
|
+
* force Issue number into string in CreditCard when given as Integer
|
data/lib/xpay.rb
CHANGED
@@ -20,6 +20,7 @@ module Xpay
|
|
20
20
|
# default_currency: GBP
|
21
21
|
|
22
22
|
autoload :Payment, 'xpay/payment'
|
23
|
+
autoload :TransactionQuery, 'xpay/transaction_query'
|
23
24
|
autoload :CreditCard, 'xpay/core/creditcard'
|
24
25
|
autoload :Customer, 'xpay/core/customer'
|
25
26
|
autoload :Operation, 'xpay/core/operation'
|
@@ -45,6 +46,7 @@ module Xpay
|
|
45
46
|
end
|
46
47
|
|
47
48
|
class PaResMissing < XpayError; end
|
49
|
+
class AttributeMissing < XpayError; end
|
48
50
|
class General < XpayError; end
|
49
51
|
|
50
52
|
class << self
|
@@ -75,6 +77,7 @@ module Xpay
|
|
75
77
|
conf.each do |key, value|
|
76
78
|
@xpay_config.send("#{key}=", value) if @xpay_config.respond_to? key
|
77
79
|
end
|
80
|
+
@request_xml = create_root_xml
|
78
81
|
return true
|
79
82
|
end
|
80
83
|
|
@@ -94,6 +97,8 @@ module Xpay
|
|
94
97
|
operation = request.add_element "Operation"
|
95
98
|
site_ref = operation.add_element "SiteReference"
|
96
99
|
site_ref.text = config.site_reference
|
100
|
+
operation.add_element("Currency").text = config.default_currency if config.default_currency
|
101
|
+
operation.add_element("SettlementDay").text = config.settlement_day if config.settlement_day
|
97
102
|
if config.default_query == "ST3DCARDQUERY"
|
98
103
|
mn = operation.add_element "MerchantName"
|
99
104
|
mn.text = config.merchant_name
|
data/lib/xpay/core/creditcard.rb
CHANGED
@@ -2,6 +2,7 @@ module Xpay
|
|
2
2
|
class CreditCard
|
3
3
|
attr_accessor :card_type, :valid_until, :valid_from, :issue, :parent_transaction_ref, :transaction_verifier
|
4
4
|
attr_writer :security_code
|
5
|
+
|
5
6
|
def initialize(options={})
|
6
7
|
if !options.nil? && options.is_a?(Hash)
|
7
8
|
options.each do |key, value|
|
@@ -18,6 +19,10 @@ module Xpay
|
|
18
19
|
@number = new_val.to_s.gsub(/[^0-9]/, "")
|
19
20
|
end
|
20
21
|
|
22
|
+
def issue=(issue)
|
23
|
+
@issue = issue.to_s
|
24
|
+
end
|
25
|
+
|
21
26
|
def security_code=(new_val)
|
22
27
|
@security_code = new_val.to_s
|
23
28
|
end
|
data/lib/xpay/payment.rb
CHANGED
@@ -67,10 +67,10 @@ module Xpay
|
|
67
67
|
# query your instance e.g. p.response_block for further information
|
68
68
|
|
69
69
|
def make_payment
|
70
|
-
@response_xml =
|
70
|
+
@response_xml = process()
|
71
71
|
if request_method=="ST3DCARDQUERY"
|
72
72
|
# In case the request was a ST3DCARDQUERY (the default case) the further processing depends on the respones. If it was an AUTH request than all is done and the response_xml gets processed
|
73
|
-
@response_xml =
|
73
|
+
@response_xml = process() if response_code==0 # try once more if the response code is ZERO in ST3DCARDQUERY (According to securtrading tech support)
|
74
74
|
case response_code
|
75
75
|
when 1 # one means -> 3D AUTH required
|
76
76
|
rewrite_request_block() # Rewrite the request block with information from the response, deleting unused items
|
@@ -85,20 +85,20 @@ module Xpay
|
|
85
85
|
threedsecure = REXML::XPath.first(@request_xml, "//ThreeDSecure")
|
86
86
|
pares = threedsecure.add_element("PaRes")
|
87
87
|
pares.text = ""
|
88
|
-
@response_xml =
|
89
|
-
rt =
|
88
|
+
@response_xml = process()
|
89
|
+
rt = response_code
|
90
90
|
end
|
91
91
|
when 2 # TWO -> do a normal AUTH request
|
92
92
|
rewrite_request_block("AUTH") # Rewrite the request block as AUTH request with information from the response, deleting unused items
|
93
|
-
@response_xml =
|
94
|
-
rt =
|
93
|
+
@response_xml = process()
|
94
|
+
rt = response_code
|
95
95
|
else # ALL other cases, payment declined
|
96
|
-
rt =
|
96
|
+
rt = response_code
|
97
97
|
end
|
98
98
|
else
|
99
|
-
rt =
|
99
|
+
rt = response_code
|
100
100
|
end
|
101
|
-
|
101
|
+
rt
|
102
102
|
end
|
103
103
|
|
104
104
|
# The response_block is a hash and can have one of several values:
|
@@ -175,33 +175,26 @@ module Xpay
|
|
175
175
|
REXML::XPath.first(@request_xml, "//Request").attributes["Type"] = auth_type
|
176
176
|
|
177
177
|
# delete term url and merchant name
|
178
|
-
|
179
|
-
|
180
|
-
op.delete_element "MerchantName"
|
178
|
+
ops = REXML::XPath.first(@request_xml, "//Operation")
|
179
|
+
["TermUrl", "MerchantName"].each { |e| ops.delete_element e }
|
181
180
|
|
182
181
|
# delete accept and user agent in customer info
|
183
182
|
customer_info = REXML::XPath.first(@request_xml, "//CustomerInfo")
|
184
|
-
customer_info.delete_element
|
185
|
-
customer_info.delete_element "//UserAgent"
|
183
|
+
["Accept", "UserAgent"].each { |e| customer_info.delete_element e }
|
186
184
|
|
187
185
|
# delete credit card details and add TransactionVerifier and TransactionReference from response xml
|
188
186
|
# CC details are not needed anymore as verifier and reference are sufficient
|
189
187
|
cc_details = REXML::XPath.first(@request_xml, "//CreditCard")
|
190
|
-
cc_details.delete_element
|
191
|
-
cc_details.
|
192
|
-
|
193
|
-
trans_ver.text = REXML::XPath.first(@response_xml, "//TransactionVerifier").text
|
194
|
-
trans_ref = cc_details.add_element("ParentTransactionReference")
|
195
|
-
trans_ref.text = REXML::XPath.first(@response_xml, "//TransactionReference").text
|
188
|
+
["Number", "Type", "SecurityCode", "StartDate", "ExpiryDate", "Issue"].each { |e| cc_details.delete_element e }
|
189
|
+
cc_details.add_element("TransactionVerifier").text = REXML::XPath.first(@response_xml, "//TransactionVerifier").text
|
190
|
+
cc_details.add_element("ParentTransactionReference").text = REXML::XPath.first(@response_xml, "//TransactionReference").text
|
196
191
|
|
197
192
|
# unless it is an AUTH request, add additional required info for a 3DAUTH request
|
198
193
|
unless auth_type == "AUTH"
|
199
194
|
pm_method = REXML::XPath.first(@request_xml, "//PaymentMethod")
|
200
195
|
threedsecure = pm_method.add_element("ThreeDSecure")
|
201
|
-
|
202
|
-
|
203
|
-
md = threedsecure.add_element("MD")
|
204
|
-
md.text = REXML::XPath.first(@response_xml, "//MD").text rescue ""
|
196
|
+
threedsecure.add_element("Enrolled").text = REXML::XPath.first(@response_xml, "//Enrolled").text
|
197
|
+
threedsecure.add_element("MD").text = REXML::XPath.first(@response_xml, "//MD").text rescue ""
|
205
198
|
end
|
206
199
|
true
|
207
200
|
end
|
data/lib/xpay/transaction.rb
CHANGED
@@ -10,24 +10,25 @@ module Xpay
|
|
10
10
|
attr_accessor :request_xml
|
11
11
|
attr_reader :three_secure, :response_xml, :response_block
|
12
12
|
|
13
|
-
def process()
|
14
|
-
a = TCPSocket.open("localhost", Xpay.config.port)
|
15
|
-
a.write(self.request_xml.to_s + "\n")
|
16
|
-
res = a.read()
|
17
|
-
a.close
|
18
|
-
# create an xml document, use everything from the start of <ResponseBlock to the end, discard header and status etc and return it
|
19
|
-
REXML::Document.new res[res.index("<ResponseBlock"), res.length]
|
20
|
-
end
|
21
13
|
|
22
14
|
def request_method
|
23
15
|
@request_method ||= REXML::XPath.first(@request_xml, "//Request").attributes["Type"]
|
24
16
|
end
|
25
17
|
|
26
18
|
def response_code
|
27
|
-
|
19
|
+
REXML::XPath.first(@response_xml, "//Result").text.to_i rescue nil
|
28
20
|
end
|
29
21
|
|
30
22
|
private
|
23
|
+
def process()
|
24
|
+
a = TCPSocket.open("localhost", Xpay.config.port)
|
25
|
+
a.write(self.request_xml.to_s + "\n")
|
26
|
+
res = a.read()
|
27
|
+
a.close
|
28
|
+
# create an xml document, use everything from the start of <ResponseBlock to the end, discard header and status etc and return it
|
29
|
+
REXML::Document.new res[res.index("<ResponseBlock"), res.length]
|
30
|
+
end
|
31
|
+
|
31
32
|
def response_xml=(new_val)
|
32
33
|
@response_xml = new_val if new_val.is_a?(REXML::Document)
|
33
34
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Xpay
|
2
|
+
|
3
|
+
# This class allows you to query the status of a transaction processed with Xpay
|
4
|
+
# the following attributes are required:
|
5
|
+
# either a TransactionReference or your own OrderReference from a previous transaction
|
6
|
+
# and your SiteReference if not already set in the config, you can also pass it to overwrite it for this transaction
|
7
|
+
class TransactionQuery < Transaction
|
8
|
+
attr_accessor :transaction_reference, :order_reference, :site_reference, :site_alias
|
9
|
+
|
10
|
+
def initialize(options={})
|
11
|
+
@request_xml = REXML::Document.new(Xpay.root_to_s)
|
12
|
+
options.each do |key, value|
|
13
|
+
self.send("#{key}=", value) if self.respond_to? key
|
14
|
+
end
|
15
|
+
create_request
|
16
|
+
end
|
17
|
+
|
18
|
+
def query
|
19
|
+
@response_xml = process()
|
20
|
+
return response_code
|
21
|
+
end
|
22
|
+
|
23
|
+
# The response_block is a hash and can have one of several values:
|
24
|
+
# the follwing values are always present after a transaction and can be queried to gain further details of the transaction:
|
25
|
+
# * result_code:
|
26
|
+
# 0 for failure, check error_code for further details
|
27
|
+
# 1 transaction was succesful
|
28
|
+
# 2 transaction was denied
|
29
|
+
# * transaction_reference
|
30
|
+
# * transactionverifier
|
31
|
+
# * transaction_time
|
32
|
+
# * auth_code
|
33
|
+
# * amount
|
34
|
+
# * the order reference
|
35
|
+
def response_block
|
36
|
+
create_response_block
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# Write the xml document needed for processing, fill in elements need and delete unused ones from the root_xml
|
42
|
+
# raises an error if any necessary elements are missing
|
43
|
+
def create_request
|
44
|
+
raise AttributeMissing.new "(2500) TransactionReference or OrderReference need to be present." if (transaction_reference.nil? && order_reference.nil?)
|
45
|
+
raise AttributeMissing.new "(2500) SiteReference must be present." if (site_reference.nil? && (REXML::XPath.first(@request_xml, "//SiteReference").text.blank? rescue true))
|
46
|
+
REXML::XPath.first(@request_xml, "//Request").attributes["Type"] = "TRANSACTIONQUERY"
|
47
|
+
ops = REXML::XPath.first(@request_xml, "//Operation")
|
48
|
+
["TermUrl", "MerchantName", "Currency", "SettlementDay"].each { |e| ops.delete_element e }
|
49
|
+
(ops.elements["SiteReference"] || ops.add_element("SiteReference")).text = self.site_reference if self.site_reference
|
50
|
+
(ops.elements["TransactionReference"] || ops.add_element("TransactionReference")).text = self.transaction_reference if self.transaction_reference
|
51
|
+
order = REXML::XPath.first(@request_xml, "//Operation")
|
52
|
+
(order.elements["OrderReference"] || order.add_element("OrderReference")).text = self.order_reference if self.order_reference
|
53
|
+
root = @request_xml.root
|
54
|
+
(root.elements["Certificate"] || root.add_element("Certificate")).text = self.site_alias if self.site_alias
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_response_block
|
59
|
+
@response_xml.is_a?(REXML::Document) ?
|
60
|
+
{
|
61
|
+
:result_code => (REXML::XPath.first(@response_xml, "//Result").text.to_i rescue nil),
|
62
|
+
:transaction_reference => (REXML::XPath.first(@response_xml, "//TransactionReference").text rescue nil),
|
63
|
+
:transactionverifier => (REXML::XPath.first(@response_xml, "//TransactionVerifier").text rescue nil),
|
64
|
+
:transaction_time => (REXML::XPath.first(@response_xml, "//TransactionCompletedTimestamp").text rescue nil),
|
65
|
+
:auth_code => (REXML::XPath.first(@response_xml, "//AuthCode").text rescue nil),
|
66
|
+
:amount => (REXML::XPath.first(@response_xml, "//Amount").text.to_i rescue nil),
|
67
|
+
:order_reference => (REXML::XPath.first(@response_xml, "//OrderReference").text rescue nil),
|
68
|
+
} : {}
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
data/lib/xpay/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
<?xml version='1.0' encoding='ISO-8859-1'?><RequestBlock Version='3.52'><Request Type='AUTH'><Operation><SiteReference>testoutlet12091</SiteReference><Currency>USD</Currency><SettlementDay>2</SettlementDay></Operation></Request><Certificate>testoutlet12091</Certificate></RequestBlock>
|
data/test/fixtures/customer.xml
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<?xml version='1.0' encoding='ISO-8859-1'?><RequestBlock Version='3.51'><Request Type='ST3DCARDQUERY'><Operation><SiteReference>site12345</SiteReference><MerchantName>CompanyName</MerchantName><TermUrl>http://localhost/gateway_callback</TermUrl></Operation><CustomerInfo><Postal><Name>JOE BLOGGS<NamePrefix>MR</NamePrefix><FirstName>Joe</FirstName><MiddleName>X</MiddleName><LastName>Bloggs</LastName><NameSuffix>PhD</NameSuffix></Name><Company>NotInventedHere.com</Company><Street>tonowhere crescent</Street><City>beyond the rainbow on stale bread</City><StateProv>East-West Swampshire</StateProv><PostalCode>X01 Z10</PostalCode><CountryCode>GB</CountryCode></Postal><Telecom><Phone>07950 843 363</Phone></Telecom><Online><Email>joe.x.bloggs@notinventedhere.com</Email></Online><Accept>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</Accept><UserAgent>Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB5; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; InfoPath.1; .NET4.0C; AskTbGLSV5/5.8.0.12304)</UserAgent></CustomerInfo></Request><Certificate>site12345</Certificate></RequestBlock>
|
1
|
+
<?xml version='1.0' encoding='ISO-8859-1'?><RequestBlock Version='3.51'><Request Type='ST3DCARDQUERY'><Operation><SiteReference>site12345</SiteReference><Currency>GBP</Currency><SettlementDay>1</SettlementDay><MerchantName>CompanyName</MerchantName><TermUrl>http://localhost/gateway_callback</TermUrl></Operation><CustomerInfo><Postal><Name>JOE BLOGGS<NamePrefix>MR</NamePrefix><FirstName>Joe</FirstName><MiddleName>X</MiddleName><LastName>Bloggs</LastName><NameSuffix>PhD</NameSuffix></Name><Company>NotInventedHere.com</Company><Street>tonowhere crescent</Street><City>beyond the rainbow on stale bread</City><StateProv>East-West Swampshire</StateProv><PostalCode>X01 Z10</PostalCode><CountryCode>GB</CountryCode></Postal><Telecom><Phone>07950 843 363</Phone></Telecom><Online><Email>joe.x.bloggs@notinventedhere.com</Email></Online><Accept>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</Accept><UserAgent>Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB5; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; InfoPath.1; .NET4.0C; AskTbGLSV5/5.8.0.12304)</UserAgent></CustomerInfo></Request><Certificate>site12345</Certificate></RequestBlock>
|
@@ -0,0 +1 @@
|
|
1
|
+
<?xml version='1.0' encoding='ISO-8859-1'?><RequestBlock Version='3.51'><Request Type='ST3DCARDQUERY'><Operation><SiteReference>site12345</SiteReference><Currency>GBP</Currency><SettlementDay>1</SettlementDay><MerchantName>CompanyName</MerchantName><TermUrl>http://localhost/gateway_callback</TermUrl></Operation></Request><Certificate>site12345</Certificate></RequestBlock>
|
data/test/fixtures/operation.xml
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<?xml version='1.0' encoding='ISO-8859-1'?><RequestBlock Version='3.51'><Request Type='AUTH'><Operation><SiteReference>site56987</SiteReference><MerchantName>TestMerchant</MerchantName><TermUrl>https://localhost/3dcallback</TermUrl><Amount>1000</Amount
|
1
|
+
<?xml version='1.0' encoding='ISO-8859-1'?><RequestBlock Version='3.51'><Request Type='AUTH'><Operation><SiteReference>site56987</SiteReference><Currency>USD</Currency><SettlementDay>1</SettlementDay><MerchantName>TestMerchant</MerchantName><TermUrl>https://localhost/3dcallback</TermUrl><Amount>1000</Amount></Operation><Order><OrderReference>TestOrder1245</OrderReference><OrderInformation>TestOrderInfo</OrderInformation></Order></Request><Certificate>site56987</Certificate></RequestBlock>
|
@@ -1 +1 @@
|
|
1
|
-
<?xml version='1.0' encoding='ISO-8859-1'?><RequestBlock Version='3.51'><Request Type='ST3DAUTH'><Operation><SiteReference>site56987</SiteReference><
|
1
|
+
<?xml version='1.0' encoding='ISO-8859-1'?><RequestBlock Version='3.51'><Request Type='ST3DAUTH'><Operation><SiteReference>site56987</SiteReference><Currency>USD</Currency><SettlementDay>1</SettlementDay><Amount>1000</Amount></Operation><PaymentMethod><CreditCard><TransactionVerifier>ArOH5um+qGhwLbuobJ5mdgzTr1qclm1j/qyG+VGDe9QSslGFXtwFA2A6jvM+qgUuZ0lLQPvJ82U1SkLOhm32dPRABlh0EkyrvKamrsDDRcsFZhWQLmS+yE0+keSaBq8C537NQAXIYcCYVvoOVKhDwdW4hZVfOtKFND+QxR2p89rw=</TransactionVerifier><ParentTransactionReference>17-9-1909368</ParentTransactionReference></CreditCard><ThreeDSecure><Enrolled>Y</Enrolled><MD>MTI4ODAwNjYzNi41MjAuMTc2MzczMzc3MDExMjg4MDA2NjM2LjUyMC4xNzYzNzMzNzcwMTEyODgwMDY2MzYuNTIwLjE3NjM3MzM3NzAxMTI4ODAwNjYzNi41MjAuMTc2MzczMzc3MDExMjg4MDA2NjM2LjUyMC4xNzYzNzMzNzcwMTEyODgwMDY2MzYuNTIwLjE3NjM3MzM3NzAxMTI4ODAwNjYzNi41MjAuMTc2MzczMzc3MDExMjg4MDA2NjM2LjUyMC4xNzYzNzMzNzcwMTEyODgwMDY2MzYuNTIwLjE3NjM3MzM3NzAxMTI4ODAwNjYzNi41MjAuMTc2MzczMzc3MDE=</MD></ThreeDSecure></PaymentMethod><CustomerInfo><Postal><Name>JOE BLOGGS<NamePrefix>MR</NamePrefix><FirstName>Joe</FirstName><MiddleName>X</MiddleName><LastName>Bloggs</LastName><NameSuffix>PhD</NameSuffix></Name><Company>NotInventedHere.com</Company><Street>tonowhere crescent</Street><City>beyond the rainbow on stale bread</City><StateProv>East-West Swampshire</StateProv><PostalCode>X01 Z10</PostalCode><CountryCode>GB</CountryCode></Postal><Telecom><Phone>07950 843 363</Phone></Telecom><Online><Email>joe.x.bloggs@notinventedhere.com</Email></Online></CustomerInfo><Order><OrderReference>TestOrder1245</OrderReference><OrderInformation>TestOrderInfo</OrderInformation></Order></Request><Certificate>site56987</Certificate></RequestBlock>
|
data/test/fixtures/root.xml
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
<RequestBlock Version='3.51'><Request Type='ST3DCARDQUERY'><Operation><Currency>GBP</Currency><SettlementDay>1</SettlementDay><MerchantName>CompanyName</MerchantName><TermUrl>http://localhost/gateway_callback</TermUrl></Operation></Request><Certificate>site12345</Certificate></RequestBlock>
|
@@ -0,0 +1 @@
|
|
1
|
+
<RequestBlock Version='3.51'><Request Type='TRANSACTIONQUERY'><Operation><SiteReference>site1234</SiteReference><TransactionReference>17-9-1908322</TransactionReference><OrderReference>121-1010272211</OrderReference></Operation></Request><Certificate>site12345</Certificate></RequestBlock>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<?xml version='1.0' encoding='ISO-8859-1'?>
|
2
|
+
<ResponseBlock Live="FALSE" Version="3.51">
|
3
|
+
<Response Type="TRANSACTIONQUERY">
|
4
|
+
<OperationResponse>
|
5
|
+
<TransactionReference>2-2-35117</TransactionReference>
|
6
|
+
<AuthCode>AUTH CODE: ab123</AuthCode>
|
7
|
+
<Result>1</Result>
|
8
|
+
<Amount>1234</Amount>
|
9
|
+
<TransactionCompletedTimestamp>2004-08-31 16:17:03</TransactionCompletedTimestamp>
|
10
|
+
<TransactionVerifier>ApTtGHQ/WUQYRj</TransactionVerifier>
|
11
|
+
</OperationResponse>
|
12
|
+
<Order>
|
13
|
+
<OrderReference>orderref0001</OrderReference>
|
14
|
+
</Order>
|
15
|
+
</Response>
|
16
|
+
</ResponseBlock>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'xpay'
|
3
|
+
|
4
|
+
|
5
|
+
class TransactionFunctionalTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context "a visa succesful no 3D payment" do
|
8
|
+
setup do
|
9
|
+
options = {:creditcard => Xpay::CreditCard.new(credit_card("visa_no3d_auth")), :operation => Xpay::Operation.new(operation("test_1")), :customer => Xpay::Customer.new(customer("test_1"))}
|
10
|
+
@p = Xpay::Payment.new(options)
|
11
|
+
Xpay.config.port = 5000
|
12
|
+
@p.make_payment
|
13
|
+
@tq = Xpay::TransactionQuery.new(:transaction_reference => @p.response_block[:transaction_reference], :site_reference => "testoutlet12092", :site_alias => "testoutlet12092")
|
14
|
+
@tq.query
|
15
|
+
end
|
16
|
+
|
17
|
+
should "create a transaction query" do
|
18
|
+
d { @p.response_block.to_yaml }
|
19
|
+
assert_instance_of Xpay::TransactionQuery, @tq
|
20
|
+
end
|
21
|
+
|
22
|
+
should "have a non empty response block" do
|
23
|
+
assert !@tq.response_block.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -15,24 +15,22 @@ end
|
|
15
15
|
def customer(which)
|
16
16
|
conf = YAML::load(ERB.new(IO.read(File.expand_path(File.dirname(__FILE__) + '/fixtures/customer.yml'))).result)[which]
|
17
17
|
end
|
18
|
-
|
19
|
-
|
20
|
-
end
|
18
|
+
|
19
|
+
|
21
20
|
|
22
21
|
def operation(which)
|
23
22
|
conf = YAML::load(ERB.new(IO.read(File.expand_path(File.dirname(__FILE__) + '/fixtures/operation.yml'))).result)[which]
|
24
23
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def operation_xml(which="operation")
|
24
|
+
|
25
|
+
|
26
|
+
def load_xml(which="")
|
29
27
|
REXML::Document.new(File.open(File.expand_path(File.dirname(__FILE__) + "/fixtures/#{which}.xml")))
|
30
28
|
end
|
31
|
-
|
32
|
-
|
33
|
-
x = REXML::Document.new(File.open(File.expand_path(File.dirname(__FILE__) + '/fixtures/root.xml'))).root.to_s
|
29
|
+
def load_xml_string(which="")
|
30
|
+
load_xml(which).root.to_s
|
34
31
|
end
|
35
32
|
|
33
|
+
|
36
34
|
def xpay_config(which)
|
37
35
|
YAML::load(IO.read(File.expand_path(File.dirname(__FILE__) + '/fixtures/xpay_defaults.yml')))[which]
|
38
36
|
end
|
@@ -56,7 +56,7 @@ class CustomerTest < Test::Unit::TestCase
|
|
56
56
|
end
|
57
57
|
should "create a xml document according to xpay spec" do
|
58
58
|
@cus.add_to_xml(@request_xml)
|
59
|
-
assert_equal(
|
59
|
+
assert_equal(load_xml_string("customer"), @request_xml.root.to_s)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -38,7 +38,7 @@ class OperationTest < Test::Unit::TestCase
|
|
38
38
|
end
|
39
39
|
should "create an xml document according to xpay spec" do
|
40
40
|
@ops.add_to_xml(@request_xml)
|
41
|
-
assert_equal
|
41
|
+
assert_equal @request_xml.root.to_s, load_xml_string("operation")
|
42
42
|
end
|
43
43
|
|
44
44
|
end
|
data/test/xpay/payment_test.rb
CHANGED
@@ -53,7 +53,7 @@ class PaymentTest < Test::Unit::TestCase
|
|
53
53
|
context "an empty payment instance with set 3D secure response" do
|
54
54
|
setup do
|
55
55
|
@p = Xpay::Payment.new()
|
56
|
-
@p.send("response_xml=",
|
56
|
+
@p.send("response_xml=", load_xml("response_3d"))
|
57
57
|
end
|
58
58
|
|
59
59
|
should "have a non-empty hash as a response block" do
|
@@ -69,13 +69,12 @@ class PaymentTest < Test::Unit::TestCase
|
|
69
69
|
Xpay::Payment.send(:public, *Xpay::Payment.private_instance_methods)
|
70
70
|
options = {:creditcard => Xpay::CreditCard.new(credit_card("class_test")), :operation => Xpay::Operation.new(operation("class_test")), :customer => Xpay::Customer.new(customer("class_test"))}
|
71
71
|
@p = Xpay::Payment.new(options)
|
72
|
-
@p.send("response_xml=",
|
72
|
+
@p.send("response_xml=", load_xml("response_3d"))
|
73
73
|
|
74
74
|
end
|
75
75
|
should "have a new request_xml after rewrite" do
|
76
76
|
@p.rewrite_request_block
|
77
|
-
assert_equal
|
78
|
-
d { @p.request_xml.to_s }
|
77
|
+
assert_equal @p.request_xml.root.to_s, load_xml_string("request_rewritten")
|
79
78
|
end
|
80
79
|
|
81
80
|
should "have a non-empty hash as a response block" do
|
@@ -89,13 +88,13 @@ class PaymentTest < Test::Unit::TestCase
|
|
89
88
|
|
90
89
|
context "a payment instance created from xml without PaRes" do
|
91
90
|
should "throw error 2500, PaRes missing" do
|
92
|
-
options = {:xml =>
|
91
|
+
options = {:xml => load_xml_string("request_rewritten")}
|
93
92
|
assert_raise(Xpay::PaResMissing) {Xpay::Payment.new(options)}
|
94
93
|
end
|
95
94
|
end
|
96
95
|
context "a payment instance created from xml without PaRes" do
|
97
96
|
setup do
|
98
|
-
options = {:xml =>
|
97
|
+
options = {:xml => load_xml_string("request_rewritten"), :pares => "ABJASDKA+SDKAJ/SGDSAD"}
|
99
98
|
@p = Xpay::Payment.new(options)
|
100
99
|
end
|
101
100
|
should "should have a request_xml document" do
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require 'xpay'
|
3
|
+
|
4
|
+
class TransactionQueryTest < Test::Unit::TestCase
|
5
|
+
context "an empty instance" do
|
6
|
+
should "raise attribute missing error" do
|
7
|
+
assert_raise(Xpay::AttributeMissing) { Xpay::TransactionQuery.new() }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context "an instance with missing site refence " do
|
12
|
+
setup do
|
13
|
+
ops = REXML::XPath.first(Xpay.root_xml, "//Operation")
|
14
|
+
ops.delete_element "SiteReference"
|
15
|
+
end
|
16
|
+
|
17
|
+
should "raise attribute missing error" do
|
18
|
+
assert_raise(Xpay::AttributeMissing) { Xpay::TransactionQuery.new(:transaction_reference => "17-9-1908322", :order_reference => "121-1010272211") }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
context "an instance with empty site refence " do
|
22
|
+
setup do
|
23
|
+
REXML::XPath.first(Xpay.root_xml, "//SiteReference").text = ""
|
24
|
+
end
|
25
|
+
|
26
|
+
should "raise attribute missing error" do
|
27
|
+
assert_raise(Xpay::AttributeMissing) { Xpay::TransactionQuery.new(:transaction_reference => "17-9-1908322", :order_reference => "121-1010272211") }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "a new instance with only a transaction reference" do
|
32
|
+
setup do
|
33
|
+
@t = Xpay::TransactionQuery.new({:transaction_reference => "17-9-1908322"})
|
34
|
+
end
|
35
|
+
|
36
|
+
should "instantiate without error" do
|
37
|
+
assert_instance_of Xpay::TransactionQuery, @t
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "a new instance with only a order reference" do
|
42
|
+
setup do
|
43
|
+
@t = Xpay::TransactionQuery.new({:order_reference => "17-9-1908322"})
|
44
|
+
end
|
45
|
+
|
46
|
+
should "instantiate without error" do
|
47
|
+
assert_instance_of Xpay::TransactionQuery, @t
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "a new instance" do
|
52
|
+
setup do
|
53
|
+
@t = Xpay::TransactionQuery.new({:transaction_reference => "17-9-1908322", :order_reference => "121-1010272211", :site_reference => "site1234"})
|
54
|
+
end
|
55
|
+
|
56
|
+
should "have a the same xml as the module" do
|
57
|
+
assert_equal @t.request_xml.root.to_s, load_xml_string("transactionquery")
|
58
|
+
end
|
59
|
+
|
60
|
+
should "have an empty repsonse block" do
|
61
|
+
assert @t.response_block.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
should "have attributes" do
|
65
|
+
assert @t.respond_to? :transaction_reference
|
66
|
+
assert @t.respond_to? :order_reference
|
67
|
+
assert @t.respond_to? :site_reference
|
68
|
+
assert @t.respond_to? :site_alias
|
69
|
+
end
|
70
|
+
|
71
|
+
context "given a response block" do
|
72
|
+
setup do
|
73
|
+
Xpay::TransactionQuery.send(:public, *Xpay::TransactionQuery.private_instance_methods)
|
74
|
+
@t.send("response_xml=", load_xml("transactionquery_response"))
|
75
|
+
end
|
76
|
+
|
77
|
+
should "have a response block" do
|
78
|
+
assert !@t.response_block.empty?
|
79
|
+
end
|
80
|
+
|
81
|
+
should "have values" do
|
82
|
+
rb = @t.response_block
|
83
|
+
assert_equal "2-2-35117", rb[:transaction_reference]
|
84
|
+
assert_equal "AUTH CODE: ab123", rb[:auth_code]
|
85
|
+
assert_equal 1, rb[:result_code]
|
86
|
+
assert_equal "2004-08-31 16:17:03", rb[:transaction_time]
|
87
|
+
assert_equal "ApTtGHQ/WUQYRj", rb[:transactionverifier]
|
88
|
+
assert_equal "orderref0001", rb[:order_reference]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
data/test/xpay_test.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
require 'xpay'
|
3
|
+
|
3
4
|
class XpayTest < Test::Unit::TestCase
|
4
5
|
context "the xpay module" do
|
5
6
|
setup do
|
@@ -7,22 +8,31 @@ class XpayTest < Test::Unit::TestCase
|
|
7
8
|
end
|
8
9
|
|
9
10
|
should "have standard config xml" do
|
10
|
-
assert_kind_of(REXML::Document
|
11
|
+
assert_kind_of(REXML::Document, @xpay.root_xml)
|
11
12
|
assert_equal @xpay.config, OpenStruct.new(xpay_config("default"))
|
12
13
|
end
|
13
14
|
should "have xml document formed to xpay spec" do
|
14
|
-
assert_equal @xpay.root_xml.root.to_s
|
15
|
+
assert_equal load_xml_string("root"), @xpay.root_xml.root.to_s
|
15
16
|
end
|
17
|
+
|
16
18
|
should "load a new config from yaml file" do
|
17
|
-
assert @xpay.load_config(File.expand_path(File.dirname(__FILE__)+ '/fixtures'))
|
19
|
+
assert @xpay.load_config(File.expand_path(File.dirname(__FILE__) + '/fixtures'))
|
18
20
|
end
|
19
21
|
|
20
|
-
context "with new configuration" do
|
22
|
+
context "with new configuration from yaml file" do
|
21
23
|
|
22
24
|
should "have a new config" do
|
23
25
|
assert_equal @xpay.config, OpenStruct.new(xpay_config("config_load_test"))
|
24
26
|
end
|
25
27
|
|
28
|
+
should "have a new root_xml" do
|
29
|
+
assert_equal load_xml_string("config_load_test"), @xpay.root_xml.root.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
should "have config.port 6000" do
|
33
|
+
assert_equal 6000, @xpay.config.port
|
34
|
+
end
|
35
|
+
|
26
36
|
should "have an environment" do
|
27
37
|
assert_equal @xpay.environment, "development"
|
28
38
|
end
|
@@ -35,7 +45,9 @@ class XpayTest < Test::Unit::TestCase
|
|
35
45
|
should "load a new config from hash" do
|
36
46
|
assert @xpay.set_config(xpay_config("default"))
|
37
47
|
assert_equal @xpay.config, OpenStruct.new(xpay_config("default"))
|
48
|
+
assert_equal load_xml_string("default_config"), @xpay.root_xml.root.to_s
|
38
49
|
end
|
39
50
|
|
40
51
|
end
|
41
52
|
end
|
53
|
+
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xpay
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 6
|
10
|
+
version: 0.0.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Volker Pacher
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-28 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -121,6 +121,7 @@ files:
|
|
121
121
|
- lib/xpay.rb
|
122
122
|
- lib/xpay/transaction.rb
|
123
123
|
- lib/xpay/version.rb
|
124
|
+
- lib/xpay/transaction_query.rb
|
124
125
|
- lib/xpay/core/customer.rb
|
125
126
|
- lib/xpay/core/operation.rb
|
126
127
|
- lib/xpay/core/creditcard.rb
|
@@ -128,22 +129,28 @@ files:
|
|
128
129
|
- rails/init.rb
|
129
130
|
- test/xpay_test.rb
|
130
131
|
- test/fixtures/customer.xml
|
132
|
+
- test/fixtures/config_load_test.xml
|
131
133
|
- test/fixtures/operation.yml
|
134
|
+
- test/fixtures/transactionquery.xml
|
132
135
|
- test/fixtures/operation.xml
|
133
136
|
- test/fixtures/response.xml
|
134
137
|
- test/fixtures/creditcards.yml
|
138
|
+
- test/fixtures/default_config.xml
|
135
139
|
- test/fixtures/customer.yml
|
136
140
|
- test/fixtures/xpay_defaults.yml
|
137
141
|
- test/fixtures/request_rewritten.xml
|
142
|
+
- test/fixtures/transactionquery_response.xml
|
138
143
|
- test/fixtures/response_3d.xml
|
139
144
|
- test/fixtures/root.xml
|
140
145
|
- test/fixtures/config/xpay.yml
|
146
|
+
- test/functional/transactionquery_functional_test.rb
|
141
147
|
- test/functional/payment_functional_test.rb
|
142
148
|
- test/test_helper.rb
|
143
149
|
- test/xpay/core/creditcard_test.rb
|
144
150
|
- test/xpay/core/customer_test.rb
|
145
151
|
- test/xpay/core/operation_test.rb
|
146
152
|
- test/xpay/payment_test.rb
|
153
|
+
- test/xpay/transactionquery_test.rb
|
147
154
|
- LICENSE
|
148
155
|
- UPGRADES
|
149
156
|
- README.rdoc
|