tlconnor-activemerchant 1.20.4

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.
Files changed (195) hide show
  1. data/CHANGELOG +805 -0
  2. data/CONTRIBUTORS +274 -0
  3. data/MIT-LICENSE +20 -0
  4. data/gem-public_cert.pem +20 -0
  5. data/lib/active_merchant.rb +63 -0
  6. data/lib/active_merchant/billing.rb +9 -0
  7. data/lib/active_merchant/billing/avs_result.rb +98 -0
  8. data/lib/active_merchant/billing/base.rb +57 -0
  9. data/lib/active_merchant/billing/check.rb +68 -0
  10. data/lib/active_merchant/billing/credit_card.rb +264 -0
  11. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  12. data/lib/active_merchant/billing/credit_card_methods.rb +129 -0
  13. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  14. data/lib/active_merchant/billing/expiry_date.rb +34 -0
  15. data/lib/active_merchant/billing/gateway.rb +170 -0
  16. data/lib/active_merchant/billing/gateways.rb +18 -0
  17. data/lib/active_merchant/billing/gateways/authorize_net.rb +694 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +944 -0
  19. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
  20. data/lib/active_merchant/billing/gateways/beanstream.rb +167 -0
  21. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +388 -0
  22. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  23. data/lib/active_merchant/billing/gateways/blue_pay.rb +11 -0
  24. data/lib/active_merchant/billing/gateways/bogus.rb +142 -0
  25. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  26. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  27. data/lib/active_merchant/billing/gateways/braintree_blue.rb +308 -0
  28. data/lib/active_merchant/billing/gateways/braintree_orange.rb +21 -0
  29. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  30. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
  31. data/lib/active_merchant/billing/gateways/certo_direct.rb +279 -0
  32. data/lib/active_merchant/billing/gateways/cyber_source.rb +430 -0
  33. data/lib/active_merchant/billing/gateways/data_cash.rb +597 -0
  34. data/lib/active_merchant/billing/gateways/efsnet.rb +235 -0
  35. data/lib/active_merchant/billing/gateways/elavon.rb +135 -0
  36. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  37. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/eway_managed.rb +265 -0
  39. data/lib/active_merchant/billing/gateways/exact.rb +227 -0
  40. data/lib/active_merchant/billing/gateways/federated_canada.rb +168 -0
  41. data/lib/active_merchant/billing/gateways/first_pay.rb +177 -0
  42. data/lib/active_merchant/billing/gateways/garanti.rb +262 -0
  43. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +250 -0
  44. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  45. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  46. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +55 -0
  47. data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
  48. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  49. data/lib/active_merchant/billing/gateways/iridium.rb +258 -0
  50. data/lib/active_merchant/billing/gateways/jetpay.rb +276 -0
  51. data/lib/active_merchant/billing/gateways/linkpoint.rb +454 -0
  52. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +157 -0
  53. data/lib/active_merchant/billing/gateways/merchant_ware.rb +289 -0
  54. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  55. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
  56. data/lib/active_merchant/billing/gateways/moneris.rb +239 -0
  57. data/lib/active_merchant/billing/gateways/nab_transact.rb +244 -0
  58. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  59. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  60. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  61. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  62. data/lib/active_merchant/billing/gateways/ogone.rb +330 -0
  63. data/lib/active_merchant/billing/gateways/optimal_payment.rb +277 -0
  64. data/lib/active_merchant/billing/gateways/orbital.rb +344 -0
  65. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -0
  66. data/lib/active_merchant/billing/gateways/pay_junction.rb +397 -0
  67. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  68. data/lib/active_merchant/billing/gateways/paybox_direct.rb +207 -0
  69. data/lib/active_merchant/billing/gateways/payflow.rb +261 -0
  70. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +208 -0
  71. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  72. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  73. data/lib/active_merchant/billing/gateways/payflow_express.rb +222 -0
  74. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  75. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  76. data/lib/active_merchant/billing/gateways/payment_express.rb +235 -0
  77. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  78. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +354 -0
  79. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
  80. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  81. data/lib/active_merchant/billing/gateways/paypal_express.rb +229 -0
  82. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
  83. data/lib/active_merchant/billing/gateways/paystation.rb +201 -0
  84. data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
  85. data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
  86. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  87. data/lib/active_merchant/billing/gateways/qbms.rb +297 -0
  88. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  89. data/lib/active_merchant/billing/gateways/quickpay.rb +298 -0
  90. data/lib/active_merchant/billing/gateways/realex.rb +315 -0
  91. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  92. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  93. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  94. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  95. data/lib/active_merchant/billing/gateways/sage_pay.rb +320 -0
  96. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  97. data/lib/active_merchant/billing/gateways/samurai.rb +121 -0
  98. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  99. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  100. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +280 -0
  101. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  102. data/lib/active_merchant/billing/gateways/skip_jack.rb +458 -0
  103. data/lib/active_merchant/billing/gateways/smart_ps.rb +271 -0
  104. data/lib/active_merchant/billing/gateways/stripe.rb +244 -0
  105. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  106. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  107. data/lib/active_merchant/billing/gateways/trust_commerce.rb +423 -0
  108. data/lib/active_merchant/billing/gateways/usa_epay.rb +23 -0
  109. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1496 -0
  110. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +206 -0
  111. data/lib/active_merchant/billing/gateways/verifi.rb +233 -0
  112. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  113. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  114. data/lib/active_merchant/billing/gateways/worldpay.rb +280 -0
  115. data/lib/active_merchant/billing/integrations.rb +17 -0
  116. data/lib/active_merchant/billing/integrations/action_view_helper.rb +72 -0
  117. data/lib/active_merchant/billing/integrations/authorize_net_sim.rb +38 -0
  118. data/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb +228 -0
  119. data/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb +340 -0
  120. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  121. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  122. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  123. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  124. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  125. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  126. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  127. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  128. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  129. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  130. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  131. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  132. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  133. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  134. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  135. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  136. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  137. data/lib/active_merchant/billing/integrations/dwolla.rb +30 -0
  138. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +31 -0
  139. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +55 -0
  140. data/lib/active_merchant/billing/integrations/dwolla/return.rb +38 -0
  141. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  142. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  143. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  144. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  145. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  146. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  147. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  148. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  149. data/lib/active_merchant/billing/integrations/helper.rb +113 -0
  150. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  151. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  152. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  153. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  154. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  155. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  156. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  157. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  158. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  159. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  160. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  161. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  162. data/lib/active_merchant/billing/integrations/payflow_link.rb +21 -0
  163. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +100 -0
  164. data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +78 -0
  165. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  166. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  167. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  168. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  169. data/lib/active_merchant/billing/integrations/quickpay.rb +21 -0
  170. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  171. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  172. data/lib/active_merchant/billing/integrations/return.rb +42 -0
  173. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  174. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  175. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +127 -0
  176. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  177. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  178. data/lib/active_merchant/billing/integrations/two_checkout.rb +22 -0
  179. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  180. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  181. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  182. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  183. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  184. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  185. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
  186. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  187. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  188. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  189. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  190. data/lib/active_merchant/billing/response.rb +32 -0
  191. data/lib/active_merchant/version.rb +3 -0
  192. data/lib/activemerchant.rb +1 -0
  193. data/lib/support/gateway_support.rb +58 -0
  194. data/lib/support/outbound_hosts.rb +25 -0
  195. metadata +411 -0
@@ -0,0 +1,227 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class ExactGateway < Gateway
4
+ URL = 'https://secure2.e-xact.com/vplug-in/transaction/rpc-enc/service.asmx'
5
+
6
+ API_VERSION = "8.5"
7
+
8
+ TEST_LOGINS = [ {:login => "A00049-01", :password => "test1"},
9
+ {:login => "A00427-01", :password => "testus"} ]
10
+
11
+ TRANSACTIONS = { :sale => "00",
12
+ :authorization => "01",
13
+ :capture => "32",
14
+ :credit => "34" }
15
+
16
+
17
+ ENVELOPE_NAMESPACES = { 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
18
+ 'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/',
19
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
20
+ }
21
+
22
+ SEND_AND_COMMIT_ATTRIBUTES = { 'xmlns:n1' => "http://secure2.e-xact.com/vplug-in/transaction/rpc-enc/Request",
23
+ 'env:encodingStyle' => 'http://schemas.xmlsoap.org/soap/encoding/'
24
+ }
25
+
26
+ SEND_AND_COMMIT_SOURCE_ATTRIBUTES = { 'xmlns:n2' => 'http://secure2.e-xact.com/vplug-in/transaction/rpc-enc/encodedTypes',
27
+ 'xsi:type' => 'n2:Transaction'
28
+ }
29
+
30
+ POST_HEADERS = { 'soapAction' => "http://secure2.e-xact.com/vplug-in/transaction/rpc-enc/SendAndCommit",
31
+ 'Content-Type' => 'text/xml'
32
+ }
33
+
34
+ SUCCESS = "true"
35
+
36
+ SENSITIVE_FIELDS = [ :verification_str2, :expiry_date, :card_number ]
37
+
38
+ self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :discover]
39
+ self.supported_countries = ['CA', 'US']
40
+ self.homepage_url = 'http://www.e-xact.com'
41
+ self.display_name = 'E-xact'
42
+
43
+ def initialize(options = {})
44
+ requires!(options, :login, :password)
45
+ @options = options
46
+
47
+ if TEST_LOGINS.include?( { :login => options[:login], :password => options[:password] } )
48
+ @test_mode = true
49
+ end
50
+
51
+ super
52
+ end
53
+
54
+ def test?
55
+ @test_mode || Base.gateway_mode == :test
56
+ end
57
+
58
+ def authorize(money, credit_card, options = {})
59
+ commit(:authorization, build_sale_or_authorization_request(money, credit_card, options))
60
+ end
61
+
62
+ def purchase(money, credit_card, options = {})
63
+ commit(:sale, build_sale_or_authorization_request(money, credit_card, options))
64
+ end
65
+
66
+ def capture(money, authorization, options = {})
67
+ commit(:capture, build_capture_or_credit_request(money, authorization, options))
68
+ end
69
+
70
+ def credit(money, authorization, options = {})
71
+ deprecated CREDIT_DEPRECATION_MESSAGE
72
+ refund(money, authorization, options)
73
+ end
74
+
75
+ def refund(money, authorization, options = {})
76
+ commit(:credit, build_capture_or_credit_request(money, authorization, options))
77
+ end
78
+
79
+ private
80
+ def build_request(action, body)
81
+ xml = Builder::XmlMarkup.new
82
+
83
+ xml.instruct!
84
+ xml.tag! 'env:Envelope', ENVELOPE_NAMESPACES do
85
+ xml.tag! 'env:Body' do
86
+ xml.tag! 'n1:SendAndCommit', SEND_AND_COMMIT_ATTRIBUTES do
87
+ xml.tag! 'SendAndCommitSource', SEND_AND_COMMIT_SOURCE_ATTRIBUTES do
88
+ add_credentials(xml)
89
+ add_transaction_type(xml, action)
90
+ xml << body
91
+ end
92
+ end
93
+ end
94
+ end
95
+ xml.target!
96
+ end
97
+
98
+ def build_sale_or_authorization_request(money, credit_card, options)
99
+ xml = Builder::XmlMarkup.new
100
+
101
+ add_amount(xml, money)
102
+ add_credit_card(xml, credit_card)
103
+ add_customer_data(xml, options)
104
+ add_invoice(xml, options)
105
+
106
+ xml.target!
107
+ end
108
+
109
+ def build_capture_or_credit_request(money, identification, options)
110
+ xml = Builder::XmlMarkup.new
111
+
112
+ add_identification(xml, identification)
113
+ add_amount(xml, money)
114
+ add_customer_data(xml, options)
115
+
116
+ xml.target!
117
+ end
118
+
119
+ def add_credentials(xml)
120
+ xml.tag! 'ExactID', @options[:login]
121
+ xml.tag! 'Password', @options[:password]
122
+ end
123
+
124
+ def add_transaction_type(xml, action)
125
+ xml.tag! 'Transaction_Type', TRANSACTIONS[action]
126
+ end
127
+
128
+ def add_identification(xml, identification)
129
+ authorization_num, transaction_tag = identification.split(';')
130
+
131
+ xml.tag! 'Authorization_Num', authorization_num
132
+ xml.tag! 'Transaction_Tag', transaction_tag
133
+ end
134
+
135
+ def add_amount(xml, money)
136
+ xml.tag! 'DollarAmount', amount(money)
137
+ end
138
+
139
+ def add_credit_card(xml, credit_card)
140
+ xml.tag! 'Card_Number', credit_card.number
141
+ xml.tag! 'Expiry_Date', expdate(credit_card)
142
+ xml.tag! 'CardHoldersName', credit_card.name
143
+
144
+ if credit_card.verification_value?
145
+ xml.tag! 'CVD_Presence_Ind', '1'
146
+ xml.tag! 'VerificationStr2', credit_card.verification_value
147
+ end
148
+ end
149
+
150
+ def add_customer_data(xml, options)
151
+ xml.tag! 'Customer_Ref', options[:customer]
152
+ xml.tag! 'Client_IP', options[:ip]
153
+ xml.tag! 'Client_Email', options[:email]
154
+ end
155
+
156
+ def add_address(xml, options)
157
+ if address = options[:billing_address] || options[:address]
158
+ xml.tag! 'ZipCode', address[:zip]
159
+ end
160
+ end
161
+
162
+ def add_invoice(xml, options)
163
+ xml.tag! 'Reference_No', options[:order_id]
164
+ xml.tag! 'Reference_3', options[:description]
165
+ end
166
+
167
+ def expdate(credit_card)
168
+ "#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}"
169
+ end
170
+
171
+ def commit(action, request)
172
+ response = parse(ssl_post(URL, build_request(action, request), POST_HEADERS))
173
+
174
+ Response.new(successful?(response), message_from(response), response,
175
+ :test => test?,
176
+ :authorization => authorization_from(response),
177
+ :avs_result => { :code => response[:avs] },
178
+ :cvv_result => response[:cvv2]
179
+ )
180
+ end
181
+
182
+ def successful?(response)
183
+ response[:transaction_approved] == SUCCESS
184
+ end
185
+
186
+ def authorization_from(response)
187
+ if response[:authorization_num] && response[:transaction_tag]
188
+ "#{response[:authorization_num]};#{response[:transaction_tag]}"
189
+ else
190
+ ''
191
+ end
192
+ end
193
+
194
+ def message_from(response)
195
+ if response[:faultcode] && response[:faultstring]
196
+ response[:faultstring]
197
+ elsif response[:error_number] != '0'
198
+ response[:error_description]
199
+ else
200
+ result = response[:exact_message] || ''
201
+ result << " - #{response[:bank_message]}" unless response[:bank_message].blank?
202
+ result
203
+ end
204
+ end
205
+
206
+ def parse(xml)
207
+ response = {}
208
+ xml = REXML::Document.new(xml)
209
+
210
+ if root = REXML::XPath.first(xml, "//types:TransactionResult")
211
+ parse_elements(response, root)
212
+ elsif root = REXML::XPath.first(xml, "//soap:Fault")
213
+ parse_elements(response, root)
214
+ end
215
+
216
+ response.delete_if{ |k,v| SENSITIVE_FIELDS.include?(k) }
217
+ end
218
+
219
+ def parse_elements(response, root)
220
+ root.elements.to_a.each do |node|
221
+ response[node.name.gsub(/EXact/, 'Exact').underscore.to_sym] = (node.text || '').strip
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
227
+
@@ -0,0 +1,168 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class FederatedCanadaGateway < Gateway
4
+ # Same URL for both test and live, testing is done by using the test username (demo) and password (password).
5
+ URL = 'https://secure.federatedgateway.com/api/transact.php'
6
+
7
+ APPROVED, DECLINED, ERROR = 1, 2, 3
8
+
9
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
10
+ self.supported_countries = ['CA']
11
+
12
+ self.default_currency = 'CAD'
13
+
14
+ # The card types supported by the payment gateway
15
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
16
+
17
+ # The homepage URL of the gateway
18
+ self.homepage_url = 'http://www.federatedcanada.com/'
19
+
20
+ # The name of the gateway
21
+ self.display_name = 'Federated Canada'
22
+
23
+ def initialize(options = {})
24
+ requires!(options, :login, :password)
25
+ @options = options
26
+ super
27
+ end
28
+
29
+ def purchase(money, creditcard, options = {})
30
+ post = {}
31
+ add_invoice(post, options)
32
+ add_creditcard(post, creditcard)
33
+ add_address(post, options)
34
+ add_customer_data(post, options)
35
+ commit('sale', money, post)
36
+ end
37
+
38
+ def authorize(money, creditcard, options = {})
39
+ post = {}
40
+ add_invoice(post, options)
41
+ add_creditcard(post, creditcard)
42
+ add_address(post, options)
43
+ add_customer_data(post, options)
44
+ commit('auth', money, post)
45
+ end
46
+
47
+ def capture(money, authorization, options = {})
48
+ options[:transactionid] = authorization
49
+ commit('capture', money, options)
50
+ end
51
+
52
+ def void(authorization, options = {})
53
+ options[:transactionid] = authorization
54
+ commit('void', nil, options)
55
+ end
56
+
57
+ def refund(money, authorization, options = {})
58
+ commit('refund', money, options.merge(:transactionid => authorization))
59
+ end
60
+
61
+ def credit(money, authorization, options = {})
62
+ deprecated CREDIT_DEPRECATION_MESSAGE
63
+ refund(money, authorization, options)
64
+ end
65
+
66
+ private
67
+
68
+ def add_customer_data(post, options)
69
+ post[:firstname] = options[:first_name]
70
+ post[:lastname] = options[:last_name]
71
+
72
+ post[:email] = options[:email]
73
+ end
74
+
75
+ def add_address(post, options)
76
+ if address = (options[:billing_address] || options[:address])
77
+ post[:company] = address[:company]
78
+ post[:address1] = address[:address1]
79
+ post[:address2] = address[:address2]
80
+ post[:city] = address[:city]
81
+ post[:state] = address[:state]
82
+ post[:zip] = address[:zip]
83
+ post[:country] = address[:country]
84
+ post[:phone] = address[:phone]
85
+ end
86
+ if address = options[:shipping_address]
87
+ post[:shipping_firstname] = address[:first_name]
88
+ post[:shipping_lastname] = address[:last_name]
89
+ post[:shipping_company] = address[:company]
90
+ post[:shipping_address1] = address[:address1]
91
+ post[:shipping_address2] = address[:address2]
92
+ post[:shipping_city] = address[:city]
93
+ post[:shipping_state] = address[:state]
94
+ post[:shipping_zip] = address[:zip]
95
+ post[:shipping_country] = address[:country]
96
+ post[:shipping_email] = address[:email]
97
+ end
98
+ end
99
+
100
+ def add_invoice(post, options)
101
+ post[:orderid] = options[:order_id]
102
+ post[:orderdescription] = options[:description]
103
+ end
104
+
105
+ def add_creditcard(post, creditcard)
106
+ post[:ccnumber] = creditcard.number
107
+ post[:ccexp] = expdate(creditcard)
108
+ post[:cvv] = creditcard.verification_value
109
+ end
110
+
111
+ def expdate(creditcard)
112
+ year = sprintf("%.4i", creditcard.year)
113
+ month = sprintf("%.2i", creditcard.month)
114
+ "#{month}#{year[-2..-1]}"
115
+ end
116
+
117
+ def parse(body)
118
+ body.split('&').inject({}) do |memo, x|
119
+ k, v = x.split('=')
120
+ memo[k] = v
121
+ memo
122
+ end
123
+ end
124
+
125
+ def commit(action, money, parameters)
126
+ parameters[:amount] = amount(money)
127
+ data = ssl_post(URL, post_data(action, parameters))
128
+ response = parse(data)
129
+ message = message_from(response)
130
+ test_mode = test?
131
+
132
+ Response.new(success?(response), message, response,
133
+ :test => test?,
134
+ :authorization => response['transactionid'],
135
+ :avs_result => {:code => response['avsresponse']},
136
+ :cvv_result => response['cvvresponse']
137
+ )
138
+ end
139
+
140
+ def success?(response)
141
+ response['response'] == '1'
142
+ end
143
+
144
+ def test?
145
+ (@options[:login].eql?('demo')) && (@options[:password].eql?('password'))
146
+ end
147
+
148
+ def message_from(response)
149
+ case response['response'].to_i
150
+ when APPROVED
151
+ "Transaction Approved"
152
+ when DECLINED
153
+ "Transaction Declined"
154
+ else
155
+ "Error in transaction data or system error"
156
+ end
157
+ end
158
+
159
+ def post_data(action, parameters = {})
160
+ parameters[:type] = action
161
+ parameters[:username] = @options[:login]
162
+ parameters[:password] = @options[:password]
163
+ parameters.map{|k, v| "#{k}=#{CGI.escape(v.to_s)}"}.join('&')
164
+ end
165
+ end
166
+ end
167
+ end
168
+
@@ -0,0 +1,177 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class FirstPayGateway < Gateway
4
+ class FirstPayPostData < PostData
5
+ # Fields that will be sent even if they are blank
6
+ self.required_fields = [ :action, :amount, :trackid ]
7
+ end
8
+
9
+ # both URLs are IP restricted
10
+ TEST_URL = 'https://apgcert.first-pay.com/AcqENGIN/SecureCapture'
11
+ LIVE_URL = 'https://acqengin.first-pay.com/AcqENGIN/SecureCapture'
12
+
13
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
14
+ self.supported_countries = ['US']
15
+
16
+ # The card types supported by the payment gateway
17
+ self.supported_cardtypes = [:visa, :master]
18
+
19
+ # The homepage URL of the gateway
20
+ self.homepage_url = 'http://www.first-pay.com'
21
+
22
+ # The name of the gateway
23
+ self.display_name = 'First Pay'
24
+
25
+ # all transactions are in cents
26
+ self.money_format = :cents
27
+
28
+ ACTIONS = {
29
+ 'sale' => 1,
30
+ 'credit' => 2,
31
+ 'void' => 3
32
+ }
33
+
34
+ def initialize(options = {})
35
+ requires!(options, :login, :password)
36
+ @options = options
37
+ super
38
+ end
39
+
40
+ def purchase(money, creditcard, options = {})
41
+ post = FirstPayPostData.new
42
+ add_invoice(post, options)
43
+ add_creditcard(post, creditcard)
44
+ add_address(post, options)
45
+ add_customer_data(post, options)
46
+
47
+ commit('sale', money, post)
48
+ end
49
+
50
+ def refund(money, reference, options = {})
51
+ requires!(options, :credit_card)
52
+
53
+ post = FirstPayPostData.new
54
+ add_invoice(post, options)
55
+ add_creditcard(post, options[:credit_card])
56
+ add_address(post, options)
57
+ add_customer_data(post, options)
58
+ add_credit_data(post, reference)
59
+
60
+ commit('credit', money, post)
61
+ end
62
+
63
+ def credit(money, reference, options = {})
64
+ deprecated CREDIT_DEPRECATION_MESSAGE
65
+ refund(money, reference, options)
66
+ end
67
+
68
+ def void(money, creditcard, options = {})
69
+ post = FirstPayPostData.new
70
+ add_creditcard(post, creditcard)
71
+ add_void_data(post, options)
72
+ add_invoice(post, options)
73
+ add_customer_data(post, options)
74
+
75
+ commit('void', money, post)
76
+ end
77
+
78
+
79
+ private
80
+
81
+ def add_customer_data(post, options)
82
+ post[:cardip] = options[:ip]
83
+ post[:email] = options[:email]
84
+ end
85
+
86
+ def add_address(post, options)
87
+ if billing_address = options[:billing_address] || options[:address]
88
+ post[:addr] = billing_address[:address1].to_s + ' ' + billing_address[:address2].to_s
89
+ post[:city] = billing_address[:city]
90
+ post[:state] = billing_address[:state]
91
+ post[:zip] = billing_address[:zip]
92
+ post[:country] = billing_address[:country]
93
+ end
94
+ end
95
+
96
+ def add_invoice(post, options)
97
+ post[:trackid] = rand(Time.now.to_i)
98
+ end
99
+
100
+ def add_creditcard(post, creditcard)
101
+ post[:member] = creditcard.first_name.to_s + " " + creditcard.last_name.to_s
102
+ post[:card] = creditcard.number
103
+ post[:exp] = expdate(creditcard)
104
+ end
105
+
106
+ def expdate(credit_card)
107
+ year = sprintf("%.4i", credit_card.year)
108
+ month = sprintf("%.2i", credit_card.month)
109
+
110
+ "#{month}#{year[-2..-1]}"
111
+ end
112
+
113
+ def add_credit_data(post, transaction_id)
114
+ post[:transid] = transaction_id
115
+ end
116
+
117
+ def add_void_data(post, options)
118
+ post[:transid] = options[:transactionid]
119
+ end
120
+
121
+ def commit(action, money, post)
122
+ response = parse( ssl_post(test? ? TEST_URL : LIVE_URL, post_data(action, post, money)) )
123
+
124
+ Response.new(response[:response] == 'CAPTURED', response[:message], response,
125
+ :test => test?,
126
+ :authorization => response[:authorization],
127
+ :avs_result => { :code => response[:avsresponse] },
128
+ :cvv_result => response[:cvvresponse])
129
+ end
130
+
131
+ def parse(body)
132
+ response = {}
133
+
134
+ # check for an error first
135
+ if body.include?('!ERROR!')
136
+ response[:response] = 'ERROR'
137
+ response[:message] = error_message_from(body)
138
+ else
139
+ # a capture / not captured response will be : delimited
140
+ split = body.split(':')
141
+ response[:response] = split[0]
142
+
143
+ # FirstPay docs are worthless. turns out the transactionid is required for credits
144
+ # so we need to store that in authorization, not the actual auth.
145
+ if response[:response] == 'CAPTURED'
146
+ response[:message] = 'CAPTURED'
147
+ response[:authorization] = split[9] # actually the transactionid
148
+ response[:auth] = split[1]
149
+ response[:avsresponse] = split[3]
150
+ response[:cvvresponse] = split[17]
151
+ else
152
+ # NOT CAPTURED response
153
+ response[:message] = split[1]
154
+ response[:transactionid] = split[9]
155
+ end
156
+ end
157
+
158
+ return response
159
+ end
160
+
161
+ def error_message_from(response)
162
+ # error messages use this format - '!ERROR! 704-MISSING BASIC DATA TYPE:card, exp, zip, addr, member, amount\n'
163
+ response.split("! ")[1].chomp
164
+ end
165
+
166
+ def post_data(action, post, money)
167
+ post[:vid] = @options[:login]
168
+ post[:password] = @options[:password]
169
+ post[:action] = ACTIONS[action]
170
+ post[:amount] = amount(money)
171
+
172
+ return post.to_post_data
173
+ end
174
+ end
175
+ end
176
+ end
177
+