activemerchant 1.32.1 → 1.33.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +41 -0
  3. data/CONTRIBUTORS +8 -0
  4. data/README.md +6 -4
  5. data/lib/active_merchant/billing/check.rb +4 -3
  6. data/lib/active_merchant/billing/credit_card.rb +7 -3
  7. data/lib/active_merchant/billing/gateways/authorize_net.rb +27 -7
  8. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +8 -1
  9. data/lib/active_merchant/billing/gateways/blue_pay.rb +201 -185
  10. data/lib/active_merchant/billing/gateways/bogus.rb +1 -1
  11. data/lib/active_merchant/billing/gateways/card_stream_modern.rb +155 -0
  12. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +94 -12
  13. data/lib/active_merchant/billing/gateways/litle.rb +41 -11
  14. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +27 -6
  15. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -2
  16. data/lib/active_merchant/billing/gateways/net_registry.rb +8 -3
  17. data/lib/active_merchant/billing/gateways/netaxept.rb +65 -117
  18. data/lib/active_merchant/billing/gateways/orbital.rb +181 -48
  19. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +12 -10
  20. data/lib/active_merchant/billing/gateways/paymill.rb +5 -5
  21. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +11 -6
  22. data/lib/active_merchant/billing/gateways/paypal_express.rb +25 -7
  23. data/lib/active_merchant/billing/gateways/pin.rb +5 -5
  24. data/lib/active_merchant/billing/gateways/sage.rb +10 -5
  25. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +16 -11
  26. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +1 -1
  27. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +21 -16
  28. data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -0
  29. data/lib/active_merchant/billing/gateways/transnational.rb +239 -0
  30. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +8 -3
  31. data/lib/active_merchant/billing/integrations/direc_pay.rb +1 -1
  32. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +1 -1
  33. data/lib/active_merchant/billing/integrations/dwolla.rb +5 -12
  34. data/lib/active_merchant/billing/integrations/dwolla/common.rb +21 -0
  35. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +15 -6
  36. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +11 -6
  37. data/lib/active_merchant/billing/integrations/dwolla/return.rb +12 -4
  38. data/lib/active_merchant/billing/integrations/notification.rb +13 -8
  39. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +13 -1
  40. data/lib/active_merchant/billing/integrations/payu_in.rb +43 -0
  41. data/lib/active_merchant/billing/integrations/payu_in/helper.rb +74 -0
  42. data/lib/active_merchant/billing/integrations/payu_in/notification.rb +167 -0
  43. data/lib/active_merchant/billing/integrations/payu_in/return.rb +53 -0
  44. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +68 -5
  45. data/lib/active_merchant/billing/integrations/rbkmoney.rb +17 -0
  46. data/lib/active_merchant/billing/integrations/rbkmoney/helper.rb +23 -0
  47. data/lib/active_merchant/billing/integrations/rbkmoney/notification.rb +91 -0
  48. data/lib/active_merchant/version.rb +1 -1
  49. metadata +14 -4
  50. metadata.gz.sig +0 -0
@@ -62,8 +62,8 @@ module ActiveMerchant #:nodoc:
62
62
  post = {
63
63
  'cardName' => creditcard.name,
64
64
  'cardNumber' => creditcard.number,
65
- 'cardExpiryMonth' => sprintf('%02d', creditcard.month),
66
- 'cardExpiryYear' => sprintf('%02d', creditcard.year)
65
+ 'cardExpiryMonth' => format(creditcard.month, :two_digits),
66
+ 'cardExpiryYear' => format(creditcard.year, :two_digits)
67
67
  }
68
68
  commit('addCard', post)
69
69
  end
@@ -41,7 +41,7 @@ module ActiveMerchant
41
41
  :purchase => 'purchase',
42
42
  :capture => 'completion',
43
43
  :status => 'status',
44
- :credit => 'refund'
44
+ :refund => 'refund'
45
45
  }
46
46
 
47
47
  # Create a new NetRegistry gateway.
@@ -94,13 +94,18 @@ module ActiveMerchant
94
94
  commit(:purchase, params)
95
95
  end
96
96
 
97
- def credit(money, identification, options = {})
97
+ def refund(money, identification, options = {})
98
98
  params = {
99
99
  'AMOUNT' => amount(money),
100
100
  'TXNREF' => identification
101
101
  }
102
102
  add_request_details(params, options)
103
- commit(:credit, params)
103
+ commit(:refund, params)
104
+ end
105
+
106
+ def credit(money, identification, options = {})
107
+ deprecated CREDIT_DEPRECATION_MESSAGE
108
+ refund(money, identification, options)
104
109
  end
105
110
 
106
111
  # Specific to NetRegistry.
@@ -30,56 +30,73 @@ module ActiveMerchant #:nodoc:
30
30
  def purchase(money, creditcard, options = {})
31
31
  requires!(options, :order_id)
32
32
 
33
- post = {}
34
- add_credentials(post, options)
35
- add_transaction(post, options)
36
- add_order(post, money, options)
37
- add_creditcard(post, creditcard)
38
- commit('Sale', post)
33
+ MultiResponse.run do |r|
34
+ r.process{authorize(money, creditcard, options)}
35
+ r.process{capture(money, r.authorization, options)}
36
+ end
39
37
  end
40
38
 
41
39
  def authorize(money, creditcard, options = {})
42
40
  requires!(options, :order_id)
43
41
 
44
- post = {}
45
- add_credentials(post, options)
46
- add_transaction(post, options)
47
- add_order(post, money, options)
48
- add_creditcard(post, creditcard)
49
- commit('Auth', post)
42
+ MultiResponse.run do |r|
43
+ r.process{setup_transaction(money, options)}
44
+ r.process{add_and_auth_credit_card(r.authorization, creditcard, options)}
45
+ r.process{query_transaction(r.authorization, options)}
46
+ end
50
47
  end
51
48
 
52
49
  def capture(money, authorization, options = {})
53
50
  post = {}
54
51
  add_credentials(post, options)
55
52
  add_authorization(post, authorization, money)
56
- commit('Capture', post, false)
53
+ post[:operation] = "Capture"
54
+ commit("Netaxept/process.aspx", post)
57
55
  end
58
56
 
59
57
  def refund(money, authorization, options = {})
60
58
  post = {}
61
59
  add_credentials(post, options)
62
60
  add_authorization(post, authorization, money)
63
- commit('Credit', post, false)
64
- end
65
-
66
- def credit(money, authorization, options = {})
67
- deprecated CREDIT_DEPRECATION_MESSAGE
68
- refund(money, authorization, options)
61
+ post[:operation] = "Credit"
62
+ commit("Netaxept/process.aspx", post)
69
63
  end
70
64
 
71
65
  def void(authorization, options = {})
72
66
  post = {}
73
67
  add_credentials(post, options)
74
68
  add_authorization(post, authorization)
75
- commit('Annul', post, false)
69
+ post[:operation] = "Annul"
70
+ commit("Netaxept/process.aspx", post)
76
71
  end
77
72
 
78
73
  private
79
74
 
80
- def add_credentials(post, options)
75
+ def setup_transaction(money, options)
76
+ post = {}
77
+ add_credentials(post, options)
78
+ add_order(post, money, options)
79
+ commit("Netaxept/Register.aspx", post)
80
+ end
81
+
82
+ def add_and_auth_credit_card(authorization, creditcard, options)
83
+ post = {}
84
+ add_credentials(post, options, false)
85
+ add_authorization(post, authorization)
86
+ add_creditcard(post, creditcard)
87
+ commit("terminal/default.aspx", post, false)
88
+ end
89
+
90
+ def query_transaction(authorization, options)
91
+ post = {}
92
+ add_credentials(post, options)
93
+ add_authorization(post, authorization)
94
+ commit("Netaxept/query.aspx", post)
95
+ end
96
+
97
+ def add_credentials(post, options, secure=true)
81
98
  post[:merchantId] = @options[:login]
82
- post[:token] = @options[:password]
99
+ post[:token] = @options[:password] if secure
83
100
  end
84
101
 
85
102
  def add_authorization(post, authorization, money=nil)
@@ -87,92 +104,45 @@ module ActiveMerchant #:nodoc:
87
104
  post[:transactionAmount] = amount(money) if money
88
105
  end
89
106
 
90
- def add_transaction(post, options)
91
- post[:transactionId] = generate_transaction_id(options)
92
- post[:serviceType] = 'M'
93
- post[:redirectUrl] = 'http://example.com'
94
- end
95
-
96
107
  def add_order(post, money, options)
108
+ post[:serviceType] = 'M'
97
109
  post[:orderNumber] = options[:order_id]
98
110
  post[:amount] = amount(money)
99
111
  post[:currencyCode] = (options[:currency] || currency(money))
112
+ post[:autoAuth] = "true"
100
113
  end
101
114
 
102
- CARD_TYPE_PREFIXES = {
103
- 'visa' => 'v',
104
- 'master' => 'm',
105
- 'american_express' => 'a',
106
- }
107
- def add_creditcard(post, creditcard)
108
- brand = Gateway.card_brand(creditcard)
109
- prefix = CARD_TYPE_PREFIXES[brand]
110
- unless prefix
111
- raise ArgumentError.new("Card type #{brand} not supported.")
112
- end
113
-
114
- post[:creditcard] = {}
115
- post[:creditcard][:"#{prefix}a"] = creditcard.number
116
- post[:creditcard][:"#{prefix}m"] = format(creditcard.month, :two_digits)
117
- post[:creditcard][:"#{prefix}y"] = format(creditcard.year, :two_digits)
118
- post[:creditcard][:"#{prefix}c"] = creditcard.verification_value
115
+ def add_creditcard(post, options)
116
+ post[:pan] = options.number
117
+ post[:expiryDate] = format(options.month, :two_digits) + format(options.year, :two_digits)
118
+ post[:securityCode] = options.verification_value
119
119
  end
120
120
 
121
- def commit(action, parameters, setup=true)
122
- parameters[:action] = action
123
-
124
- response = {:success => false}
125
-
126
- catch(:exception) do
127
- if setup
128
- commit_transaction_setup(response, parameters)
129
- commit_payment_details(response, parameters)
130
- commit_process_setup(response, parameters)
131
- end
132
- commit_transaction(response, parameters)
133
- response[:success] = true
134
- end
135
-
136
- Response.new(response[:success], response[:message], response, :test => test?, :authorization => response[:authorization])
137
- end
138
-
139
- def commit_transaction_setup(response, parameters)
140
- response[:setup] = parse(ssl_get(build_url("REST/Setup.aspx", pick(parameters, :merchantId, :token, :serviceType, :amount, :currencyCode, :redirectUrl, :orderNumber, :transactionId))))
141
- process(response, :setup)
142
- end
143
-
144
- def commit_payment_details(response, parameters)
145
- data = encode(parameters[:creditcard].merge(:BBSePay_transaction => response[:setup]['SetupString']))
146
- response[:paymentDetails] = parse(ssl_post(build_url("terminal/default.aspx"), data), false)
147
- process(response, :paymentDetails)
148
- end
149
-
150
- def commit_process_setup(response, parameters)
151
- result = ssl_get(build_url("REST/ProcessSetup.aspx", pick(parameters, :merchantId, :token, :transactionId).merge(:transactionString => response[:paymentDetails][:result])))
152
- response[:processSetup] = parse(result)
153
- process(response, :processSetup)
154
- end
121
+ def commit(path, parameters, xml=true)
122
+ raw = parse(ssl_get(build_url(path, parameters)), xml)
155
123
 
156
- def commit_transaction(response, parameters)
157
- result = ssl_get(build_url("REST/#{parameters[:action]}.aspx", pick(parameters, :merchantId, :token, :transactionId, :transactionAmount)))
158
- response[:action] = parse(result)
159
- process(response, :action)
160
- end
161
-
162
- def process(response, step)
163
- if response[step][:container] =~ /Exception|Error/
164
- response[:message] = response[step]['Message']
165
- throw :exception
124
+ success = false
125
+ authorization = (raw["TransactionId"] || parameters[:transactionId])
126
+ if raw[:container] =~ /Exception|Error/
127
+ message = (raw["Message"] || raw["Error"]["Message"])
128
+ elsif raw["Error"] && !raw["Error"].empty?
129
+ message = (raw["Error"]["ResponseText"] || raw["Error"]["ResponseCode"])
166
130
  else
167
- message = (response[step]['ResponseText'] || response[step]['ResponseCode'])
168
- response[:message] = (message || response[:message])
169
-
170
- response[:authorization] = response[step]['TransactionId']
131
+ message = (raw["ResponseText"] || raw["ResponseCode"] || "OK")
132
+ success = true
171
133
  end
134
+
135
+ Response.new(
136
+ success,
137
+ message,
138
+ raw,
139
+ :test => test?,
140
+ :authorization => authorization
141
+ )
172
142
  end
173
143
 
174
144
  def parse(result, expects_xml=true)
175
- if expects_xml || /^</ =~ result
145
+ if expects_xml
176
146
  doc = REXML::Document.new(result)
177
147
  extract_xml(doc.root).merge(:container => doc.root.name)
178
148
  else
@@ -192,20 +162,8 @@ module ActiveMerchant #:nodoc:
192
162
  end
193
163
  end
194
164
 
195
- def url
196
- (test? ? self.test_url : self.live_url)
197
- end
198
-
199
- def generate_transaction_id(options)
200
- Digest::MD5.hexdigest("#{options.inspect}+#{Time.now}+#{rand}")
201
- end
202
-
203
- def pick(hash, *keys)
204
- keys.inject({}){|h,key| h[key] = hash[key] if hash[key]; h}
205
- end
206
-
207
165
  def build_url(base, parameters=nil)
208
- url = "#{test? ? self.test_url : self.live_url}"
166
+ url = (test? ? self.test_url : self.live_url).dup
209
167
  url << base
210
168
  if parameters
211
169
  url << '?'
@@ -217,16 +175,6 @@ module ActiveMerchant #:nodoc:
217
175
  def encode(hash)
218
176
  hash.collect{|(k,v)| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}"}.join('&')
219
177
  end
220
-
221
- class Response < Billing::Response
222
- attr_reader :error_detail
223
- def initialize(success, message, raw, options)
224
- super
225
- unless success
226
- @error_detail = raw[:processSetup]['Result']['ResponseText'] if raw[:processSetup] && raw[:processSetup]['Result']
227
- end
228
- end
229
- end
230
178
  end
231
179
  end
232
180
  end
@@ -32,8 +32,8 @@ module ActiveMerchant #:nodoc:
32
32
  API_VERSION = "5.6"
33
33
 
34
34
  POST_HEADERS = {
35
- "MIME-Version" => "1.0",
36
- "Content-Type" => "Application/PTI46",
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('A', money, options) do |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
- add_customer_data(xml, options) if @options[:customer_profiles]
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('AC', money, options) do |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
- add_customer_data(xml, options) if @options[:customer_profiles]
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('R', money, options.merge(:authorization => authorization)) do |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= {})
@@ -132,7 +195,7 @@ module ActiveMerchant #:nodoc:
132
195
  end
133
196
 
134
197
  order = build_void_request_xml(authorization, options)
135
- commit(order, :void)
198
+ commit(order, :void, options[:trace_number])
136
199
  end
137
200
 
138
201
 
@@ -158,25 +221,25 @@ module ActiveMerchant #:nodoc:
158
221
  # 'MS' - Manual Suspend
159
222
 
160
223
  def add_customer_profile(creditcard, options = {})
161
- options.merge!(:customer_profile_action => 'C')
224
+ options.merge!(:customer_profile_action => CREATE)
162
225
  order = build_customer_request_xml(creditcard, options)
163
226
  commit(order, :add_customer_profile)
164
227
  end
165
228
 
166
229
  def update_customer_profile(creditcard, options = {})
167
- options.merge!(:customer_profile_action => 'U')
230
+ options.merge!(:customer_profile_action => UPDATE)
168
231
  order = build_customer_request_xml(creditcard, options)
169
232
  commit(order, :update_customer_profile)
170
233
  end
171
234
 
172
235
  def retrieve_customer_profile(customer_ref_num)
173
- options = {:customer_profile_action => 'R', :customer_ref_num => customer_ref_num}
236
+ options = {:customer_profile_action => RETRIEVE, :customer_ref_num => customer_ref_num}
174
237
  order = build_customer_request_xml(nil, options)
175
238
  commit(order, :retrieve_customer_profile)
176
239
  end
177
240
 
178
241
  def delete_customer_profile(customer_ref_num)
179
- options = {:customer_profile_action => 'D', :customer_ref_num => customer_ref_num}
242
+ options = {:customer_profile_action => DELETE, :customer_ref_num => customer_ref_num}
180
243
  order = build_customer_request_xml(nil, options)
181
244
  commit(order, :delete_customer_profile)
182
245
  end
@@ -196,12 +259,12 @@ module ActiveMerchant #:nodoc:
196
259
  xml.tag! :CustomerRefNum, options[:customer_ref_num]
197
260
  else
198
261
  if options[:customer_ref_num]
199
- xml.tag! :CustomerProfileFromOrderInd, 'S'
262
+ xml.tag! :CustomerProfileFromOrderInd, USE_CUSTOMER_REF_NUM
200
263
  xml.tag! :CustomerRefNum, options[:customer_ref_num]
201
264
  else
202
- xml.tag! :CustomerProfileFromOrderInd, 'A'
265
+ xml.tag! :CustomerProfileFromOrderInd, AUTO_GENERATE
203
266
  end
204
- xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] || 'NO'
267
+ xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] || NO_MAPPING_TO_ORDER_DATA
205
268
  end
206
269
  end
207
270
 
@@ -215,32 +278,51 @@ module ActiveMerchant #:nodoc:
215
278
  end
216
279
 
217
280
  def add_address(xml, creditcard, options)
218
- if address = options[:billing_address] || options[:address]
281
+ if(address = (options[:billing_address] || options[:address]))
219
282
  avs_supported = AVS_SUPPORTED_COUNTRIES.include?(address[:country].to_s)
220
283
 
221
284
  if avs_supported
222
- xml.tag! :AVSzip, address[:zip] ? address[:zip].to_s[0..9] : nil
223
- xml.tag! :AVSaddress1, address[:address1] ? address[:address1][0..29] : nil
224
- xml.tag! :AVSaddress2, address[:address2] ? address[:address2][0..29] : nil
225
- xml.tag! :AVScity, address[:city] ? address[:city][0..19] : nil
226
- xml.tag! :AVSstate, address[:state]
227
- xml.tag! :AVSphoneNum, address[:phone] ? address[:phone].scan(/\d/).join.to_s[0..13] : nil
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)
228
291
  end
229
- xml.tag! :AVSname, creditcard.name ? creditcard.name[0..29] : nil
230
- xml.tag! :AVScountryCode, avs_supported ? address[:country] : ''
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]
231
312
  end
232
313
  end
233
314
 
234
315
  # For Profile requests
235
316
  def add_customer_address(xml, options)
236
- if address = options[:billing_address] || options[:address]
237
- xml.tag! :CustomerAddress1, address[:address1]
238
- xml.tag! :CustomerAddress2, address[:address2]
239
- 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)
240
321
  xml.tag! :CustomerState, address[:state]
241
- xml.tag! :CustomerZIP, address[:zip]
242
- xml.tag! :CustomerPhone, address[:phone] ? address[:phone].scan(/\d/).to_s : nil
243
- xml.tag! :CustomerCountryCode, address[:country]
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)
244
326
  end
245
327
  end
246
328
 
@@ -261,7 +343,7 @@ module ActiveMerchant #:nodoc:
261
343
  # Do not submit the attribute at all.
262
344
  # - http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf
263
345
  if %w( visa discover ).include?(creditcard.brand)
264
- xml.tag! :CardSecValInd, creditcard.verification_value? ? '1' : '9'
346
+ xml.tag! :CardSecValInd, (creditcard.verification_value? ? '1' : '9')
265
347
  end
266
348
  xml.tag! :CardSecVal, creditcard.verification_value if creditcard.verification_value?
267
349
  end
@@ -273,6 +355,27 @@ module ActiveMerchant #:nodoc:
273
355
  xml.tag! :CurrencyExponent, '2' # Will need updating to support currencies such as the Yen.
274
356
  end
275
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
276
379
 
277
380
  def parse(body)
278
381
  response = {}
@@ -295,8 +398,10 @@ module ActiveMerchant #:nodoc:
295
398
  end
296
399
  end
297
400
 
298
- def commit(order, message_type)
401
+ def commit(order, message_type, trace_number=nil)
299
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
300
405
  request = lambda{|url| parse(ssl_post(url, order, headers))}
301
406
 
302
407
  # Failover URL will be attempted in the event of a connection error
@@ -318,9 +423,9 @@ module ActiveMerchant #:nodoc:
318
423
 
319
424
  def remote_url(url=:primary)
320
425
  if url == :primary
321
- self.test? ? self.test_url : self.live_url
426
+ (self.test? ? self.test_url : self.live_url)
322
427
  else
323
- self.test? ? self.secondary_test_url : self.secondary_live_url
428
+ (self.test? ? self.secondary_test_url : self.secondary_live_url)
324
429
  end
325
430
  end
326
431
 
@@ -349,7 +454,18 @@ module ActiveMerchant #:nodoc:
349
454
  xml.tag! :Request do
350
455
  xml.tag! :NewOrder do
351
456
  add_xml_credentials(xml)
352
- xml.tag! :IndustryType, parameters[:industry_type] || "EC"
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
353
469
  xml.tag! :MessageType, action
354
470
  add_bin_merchant_and_terminal(xml, parameters)
355
471
 
@@ -359,6 +475,8 @@ module ActiveMerchant #:nodoc:
359
475
  xml.tag! :Amount, amount(money)
360
476
  xml.tag! :Comments, parameters[:comments] if parameters[:comments]
361
477
 
478
+ # CustomerAni, AVSPhoneType and AVSDestPhoneType could be added here.
479
+
362
480
  if parameters[:soft_descriptors].is_a?(OrbitalSoftDescriptors)
363
481
  add_soft_descriptors(xml, parameters[:soft_descriptors])
364
482
  end
@@ -366,7 +484,7 @@ module ActiveMerchant #:nodoc:
366
484
  set_recurring_ind(xml, parameters)
367
485
 
368
486
  # Append Transaction Reference Number at the end for Refund transactions
369
- if action == "R"
487
+ if action == REFUND
370
488
  tx_ref_num, _ = split_authorization(parameters[:authorization])
371
489
  xml.tag! :TxRefNum, tx_ref_num
372
490
  end
@@ -411,6 +529,8 @@ module ActiveMerchant #:nodoc:
411
529
  xml.tag! :AdjustedAmt, parameters[:amount] # setting adjusted amount to nil will void entire amount
412
530
  xml.tag! :OrderID, format_order_id(order_id || parameters[:order_id])
413
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]
414
534
  end
415
535
  end
416
536
  xml.target!
@@ -435,8 +555,10 @@ module ActiveMerchant #:nodoc:
435
555
  end
436
556
 
437
557
  def add_xml_credentials(xml)
438
- xml.tag! :OrbitalConnectionUsername, @options[:login] unless ip_authentication?
439
- xml.tag! :OrbitalConnectionPassword, @options[:password] unless ip_authentication?
558
+ unless ip_authentication?
559
+ xml.tag! :OrbitalConnectionUsername, @options[:login]
560
+ xml.tag! :OrbitalConnectionPassword, @options[:password]
561
+ end
440
562
  end
441
563
 
442
564
  def add_bin_merchant_and_terminal(xml, parameters)
@@ -475,22 +597,33 @@ module ActiveMerchant #:nodoc:
475
597
  add_customer_address(xml, options)
476
598
 
477
599
  xml.tag! :CustomerProfileAction, options[:customer_profile_action] # C, R, U, D
478
- xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] || 'NO'
479
-
480
- if options[:customer_profile_action] == 'C'
481
- xml.tag! :CustomerProfileFromOrderInd, options[:customer_ref_num] ? 'S' : 'A'
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)
482
612
  end
483
613
 
484
614
  xml.tag! :OrderDefaultDescription, options[:order_default_description][0..63] if options[:order_default_description]
485
615
  xml.tag! :OrderDefaultAmount, options[:order_default_amount] if options[:order_default_amount]
486
616
 
487
- if ['C', 'U'].include? options[:customer_profile_action]
617
+ if [CREATE, UPDATE].include? options[:customer_profile_action]
488
618
  xml.tag! :CustomerAccountType, 'CC' # Only credit card supported
489
- xml.tag! :Status, options[:status] || 'A' # Active
619
+ xml.tag! :Status, options[:status] || ACTIVE # Active
490
620
  end
491
621
 
492
622
  xml.tag! :CCAccountNum, creditcard.number if creditcard
493
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)
494
627
  end
495
628
  end
496
629
  xml.target!