global_collect 0.1.0
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/COPYING +11 -0
- data/README.markdown +109 -0
- data/Rakefile +34 -0
- data/VERSION +1 -0
- data/examples/cancel_payment.rb +14 -0
- data/examples/convert_amount.rb +14 -0
- data/examples/get_order_status.rb +15 -0
- data/examples/insert_order_with_payment.rb +37 -0
- data/examples/process_challenged.rb +13 -0
- data/examples/set_payment.rb +23 -0
- data/examples/test_connection.rb +13 -0
- data/global_collect.gemspec +170 -0
- data/lib/global_collect/api_client.rb +71 -0
- data/lib/global_collect/builders/do_refund/credit_card_payment.rb +12 -0
- data/lib/global_collect/builders/do_refund/payment.rb +39 -0
- data/lib/global_collect/builders/insert_order_with_payment/credit_card_online_payment.rb +38 -0
- data/lib/global_collect/builders/insert_order_with_payment/hosted_credit_card_online_payment.rb +4 -0
- data/lib/global_collect/builders/insert_order_with_payment/order.rb +75 -0
- data/lib/global_collect/builders/insert_order_with_payment/payment.rb +25 -0
- data/lib/global_collect/builders/set_payment/payment.rb +23 -0
- data/lib/global_collect/const/payment_product.rb +38 -0
- data/lib/global_collect/const/payment_status.rb +90 -0
- data/lib/global_collect/field_validator.rb +47 -0
- data/lib/global_collect/request_models/base.rb +37 -0
- data/lib/global_collect/request_models/do_refund/credit_card_payment.rb +12 -0
- data/lib/global_collect/request_models/do_refund/payment.rb +39 -0
- data/lib/global_collect/request_models/insert_order_with_payment/credit_card_online_payment.rb +44 -0
- data/lib/global_collect/request_models/insert_order_with_payment/hosted_credit_card_online_payment.rb +19 -0
- data/lib/global_collect/request_models/insert_order_with_payment/order.rb +67 -0
- data/lib/global_collect/request_models/insert_order_with_payment/payment.rb +17 -0
- data/lib/global_collect/request_models/set_payment/payment.rb +17 -0
- data/lib/global_collect/requests/base.rb +43 -0
- data/lib/global_collect/requests/cancel_payment.rb +22 -0
- data/lib/global_collect/requests/composite.rb +23 -0
- data/lib/global_collect/requests/convert_amount.rb +29 -0
- data/lib/global_collect/requests/do_refund.rb +8 -0
- data/lib/global_collect/requests/get_order_status.rb +24 -0
- data/lib/global_collect/requests/insert_order_with_payment.rb +10 -0
- data/lib/global_collect/requests/process_challenged.rb +22 -0
- data/lib/global_collect/requests/set_payment.rb +9 -0
- data/lib/global_collect/requests/simple.rb +39 -0
- data/lib/global_collect/requests/test_connection.rb +8 -0
- data/lib/global_collect/responses/base.rb +73 -0
- data/lib/global_collect/responses/convert_amount/response_methods.rb +8 -0
- data/lib/global_collect/responses/do_refund/response_methods.rb +24 -0
- data/lib/global_collect/responses/get_order_status/v1_response_methods.rb +49 -0
- data/lib/global_collect/responses/get_order_status/v2_response_methods.rb +67 -0
- data/lib/global_collect/responses/insert_order_with_payment/credit_card_online_payment_response_methods.rb +31 -0
- data/lib/global_collect/responses/insert_order_with_payment/hosted_merchant_link_payment_response_methods.rb +16 -0
- data/lib/global_collect/responses/success_row.rb +15 -0
- data/lib/global_collect.rb +81 -0
- data/spec/api_client_spec.rb +93 -0
- data/spec/builders/do_refund/credit_card_payment_spec.rb +32 -0
- data/spec/builders/do_refund/payment_spec.rb +51 -0
- data/spec/builders/insert_order_with_payment/credit_card_online_payment_spec.rb +59 -0
- data/spec/builders/insert_order_with_payment/hosted_credit_card_online_payment_spec.rb +59 -0
- data/spec/builders/insert_order_with_payment/order_spec.rb +88 -0
- data/spec/builders/insert_order_with_payment/payment_spec.rb +37 -0
- data/spec/builders/set_payment/payment_spec.rb +35 -0
- data/spec/field_validator_spec.rb +79 -0
- data/spec/global_collect_spec.rb +43 -0
- data/spec/request_models/base_spec.rb +31 -0
- data/spec/request_models/insert_order_with_payment/credit_card_online_payment_spec.rb +11 -0
- data/spec/request_models/insert_order_with_payment/hosted_credit_card_online_payment_spec.rb +38 -0
- data/spec/requests/base_spec.rb +40 -0
- data/spec/requests/composite_spec.rb +48 -0
- data/spec/requests/convert_amount.rb +34 -0
- data/spec/requests/insert_order_with_payment_spec.rb +60 -0
- data/spec/requests/simple_spec.rb +37 -0
- data/spec/responses/base_spec.rb +59 -0
- data/spec/responses/convert_amount/response_methods_spec.rb +13 -0
- data/spec/responses/do_refund/response_methods_spec.rb +15 -0
- data/spec/responses/get_order_status/v1_response_methods_spec.rb +28 -0
- data/spec/responses/get_order_status/v2_response_methods_spec.rb +28 -0
- data/spec/responses/insert_order_with_payment/credit_card_online_payment_response_methods_spec.rb +13 -0
- data/spec/responses/insert_order_with_payment/hosted_merchant_link_payment_response_methods_spec.rb +13 -0
- data/spec/responses/succcess_row_spec.rb +26 -0
- data/spec/spec_helper.rb +130 -0
- data/spec/support/challenged_iowp_response.xml +51 -0
- data/spec/support/successful_convert_amount_response.xml +29 -0
- data/spec/support/successful_do_refund_response.xml +36 -0
- data/spec/support/successful_get_order_status_v1_response.xml +72 -0
- data/spec/support/successful_get_order_status_v2_response.xml +50 -0
- data/spec/support/successful_hosted_iowp_response.xml +60 -0
- data/spec/support/successful_iowp_response.xml +49 -0
- data/spec/support/successful_process_challenged_response.xml +26 -0
- data/spec/support/unsuccessful_do_refund_response.xml +29 -0
- data/spec/support/unsuccessful_iowp_response.xml +42 -0
- data/spec/support/unsuccessful_process_challenged_response.xml +30 -0
- metadata +213 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
module GlobalCollect
|
2
|
+
class ApiClient
|
3
|
+
include HTTParty
|
4
|
+
# WDL §4 specifies the body should be xml
|
5
|
+
format :xml
|
6
|
+
# WDL §3.1 specifies the content type
|
7
|
+
headers "Content-Type" => "text/xml; charset=utf-8"
|
8
|
+
# WDL §3.6 recommends this timeout
|
9
|
+
DEFAULT_TIMEOUT = 70
|
10
|
+
# Net::HTTP warns that debug_output should not be set in production
|
11
|
+
# because it is a security problem.
|
12
|
+
debug_output(nil)
|
13
|
+
|
14
|
+
|
15
|
+
attr_reader :service, :environment, :authentication
|
16
|
+
def initialize(service, environment, authentication)
|
17
|
+
@serivce = service
|
18
|
+
@environment = environment
|
19
|
+
@authentication = authentication
|
20
|
+
@service_url = ApiClient.service_url(service, environment, authentication)
|
21
|
+
end
|
22
|
+
|
23
|
+
def make_request(request, add_mixins=true)
|
24
|
+
xml = request.to_xml
|
25
|
+
GlobalCollect.wire_logger.info("POST [#{request.action} v#{request.version}] => [#{@service_url}] - body:\n#{xml}")
|
26
|
+
|
27
|
+
response = nil
|
28
|
+
request_time = Benchmark.realtime do
|
29
|
+
response = self.class.post(@service_url,
|
30
|
+
:body => xml,
|
31
|
+
:timeout => DEFAULT_TIMEOUT
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
unless response
|
36
|
+
error_message = "Request [#{request.action} v#{request.version}] => [#{@service_url}] failed! No response!"
|
37
|
+
GlobalCollect.wire_logger.error(error_message)
|
38
|
+
raise error_message
|
39
|
+
end
|
40
|
+
GlobalCollect.wire_logger.info("RESP [#{request.action} v#{request.version}] => #{response.code} - #{request_time} s - body:\n#{response.body}")
|
41
|
+
|
42
|
+
base = GlobalCollect::Responses::Base.new(response.delegate, response.body)
|
43
|
+
raise "Malformed response to #{request.action} request! Body: '#{response.body}'" if base.malformed?
|
44
|
+
request.suggested_response_mixins.each{|m| base.extend(m) } if add_mixins
|
45
|
+
base
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def self.service_url(service, environment, authentication)
|
51
|
+
# WDL §§3.4-5 specify the allowed arguments
|
52
|
+
raise ArgumentError.new("Only [Hosted] Merchant Link is currently supported!") unless [:merchant_link].include?(service)
|
53
|
+
raise ArgumentError.new("Only :test and :production are valid environemnts!") unless [:test, :production].include?(environment)
|
54
|
+
raise ArgumentError.new("Only :ip_check and :client_auth are valid authentication schemes!") unless [:ip_check, :client_auth].include?(authentication)
|
55
|
+
{
|
56
|
+
:merchant_link => {
|
57
|
+
# WDL §3.4 specifies the test environment urls
|
58
|
+
:test => {
|
59
|
+
:ip_check => "https://ps.gcsip.nl/wdl/wdl",
|
60
|
+
:client_auth => "https://ca.gcsip.nl/wdl/wdl"
|
61
|
+
},
|
62
|
+
# WDL §3.5 specifies the prodution environment urls
|
63
|
+
:production => {
|
64
|
+
:ip_check => "https://ps.gcsip.com/wdl/wdl",
|
65
|
+
:client_auth => "https://ca.gcsip.com/wdl/wdl"
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}[service][environment][authentication]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module GlobalCollect::Builders::DoRefund
|
2
|
+
class Payment < Struct.new(:payment)
|
3
|
+
def build(node)
|
4
|
+
node.tag!("PAYMENT") do |payment_node|
|
5
|
+
payment_fields.each do |field|
|
6
|
+
payment_node.tag!(field, payment[field]) if payment[field]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# WDL §5.28 Table 105 specifies general payment fields
|
12
|
+
def payment_fields
|
13
|
+
%w[
|
14
|
+
ORDERID
|
15
|
+
EFFORTID
|
16
|
+
MERCHANTREFERENCE
|
17
|
+
REFERENCEORIGPAYMENT
|
18
|
+
CURRENCYCODE
|
19
|
+
AMOUNT
|
20
|
+
COUNTRYCODE
|
21
|
+
REFUNDDATE
|
22
|
+
SURNAME
|
23
|
+
FIRSTNAME
|
24
|
+
PREFIXSURNAME
|
25
|
+
TITLE
|
26
|
+
COMPANYNAME
|
27
|
+
COMPANYDATA
|
28
|
+
STREET
|
29
|
+
HOUSENUMBER
|
30
|
+
ADDITIONALADDRESSINFO
|
31
|
+
ZIP
|
32
|
+
CITY
|
33
|
+
STATE
|
34
|
+
EMAILADDRESS
|
35
|
+
EMAILTYPEINDICATOR
|
36
|
+
]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module GlobalCollect::Builders::InsertOrderWithPayment
|
2
|
+
class CreditCardOnlinePayment < Payment
|
3
|
+
# WDL §5.28 Table 106 specifies credit card payment fields
|
4
|
+
def payment_fields
|
5
|
+
super + %w[
|
6
|
+
EXPIRYDATE
|
7
|
+
CREDITCARDNUMBER
|
8
|
+
ISSUENUMBER
|
9
|
+
CVV
|
10
|
+
CVVINDICATOR
|
11
|
+
AVSINDICATOR
|
12
|
+
AUTHENTICATIONINDICATOR
|
13
|
+
STTINDICATOR
|
14
|
+
FIRSTNAME
|
15
|
+
PREFIXSURNAME
|
16
|
+
SURNAME
|
17
|
+
STREET
|
18
|
+
HOUSENUMBER
|
19
|
+
CUSTOMERIPADDRESS
|
20
|
+
ADDITIONALADDRESSINFO
|
21
|
+
ZIP
|
22
|
+
CITY
|
23
|
+
STATE
|
24
|
+
PHONENUMBER
|
25
|
+
EMAIL
|
26
|
+
BIRTHDATE
|
27
|
+
DCCINDICATOR
|
28
|
+
ISSUERAMOUNT
|
29
|
+
ISSUERCURRENCYCODE
|
30
|
+
MARGINRATEPERCENTAGE
|
31
|
+
EXCHANGERATESOURCENAME
|
32
|
+
EXCHANGERATE
|
33
|
+
EXCHANGERATEVALIDTO
|
34
|
+
MAC
|
35
|
+
]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module GlobalCollect::Builders::InsertOrderWithPayment
|
2
|
+
class Order < Struct.new(:order)
|
3
|
+
def build(node)
|
4
|
+
node.tag!("ORDER") do |order_node|
|
5
|
+
order_fields.each do |field|
|
6
|
+
order_node.tag!(field, order[field]) if order[field]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# WDL §5.28.1 First table specifies the full list of possible fields
|
12
|
+
def order_fields
|
13
|
+
%w[
|
14
|
+
ORDERID
|
15
|
+
ORDERTYPE
|
16
|
+
AMOUNT
|
17
|
+
AMOUNTSIGN
|
18
|
+
CURRENCYCODE
|
19
|
+
LANGUAGECODE
|
20
|
+
COUNTRYCODE
|
21
|
+
OVERWRITEPAYMENTREFERNCE
|
22
|
+
IPADDRESSCUSTOMER
|
23
|
+
CUSTOMERID
|
24
|
+
MANDATE
|
25
|
+
TITLE
|
26
|
+
FIRSTNAME
|
27
|
+
PREFIXSURNAME
|
28
|
+
SURNAME
|
29
|
+
STREET
|
30
|
+
HOUSENUMBER
|
31
|
+
ADDITIONALADDRESSINFO
|
32
|
+
ZIP
|
33
|
+
CITY
|
34
|
+
STATE
|
35
|
+
SHIPPINGTITLE
|
36
|
+
SHIPPINGFIRSTNAME
|
37
|
+
SHIPPINGPREFIXSURNAME
|
38
|
+
SHIPPINGSURNAME
|
39
|
+
SHIPPINGSTREET
|
40
|
+
SHIPPINGHOUSENUMBER
|
41
|
+
SHIPPINGADDITIONALADDRESSINFO
|
42
|
+
SHIPPINGZIP
|
43
|
+
SHIPPINGCITY
|
44
|
+
SHIPPINGSTATE
|
45
|
+
SHIPPINGCOUNTRYCODE
|
46
|
+
MERCHANTREFERENCE
|
47
|
+
DESCRIPTOR
|
48
|
+
RESELLERID
|
49
|
+
EMAIL
|
50
|
+
EMAILTYPEINDICATOR
|
51
|
+
COMPANYNAME
|
52
|
+
COMPANYDATA
|
53
|
+
SEX
|
54
|
+
VATNUMBER
|
55
|
+
PHONENUMBER
|
56
|
+
FAXNUMBER
|
57
|
+
INVOICENUMBER
|
58
|
+
INVOICETYPE
|
59
|
+
INVOICEDATE
|
60
|
+
INVOICECLASS
|
61
|
+
ORDERDATE
|
62
|
+
BIRTHDATE
|
63
|
+
TEXTQUALIFIER1
|
64
|
+
TEXTQUALIFIER2
|
65
|
+
TEXTQUALIFIER3
|
66
|
+
ADDITIONALDATA
|
67
|
+
STARTDATE
|
68
|
+
ENDDATE
|
69
|
+
NUMBEROFPAYMENTS
|
70
|
+
STEPWEEK
|
71
|
+
STEPMONTH
|
72
|
+
]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module GlobalCollect::Builders::InsertOrderWithPayment
|
2
|
+
class Payment < Struct.new(:payment)
|
3
|
+
def build(node)
|
4
|
+
node.tag!("PAYMENT") do |payment_node|
|
5
|
+
payment_fields.each do |field|
|
6
|
+
payment_node.tag!(field, payment[field]) if payment[field]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# WDL §5.28 Table 105 specifies general payment fields
|
12
|
+
def payment_fields
|
13
|
+
%w[
|
14
|
+
PAYMENTPRODUCTID
|
15
|
+
AMOUNT
|
16
|
+
AMOUNTSIGN
|
17
|
+
CURRENCYCODE
|
18
|
+
LANGUAGECODE
|
19
|
+
COUNTRYCODE
|
20
|
+
HOSTEDINDICATOR
|
21
|
+
RETURNURL
|
22
|
+
]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module GlobalCollect::Builders::SetPayment
|
2
|
+
class Payment < Struct.new(:payment)
|
3
|
+
def build(node)
|
4
|
+
node.tag!("PAYMENT") do |payment_node|
|
5
|
+
payment_fields.each do |field|
|
6
|
+
payment_node.tag!(field, payment[field]) if payment[field]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# WDL §5.33.1 specifies general payment fields
|
12
|
+
def payment_fields
|
13
|
+
%w[
|
14
|
+
ORDERID
|
15
|
+
EFFORTID
|
16
|
+
PAYMENTPRODUCTID
|
17
|
+
AMOUNT
|
18
|
+
CURRENCYCODE
|
19
|
+
DATECOLLECT
|
20
|
+
]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module GlobalCollect::Const
|
2
|
+
module PaymentProduct
|
3
|
+
def self.from_sym(sym)
|
4
|
+
info(sym)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.from_code(code)
|
8
|
+
sym = PRODUCTS.detect{|k,v| v.first == code.to_i }.first
|
9
|
+
from_sym(sym)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def self.info(sym)
|
14
|
+
raise ArgumentError.new("Invalid payment product symbol ''!") unless PRODUCTS[sym]
|
15
|
+
Product.new(sym, *PRODUCTS[sym])
|
16
|
+
end
|
17
|
+
class Product < Struct.new(:symbol, :code, :description)
|
18
|
+
def to_s
|
19
|
+
symbol.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
PRODUCTS = {
|
24
|
+
:visa => [1 , "Visa Online" ],
|
25
|
+
:amex => [2 , "American Express Online"],
|
26
|
+
:mc => [3 , "MasterCard Online" ],
|
27
|
+
:visa_delta => [111, "Visa Delta" ],
|
28
|
+
:maestro => [117, "Maestro" ],
|
29
|
+
:solo => [118, "Solo" ],
|
30
|
+
:visa_electron => [122, "Visa Electron" ],
|
31
|
+
:dankort => [123, "Dankort" ],
|
32
|
+
:laser => [124, "Laser" ],
|
33
|
+
:jcb => [125, "JCB" ],
|
34
|
+
:discover => [128, "Discover" ],
|
35
|
+
:carte_bleue => [130, "Carte Bleue Online" ]
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module GlobalCollect::Const
|
2
|
+
module PaymentStatus
|
3
|
+
def self.from_code(code)
|
4
|
+
code = code.to_i
|
5
|
+
raise ArgumentError.new("Invalid payment status code!") unless STATUSES.key?(code)
|
6
|
+
Status.new(code, *STATUSES[code])
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.from_name(name)
|
10
|
+
code, strings = STATUSES.detect{|k,v| v.first == name }
|
11
|
+
status(code) if code
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
STATUSES = {
|
17
|
+
0 => ["CREATED" , "The payment attempt was created." ],
|
18
|
+
20 => ["PENDING AT MERCHANT" , "The Hosted Merchant Link transaction is waiting for the consumer to be redirected by the merchant to WebCollect." ],
|
19
|
+
25 => ["PENDING AT GLOBALCOLLECT" , "The Hosted Merchant Link transaction is waiting for the consumer to enter missing data on the payment pages of GlobalCollect." ],
|
20
|
+
30 => ["PENDING AT GLOBALCOLLECT" , "The Hosted Merchant Link transaction is waiting for the consumer to be redirected by WebCollect to the payment pages of the bank (optionally after the completion of missing data)." ],
|
21
|
+
50 => ["PENDING AT BANK (Real-time Bank Transfer)/ENROLLED (Credit Card Online)" , "The payment request and consumer have been forwarded to the payment pages of the bank./The payment request and consumer have been forwarded to the authentication pages of the card issuer." ],
|
22
|
+
55 => ["PENDING AT CONSUMER" , "The consumer received all payment details to initiate the transaction. The consumer must go to the (bank) office to initiate the payment." ],
|
23
|
+
60 => ["NOT ENROLLED" , "The consumer is not enrolled for 3D Secure authentications." ],
|
24
|
+
65 => ["PENDING PAYMENT (CONSUMER AT BANK)" , "The consumer is at an office to initiate a transaction. The status isused when the supplier polls the WebCollect database to verify if apayment on an order is (still) possible." ],
|
25
|
+
70 => ["INDOUBT AT BANK" , "The status of the payment is in doubt at the bank." ],
|
26
|
+
100 => ["REJECTED" , "WebCollect rejected the payment instruction." ],
|
27
|
+
120 => ["REJECTED BY BANK" , "The bank rejected the payment." ],
|
28
|
+
125 => ["CANCELLED BY BANK" , "The consumer cancelled the payment while on the bank’s payment pages." ],
|
29
|
+
130 => ["FAILED VERIFICATION" , "The payment has failed." ],
|
30
|
+
140 => ["EXPIRED AT BANK" , "The payment was not completed within the given set time limit by the consumer and is expired. The payment has failed." ],
|
31
|
+
150 => ["TIMED OUT AT BANK" , "WebCollect did not receive information regarding the outcome of the payment at the bank." ],
|
32
|
+
160 => ["DENIED" , "The transaction had been rejected for reasons of suspected fraud." ],
|
33
|
+
170 => ["AUTHORISATION EXPIRED" , "The authorisation is expired because no explicit settlement request was received in time." ],
|
34
|
+
172 => ["AUTHENTICATION_ENROLLMENT_EXPIRED" , "The enrolment period was pending too long." ],
|
35
|
+
175 => ["AUTHENTICATION_VALIDATION_EXPIRED" , "The validation period was pending too long." ],
|
36
|
+
180 => ["INVALED PARES OR NOT COMPLETED" , "The cardholder authentication response from the bank was invalid or not completed." ],
|
37
|
+
200 => ["CARDHOLDER AUTHENTICATED" , "The cardholder was successfully authenticated." ],
|
38
|
+
220 => ["COULD NOT AUTHENTICATE" , "The authentication service was out of order, cardholder could not be authenticated." ],
|
39
|
+
230 => ["CARDHOLDER NOT PARTICIPATING" , "The cardholder is not participating in the 3D Secure authentication program." ],
|
40
|
+
280 => ["INVALED PARES OR NOT COMPLETED" , "The cardholder authentication response from the bank was invalid or not completed. Authorization not possible." ],
|
41
|
+
300 => ["AUTHORISATION TESTED" , "Authorisation tested. This payment will be re-authorised and settled offline." ],
|
42
|
+
310 => ["NOT ENROLLED" , "The consumer is not enrolled for 3D Secure authentications. Authorization not possible." ],
|
43
|
+
320 => ["COULD NOT AUTHENTICATE" , "The authentication service was out of order, cardholder could not be authenticated. Authorization not possible." ],
|
44
|
+
330 => ["CARDHOLDER NOT PARTICIPATING" , "The cardholder is not participating in the 3D Secure authentication program. Authorization not possible." ],
|
45
|
+
350 => ["CARDHOLDER AUTHENTICATED" , "The cardholder was successfully authenticated. Authorization not possible." ],
|
46
|
+
400 => ["REVISED" , "The consumer or WebCollect has revised the payment (with other payment product)." ],
|
47
|
+
525 => ["CHALLENGED" , "The payment was challenged by your Fraud Ruleset and is pending. Use Process Challenged API or Web Payment Console if you choose to process further." ],
|
48
|
+
550 => ["REFERRED" , "The payment was referred. A ‘manual’ authorisation attempt will be made shortly." ],
|
49
|
+
600 => ["PENDING" , "The payment instruction is pending waiting for a mandate (direct debit), settlement (credit card online) or acceptation (recurringorders)." ],
|
50
|
+
650 => ["PENDING VERIFICATION" , "The real-time bank payment is pending verification by the batch process. If followed by 50 PENDING AT BANK, the verificationcould not be carried out successfully." ],
|
51
|
+
800 => ["READY" , "GlobalCollect accepted the payment instruction. For Credit Card Online the payment is authorized, but not yet settled. For a Real-time Bank Transfer the return message from the bank indicates that the payment was successful."],
|
52
|
+
850 => ["MARKED FOR SENDING" , "Temporary status. The payment instruction was accepted and is being further processed." ],
|
53
|
+
900 => ["SENT" , "Temporary status. The payment instruction was accepted and is being further processed." ],
|
54
|
+
900 => ["PROCESSED" , "The refund was processed." ],
|
55
|
+
950 => ["INVOICE_SENT" , "The invoice was printed and sent." ],
|
56
|
+
975 => ["SETTLEMENT IN PROGRESS" , "The settlement file was sent for processing at the financiali nstitution." ],
|
57
|
+
1000 => ["PAID" , "The payment was paid." ],
|
58
|
+
1010 => ["ACCOUNT DEBITED" , "GlobalCollect debited the consumer account." ],
|
59
|
+
1020 => ["CORRECTED" , "GlobalCollect corrected the payment information given." ],
|
60
|
+
1030 => ["WITHDRAWN CHARGEBACK" , "The chargeback has been withdrawn." ],
|
61
|
+
1050 => ["REMITTED" , "The funds have been made available for remittance to the merchant." ],
|
62
|
+
1100 => ["REJECTED" , "GlobalCollect rejected the payment attempt." ],
|
63
|
+
1110 => ["REFUSED BY ACCEPTING BANK" , "The acquiring bank rejected the direct debit." ],
|
64
|
+
1120 => ["REFUSED SETTLEMENT" , "Refused settlement before payment from Acquirer." ],
|
65
|
+
1150 => ["REFUSED SETTLEMENT" , "Refused settlement after payment from Acquirer" ],
|
66
|
+
1210 => ["REFUSED BY CONSUMER BANK" , "The bank of the consumer rejected the direct debit." ],
|
67
|
+
1250 => ["BOUNCED" , "The payment bounced." ],
|
68
|
+
1500 => ["CHARGED BACK BY CONSUMER" , "The payment was charged back by the consumer." ],
|
69
|
+
1510 => ["REVERSAL BY CONSUMER" , "The consumer reversed the direct debit payment." ],
|
70
|
+
1520 => ["REVERSED" , "The payment was reversed." ],
|
71
|
+
1800 => ["REFUNDED" , "The payment was refunded." ],
|
72
|
+
1810 => ["CORRECTED REFUND" , "GlobalCollect corrected the refund information given." ],
|
73
|
+
1850 => ["REFUSED REFUND" , "Refund is refused by the Acquirer" ],
|
74
|
+
2000 => ["ACCOUNT CREDITED" , "GlobalCollect credited the consumer account." ],
|
75
|
+
2030 => ["WITHDRAWN REVERSED PAYOUT" , "Withdrawn Reversed Payout" ],
|
76
|
+
2110 => ["REJECTED BY GLOBALCOLLECT" , "GlobalCollect rejected the payout attempt." ],
|
77
|
+
2120 => ["REFUSED BY ACCEPTING BANK" , "The acquiring bank rejected the payout attempt." ],
|
78
|
+
2130 => ["REFUSED BY CONSUMER BANK" , "The consumer bank rejected the payout attempt." ],
|
79
|
+
2210 => ["REVERSAL BY CONSUMER" , "The consumer reversed the payout." ],
|
80
|
+
2220 => ["REVERSED" , "The payout was reversed." ],
|
81
|
+
99999 => ["CANCELLED" , "Payment/Refund/Payout attempt was cancelled by the merchant." ]
|
82
|
+
}
|
83
|
+
|
84
|
+
class Status < Struct.new(:code, :name, :description)
|
85
|
+
def to_s
|
86
|
+
name
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module GlobalCollect
|
2
|
+
# WDL §5 TABLE 10 specifies the tokens and their meaning
|
3
|
+
class FieldValidator
|
4
|
+
def initialize(token, required)
|
5
|
+
if token =~ /([A-Z]{1,2})(\d+)?/
|
6
|
+
@type = $1
|
7
|
+
@size = $2.to_i
|
8
|
+
@required = (required == "R")
|
9
|
+
else
|
10
|
+
raise ArgumentError.new("Invalid validation token '#{token}'!")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_sym
|
15
|
+
case @type
|
16
|
+
when "D" then :datetime
|
17
|
+
when "AN" then :alphanumeric
|
18
|
+
when "N" then :numeric
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
"<FieldValidator #{to_sym}[#{@size}]>"
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate(value)
|
27
|
+
return false if @required && value.nil?
|
28
|
+
return true if !@required && value.nil?
|
29
|
+
value = value.to_s
|
30
|
+
case @type
|
31
|
+
# Examples throughout §5 suggest this date format.
|
32
|
+
# See §5.1.3. Example for instance.
|
33
|
+
when "D"
|
34
|
+
size = @size.zero? ? 14 : @size
|
35
|
+
return !!(value =~ /^\d{#{size}}$/) && (!!Time.parse(value) rescue false)
|
36
|
+
# This is a liberal interpretation of alphanumeric, but examples like
|
37
|
+
# §5.3.1 (IPADDRESS), §5.28.1 (CITY) suggest that spaces and punctuation
|
38
|
+
# are acceptable as well. This leaves us just checking max size.
|
39
|
+
when "AN"
|
40
|
+
return (value.size <= @size)
|
41
|
+
# §5.28.1 (AMOUNT) seems to allow for size <= the specifier.
|
42
|
+
when "N"
|
43
|
+
return !!(value =~ /^\d{1,#{@size}}$/)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|