breadmachine 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|