activemerchant 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +226 -0
  3. data/CONTRIBUTERS +52 -0
  4. data/README +34 -24
  5. data/Rakefile +152 -0
  6. data/gem-public_cert.pem +20 -0
  7. data/init.rb +3 -0
  8. data/lib/active_merchant.rb +3 -1
  9. data/lib/active_merchant/billing/credit_card.rb +21 -17
  10. data/lib/active_merchant/billing/credit_card_methods.rb +17 -19
  11. data/lib/active_merchant/billing/gateway.rb +160 -44
  12. data/lib/active_merchant/billing/gateways.rb +2 -15
  13. data/lib/active_merchant/billing/gateways/authorize_net.rb +21 -21
  14. data/lib/active_merchant/billing/gateways/bogus.rb +6 -6
  15. data/lib/active_merchant/billing/gateways/brain_tree.rb +191 -0
  16. data/lib/active_merchant/billing/gateways/card_stream.rb +207 -0
  17. data/lib/active_merchant/billing/gateways/cyber_source.rb +402 -0
  18. data/lib/active_merchant/billing/gateways/data_cash.rb +41 -97
  19. data/lib/active_merchant/billing/gateways/efsnet.rb +256 -0
  20. data/lib/active_merchant/billing/gateways/eway.rb +77 -29
  21. data/lib/active_merchant/billing/gateways/exact.rb +230 -0
  22. data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -33
  23. data/lib/active_merchant/billing/gateways/moneris.rb +155 -125
  24. data/lib/active_merchant/billing/gateways/net_registry.rb +257 -0
  25. data/lib/active_merchant/billing/gateways/pay_junction.rb +407 -0
  26. data/lib/active_merchant/billing/gateways/payflow.rb +163 -25
  27. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +56 -38
  28. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +10 -1
  29. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +9 -0
  30. data/lib/active_merchant/billing/gateways/payflow_express.rb +36 -11
  31. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +6 -0
  32. data/lib/active_merchant/billing/gateways/payflow_uk.rb +7 -3
  33. data/lib/active_merchant/billing/gateways/payment_express.rb +261 -0
  34. data/lib/active_merchant/billing/gateways/paypal.rb +18 -4
  35. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +31 -15
  36. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +8 -0
  37. data/lib/active_merchant/billing/gateways/paypal_express.rb +33 -8
  38. data/lib/active_merchant/billing/gateways/plugnpay.rb +300 -0
  39. data/lib/active_merchant/billing/gateways/protx.rb +285 -0
  40. data/lib/active_merchant/billing/gateways/psigate.rb +13 -12
  41. data/lib/active_merchant/billing/gateways/psl_card.rb +297 -0
  42. data/lib/active_merchant/billing/gateways/quickpay.rb +197 -0
  43. data/lib/active_merchant/billing/gateways/realex.rb +212 -0
  44. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  45. data/lib/active_merchant/billing/gateways/trans_first.rb +136 -0
  46. data/lib/active_merchant/billing/gateways/trust_commerce.rb +43 -20
  47. data/lib/active_merchant/billing/gateways/usa_epay.rb +6 -5
  48. data/lib/active_merchant/billing/gateways/verifi.rb +235 -0
  49. data/lib/active_merchant/billing/gateways/viaklix.rb +171 -0
  50. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +0 -2
  51. data/lib/active_merchant/billing/integrations/helper.rb +8 -1
  52. data/lib/active_merchant/billing/integrations/nochex.rb +62 -1
  53. data/lib/active_merchant/billing/integrations/nochex/notification.rb +9 -16
  54. data/lib/active_merchant/billing/integrations/notification.rb +1 -1
  55. data/lib/active_merchant/billing/integrations/paypal/helper.rb +59 -46
  56. data/lib/active_merchant/billing/integrations/paypal/notification.rb +14 -47
  57. data/lib/active_merchant/lib/error.rb +4 -0
  58. data/lib/active_merchant/lib/post_data.rb +22 -0
  59. data/lib/active_merchant/lib/posts_data.rb +23 -5
  60. data/lib/active_merchant/lib/requires_parameters.rb +2 -2
  61. data/lib/active_merchant/lib/validateable.rb +1 -1
  62. data/lib/support/gateway_support.rb +45 -0
  63. data/lib/tasks/cia.rb +1 -1
  64. data/script/generate +14 -0
  65. data/script/generator/base.rb +45 -0
  66. data/script/generator/generator.rb +24 -0
  67. data/script/generator/generators/gateway/gateway_generator.rb +14 -0
  68. data/script/generator/generators/gateway/templates/gateway.rb +73 -0
  69. data/script/generator/generators/gateway/templates/gateway_test.rb +41 -0
  70. data/script/generator/generators/gateway/templates/remote_gateway_test.rb +56 -0
  71. data/script/generator/generators/integration/integration_generator.rb +25 -0
  72. data/script/generator/generators/integration/templates/helper.rb +34 -0
  73. data/script/generator/generators/integration/templates/helper_test.rb +54 -0
  74. data/script/generator/generators/integration/templates/integration.rb +18 -0
  75. data/script/generator/generators/integration/templates/module_test.rb +9 -0
  76. data/script/generator/generators/integration/templates/notification.rb +100 -0
  77. data/script/generator/generators/integration/templates/notification_test.rb +41 -0
  78. data/script/generator/manifest.rb +20 -0
  79. data/test/extra/binding_of_caller.rb +80 -0
  80. data/test/extra/breakpoint.rb +547 -0
  81. data/test/fixtures.yml +251 -0
  82. data/test/remote_tests/remote_authorize_net_test.rb +113 -0
  83. data/test/remote_tests/remote_brain_tree_test.rb +78 -0
  84. data/test/remote_tests/remote_card_stream_test.rb +160 -0
  85. data/test/remote_tests/remote_cyber_source_test.rb +130 -0
  86. data/test/remote_tests/remote_data_cash_test.rb +155 -0
  87. data/test/remote_tests/remote_efsnet_test.rb +93 -0
  88. data/test/remote_tests/remote_eway_test.rb +71 -0
  89. data/test/remote_tests/remote_exact_test.rb +59 -0
  90. data/test/remote_tests/remote_gestpay_integration_test.rb +37 -0
  91. data/test/remote_tests/remote_linkpoint_test.rb +144 -0
  92. data/test/remote_tests/remote_moneris_test.rb +110 -0
  93. data/test/remote_tests/remote_net_registry_test.rb +120 -0
  94. data/test/remote_tests/remote_pay_junction_test.rb +162 -0
  95. data/test/remote_tests/remote_payflow_express_test.rb +50 -0
  96. data/test/remote_tests/remote_payflow_test.rb +241 -0
  97. data/test/remote_tests/remote_payflow_uk_test.rb +172 -0
  98. data/test/remote_tests/remote_payment_express_test.rb +136 -0
  99. data/test/remote_tests/remote_paypal_express_test.rb +49 -0
  100. data/test/remote_tests/remote_paypal_integration_test.rb +14 -0
  101. data/test/remote_tests/remote_paypal_test.rb +163 -0
  102. data/test/remote_tests/remote_plugnpay_test.rb +70 -0
  103. data/test/remote_tests/remote_protx_test.rb +184 -0
  104. data/test/remote_tests/remote_psigate_test.rb +87 -0
  105. data/test/remote_tests/remote_psl_card_test.rb +105 -0
  106. data/test/remote_tests/remote_quickpay_test.rb +182 -0
  107. data/test/remote_tests/remote_realex_test.rb +227 -0
  108. data/test/remote_tests/remote_secure_pay_test.rb +36 -0
  109. data/test/remote_tests/remote_trans_first_test.rb +37 -0
  110. data/test/remote_tests/remote_trust_commerce_test.rb +136 -0
  111. data/test/remote_tests/remote_usa_epay_test.rb +57 -0
  112. data/test/remote_tests/remote_verifi_test.rb +107 -0
  113. data/test/remote_tests/remote_viaklix_test.rb +53 -0
  114. data/test/test_helper.rb +132 -0
  115. data/test/unit/base_test.rb +61 -0
  116. data/test/unit/country_code_test.rb +33 -0
  117. data/test/unit/country_test.rb +64 -0
  118. data/test/unit/credit_card_formatting_test.rb +24 -0
  119. data/test/unit/credit_card_methods_test.rb +37 -0
  120. data/test/unit/credit_card_test.rb +365 -0
  121. data/test/unit/gateways/authorize_net_test.rb +140 -0
  122. data/test/unit/gateways/bogus_test.rb +43 -0
  123. data/test/unit/gateways/brain_tree_test.rb +77 -0
  124. data/test/unit/gateways/card_stream_test.rb +37 -0
  125. data/test/unit/gateways/cyber_source_test.rb +151 -0
  126. data/test/unit/gateways/data_cash_test.rb +23 -0
  127. data/test/unit/gateways/efsnet_test.rb +70 -0
  128. data/test/unit/gateways/eway_test.rb +105 -0
  129. data/test/unit/gateways/exact_test.rb +118 -0
  130. data/test/unit/gateways/gateway_test.rb +24 -0
  131. data/test/unit/gateways/linkpoint_test.rb +165 -0
  132. data/test/unit/gateways/moneris_test.rb +167 -0
  133. data/test/unit/gateways/net_registry_test.rb +478 -0
  134. data/test/unit/gateways/pay_junction_test.rb +61 -0
  135. data/test/unit/gateways/payflow_express_test.rb +165 -0
  136. data/test/unit/gateways/payflow_express_uk_test.rb +14 -0
  137. data/test/unit/gateways/payflow_test.rb +230 -0
  138. data/test/unit/gateways/payflow_uk_test.rb +68 -0
  139. data/test/unit/gateways/payment_express_test.rb +215 -0
  140. data/test/unit/gateways/paypal_express_test.rb +222 -0
  141. data/test/unit/gateways/paypal_test.rb +241 -0
  142. data/test/unit/gateways/plugnpay_test.rb +79 -0
  143. data/test/unit/gateways/protx_test.rb +110 -0
  144. data/test/unit/gateways/psigate_test.rb +110 -0
  145. data/test/unit/gateways/psl_card_test.rb +51 -0
  146. data/test/unit/gateways/quickpay_test.rb +125 -0
  147. data/test/unit/gateways/realex_test.rb +150 -0
  148. data/test/unit/gateways/secure_pay_test.rb +78 -0
  149. data/test/unit/gateways/trans_first_test.rb +125 -0
  150. data/test/unit/gateways/trust_commerce_test.rb +57 -0
  151. data/test/unit/gateways/usa_epay_test.rb +117 -0
  152. data/test/unit/gateways/verifi_test.rb +91 -0
  153. data/test/unit/gateways/viaklix_test.rb +72 -0
  154. data/test/unit/integrations/action_view_helper_test.rb +54 -0
  155. data/test/unit/integrations/bogus_module_test.rb +16 -0
  156. data/test/unit/integrations/chronopay_module_test.rb +9 -0
  157. data/test/unit/integrations/gestpay_module_test.rb +10 -0
  158. data/test/unit/integrations/helpers/bogus_helper_test.rb +28 -0
  159. data/test/unit/integrations/helpers/chronopay_helper_test.rb +67 -0
  160. data/test/unit/integrations/helpers/gestpay_helper_test.rb +100 -0
  161. data/test/unit/integrations/helpers/nochex_helper_test.rb +53 -0
  162. data/test/unit/integrations/helpers/paypal_helper_test.rb +162 -0
  163. data/test/unit/integrations/helpers/two_checkout_helper_test.rb +92 -0
  164. data/test/unit/integrations/nochex_module_test.rb +9 -0
  165. data/test/unit/integrations/notifications/chronopay_notification_test.rb +66 -0
  166. data/test/unit/integrations/notifications/gestpay_notification_test.rb +60 -0
  167. data/test/unit/integrations/notifications/nochex_notification_test.rb +51 -0
  168. data/test/unit/integrations/notifications/notification_test.rb +41 -0
  169. data/test/unit/integrations/notifications/paypal_notification_test.rb +85 -0
  170. data/test/unit/integrations/notifications/two_checkout_notification_test.rb +55 -0
  171. data/test/unit/integrations/paypal_module_test.rb +24 -0
  172. data/test/unit/integrations/two_checkout_module_test.rb +9 -0
  173. data/test/unit/post_data_test.rb +55 -0
  174. data/test/unit/response_test.rb +14 -0
  175. data/test/unit/validateable_test.rb +56 -0
  176. metadata +160 -7
  177. metadata.gz.sig +0 -0
  178. data/lib/active_merchant/billing/gateways/payflow/f73e89fd.0 +0 -17
@@ -2,13 +2,20 @@
2
2
 
3
3
  module ActiveMerchant
4
4
  module Billing
5
- # ActiveMerchant Datacash Gateway
6
- #
7
- # Datacash allows a policy for CV2 checks. There is currently no way
8
- # to modify this programatically. The policy may be changed in the
9
- # add_credit_card method.
10
- #
11
5
  class DataCashGateway < Gateway
6
+ self.default_currency = 'GBP'
7
+ self.supported_countries = ['GB']
8
+
9
+ # From the DataCash docs; Page 13, the following cards are
10
+ # usable:
11
+ # American Express, ATM, Carte Blanche, Diners Club, Discover,
12
+ # EnRoute, GE Capital, JCB, Laser, Maestro, Mastercard, Solo,
13
+ # Switch, Visa, Visa Delta, VISA Electron, Visa Purchasing
14
+ self.supported_cardtypes = [ :visa, :master, :american_express, :discover, :diners_club, :jcb,
15
+ :maestro, :switch, :solo, :laser ]
16
+
17
+ self.homepage_url = 'http://www.datacash.com/'
18
+ self.display_name = 'DataCash'
12
19
 
13
20
  # Datacash server URLs
14
21
  TEST_URL = 'https://testserver.datacash.com/Transaction'
@@ -25,7 +32,7 @@ module ActiveMerchant
25
32
  POLICY_ACCEPT = 'accept'
26
33
  POLICY_REJECT = 'reject'
27
34
 
28
- #Datacash success code
35
+ # Datacash success code
29
36
  DATACASH_SUCCESS = '1'
30
37
 
31
38
  # Class attributes
@@ -33,16 +40,16 @@ module ActiveMerchant
33
40
  attr_reader :response
34
41
  attr_reader :options
35
42
 
36
- # Create a new DataCashGateway
43
+ # Creates a new DataCashGateway
37
44
  #
38
- # The gateway requires that a valid :login and :password be passed
39
- # in the options hash
45
+ # The gateway requires that a valid login and password be passed
46
+ # in the +options+ hash.
40
47
  #
41
- # Parameters:
42
- # -options:
43
- # :login - the Datacash account login
44
- # :password - the Datacash account password
45
- # :test - boolean, use the test or live Datacash url
48
+ # ==== Options
49
+ #
50
+ # * <tt>:login</tt> -- The Datacash account login.
51
+ # * <tt>:password</tt> -- The Datacash account password.
52
+ # * <tt>:test => +true+ or +false+</tt> -- Use the test or live Datacash url.
46
53
  #
47
54
  def initialize(options = {})
48
55
  requires!(options, :login, :password)
@@ -50,16 +57,13 @@ module ActiveMerchant
50
57
  super
51
58
  end
52
59
 
53
- # Purchase the item straight away
60
+ # Perform a purchase, which is essentially an authorization and capture in a single operation.
54
61
  #
55
- # Parameters:
56
- # -money: Money object for the total to be charged
57
- # -credit_card: ActiveMerchant::Billing::CreditCard details for the transaction
58
- # -options:
62
+ # ==== Parameters
59
63
  #
60
- # Returns:
61
- # -ActiveRecord::Billing::Response object
62
- #
64
+ # * <tt>money</tt> -- The amount to be purchased. Either an Integer value in cents or a Money object.
65
+ # * <tt>credit_card</tt> -- The CreditCard details for the transaction.
66
+ # * <tt>options</tt> -- A hash of optional parameters.
63
67
  def purchase(money, credit_card, options = {})
64
68
  if result = test_result_from_cc_number(credit_card.number)
65
69
  return result
@@ -70,19 +74,14 @@ module ActiveMerchant
70
74
  commit(request)
71
75
  end
72
76
 
73
- # Authorize the transaction
74
- #
75
- # Reserves the funds on the customer's credit card, but does not
77
+ # Performs an authorization, which reserves the funds on the customer's credit card, but does not
76
78
  # charge the card.
77
79
  #
78
- # Parameters:
79
- # -money: Money object for the total to be charged
80
- # -credit_card: ActiveMerchant::Billing::CreditCard details for the transaction
81
- # -options:
80
+ # ==== Parameters
82
81
  #
83
- # Returns:
84
- # -ActiveRecord::Billing::Response object
85
- #
82
+ # * <tt>money</tt> -- The amount to be authorized. Either an Integer value in cents or a Money object.
83
+ # * <tt>credit_card</tt> -- The CreditCard details for the transaction.
84
+ # * <tt>options</tt> -- A hash of optional parameters.
86
85
  def authorize(money, credit_card, options = {})
87
86
  if result = test_result_from_cc_number(credit_card.number)
88
87
  return result
@@ -93,24 +92,12 @@ module ActiveMerchant
93
92
  commit(request)
94
93
  end
95
94
 
96
- # Datacash requires both the reference and the authcode of the original
97
- # authorization. To maintain the same interface as the other
98
- # gateways the two numbers are concatenated together with an ; separator as
99
- # the authorization number returned by authorization
100
-
101
- # Captures the funds from an authorized transaction.
102
- # authorization must be a valid Datacash reference and :authcode must be
103
- # a valid Datacash authcode from a prior authorized transaction.
95
+ # Captures the funds from an authorized transaction.
104
96
  #
105
- # This needs to create a 'historic txn' to fulfill
106
- #
107
- # Parameters:
108
- # -money: Money object for the total to be charged
109
- # -authorization: the Datacash reference and authcode from the previous authorization
97
+ # ==== Parameters
110
98
  #
111
- # Returns:
112
- # -ActiveRecord::Billing::Response object
113
- #
99
+ # * <tt>money</tt> -- The amount to be captured. Either an Integer value in cents or a Money object.
100
+ # * <tt>authorization</tt> -- The authorization returned from the previous authorize request.
114
101
  def capture(money, authorization, options = {})
115
102
  request = build_void_or_capture_request(FULFILL_TYPE, money, authorization, options)
116
103
 
@@ -119,46 +106,16 @@ module ActiveMerchant
119
106
 
120
107
  # Void a previous transaction
121
108
  #
122
- # This needs to create a 'historic txn' to fulfil
123
- #
124
- # Parameters:
125
- # -authorization: the Datacash reference from the previous authorization
109
+ # ==== Parameters
126
110
  #
127
- # Returns:
128
- # -ActiveRecord::Billing::Response object
129
- #
111
+ # * <tt>authorization</tt> - The authorization returned from the previous authorize request.
130
112
  def void(authorization, options = {})
131
113
  request = build_void_or_capture_request(CANCEL_TYPE, nil, authorization, options)
132
114
 
133
115
  commit(request)
134
116
  end
135
117
 
136
- # From the DataCash docs; Page 13, the following cards are
137
- # usable
138
- #
139
- # American Express, ATM, Carte Blanche, Diners Club, Discover,
140
- # EnRoute, GE Capital, JCB, Laser, Maestro, Mastercard, Solo,
141
- # Switch, Unknown, Visa, Visa Delta, VISA Electron, Visa Purchasing
142
- #
143
- # Parameters:
144
- # -none
145
- #
146
- # Returns:
147
- # -the list of all supported cards
148
- #
149
- def self.supported_cardtypes
150
- [ :visa, :master, :american_express, :discover, :diners_club, :jcb,
151
- :switch, :solo ]
152
- end
153
-
154
- # Return whether or not the gateway is in test mode
155
- #
156
- # Parameters:
157
- # -none
158
- #
159
- # Returns:
160
- # -boolean
161
- #
118
+ # Is the gateway running in test mode?
162
119
  def test?
163
120
  @options[:test] || Base.gateway_mode == :test
164
121
  end
@@ -213,7 +170,7 @@ module ActiveMerchant
213
170
  if money
214
171
  xml.tag! :TxnDetails do
215
172
  xml.tag! :merchantreference, format_reference_number(options[:order_id])
216
- xml.tag! :amount, amount(money), :currency => currency(money)
173
+ xml.tag! :amount, amount(money), :currency => options[:currency] || currency(money)
217
174
  end
218
175
  end
219
176
  end
@@ -296,7 +253,7 @@ module ActiveMerchant
296
253
  end
297
254
  xml.tag! :TxnDetails do
298
255
  xml.tag! :merchantreference, format_reference_number(options[:order_id])
299
- xml.tag! :amount, amount(money), :currency => currency(money)
256
+ xml.tag! :amount, amount(money), :currency => options[:currency] || currency(money)
300
257
  end
301
258
  end
302
259
  end
@@ -404,19 +361,6 @@ module ActiveMerchant
404
361
  )
405
362
  end
406
363
 
407
- # Find the currency of the Money object passed
408
- #
409
- # Parameters:
410
- # -money: The money object that we are looking at
411
- #
412
- # Returns:
413
- # -string: The three digit currency code (These are
414
- # ISO 4217 codes)
415
- #
416
- def currency(money)
417
- money.respond_to?(:currency) ? money.currency : 'GBP'
418
- end
419
-
420
364
  # Returns a date string in the format Datacash expects
421
365
  #
422
366
  # Parameters:
@@ -0,0 +1,256 @@
1
+ require 'rexml/document'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+
6
+ class EfsnetGateway < Gateway
7
+ attr_reader :url
8
+ attr_reader :response
9
+ attr_reader :options
10
+
11
+ self.supported_countries = ['US']
12
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
13
+ self.homepage_url = 'http://www.concordefsnet.com/'
14
+ self.display_name = 'Efsnet'
15
+
16
+ TEST_URL = 'https://testefsnet.concordebiz.com/efsnet.dll'
17
+ LIVE_URL = 'https://efsnet.concordebiz.com/efsnet.dll'
18
+
19
+ # login is your Store ID
20
+ # password is your Store Key
21
+ def initialize(options = {})
22
+ requires!(options, :login, :password)
23
+
24
+ @options = options
25
+ @url = test? ? TEST_URL : LIVE_URL
26
+
27
+ super
28
+ end
29
+
30
+ def test?
31
+ @options[:test] || Base.gateway_mode == :test
32
+ end
33
+
34
+ def authorize(money, creditcard, options = {})
35
+ request = build_credit_card_request(money, creditcard, options)
36
+ commit(:credit_card_authorize, request)
37
+ end
38
+
39
+ def purchase(money, creditcard, options = {})
40
+ request = build_credit_card_request(money, creditcard, options)
41
+ commit(:credit_card_charge, request)
42
+ end
43
+
44
+ def capture(money, identification, options = {})
45
+ request = build_refund_or_settle_request(money, identification, options)
46
+ commit(:credit_card_settle, request)
47
+ end
48
+
49
+ def credit(money, identification_or_credit_card, options = {})
50
+ if identification_or_credit_card.is_a?(String)
51
+ # Perform authorization reversal
52
+ request = build_refund_or_settle_request(money, identification_or_credit_card, options)
53
+ commit(:credit_card_refund, request)
54
+ else
55
+ # Perform credit
56
+ request = build_credit_card_request(money, identification_or_credit_card, options)
57
+ commit(:credit_card_credit, request)
58
+ end
59
+ end
60
+
61
+ def void(identification, options = {})
62
+ requires!(options, :order_id)
63
+ original_transaction_id, original_transaction_amount = identification.split(";")
64
+ commit(:void_transaction, {:reference_number => options[:order_id], :transaction_ID => original_transaction_id})
65
+ end
66
+
67
+ def voice_authorize(money, authorization_code, creditcard, options = {})
68
+ options[:authorization_number] = authorization_code
69
+ request = build_credit_card_request(money, creditcard, options)
70
+ commit(:credit_card_voice_authorize, request)
71
+ end
72
+
73
+ def force(money, authorization_code, creditcard, options = {})
74
+ options[:authorization_number] = authorization_code
75
+ request = build_credit_card_request(money, creditcard, options)
76
+ commit(:credit_card_capture, request)
77
+ end
78
+
79
+ def system_check
80
+ commit(:system_check, {})
81
+ end
82
+
83
+ private
84
+
85
+ def build_refund_or_settle_request(money, identification, options = {})
86
+ original_transaction_id, original_transaction_amount = identification.split(";")
87
+
88
+ requires!(options, :order_id)
89
+
90
+ post = {
91
+ :reference_number => options[:order_id],
92
+ :transaction_amount => amount(money),
93
+ :original_transaction_amount => original_transaction_amount,
94
+ :original_transaction_ID => original_transaction_id,
95
+ :client_ip_address => options[:ip]
96
+ }
97
+ end
98
+
99
+ def build_credit_card_request(money, creditcard, options = {})
100
+ requires!(options, :order_id)
101
+
102
+ post = {
103
+ :reference_number => options[:order_id],
104
+ :authorization_number => options[:authorization_number],
105
+ :transaction_amount => amount(money),
106
+ :client_ip_address => options[:ip]
107
+
108
+ }
109
+ add_creditcard(post,creditcard)
110
+ add_address(post,options)
111
+ post
112
+ end
113
+
114
+ def add_address(post,options)
115
+ if address = options[:billing_address] || options[:address]
116
+ if address[:address2]
117
+ post[:billing_address] = address[:address1].to_s << ' ' << address[:address2].to_s
118
+ else
119
+ post[:billing_address] = address[:address1].to_s
120
+ end
121
+ post[:billing_city] = address[:city].to_s
122
+ post[:billing_state] = address[:state].blank? ? 'n/a' : address[:state]
123
+ post[:billing_postal_code] = address[:zip].to_s
124
+ post[:billing_country] = address[:country].to_s
125
+ end
126
+
127
+ if address = options[:shipping_address]
128
+ if address[:address2]
129
+ post[:shipping_address] = address[:address1].to_s << ' ' << address[:address2].to_s
130
+ else
131
+ post[:shipping_address] = address[:address1].to_s
132
+ end
133
+ post[:shipping_city] = address[:city].to_s
134
+ post[:shipping_state] = address[:state].blank? ? 'n/a' : address[:state]
135
+ post[:shipping_postal_code] = address[:zip].to_s
136
+ post[:shipping_country] = address[:country].to_s
137
+ end
138
+ end
139
+
140
+ def add_creditcard(post, creditcard)
141
+ post[:billing_name] = creditcard.name if creditcard.name
142
+ post[:account_number] = creditcard.number
143
+ post[:card_verification_value] = creditcard.verification_value if creditcard.verification_value?
144
+ post[:expiration_month] = sprintf("%.2i", creditcard.month)
145
+ post[:expiration_year] = sprintf("%.4i", creditcard.year)[-2..-1]
146
+ end
147
+
148
+
149
+ def commit(action, parameters)
150
+ if result = test_result_from_cc_number(parameters[:account_number])
151
+ return result
152
+ end
153
+
154
+ parameters.delete_if {|key,value| value.blank?}
155
+
156
+ headers = { 'Content-Type' => 'text/xml' }
157
+ data = ssl_post @url, post_data(action, parameters), headers
158
+
159
+ @response = parse(data)
160
+
161
+ success = (response[:response_code] and response[:response_code] == '0')
162
+ message = message_form(response[:result_message])
163
+
164
+ authorization = [ response[:transaction_id], parameters[:transaction_amount] ].compact.join(';')
165
+
166
+ Response.new(success, message, @response,
167
+ :test => test?,
168
+ :authorization => authorization
169
+ )
170
+ end
171
+
172
+ # Parse response xml into a convinient hash
173
+ def parse(xml)
174
+ #<Reply>
175
+ #<TransactionReply>
176
+ #<ResponseCode>0</ResponseCode>
177
+ #<ResultCode>00</ResultCode>
178
+ #<ResultMessage>APPROVED</ResultMessage>
179
+ #<TransactionID>200011125443</TransactionID>
180
+ #<AVSResponseCode>N</AVSResponseCode>
181
+ #<CVVResponseCode></CVVResponseCode>
182
+ #<ApprovalNumber>123456</ApprovalNumber>
183
+ #<AuthorizationNumber>123456</AuthorizationNumber>
184
+ #<TransactionDate>070728</TransactionDate>
185
+ #<TransactionTime>024734</TransactionTime>
186
+ #<ReferenceNumber>19786</ReferenceNumber>
187
+ #<AccountNumber>XXXXXXXXXXXX5454</AccountNumber>
188
+ #<TransactionAmount>1.00</TransactionAmount>
189
+ #</TransactionReply>
190
+ #</Reply>
191
+
192
+ response = {}
193
+
194
+ xml = REXML::Document.new(xml)
195
+
196
+ xml.elements.each('//Reply//TransactionReply/*') do |node|
197
+
198
+ response[node.name.underscore.to_sym] = normalize(node.text)
199
+
200
+ end unless xml.root.nil?
201
+
202
+ response
203
+ end
204
+
205
+ def post_data(action, parameters = {})
206
+ xml = REXML::Document.new("<?xml version='1.0' encoding='UTF-8'?>")
207
+ root = xml.add_element("Request")
208
+ root.attributes["StoreID"] = options[:login]
209
+ root.attributes["StoreKey"] = options[:password]
210
+ root.attributes["ApplicationID"] = 'ot 1.0'
211
+ transaction = root.add_element(action.to_s.camelize)
212
+
213
+ actions[action].each do |key|
214
+ transaction.add_element(key.to_s.camelize).text = parameters[key] unless parameters[key].blank?
215
+ end
216
+
217
+ xml.to_s
218
+ end
219
+
220
+ def message_form(message)
221
+ return 'Unspecified error' if message.blank?
222
+ message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
223
+ end
224
+
225
+ # Make a ruby type out of the response string
226
+ def normalize(field)
227
+ case field
228
+ when "true" then true
229
+ when "false" then false
230
+ when "" then nil
231
+ when "null" then nil
232
+ else field
233
+ end
234
+ end
235
+
236
+ def actions
237
+ ACTIONS
238
+ end
239
+
240
+
241
+ CREDIT_CARD_FIELDS = [:authorization_number, :client_ip_address, :billing_address, :billing_city, :billing_state, :billing_postal_code, :billing_country, :billing_name, :card_verification_value, :expiration_month, :expiration_year, :reference_number, :transaction_amount, :account_number ]
242
+
243
+ ACTIONS = {
244
+ :credit_card_authorize => CREDIT_CARD_FIELDS,
245
+ :credit_card_charge => CREDIT_CARD_FIELDS,
246
+ :credit_card_voice_authorize => CREDIT_CARD_FIELDS,
247
+ :credit_card_capture => CREDIT_CARD_FIELDS,
248
+ :credit_card_credit => CREDIT_CARD_FIELDS << :original_transaction_amount,
249
+ :credit_card_refund => [:reference_number, :transaction_amount, :original_transaction_amount, :original_transaction_ID, :client_ip_address],
250
+ :void_transaction => [:reference_number, :transaction_ID],
251
+ :credit_card_settle => [:reference_number, :transaction_amount, :original_transaction_amount, :original_transaction_ID, :client_ip_address],
252
+ :system_check => [:system_check],
253
+ }
254
+ end
255
+ end
256
+ end