xpay 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +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
|