breadmachine 0.0.0 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +48 -4
- data/lib/breadmachine/dto/card.rb +23 -9
- data/lib/breadmachine/dto/customer_info.rb +19 -5
- data/lib/breadmachine/dto/order_info.rb +18 -5
- data/lib/breadmachine/extensions/string.rb +11 -0
- data/lib/breadmachine/extensions.rb +2 -1
- data/lib/breadmachine/secure_trading/auth_request.rb +4 -2
- data/lib/breadmachine/secure_trading/auth_reversal_request.rb +3 -5
- data/lib/breadmachine/secure_trading/auth_reversal_response.rb +6 -1
- data/lib/breadmachine/secure_trading/card_xml.rb +13 -9
- data/lib/breadmachine/secure_trading/payment_methods.rb +18 -6
- data/lib/breadmachine/secure_trading/st_3d_auth_request.rb +32 -10
- data/lib/breadmachine/secure_trading/st_3d_auth_response.rb +20 -11
- data/lib/breadmachine/secure_trading/st_3d_card_query_request.rb +28 -9
- data/lib/breadmachine/secure_trading/st_3d_card_query_response.rb +122 -23
- data/lib/breadmachine/secure_trading/xpay.rb +121 -10
- data/lib/breadmachine/secure_trading/xpay_response.rb +29 -0
- data/lib/breadmachine/secure_trading/xpay_socket.rb +5 -1
- data/lib/breadmachine/secure_trading.rb +4 -2
- data/lib/breadmachine.rb +7 -2
- data/spec/secure_trading/auth_request_spec.rb +12 -7
- data/spec/secure_trading/card_xml_spec.rb +43 -17
- data/spec/secure_trading/order_info_xml_spec.rb +2 -2
- data/spec/secure_trading/st_3d_auth_request_spec.rb +12 -7
- data/spec/secure_trading/st_3d_card_query_request_spec.rb +19 -8
- data/spec/secure_trading/st_3d_card_query_response_spec.rb +87 -30
- data/spec/secure_trading/st_auth_reversal_request_spec.rb +42 -0
- data/spec/secure_trading/xpay_response_spec.rb +26 -0
- data/spec/secure_trading/xpay_socket_spec.rb +15 -2
- data/spec/secure_trading/xpay_spec.rb +19 -2
- metadata +35 -3
- data/spec/secure_trading/st_auth_request_spec.rb +0 -0
data/README.rdoc
CHANGED
@@ -1,18 +1,62 @@
|
|
1
1
|
= breadmachine
|
2
2
|
|
3
|
-
|
3
|
+
Note the version number and consider very carefully whether you really need to
|
4
|
+
use this code.
|
5
|
+
|
6
|
+
Make dough with BreadMachine, a ruby interface for the SecureTrading XPay gateway.
|
7
|
+
|
8
|
+
Should work with XPay v3.51 and v4.0.
|
9
|
+
|
10
|
+
== Installation
|
11
|
+
|
12
|
+
Until we get a config file going, make an initializer called breadmachine.rb
|
13
|
+
in config/initializers, and stick the following into it:
|
14
|
+
|
15
|
+
BreadMachine::SecureTrading.configure do |config|
|
16
|
+
config.currency = 'GBP'
|
17
|
+
config.site_reference = 'yourxpaysitereference'
|
18
|
+
config.term_url = 'http://www.foo.com/your_callback_url'
|
19
|
+
config.merchant_name = "Hubbub"
|
20
|
+
end
|
21
|
+
|
22
|
+
# TODO: check to see that this is absolutely true wrt currency
|
23
|
+
config.currency: the standard ISO reference for your currency
|
24
|
+
|
25
|
+
config.site_reference: provided to you by SecureTrading
|
26
|
+
|
27
|
+
config.term_url: the resource that your ACS will post back to after a 3-D
|
28
|
+
Secure authentication check. If you decide to append any parameters to this
|
29
|
+
when your callback executes (i.e. http://www.foo.com/your_callback_url/123-ordernumber)
|
30
|
+
then remember to include a trailing slash on it - BreadMachine will just concatenate
|
31
|
+
the values together.
|
32
|
+
|
33
|
+
config.merchant_name: provided by SecureTrading
|
34
|
+
|
35
|
+
== Glossary
|
36
|
+
|
37
|
+
The terminology surrounding credit card payment systems is arcane and can cause
|
38
|
+
a lot of confusion. Here are some terms you might need to be familiar with:
|
39
|
+
|
40
|
+
=== 3-D Secure
|
41
|
+
|
42
|
+
The glorious credit card fraud prevention scheme beloved by web developers everywhere.
|
43
|
+
|
44
|
+
=== 3-D Secure ACS
|
45
|
+
|
46
|
+
This is the 3-D Secure Access Control Server, i.e. the 3-D Secure "verified by visa/mastercard" password page which you redirect your users to.
|
4
47
|
|
5
48
|
== Note on Patches/Pull Requests
|
6
|
-
|
49
|
+
|
7
50
|
* Fork the project.
|
8
51
|
* Make your feature addition or bug fix.
|
9
52
|
* Add tests for it. This is important so I don't break it in a
|
10
53
|
future version unintentionally.
|
11
54
|
* Commit, do not mess with rakefile, version, or history.
|
12
55
|
(if you want to have your own version, that is fine but
|
13
|
-
|
56
|
+
bump version in a commit by itself I can ignore when I pull)
|
14
57
|
* Send me a pull request. Bonus points for topic branches.
|
15
58
|
|
16
59
|
== Copyright
|
17
60
|
|
18
|
-
Copyright (c) 2009 Matt Southerden. See LICENSE for details.
|
61
|
+
Copyright (c) 2009 Matt Southerden, Dave Hrycyszyn. See LICENSE for details.
|
62
|
+
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module BreadMachine
|
2
|
-
|
2
|
+
|
3
|
+
# A data transfer object that represents the user's credit card.
|
4
|
+
#
|
3
5
|
class Card
|
4
|
-
|
5
|
-
include BreadMachine::SecureTrading::CardXml
|
6
|
-
|
6
|
+
|
7
7
|
attr_accessor :issuer
|
8
8
|
attr_accessor :number
|
9
9
|
attr_accessor :expiry_date
|
@@ -11,12 +11,26 @@ module BreadMachine
|
|
11
11
|
attr_accessor :issue
|
12
12
|
attr_accessor :security_code
|
13
13
|
attr_accessor :transaction_verifier
|
14
|
-
attr_accessor :
|
15
|
-
|
14
|
+
attr_accessor :transaction_reference
|
15
|
+
|
16
|
+
# Required properties include :issuer, :number, and :expiry_date.
|
17
|
+
#
|
18
|
+
# :issuer should be a downcased string ("amex", "visa", "mastercard")
|
19
|
+
# :number should be an integer
|
20
|
+
# :expiry_date should be a string in the format "mm/yy"
|
21
|
+
#
|
22
|
+
# :issue is required for Solo cards.
|
23
|
+
# :start_date is required for "some" cards. The XPay spec says "for a full
|
24
|
+
# list of cards requiring start_date, please contact your acquiring bank".
|
25
|
+
#
|
26
|
+
# TODO: make expiry_date and start_date into Date objects to save crappy
|
27
|
+
# string munging.
|
28
|
+
#
|
16
29
|
def initialize(attributes = {})
|
17
30
|
attributes.each { |key, value| send("#{key}=", value) }
|
18
31
|
end
|
19
|
-
|
32
|
+
|
20
33
|
end
|
21
|
-
|
22
|
-
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
@@ -1,16 +1,30 @@
|
|
1
1
|
module BreadMachine
|
2
|
-
|
2
|
+
|
3
|
+
# Billing details for customer. This is used by XPay and the acquiring banks
|
4
|
+
# to keep an audit trail for fraud prevention purposes, so it's necessary for
|
5
|
+
# some kinds of auth queries (e.g. AVS checks).
|
6
|
+
#
|
3
7
|
class CustomerInfo
|
4
|
-
|
8
|
+
|
5
9
|
attr_accessor :name_prefix, :first_name, :middle_name, :last_name, :name_suffix,
|
6
10
|
:company, :street, :city, :state, :postcode, :iso_2_country,
|
7
11
|
:telephone, :email,
|
8
12
|
:accept, :user_agent
|
9
|
-
|
13
|
+
|
14
|
+
# XPay doesn't require any of this info for regular transactions, but if
|
15
|
+
# you've got your XPay system set up to decline if an AVS check fails, you'd
|
16
|
+
# better include it.
|
17
|
+
#
|
18
|
+
# 3-D Secure card enrollment checks *require* :user_agent and :accept
|
19
|
+
#
|
20
|
+
# The XPay API reference strongly recommends that all of this info is filled
|
21
|
+
# in, regardless of what kind of API call you're making.
|
22
|
+
#
|
10
23
|
def initialize(attributes = {})
|
11
24
|
attributes.each { |key, value| send("#{key}=", value) }
|
12
25
|
end
|
13
|
-
|
26
|
+
|
14
27
|
end
|
15
|
-
|
28
|
+
|
16
29
|
end
|
30
|
+
|
@@ -1,13 +1,26 @@
|
|
1
1
|
module BreadMachine
|
2
|
-
|
2
|
+
|
3
|
+
# Order reference information for auditing purposes.
|
4
|
+
#
|
3
5
|
class OrderInfo
|
4
|
-
|
6
|
+
|
5
7
|
attr_accessor :order_reference, :order_information
|
6
|
-
|
8
|
+
|
9
|
+
# It is strongly advised that these properties are included in transactions,
|
10
|
+
# but they are not required.
|
11
|
+
#
|
12
|
+
# Suggested usage:
|
13
|
+
#
|
14
|
+
# :order_reference should be something like the order or invoice number.
|
15
|
+
# :order_information could be the first 255 characters of the names of the
|
16
|
+
# items in the order (as an example) - basically anything that can
|
17
|
+
# identify an order in a human-friendly way.
|
18
|
+
#
|
7
19
|
def initialize(attributes = {})
|
8
20
|
attributes.each { |key, value| send("#{key}=", value) }
|
9
21
|
end
|
10
|
-
|
22
|
+
|
11
23
|
end
|
12
|
-
|
24
|
+
|
13
25
|
end
|
26
|
+
|
@@ -1 +1,2 @@
|
|
1
|
-
require 'breadmachine/extensions/money'
|
1
|
+
require 'breadmachine/extensions/money'
|
2
|
+
require 'breadmachine/extensions/string'
|
@@ -3,9 +3,11 @@ module BreadMachine
|
|
3
3
|
|
4
4
|
class AuthRequest
|
5
5
|
|
6
|
-
def initialize(amount, card, customer_info, order_info, settlement_day
|
6
|
+
def initialize(amount, card, customer_info, order_info, settlement_day)
|
7
|
+
raise ArgumentError, 'Currency mismatch' unless amount.currency == BreadMachine::SecureTrading::configuration.currency
|
8
|
+
|
7
9
|
@amount = amount
|
8
|
-
@card = card
|
10
|
+
@card = BreadMachine::SecureTrading::CardXml.new(card)
|
9
11
|
@customer_info = BreadMachine::SecureTrading::CustomerInfoAuthXml.new(customer_info)
|
10
12
|
@order_info = BreadMachine::SecureTrading::OrderInfoXml.new(order_info)
|
11
13
|
@settlement_day = settlement_day
|
@@ -3,14 +3,13 @@ module BreadMachine
|
|
3
3
|
|
4
4
|
class AuthReversalRequest
|
5
5
|
|
6
|
-
def initialize(transaction,
|
6
|
+
def initialize(transaction, order_info)
|
7
7
|
@transaction = transaction
|
8
|
-
@customer_info = BreadMachine::SecureTrading::CustomerInfoAuthXml.new(customer_info)
|
9
8
|
@order_info = BreadMachine::SecureTrading::OrderInfoXml.new(order_info)
|
10
9
|
end
|
11
10
|
|
12
11
|
def response(xml)
|
13
|
-
|
12
|
+
AuthReversalResponse.new(xml)
|
14
13
|
end
|
15
14
|
|
16
15
|
def to_xml
|
@@ -19,14 +18,13 @@ module BreadMachine
|
|
19
18
|
xml.Operation {
|
20
19
|
xml.SiteReference BreadMachine::SecureTrading::configuration.site_reference
|
21
20
|
}
|
22
|
-
# xml << @customer_info.to_xml
|
23
21
|
xml.PaymentMethod {
|
24
22
|
xml.CreditCard {
|
25
23
|
xml.ParentTransactionReference @transaction.transaction_reference
|
26
24
|
xml.TransactionVerifier @transaction.transaction_verifier
|
27
25
|
}
|
28
26
|
}
|
29
|
-
|
27
|
+
xml << @order_info.to_xml
|
30
28
|
}
|
31
29
|
end
|
32
30
|
|
@@ -1,19 +1,23 @@
|
|
1
1
|
module BreadMachine
|
2
2
|
module SecureTrading
|
3
3
|
|
4
|
-
|
4
|
+
class CardXml
|
5
|
+
|
6
|
+
def initialize(card)
|
7
|
+
@card = card
|
8
|
+
end
|
5
9
|
|
6
10
|
def to_xml
|
7
11
|
xml = Builder::XmlMarkup.new(:indent => 2)
|
8
12
|
xml.CreditCard {
|
9
|
-
xml.Type @issuer
|
10
|
-
xml.Number @number
|
11
|
-
xml.ExpiryDate @expiry_date
|
12
|
-
xml.StartDate @start_date
|
13
|
-
xml.Issue @issue
|
14
|
-
xml.SecurityCode @security_code
|
15
|
-
xml.TransactionVerifier @transaction_verifier
|
16
|
-
xml.ParentTransactionReference @
|
13
|
+
xml.Type @card.issuer unless @card.issuer.blank?
|
14
|
+
xml.Number @card.number unless @card.number.blank?
|
15
|
+
xml.ExpiryDate @card.expiry_date unless @card.expiry_date.blank?
|
16
|
+
xml.StartDate @card.start_date unless @card.start_date.blank?
|
17
|
+
xml.Issue @card.issue unless @card.issue.blank?
|
18
|
+
xml.SecurityCode @card.security_code unless @card.security_code.blank?
|
19
|
+
xml.TransactionVerifier @card.transaction_verifier unless @card.transaction_verifier.blank?
|
20
|
+
xml.ParentTransactionReference @card.transaction_reference unless @card.transaction_reference.blank?
|
17
21
|
}
|
18
22
|
end
|
19
23
|
|
@@ -1,13 +1,24 @@
|
|
1
1
|
module BreadMachine
|
2
2
|
module SecureTrading
|
3
|
-
|
3
|
+
|
4
4
|
module PaymentMethods
|
5
|
-
|
5
|
+
|
6
6
|
def auth(*args)
|
7
7
|
request = SecureTrading::AuthRequest.new(*args)
|
8
8
|
return SecureTrading::XPay.exchange(request)
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
|
+
def repeat_auth(*args)
|
12
|
+
request = SecureTrading::AuthRequest.new(*args)
|
13
|
+
return SecureTrading::XPay.exchange(request)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Checks to see whether a card is enrolled in 3-D Secure. Returns a
|
17
|
+
# ST3DCardQueryResponse which can tell us whether the card is enrolled
|
18
|
+
# and what kind of authorisation to perform.
|
19
|
+
#
|
20
|
+
# Arguments are: amount, creditcard, customer_info, order_info
|
21
|
+
#
|
11
22
|
def three_d_secure_enrolled?(*args)
|
12
23
|
request = SecureTrading::St3dCardQueryRequest.new(*args)
|
13
24
|
return SecureTrading::XPay.exchange(request)
|
@@ -17,12 +28,13 @@ module BreadMachine
|
|
17
28
|
request = SecureTrading::St3dAuthRequest.new(*args)
|
18
29
|
return SecureTrading::XPay.exchange(request)
|
19
30
|
end
|
20
|
-
|
31
|
+
|
21
32
|
def reverse(*args)
|
22
33
|
request = SecureTrading::AuthReversalRequest.new(*args)
|
23
34
|
return SecureTrading::XPay.exchange(request)
|
24
35
|
end
|
25
36
|
end
|
26
|
-
|
37
|
+
|
27
38
|
end
|
28
|
-
end
|
39
|
+
end
|
40
|
+
|
@@ -1,22 +1,43 @@
|
|
1
1
|
module BreadMachine
|
2
2
|
module SecureTrading
|
3
|
-
|
3
|
+
|
4
4
|
class St3dAuthRequest
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
# A 3-D Secure auth reqeust to ask XPay to reserve funds at an acquiring
|
7
|
+
# bank, checking whether this card has funds available to cover the given
|
8
|
+
# amount.
|
9
|
+
#
|
10
|
+
# Although XPay doesn't absolutely require all of the order
|
11
|
+
# information etc., BreadMachine does as it's better for history tracking
|
12
|
+
# and is strongly recommended by XPay.
|
13
|
+
#
|
14
|
+
# settlement_day allows you to tell XPay when the auth request should be
|
15
|
+
# queued for settlement. The default, 1 day, will automatically tell
|
16
|
+
# SecureTrading to settle the amount on the day after the auth request.
|
17
|
+
# Note that even if you pass nil to settlement_day, the standard behaviour
|
18
|
+
# of XPay is to queue the auth request for settlement 1 day after the auth
|
19
|
+
# request. Passing a settlement_day of 0 will tell XPay not to settle
|
20
|
+
# without manual intervention.
|
21
|
+
#
|
22
|
+
def initialize(amount, card, customer_info, order_info, three_d_secure, settlement_day)
|
23
|
+
raise ArgumentError, 'Currency mismatch' unless amount.currency == BreadMachine::SecureTrading::configuration.currency
|
24
|
+
|
7
25
|
@amount = amount
|
8
|
-
@card = card
|
9
|
-
@card.parent_transaction_reference = three_d_secure.transaction_reference
|
26
|
+
@card = BreadMachine::SecureTrading::CardXml.new(card)
|
10
27
|
@customer_info = BreadMachine::SecureTrading::CustomerInfoAuthXml.new(customer_info)
|
11
28
|
@order_info = BreadMachine::SecureTrading::OrderInfoXml.new(order_info)
|
12
29
|
@three_d_secure = BreadMachine::SecureTrading::ThreeDSecureCredentialsXml.new(three_d_secure)
|
13
30
|
@settlement_day = settlement_day
|
14
31
|
end
|
15
|
-
|
32
|
+
|
33
|
+
# The specific response for this request to the XPay daemon.
|
34
|
+
#
|
16
35
|
def response(xml)
|
17
36
|
St3dAuthResponse.new(xml)
|
18
37
|
end
|
19
|
-
|
38
|
+
|
39
|
+
# Generate the expected XML for this XPay request.
|
40
|
+
#
|
20
41
|
def to_xml
|
21
42
|
xml = Builder::XmlMarkup.new(:indent => 2)
|
22
43
|
xml.Request("Type" => "ST3DAUTH") {
|
@@ -34,8 +55,9 @@ module BreadMachine
|
|
34
55
|
xml << @order_info.to_xml
|
35
56
|
}
|
36
57
|
end
|
37
|
-
|
58
|
+
|
38
59
|
end
|
39
|
-
|
60
|
+
|
40
61
|
end
|
41
|
-
end
|
62
|
+
end
|
63
|
+
|
@@ -1,25 +1,34 @@
|
|
1
1
|
module BreadMachine
|
2
2
|
module SecureTrading
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
|
4
|
+
# A response object which tells us what happened with a 3-D Secure
|
5
|
+
# AUTH request.
|
6
|
+
#
|
7
|
+
class St3dAuthResponse < XpayResponse
|
8
|
+
|
9
|
+
# Returns true if the AUTH request was successful, i.e. if the funds were
|
10
|
+
# successfully reserved.
|
11
|
+
#
|
10
12
|
def successful?
|
11
13
|
@xml.xpath('//OperationResponse/Result').text == "1"
|
12
14
|
end
|
13
15
|
|
16
|
+
def declined?
|
17
|
+
@xml.xpath('//OperationResponse/Result').text == "2"
|
18
|
+
end
|
19
|
+
|
20
|
+
# A unique identifier for this AUTH transaction.
|
21
|
+
#
|
14
22
|
def transaction_reference
|
15
23
|
@xml.xpath('//OperationResponse/TransactionReference').text
|
16
24
|
end
|
17
|
-
|
25
|
+
|
18
26
|
def transaction_verifier
|
19
27
|
@xml.xpath('//OperationResponse/TransactionVerifier').text
|
20
28
|
end
|
21
|
-
|
29
|
+
|
22
30
|
end
|
23
|
-
|
31
|
+
|
24
32
|
end
|
25
|
-
end
|
33
|
+
end
|
34
|
+
|
@@ -1,19 +1,27 @@
|
|
1
1
|
module BreadMachine
|
2
2
|
module SecureTrading
|
3
|
-
|
3
|
+
|
4
|
+
# A 3-D Secure query to figure out whether a given card is enrolled in
|
5
|
+
# 3-D Secure. Although XPay doesn't absolutely require all of the order
|
6
|
+
# information etc., BreadMachine does as it's better for history tracking
|
7
|
+
# and is strongly recommended by XPay.
|
8
|
+
#
|
4
9
|
class St3dCardQueryRequest
|
5
|
-
|
6
|
-
def initialize(amount, card, customer_info, order_info)
|
10
|
+
|
11
|
+
def initialize(amount, card, customer_info, order_info, options = {})
|
12
|
+
raise ArgumentError, 'Currency mismatch' unless amount.currency == BreadMachine::SecureTrading::configuration.currency
|
13
|
+
|
7
14
|
@amount = amount
|
8
15
|
@customer_info = BreadMachine::SecureTrading::CustomerInfoEnrolmentXml.new(customer_info)
|
9
16
|
@order_info = BreadMachine::SecureTrading::OrderInfoXml.new(order_info)
|
10
|
-
@card = card
|
17
|
+
@card = BreadMachine::SecureTrading::CardXml.new(card)
|
18
|
+
@options = options
|
11
19
|
end
|
12
|
-
|
20
|
+
|
13
21
|
def response(xml)
|
14
22
|
St3dCardQueryResponse.new(xml)
|
15
23
|
end
|
16
|
-
|
24
|
+
|
17
25
|
def to_xml
|
18
26
|
xml = Builder::XmlMarkup.new(:indent => 2)
|
19
27
|
xml.Request("Type" => "ST3DCARDQUERY") {
|
@@ -21,7 +29,7 @@ module BreadMachine
|
|
21
29
|
xml.Amount @amount.cents
|
22
30
|
xml.Currency BreadMachine::SecureTrading::configuration.currency
|
23
31
|
xml.SiteReference BreadMachine::SecureTrading::configuration.site_reference
|
24
|
-
xml.TermUrl
|
32
|
+
xml.TermUrl self.term_url
|
25
33
|
xml.MerchantName BreadMachine::SecureTrading::configuration.merchant_name
|
26
34
|
}
|
27
35
|
xml << @customer_info.to_xml
|
@@ -31,7 +39,18 @@ module BreadMachine
|
|
31
39
|
xml << @order_info.to_xml
|
32
40
|
}
|
33
41
|
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def term_url
|
46
|
+
if @options.key?(:term_url_append)
|
47
|
+
BreadMachine::SecureTrading::configuration.term_url + @options[:term_url_append]
|
48
|
+
else
|
49
|
+
BreadMachine::SecureTrading::configuration.term_url
|
50
|
+
end
|
51
|
+
end
|
34
52
|
end
|
35
|
-
|
53
|
+
|
36
54
|
end
|
37
|
-
end
|
55
|
+
end
|
56
|
+
|
@@ -1,46 +1,145 @@
|
|
1
1
|
module BreadMachine
|
2
2
|
module SecureTrading
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
|
4
|
+
# A response object which tells us what happened with a 3-D Secure
|
5
|
+
# enrollment check.
|
6
|
+
#
|
7
|
+
class St3dCardQueryResponse < XpayResponse
|
8
|
+
|
9
|
+
# Checks whether the request was successfully processed. A true response
|
10
|
+
# does not necessarily mean anything other than the XPay service
|
11
|
+
# acknowledged that it has talked to you successfully.
|
12
|
+
#
|
13
|
+
# From the XPay docs:
|
14
|
+
# self.result '2' means "the request was successfully processed but the
|
15
|
+
# 3-D Secure process cannot be continued". This would happen in the case
|
16
|
+
# of a credit card provider which is not participating in 3-D Secure.
|
17
|
+
#
|
10
18
|
def successful?
|
11
|
-
|
19
|
+
self.result == '1' || self.result == '2'
|
12
20
|
end
|
13
|
-
|
21
|
+
|
22
|
+
# Is the card enrolled in 3-D Secure?
|
23
|
+
#
|
24
|
+
# Returns "Y", "N", "U", "N/A"
|
25
|
+
#
|
26
|
+
# From our reading of the XPay documentation,
|
27
|
+
# N/A (not available) will be returned in cases where the result is an error.
|
28
|
+
# N (no) will be returned if the card is not currently enrolled.
|
29
|
+
# U (unknown) will be returned in cases where the credit card provider
|
30
|
+
# returns an ambiguous response to the enrollment check. You should
|
31
|
+
# redirect the user to a 3-D Secure auth check page in this case.
|
32
|
+
# Y (yes) will be returned if the card is enrolled. You should redirect the
|
33
|
+
# user to a 3-D Secure auth check page in this case.
|
34
|
+
#
|
14
35
|
def enrolled
|
15
|
-
|
16
|
-
'N/A' => :na,
|
17
|
-
'Y' => :yes,
|
18
|
-
'N' => :no,
|
19
|
-
'U' => :unknown
|
20
|
-
}[@xml.xpath('//OperationResponse/Enrolled').text]
|
36
|
+
@xml.xpath('//OperationResponse/Enrolled').text
|
21
37
|
end
|
22
|
-
|
38
|
+
|
39
|
+
# If this is true, you should redirect your user to a 3-D Secure access
|
40
|
+
# control server (ACS) page.
|
41
|
+
#
|
42
|
+
# Result = 1 from the card enrollment query means that the card issuer is
|
43
|
+
# part of 3-D Secure and that a 3-D Secure auth should be performed.
|
44
|
+
#
|
45
|
+
# Enrolled = "Y" means that the card is enrolled in 3-D Secure and that
|
46
|
+
# the user should be redirected to ACS to authenticate.
|
47
|
+
#
|
48
|
+
def three_d_auth_with_redirect?
|
49
|
+
self.result == "1" && enrolled == "Y"
|
50
|
+
end
|
51
|
+
|
52
|
+
# If a card provider is part of 3D-Secure but the card is not enrolled,
|
53
|
+
# it is still necessary to do a 3-D Secure auth request for funds even
|
54
|
+
# though we do not need to redirect the user to the ACS server.
|
55
|
+
#
|
56
|
+
def three_d_auth_without_redirect?
|
57
|
+
self.result == "1" && enrolled != "Y"
|
58
|
+
end
|
59
|
+
|
60
|
+
# If this returns true, you can perform a regular auth check for funds.
|
61
|
+
#
|
62
|
+
def normal_auth?
|
63
|
+
self.result != "1"
|
64
|
+
end
|
65
|
+
|
66
|
+
# A unique reference generated according to the 3-D Secure specification
|
67
|
+
# (currently up to 1024 bytes in base64 format). It will be returned to
|
68
|
+
# the merchant in the case of receiving an <Enrolled> of Y. This can be
|
69
|
+
# used by the merchant to tie up a response obtained from an ACS after the
|
70
|
+
# customer’s authentication process.
|
71
|
+
#
|
23
72
|
def md
|
24
73
|
@xml.xpath('//OperationResponse/MD').text
|
25
74
|
end
|
26
|
-
|
75
|
+
|
76
|
+
# The pa_req contains purchase transaction details upon which ACS
|
77
|
+
# authentication decisions are based.
|
78
|
+
#
|
79
|
+
# If you are making your own customised redirect page instead of using
|
80
|
+
# the <Html> provided then this field MUST be included in that html, as a
|
81
|
+
# hidden field.
|
82
|
+
#
|
27
83
|
def pa_req
|
28
84
|
@xml.xpath('//OperationResponse/PaReq').text
|
29
85
|
end
|
30
|
-
|
86
|
+
|
87
|
+
# The URL of the 3-D Secure ACS page (see README) to redirect to.
|
88
|
+
#
|
31
89
|
def acs_url
|
32
90
|
@xml.xpath('//OperationResponse/AcsUrl').text
|
33
91
|
end
|
34
92
|
|
93
|
+
# The URL which the ACS will send the user to after they have
|
94
|
+
# authenticated.
|
95
|
+
#
|
96
|
+
# This is informational as you passed it in so hopefully you know what it
|
97
|
+
# is. ;)
|
98
|
+
#
|
99
|
+
def term_url
|
100
|
+
@xml.xpath('//OperationResponse/TermUrl').text
|
101
|
+
end
|
102
|
+
|
35
103
|
def transaction_reference
|
36
104
|
@xml.xpath('//OperationResponse/TransactionReference').text
|
37
105
|
end
|
38
|
-
|
106
|
+
|
107
|
+
def transaction_verifier
|
108
|
+
@xml.xpath('//OperationResponse/TransactionVerifier').text
|
109
|
+
end
|
110
|
+
|
39
111
|
def auth_type
|
40
|
-
|
112
|
+
self.result == '1' ?
|
113
|
+
BreadMachine::SecureTrading::St3dAuthRequest :
|
114
|
+
BreadMachine::SecureTrading::AuthRequest
|
41
115
|
end
|
42
|
-
|
116
|
+
|
117
|
+
|
118
|
+
# The ACS HTML POST form returned by the request. This is an extremely
|
119
|
+
# ugly html page containing all of the form parameters needed to identify
|
120
|
+
# the user for a 3-D Secure authentication check. It's possible (and
|
121
|
+
# probably desirable) to make your own page and style it how you want,
|
122
|
+
# including the same parameters, but this page is a good first step
|
123
|
+
# during integration.
|
124
|
+
#
|
125
|
+
# If you need to redirect a user to the 3-D Secure ACS page, you can do
|
126
|
+
# something like
|
127
|
+
#
|
128
|
+
# if response.should_redirect?
|
129
|
+
# render :text => CGI.unescape(response.html)
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
# The returned HTML contains a javascript call which will submit the form
|
133
|
+
# automatically with the correct POST parameters for this request (or
|
134
|
+
# display an ugly HTML page telling the user to click to redirect to
|
135
|
+
# 3-D Secure).
|
136
|
+
#
|
137
|
+
def html
|
138
|
+
@xml.xpath('//OperationResponse/Html').text
|
139
|
+
end
|
140
|
+
|
43
141
|
end
|
44
|
-
|
142
|
+
|
45
143
|
end
|
46
|
-
end
|
144
|
+
end
|
145
|
+
|