activemerchant 1.29.1 → 1.34.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/CHANGELOG +143 -0
- data/CONTRIBUTORS +43 -0
- data/README.md +59 -51
- data/lib/active_merchant/billing/check.rb +15 -14
- data/lib/active_merchant/billing/credit_card.rb +14 -5
- data/lib/active_merchant/billing/credit_card_formatting.rb +8 -8
- data/lib/active_merchant/billing/gateway.rb +2 -2
- data/lib/active_merchant/billing/gateways/authorize_net.rb +36 -8
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +17 -5
- data/lib/active_merchant/billing/gateways/balanced.rb +9 -3
- data/lib/active_merchant/billing/gateways/banwire.rb +15 -1
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +8 -1
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -2
- data/lib/active_merchant/billing/gateways/beanstream.rb +26 -24
- data/lib/active_merchant/billing/gateways/blue_pay.rb +201 -187
- data/lib/active_merchant/billing/gateways/bogus.rb +1 -1
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +7 -3
- data/lib/active_merchant/billing/gateways/card_stream_modern.rb +155 -0
- data/lib/active_merchant/billing/gateways/cc5.rb +156 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +55 -22
- data/lib/active_merchant/billing/gateways/data_cash.rb +3 -3
- data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
- data/lib/active_merchant/billing/gateways/eway.rb +114 -171
- data/lib/active_merchant/billing/gateways/eway_managed.rb +52 -22
- data/lib/active_merchant/billing/gateways/finansbank.rb +22 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +314 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +0 -4
- data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +13 -2
- data/lib/active_merchant/billing/gateways/iridium.rb +8 -2
- data/lib/active_merchant/billing/gateways/litle.rb +354 -105
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +28 -7
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +44 -9
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +190 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +4 -6
- data/lib/active_merchant/billing/gateways/moneris_us.rb +1 -1
- data/lib/active_merchant/billing/gateways/nab_transact.rb +20 -3
- data/lib/active_merchant/billing/gateways/net_registry.rb +8 -3
- data/lib/active_merchant/billing/gateways/netaxept.rb +65 -117
- data/lib/active_merchant/billing/gateways/netbilling.rb +1 -0
- data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +7 -5
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +43 -18
- data/lib/active_merchant/billing/gateways/orbital.rb +190 -53
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +12 -10
- data/lib/active_merchant/billing/gateways/payment_express.rb +62 -1
- data/lib/active_merchant/billing/gateways/paymill.rb +179 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +12 -7
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +14 -9
- data/lib/active_merchant/billing/gateways/paypal_express.rb +59 -18
- data/lib/active_merchant/billing/gateways/pin.rb +165 -0
- data/lib/active_merchant/billing/gateways/qbms.rb +3 -2
- data/lib/active_merchant/billing/gateways/quickpay.rb +66 -28
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +16 -11
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +1 -1
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +21 -16
- data/lib/active_merchant/billing/gateways/sage.rb +10 -5
- data/lib/active_merchant/billing/gateways/sage_pay.rb +7 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +1 -1
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +233 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +49 -21
- data/lib/active_merchant/billing/gateways/transnational.rb +239 -0
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -4
- data/lib/active_merchant/billing/gateways/webpay.rb +8 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +15 -9
- data/lib/active_merchant/billing/gateways/worldpay.rb +60 -24
- data/lib/active_merchant/billing/integrations/direc_pay/status.rb +1 -1
- data/lib/active_merchant/billing/integrations/direc_pay.rb +1 -1
- data/lib/active_merchant/billing/integrations/dwolla/common.rb +23 -0
- data/lib/active_merchant/billing/integrations/dwolla/helper.rb +18 -6
- data/lib/active_merchant/billing/integrations/dwolla/notification.rb +16 -7
- data/lib/active_merchant/billing/integrations/dwolla/return.rb +16 -5
- data/lib/active_merchant/billing/integrations/dwolla.rb +5 -12
- data/lib/active_merchant/billing/integrations/notification.rb +13 -8
- data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +19 -3
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +39 -31
- data/lib/active_merchant/billing/integrations/payu_in/helper.rb +74 -0
- data/lib/active_merchant/billing/integrations/payu_in/notification.rb +167 -0
- data/lib/active_merchant/billing/integrations/payu_in/return.rb +53 -0
- data/lib/active_merchant/billing/integrations/payu_in.rb +43 -0
- data/lib/active_merchant/billing/integrations/pxpay/helper.rb +1 -0
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +13 -10
- data/lib/active_merchant/billing/integrations/quickpay/notification.rb +78 -15
- data/lib/active_merchant/billing/integrations/rbkmoney/helper.rb +23 -0
- data/lib/active_merchant/billing/integrations/rbkmoney/notification.rb +91 -0
- data/lib/active_merchant/billing/integrations/rbkmoney.rb +17 -0
- data/lib/active_merchant/billing/integrations/robokassa/common.rb +1 -1
- data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +7 -3
- data/lib/active_merchant/billing/integrations/world_pay.rb +15 -8
- data/lib/active_merchant/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +124 -50
- metadata.gz.sig +0 -0
|
@@ -32,8 +32,8 @@ module ActiveMerchant #:nodoc:
|
|
|
32
32
|
API_VERSION = "5.6"
|
|
33
33
|
|
|
34
34
|
POST_HEADERS = {
|
|
35
|
-
"MIME-Version" => "1.
|
|
36
|
-
"Content-Type" => "
|
|
35
|
+
"MIME-Version" => "1.1",
|
|
36
|
+
"Content-Type" => "application/PTI56",
|
|
37
37
|
"Content-transfer-encoding" => "text",
|
|
38
38
|
"Request-number" => '1',
|
|
39
39
|
"Document-type" => "Request",
|
|
@@ -80,6 +80,63 @@ module ActiveMerchant #:nodoc:
|
|
|
80
80
|
"EUR" => '978'
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
# INDUSTRY TYPES
|
|
84
|
+
ECOMMERCE_TRANSACTION = 'EC'
|
|
85
|
+
RECURRING_PAYMENT_TRANSACTION = 'RC'
|
|
86
|
+
MAIL_ORDER_TELEPHONE_ORDER_TRANSACTION = 'MO'
|
|
87
|
+
INTERACTIVE_VOICE_RESPONSE = 'IV'
|
|
88
|
+
# INTERACTIVE_VOICE_RESPONSE = 'IN'
|
|
89
|
+
|
|
90
|
+
# Auth Only No Capture
|
|
91
|
+
AUTH_ONLY = 'A'
|
|
92
|
+
# AC - Auth and Capture = 'AC'
|
|
93
|
+
AUTH_AND_CAPTURE = 'AC'
|
|
94
|
+
# F - Force Auth No Capture and no online authorization = 'F'
|
|
95
|
+
FORCE_AUTH_ONLY = 'F'
|
|
96
|
+
# FR - Force Auth No Capture and no online authorization = 'FR'
|
|
97
|
+
# FC - Force Auth and Capture no online authorization = 'FC'
|
|
98
|
+
FORCE_AUTH_AND_CAPTURE = 'FC'
|
|
99
|
+
# Refund and Capture no online authorization
|
|
100
|
+
REFUND = 'R'
|
|
101
|
+
|
|
102
|
+
# Tax Inds
|
|
103
|
+
TAX_NOT_PROVIDED = 0
|
|
104
|
+
TAX_INCLUDED = 1
|
|
105
|
+
NON_TAXABLE_TRANSACTION = 2
|
|
106
|
+
|
|
107
|
+
# Customer Profile Actions
|
|
108
|
+
CREATE = 'C'
|
|
109
|
+
RETRIEVE = 'R'
|
|
110
|
+
UPDATE = 'U'
|
|
111
|
+
DELETE = 'D'
|
|
112
|
+
|
|
113
|
+
RECURRING = 'R'
|
|
114
|
+
DEFERRED = 'D'
|
|
115
|
+
|
|
116
|
+
# Status
|
|
117
|
+
# Profile Status Flag
|
|
118
|
+
# This field is used to set the status of a Customer Profile.
|
|
119
|
+
ACTIVE = 'A'
|
|
120
|
+
INACTIVE = 'I'
|
|
121
|
+
MANUAL_SUSPEND = 'MS'
|
|
122
|
+
|
|
123
|
+
# CustomerProfileOrderOverrideInd
|
|
124
|
+
# Defines if any Order Data can be pre-populated from
|
|
125
|
+
# the Customer Reference Number (CustomerRefNum)
|
|
126
|
+
NO_MAPPING_TO_ORDER_DATA = 'NO'
|
|
127
|
+
USE_CRN_FOR_ORDER_ID = 'OI'
|
|
128
|
+
USE_CRN_FOR_COMMENTS = 'OD'
|
|
129
|
+
USE_CRN_FOR_ORDER_ID_AND_COMMENTS = 'OA'
|
|
130
|
+
|
|
131
|
+
# CustomerProfileFromOrderInd
|
|
132
|
+
# Method to use to Generate the Customer Profile Number
|
|
133
|
+
# When Customer Profile Action Type = Create, defines
|
|
134
|
+
# what the Customer Profile Number will be:
|
|
135
|
+
AUTO_GENERATE = 'A' # Auto-Generate the CustomerRefNum
|
|
136
|
+
USE_CUSTOMER_REF_NUM = 'S' # Use CustomerRefNum field
|
|
137
|
+
USE_ORDER_ID = 'O' # Use OrderID field
|
|
138
|
+
USE_COMMENTS = 'D' # Use Comments field
|
|
139
|
+
|
|
83
140
|
def initialize(options = {})
|
|
84
141
|
requires!(options, :merchant_id)
|
|
85
142
|
requires!(options, :login, :password) unless options[:ip_authentication]
|
|
@@ -88,22 +145,28 @@ module ActiveMerchant #:nodoc:
|
|
|
88
145
|
|
|
89
146
|
# A – Authorization request
|
|
90
147
|
def authorize(money, creditcard, options = {})
|
|
91
|
-
order = build_new_order_xml(
|
|
148
|
+
order = build_new_order_xml(AUTH_ONLY, money, options) do |xml|
|
|
92
149
|
add_creditcard(xml, creditcard, options[:currency]) unless creditcard.nil? && options[:profile_txn]
|
|
93
150
|
add_address(xml, creditcard, options)
|
|
94
|
-
|
|
151
|
+
if @options[:customer_profiles]
|
|
152
|
+
add_customer_data(xml, options)
|
|
153
|
+
add_managed_billing(xml, options)
|
|
154
|
+
end
|
|
95
155
|
end
|
|
96
|
-
commit(order, :authorize)
|
|
156
|
+
commit(order, :authorize, options[:trace_number])
|
|
97
157
|
end
|
|
98
158
|
|
|
99
159
|
# AC – Authorization and Capture
|
|
100
160
|
def purchase(money, creditcard, options = {})
|
|
101
|
-
order = build_new_order_xml(
|
|
161
|
+
order = build_new_order_xml(AUTH_AND_CAPTURE, money, options) do |xml|
|
|
102
162
|
add_creditcard(xml, creditcard, options[:currency]) unless creditcard.nil? && options[:profile_txn]
|
|
103
163
|
add_address(xml, creditcard, options)
|
|
104
|
-
|
|
164
|
+
if @options[:customer_profiles]
|
|
165
|
+
add_customer_data(xml, options)
|
|
166
|
+
add_managed_billing(xml, options)
|
|
167
|
+
end
|
|
105
168
|
end
|
|
106
|
-
commit(order, :purchase)
|
|
169
|
+
commit(order, :purchase, options[:trace_number])
|
|
107
170
|
end
|
|
108
171
|
|
|
109
172
|
# MFC - Mark For Capture
|
|
@@ -113,11 +176,11 @@ module ActiveMerchant #:nodoc:
|
|
|
113
176
|
|
|
114
177
|
# R – Refund request
|
|
115
178
|
def refund(money, authorization, options = {})
|
|
116
|
-
order = build_new_order_xml(
|
|
179
|
+
order = build_new_order_xml(REFUND, money, options.merge(:authorization => authorization)) do |xml|
|
|
117
180
|
add_refund(xml, options[:currency])
|
|
118
181
|
xml.tag! :CustomerRefNum, options[:customer_ref_num] if @options[:customer_profiles] && options[:profile_txn]
|
|
119
182
|
end
|
|
120
|
-
commit(order, :refund)
|
|
183
|
+
commit(order, :refund, options[:trace_number])
|
|
121
184
|
end
|
|
122
185
|
|
|
123
186
|
def credit(money, authorization, options= {})
|
|
@@ -125,10 +188,14 @@ module ActiveMerchant #:nodoc:
|
|
|
125
188
|
refund(money, authorization, options)
|
|
126
189
|
end
|
|
127
190
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
191
|
+
def void(authorization, options = {}, deprecated = {})
|
|
192
|
+
if(!options.kind_of?(Hash))
|
|
193
|
+
deprecated("Calling the void method with an amount parameter is deprecated and will be removed in a future version.")
|
|
194
|
+
return void(options, deprecated.merge(:amount => authorization))
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
order = build_void_request_xml(authorization, options)
|
|
198
|
+
commit(order, :void, options[:trace_number])
|
|
132
199
|
end
|
|
133
200
|
|
|
134
201
|
|
|
@@ -154,25 +221,25 @@ module ActiveMerchant #:nodoc:
|
|
|
154
221
|
# 'MS' - Manual Suspend
|
|
155
222
|
|
|
156
223
|
def add_customer_profile(creditcard, options = {})
|
|
157
|
-
options.merge!(:customer_profile_action =>
|
|
224
|
+
options.merge!(:customer_profile_action => CREATE)
|
|
158
225
|
order = build_customer_request_xml(creditcard, options)
|
|
159
226
|
commit(order, :add_customer_profile)
|
|
160
227
|
end
|
|
161
228
|
|
|
162
229
|
def update_customer_profile(creditcard, options = {})
|
|
163
|
-
options.merge!(:customer_profile_action =>
|
|
230
|
+
options.merge!(:customer_profile_action => UPDATE)
|
|
164
231
|
order = build_customer_request_xml(creditcard, options)
|
|
165
232
|
commit(order, :update_customer_profile)
|
|
166
233
|
end
|
|
167
234
|
|
|
168
235
|
def retrieve_customer_profile(customer_ref_num)
|
|
169
|
-
options = {:customer_profile_action =>
|
|
236
|
+
options = {:customer_profile_action => RETRIEVE, :customer_ref_num => customer_ref_num}
|
|
170
237
|
order = build_customer_request_xml(nil, options)
|
|
171
238
|
commit(order, :retrieve_customer_profile)
|
|
172
239
|
end
|
|
173
240
|
|
|
174
241
|
def delete_customer_profile(customer_ref_num)
|
|
175
|
-
options = {:customer_profile_action =>
|
|
242
|
+
options = {:customer_profile_action => DELETE, :customer_ref_num => customer_ref_num}
|
|
176
243
|
order = build_customer_request_xml(nil, options)
|
|
177
244
|
commit(order, :delete_customer_profile)
|
|
178
245
|
end
|
|
@@ -192,12 +259,12 @@ module ActiveMerchant #:nodoc:
|
|
|
192
259
|
xml.tag! :CustomerRefNum, options[:customer_ref_num]
|
|
193
260
|
else
|
|
194
261
|
if options[:customer_ref_num]
|
|
195
|
-
xml.tag! :CustomerProfileFromOrderInd,
|
|
262
|
+
xml.tag! :CustomerProfileFromOrderInd, USE_CUSTOMER_REF_NUM
|
|
196
263
|
xml.tag! :CustomerRefNum, options[:customer_ref_num]
|
|
197
264
|
else
|
|
198
|
-
xml.tag! :CustomerProfileFromOrderInd,
|
|
265
|
+
xml.tag! :CustomerProfileFromOrderInd, AUTO_GENERATE
|
|
199
266
|
end
|
|
200
|
-
xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] ||
|
|
267
|
+
xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] || NO_MAPPING_TO_ORDER_DATA
|
|
201
268
|
end
|
|
202
269
|
end
|
|
203
270
|
|
|
@@ -211,32 +278,51 @@ module ActiveMerchant #:nodoc:
|
|
|
211
278
|
end
|
|
212
279
|
|
|
213
280
|
def add_address(xml, creditcard, options)
|
|
214
|
-
if
|
|
281
|
+
if(address = (options[:billing_address] || options[:address]))
|
|
215
282
|
avs_supported = AVS_SUPPORTED_COUNTRIES.include?(address[:country].to_s)
|
|
216
283
|
|
|
217
284
|
if avs_supported
|
|
218
|
-
xml.tag! :AVSzip, address[:zip]
|
|
219
|
-
xml.tag! :AVSaddress1, address[:address1]
|
|
220
|
-
xml.tag! :AVSaddress2, address[:address2]
|
|
221
|
-
xml.tag! :AVScity, address[:city]
|
|
222
|
-
xml.tag! :AVSstate,
|
|
223
|
-
xml.tag! :AVSphoneNum,
|
|
285
|
+
xml.tag! :AVSzip, (address[:zip] ? address[:zip].to_s[0..9] : nil)
|
|
286
|
+
xml.tag! :AVSaddress1, (address[:address1] ? address[:address1][0..29] : nil)
|
|
287
|
+
xml.tag! :AVSaddress2, (address[:address2] ? address[:address2][0..29] : nil)
|
|
288
|
+
xml.tag! :AVScity, (address[:city] ? address[:city][0..19] : nil)
|
|
289
|
+
xml.tag! :AVSstate, address[:state]
|
|
290
|
+
xml.tag! :AVSphoneNum, (address[:phone] ? address[:phone].scan(/\d/).join.to_s[0..13] : nil)
|
|
224
291
|
end
|
|
225
|
-
|
|
226
|
-
xml.tag! :
|
|
292
|
+
# can't look in billing address?
|
|
293
|
+
xml.tag! :AVSname, ((creditcard && creditcard.name) ? creditcard.name[0..29] : nil)
|
|
294
|
+
xml.tag! :AVScountryCode, (avs_supported ? address[:country] : '')
|
|
295
|
+
|
|
296
|
+
# Needs to come after AVScountryCode
|
|
297
|
+
add_destination_address(xml, address) if avs_supported
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def add_destination_address(xml, address)
|
|
302
|
+
if address[:dest_zip]
|
|
303
|
+
xml.tag! :AVSDestzip, (address[:dest_zip] ? address[:dest_zip].to_s[0..9] : nil)
|
|
304
|
+
xml.tag! :AVSDestaddress1, (address[:dest_address1] ? address[:dest_address1][0..29] : nil)
|
|
305
|
+
xml.tag! :AVSDestaddress2, (address[:dest_address2] ? address[:dest_address2][0..29] : nil)
|
|
306
|
+
xml.tag! :AVSDestcity, (address[:dest_city] ? address[:dest_city][0..19] : nil)
|
|
307
|
+
xml.tag! :AVSDeststate, address[:dest_state]
|
|
308
|
+
xml.tag! :AVSDestphoneNum, (address[:dest_phone] ? address[:dest_phone].scan(/\d/).join.to_s[0..13] : nil)
|
|
309
|
+
|
|
310
|
+
xml.tag! :AVSDestname, (address[:dest_name] ? address[:dest_name][0..29] : nil)
|
|
311
|
+
xml.tag! :AVSDestcountryCode, address[:dest_country]
|
|
227
312
|
end
|
|
228
313
|
end
|
|
229
314
|
|
|
230
315
|
# For Profile requests
|
|
231
316
|
def add_customer_address(xml, options)
|
|
232
|
-
if
|
|
233
|
-
xml.tag! :CustomerAddress1, address[:address1]
|
|
234
|
-
xml.tag! :CustomerAddress2, address[:address2]
|
|
235
|
-
xml.tag! :CustomerCity, address[:city]
|
|
317
|
+
if(address = (options[:billing_address] || options[:address]))
|
|
318
|
+
xml.tag! :CustomerAddress1, (address[:address1] ? address[:address1][0..29] : nil)
|
|
319
|
+
xml.tag! :CustomerAddress2, (address[:address2] ? address[:address2][0..29] : nil)
|
|
320
|
+
xml.tag! :CustomerCity, (address[:city] ? address[:city][0..19] : nil)
|
|
236
321
|
xml.tag! :CustomerState, address[:state]
|
|
237
|
-
xml.tag! :CustomerZIP, address[:zip]
|
|
238
|
-
xml.tag! :
|
|
239
|
-
xml.tag! :
|
|
322
|
+
xml.tag! :CustomerZIP, (address[:zip] ? address[:zip].to_s[0..9] : nil)
|
|
323
|
+
xml.tag! :CustomerEmail, address[:email].to_s[0..49] if address[:email]
|
|
324
|
+
xml.tag! :CustomerPhone, (address[:phone] ? address[:phone].scan(/\d/).join.to_s : nil)
|
|
325
|
+
xml.tag! :CustomerCountryCode, (address[:country] ? address[:country][0..1] : nil)
|
|
240
326
|
end
|
|
241
327
|
end
|
|
242
328
|
|
|
@@ -257,7 +343,7 @@ module ActiveMerchant #:nodoc:
|
|
|
257
343
|
# Do not submit the attribute at all.
|
|
258
344
|
# - http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf
|
|
259
345
|
if %w( visa discover ).include?(creditcard.brand)
|
|
260
|
-
xml.tag! :CardSecValInd, creditcard.verification_value? ? '1' : '9'
|
|
346
|
+
xml.tag! :CardSecValInd, (creditcard.verification_value? ? '1' : '9')
|
|
261
347
|
end
|
|
262
348
|
xml.tag! :CardSecVal, creditcard.verification_value if creditcard.verification_value?
|
|
263
349
|
end
|
|
@@ -269,6 +355,27 @@ module ActiveMerchant #:nodoc:
|
|
|
269
355
|
xml.tag! :CurrencyExponent, '2' # Will need updating to support currencies such as the Yen.
|
|
270
356
|
end
|
|
271
357
|
|
|
358
|
+
def add_managed_billing(xml, options)
|
|
359
|
+
if mb = options[:managed_billing]
|
|
360
|
+
# default to recurring (R). Other option is deferred (D).
|
|
361
|
+
xml.tag! :MBType, mb[:type] || RECURRING
|
|
362
|
+
# default to Customer Reference Number
|
|
363
|
+
xml.tag! :MBOrderIdGenerationMethod, mb[:order_id_generation_method] || 'IO'
|
|
364
|
+
# By default use MBRecurringEndDate, set to N.
|
|
365
|
+
# MMDDYYYY
|
|
366
|
+
xml.tag! :MBRecurringStartDate, mb[:start_date].scan(/\d/).join.to_s if mb[:start_date]
|
|
367
|
+
# MMDDYYYY
|
|
368
|
+
xml.tag! :MBRecurringEndDate, mb[:end_date].scan(/\d/).join.to_s if mb[:end_date]
|
|
369
|
+
# By default listen to any value set in MBRecurringEndDate.
|
|
370
|
+
xml.tag! :MBRecurringNoEndDateFlag, mb[:no_end_date_flag] || 'N' # 'Y' || 'N' (Yes or No).
|
|
371
|
+
xml.tag! :MBRecurringMaxBillings, mb[:max_billings] if mb[:max_billings]
|
|
372
|
+
xml.tag! :MBRecurringFrequency, mb[:frequency] if mb[:frequency]
|
|
373
|
+
xml.tag! :MBDeferredBillDate, mb[:deferred_bill_date] if mb[:deferred_bill_date]
|
|
374
|
+
xml.tag! :MBMicroPaymentMaxDollarValue, mb[:max_dollar_value] if mb[:max_dollar_value]
|
|
375
|
+
xml.tag! :MBMicroPaymentMaxBillingDays, mb[:max_billing_days] if mb[:max_billing_days]
|
|
376
|
+
xml.tag! :MBMicroPaymentMaxTransactions, mb[:max_transactions] if mb[:max_transactions]
|
|
377
|
+
end
|
|
378
|
+
end
|
|
272
379
|
|
|
273
380
|
def parse(body)
|
|
274
381
|
response = {}
|
|
@@ -291,8 +398,10 @@ module ActiveMerchant #:nodoc:
|
|
|
291
398
|
end
|
|
292
399
|
end
|
|
293
400
|
|
|
294
|
-
def commit(order, message_type)
|
|
401
|
+
def commit(order, message_type, trace_number=nil)
|
|
295
402
|
headers = POST_HEADERS.merge("Content-length" => order.size.to_s)
|
|
403
|
+
headers.merge!( "Trace-number" => trace_number.to_s,
|
|
404
|
+
"Merchant-Id" => @options[:merchant_id] ) if @options[:retry_logic] && trace_number
|
|
296
405
|
request = lambda{|url| parse(ssl_post(url, order, headers))}
|
|
297
406
|
|
|
298
407
|
# Failover URL will be attempted in the event of a connection error
|
|
@@ -314,9 +423,9 @@ module ActiveMerchant #:nodoc:
|
|
|
314
423
|
|
|
315
424
|
def remote_url(url=:primary)
|
|
316
425
|
if url == :primary
|
|
317
|
-
self.test? ? self.test_url : self.live_url
|
|
426
|
+
(self.test? ? self.test_url : self.live_url)
|
|
318
427
|
else
|
|
319
|
-
self.test? ? self.secondary_test_url : self.secondary_live_url
|
|
428
|
+
(self.test? ? self.secondary_test_url : self.secondary_live_url)
|
|
320
429
|
end
|
|
321
430
|
end
|
|
322
431
|
|
|
@@ -345,7 +454,18 @@ module ActiveMerchant #:nodoc:
|
|
|
345
454
|
xml.tag! :Request do
|
|
346
455
|
xml.tag! :NewOrder do
|
|
347
456
|
add_xml_credentials(xml)
|
|
348
|
-
|
|
457
|
+
# EC - Ecommerce transaction
|
|
458
|
+
# RC - Recurring Payment transaction
|
|
459
|
+
# MO - Mail Order Telephone Order transaction
|
|
460
|
+
# IV - Interactive Voice Response
|
|
461
|
+
# IN - Interactive Voice Response
|
|
462
|
+
xml.tag! :IndustryType, parameters[:industry_type] || ECOMMERCE_TRANSACTION
|
|
463
|
+
# A - Auth Only No Capture
|
|
464
|
+
# AC - Auth and Capture
|
|
465
|
+
# F - Force Auth No Capture and no online authorization
|
|
466
|
+
# FR - Force Auth No Capture and no online authorization
|
|
467
|
+
# FC - Force Auth and Capture no online authorization
|
|
468
|
+
# R - Refund and Capture no online authorization
|
|
349
469
|
xml.tag! :MessageType, action
|
|
350
470
|
add_bin_merchant_and_terminal(xml, parameters)
|
|
351
471
|
|
|
@@ -355,6 +475,8 @@ module ActiveMerchant #:nodoc:
|
|
|
355
475
|
xml.tag! :Amount, amount(money)
|
|
356
476
|
xml.tag! :Comments, parameters[:comments] if parameters[:comments]
|
|
357
477
|
|
|
478
|
+
# CustomerAni, AVSPhoneType and AVSDestPhoneType could be added here.
|
|
479
|
+
|
|
358
480
|
if parameters[:soft_descriptors].is_a?(OrbitalSoftDescriptors)
|
|
359
481
|
add_soft_descriptors(xml, parameters[:soft_descriptors])
|
|
360
482
|
end
|
|
@@ -362,7 +484,7 @@ module ActiveMerchant #:nodoc:
|
|
|
362
484
|
set_recurring_ind(xml, parameters)
|
|
363
485
|
|
|
364
486
|
# Append Transaction Reference Number at the end for Refund transactions
|
|
365
|
-
if action ==
|
|
487
|
+
if action == REFUND
|
|
366
488
|
tx_ref_num, _ = split_authorization(parameters[:authorization])
|
|
367
489
|
xml.tag! :TxRefNum, tx_ref_num
|
|
368
490
|
end
|
|
@@ -396,7 +518,7 @@ module ActiveMerchant #:nodoc:
|
|
|
396
518
|
xml.target!
|
|
397
519
|
end
|
|
398
520
|
|
|
399
|
-
def build_void_request_xml(
|
|
521
|
+
def build_void_request_xml(authorization, parameters = {})
|
|
400
522
|
tx_ref_num, order_id = split_authorization(authorization)
|
|
401
523
|
xml = xml_envelope
|
|
402
524
|
xml.tag! :Request do
|
|
@@ -404,9 +526,11 @@ module ActiveMerchant #:nodoc:
|
|
|
404
526
|
add_xml_credentials(xml)
|
|
405
527
|
xml.tag! :TxRefNum, tx_ref_num
|
|
406
528
|
xml.tag! :TxRefIdx, parameters[:transaction_index]
|
|
407
|
-
xml.tag! :AdjustedAmt, amount
|
|
529
|
+
xml.tag! :AdjustedAmt, parameters[:amount] # setting adjusted amount to nil will void entire amount
|
|
408
530
|
xml.tag! :OrderID, format_order_id(order_id || parameters[:order_id])
|
|
409
531
|
add_bin_merchant_and_terminal(xml, parameters)
|
|
532
|
+
xml.tag! :ReversalRetryNumber, parameters[:reversal_retry_number] if parameters[:reversal_retry_number]
|
|
533
|
+
xml.tag! :OnlineReversalInd, parameters[:online_reversal_ind] if parameters[:online_reversal_ind]
|
|
410
534
|
end
|
|
411
535
|
end
|
|
412
536
|
xml.target!
|
|
@@ -431,8 +555,10 @@ module ActiveMerchant #:nodoc:
|
|
|
431
555
|
end
|
|
432
556
|
|
|
433
557
|
def add_xml_credentials(xml)
|
|
434
|
-
|
|
435
|
-
|
|
558
|
+
unless ip_authentication?
|
|
559
|
+
xml.tag! :OrbitalConnectionUsername, @options[:login]
|
|
560
|
+
xml.tag! :OrbitalConnectionPassword, @options[:password]
|
|
561
|
+
end
|
|
436
562
|
end
|
|
437
563
|
|
|
438
564
|
def add_bin_merchant_and_terminal(xml, parameters)
|
|
@@ -471,22 +597,33 @@ module ActiveMerchant #:nodoc:
|
|
|
471
597
|
add_customer_address(xml, options)
|
|
472
598
|
|
|
473
599
|
xml.tag! :CustomerProfileAction, options[:customer_profile_action] # C, R, U, D
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
600
|
+
# NO No mapping to order data
|
|
601
|
+
# OI Use <CustomerRefNum> for <OrderID>
|
|
602
|
+
# OD Use <CustomerReferNum> for <Comments>
|
|
603
|
+
# OA Use <CustomerRefNum> for <OrderID> and <Comments>
|
|
604
|
+
xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] || NO_MAPPING_TO_ORDER_DATA
|
|
605
|
+
|
|
606
|
+
if options[:customer_profile_action] == CREATE
|
|
607
|
+
# A Auto-Generate the CustomerRefNum
|
|
608
|
+
# S Use CustomerRefNum field
|
|
609
|
+
# O Use OrderID field
|
|
610
|
+
# D Use Comments field
|
|
611
|
+
xml.tag! :CustomerProfileFromOrderInd, (options[:customer_ref_num] ? USE_CUSTOMER_REF_NUM : AUTO_GENERATE)
|
|
478
612
|
end
|
|
479
613
|
|
|
480
614
|
xml.tag! :OrderDefaultDescription, options[:order_default_description][0..63] if options[:order_default_description]
|
|
481
615
|
xml.tag! :OrderDefaultAmount, options[:order_default_amount] if options[:order_default_amount]
|
|
482
616
|
|
|
483
|
-
if [
|
|
617
|
+
if [CREATE, UPDATE].include? options[:customer_profile_action]
|
|
484
618
|
xml.tag! :CustomerAccountType, 'CC' # Only credit card supported
|
|
485
|
-
xml.tag! :Status, options[:status] ||
|
|
619
|
+
xml.tag! :Status, options[:status] || ACTIVE # Active
|
|
486
620
|
end
|
|
487
621
|
|
|
488
622
|
xml.tag! :CCAccountNum, creditcard.number if creditcard
|
|
489
623
|
xml.tag! :CCExpireDate, creditcard.expiry_date.expiration.strftime("%m%y") if creditcard
|
|
624
|
+
|
|
625
|
+
# This has to come after CCExpireDate.
|
|
626
|
+
add_managed_billing(xml, options)
|
|
490
627
|
end
|
|
491
628
|
end
|
|
492
629
|
xml.target!
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'nokogiri'
|
|
1
2
|
module ActiveMerchant #:nodoc:
|
|
2
3
|
module Billing #:nodoc:
|
|
3
4
|
module PayflowCommonAPI
|
|
@@ -139,17 +140,18 @@ module ActiveMerchant #:nodoc:
|
|
|
139
140
|
|
|
140
141
|
def parse(data)
|
|
141
142
|
response = {}
|
|
142
|
-
xml =
|
|
143
|
-
|
|
143
|
+
xml = Nokogiri::XML(data)
|
|
144
|
+
xml.remove_namespaces!
|
|
145
|
+
root = xml.xpath("//ResponseData")
|
|
144
146
|
|
|
145
147
|
# REXML::XPath in Ruby 1.8.6 is now unable to match nodes based on their attributes
|
|
146
|
-
tx_result =
|
|
148
|
+
tx_result = root.xpath(".//TransactionResult").first
|
|
147
149
|
|
|
148
|
-
if tx_result && tx_result.attributes['Duplicate'] == "true"
|
|
150
|
+
if tx_result && tx_result.attributes['Duplicate'].to_s == "true"
|
|
149
151
|
response[:duplicate] = true
|
|
150
152
|
end
|
|
151
153
|
|
|
152
|
-
root.
|
|
154
|
+
root.xpath(".//*").each do |node|
|
|
153
155
|
parse_element(response, node)
|
|
154
156
|
end
|
|
155
157
|
|
|
@@ -165,14 +167,14 @@ module ActiveMerchant #:nodoc:
|
|
|
165
167
|
# in an RPPaymentResults element so we'll come here multiple times
|
|
166
168
|
response[node_name] ||= []
|
|
167
169
|
response[node_name] << ( payment_result_response = {} )
|
|
168
|
-
node.
|
|
169
|
-
when node.
|
|
170
|
-
node.
|
|
170
|
+
node.xpath(".//*").each{ |e| parse_element(payment_result_response, e) }
|
|
171
|
+
when node.xpath(".//*").to_a.any?
|
|
172
|
+
node.xpath(".//*").each{|e| parse_element(response, e) }
|
|
171
173
|
when node_name.to_s =~ /amt$/
|
|
172
174
|
# *Amt elements don't put the value in the #text - instead they use a Currency attribute
|
|
173
|
-
response[node_name] = node.attributes['Currency']
|
|
175
|
+
response[node_name] = node.attributes['Currency'].to_s
|
|
174
176
|
when node_name == :ext_data
|
|
175
|
-
response[node.attributes['Name'].underscore.to_sym] = node.attributes['Value']
|
|
177
|
+
response[node.attributes['Name'].to_s.underscore.to_sym] = node.attributes['Value'].to_s
|
|
176
178
|
else
|
|
177
179
|
response[node_name] = node.text
|
|
178
180
|
end
|
|
@@ -140,6 +140,7 @@ module ActiveMerchant #:nodoc:
|
|
|
140
140
|
add_amount(result, money, options)
|
|
141
141
|
add_invoice(result, options)
|
|
142
142
|
add_address_verification_data(result, options)
|
|
143
|
+
add_optional_elements(result, options)
|
|
143
144
|
result
|
|
144
145
|
end
|
|
145
146
|
|
|
@@ -149,6 +150,7 @@ module ActiveMerchant #:nodoc:
|
|
|
149
150
|
add_amount(result, money, options)
|
|
150
151
|
add_invoice(result, options)
|
|
151
152
|
add_reference(result, identification)
|
|
153
|
+
add_optional_elements(result, options)
|
|
152
154
|
result
|
|
153
155
|
end
|
|
154
156
|
|
|
@@ -157,6 +159,7 @@ module ActiveMerchant #:nodoc:
|
|
|
157
159
|
add_credit_card(result, credit_card)
|
|
158
160
|
add_amount(result, 100, options) #need to make an auth request for $1
|
|
159
161
|
add_token_request(result, options)
|
|
162
|
+
add_optional_elements(result, options)
|
|
160
163
|
result
|
|
161
164
|
end
|
|
162
165
|
|
|
@@ -209,7 +212,7 @@ module ActiveMerchant #:nodoc:
|
|
|
209
212
|
|
|
210
213
|
def add_invoice(xml, options)
|
|
211
214
|
xml.add_element("TxnId").text = options[:order_id].to_s.slice(0, 16) unless options[:order_id].blank?
|
|
212
|
-
xml.add_element("MerchantReference").text = options[:description] unless options[:description].blank?
|
|
215
|
+
xml.add_element("MerchantReference").text = options[:description].to_s.slice(0, 50) unless options[:description].blank?
|
|
213
216
|
end
|
|
214
217
|
|
|
215
218
|
def add_address_verification_data(xml, options)
|
|
@@ -223,6 +226,52 @@ module ActiveMerchant #:nodoc:
|
|
|
223
226
|
xml.add_element("AvsPostCode").text = address[:zip]
|
|
224
227
|
end
|
|
225
228
|
|
|
229
|
+
# The options hash may contain optional data which will be passed
|
|
230
|
+
# through the the specialized optional fields at PaymentExpress
|
|
231
|
+
# as follows:
|
|
232
|
+
#
|
|
233
|
+
# {
|
|
234
|
+
# :client_type => :web, # Possible values are: :web, :ivr, :moto, :unattended, :internet, or :recurring
|
|
235
|
+
# :txn_data1 => "String up to 255 characters",
|
|
236
|
+
# :txn_data2 => "String up to 255 characters",
|
|
237
|
+
# :txn_data3 => "String up to 255 characters"
|
|
238
|
+
# }
|
|
239
|
+
#
|
|
240
|
+
# +:client_type+, while not documented for PxPost, will be sent as
|
|
241
|
+
# the +ClientType+ XML element as described in the documentation for
|
|
242
|
+
# the PaymentExpress WebService: http://www.paymentexpress.com/Technical_Resources/Ecommerce_NonHosted/WebService#clientType
|
|
243
|
+
# (PaymentExpress have confirmed that this value works the same in PxPost).
|
|
244
|
+
# The value sent for +:client_type+ will be normalized and sent
|
|
245
|
+
# as one of the explicit values allowed by PxPost:
|
|
246
|
+
#
|
|
247
|
+
# :web => "Web"
|
|
248
|
+
# :ivr => "IVR"
|
|
249
|
+
# :moto => "MOTO"
|
|
250
|
+
# :unattended => "Unattended"
|
|
251
|
+
# :internet => "Internet"
|
|
252
|
+
# :recurring => "Recurring"
|
|
253
|
+
#
|
|
254
|
+
# If you set the +:client_type+ to any value not listed above,
|
|
255
|
+
# the ClientType element WILL NOT BE INCLUDED at all in the
|
|
256
|
+
# POST data.
|
|
257
|
+
#
|
|
258
|
+
# +:txn_data1+, +:txn_data2+, and +:txn_data3+ will be sent as
|
|
259
|
+
# +TxnData1+, +TxnData2+, and +TxnData3+, respectively, and are
|
|
260
|
+
# free form fields of the merchant's choosing, as documented here:
|
|
261
|
+
# http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#txndata
|
|
262
|
+
#
|
|
263
|
+
# These optional elements are added to all transaction types:
|
|
264
|
+
# +purchase+, +authorize+, +capture+, +refund+, +store+
|
|
265
|
+
def add_optional_elements(xml, options)
|
|
266
|
+
if client_type = normalized_client_type(options[:client_type])
|
|
267
|
+
xml.add_element("ClientType").text = client_type
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
xml.add_element("TxnData1").text = options[:txn_data1].to_s.slice(0,255) unless options[:txn_data1].blank?
|
|
271
|
+
xml.add_element("TxnData2").text = options[:txn_data2].to_s.slice(0,255) unless options[:txn_data2].blank?
|
|
272
|
+
xml.add_element("TxnData3").text = options[:txn_data3].to_s.slice(0,255) unless options[:txn_data3].blank?
|
|
273
|
+
end
|
|
274
|
+
|
|
226
275
|
def new_transaction
|
|
227
276
|
REXML::Document.new.add_element("Txn")
|
|
228
277
|
end
|
|
@@ -266,6 +315,18 @@ module ActiveMerchant #:nodoc:
|
|
|
266
315
|
def format_date(month, year)
|
|
267
316
|
"#{format(month, :two_digits)}#{format(year, :two_digits)}"
|
|
268
317
|
end
|
|
318
|
+
|
|
319
|
+
def normalized_client_type(client_type_from_options)
|
|
320
|
+
case client_type_from_options.to_s.downcase
|
|
321
|
+
when 'web' then "Web"
|
|
322
|
+
when 'ivr' then "IVR"
|
|
323
|
+
when 'moto' then "MOTO"
|
|
324
|
+
when 'unattended' then "Unattended"
|
|
325
|
+
when 'internet' then "Internet"
|
|
326
|
+
when 'recurring' then "Recurring"
|
|
327
|
+
else nil
|
|
328
|
+
end
|
|
329
|
+
end
|
|
269
330
|
end
|
|
270
331
|
|
|
271
332
|
class PaymentExpressResponse < Response
|