gonow-activemerchant 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. data/CHANGELOG +690 -0
  2. data/CONTRIBUTORS +237 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +165 -0
  5. data/gem-public_cert.pem +20 -0
  6. data/lib/active_merchant.rb +47 -0
  7. data/lib/active_merchant/billing.rb +9 -0
  8. data/lib/active_merchant/billing/avs_result.rb +98 -0
  9. data/lib/active_merchant/billing/base.rb +57 -0
  10. data/lib/active_merchant/billing/check.rb +68 -0
  11. data/lib/active_merchant/billing/credit_card.rb +178 -0
  12. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  13. data/lib/active_merchant/billing/credit_card_methods.rb +125 -0
  14. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  15. data/lib/active_merchant/billing/expiry_date.rb +34 -0
  16. data/lib/active_merchant/billing/gateway.rb +170 -0
  17. data/lib/active_merchant/billing/gateways.rb +18 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net.rb +664 -0
  19. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +858 -0
  20. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
  21. data/lib/active_merchant/billing/gateways/beanstream.rb +139 -0
  22. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +282 -0
  23. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  24. data/lib/active_merchant/billing/gateways/blue_pay.rb +11 -0
  25. data/lib/active_merchant/billing/gateways/bogus.rb +132 -0
  26. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  27. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  28. data/lib/active_merchant/billing/gateways/braintree_blue.rb +293 -0
  29. data/lib/active_merchant/billing/gateways/braintree_orange.rb +17 -0
  30. data/lib/active_merchant/billing/gateways/braspag.rb +188 -0
  31. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -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 +134 -0
  36. data/lib/active_merchant/billing/gateways/epay.rb +268 -0
  37. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/eway_managed.rb +231 -0
  39. data/lib/active_merchant/billing/gateways/exact.rb +222 -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 +156 -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 +209 -0
  57. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  58. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  59. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  60. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  61. data/lib/active_merchant/billing/gateways/ogone.rb +292 -0
  62. data/lib/active_merchant/billing/gateways/orbital.rb +321 -0
  63. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -0
  64. data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
  65. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  66. data/lib/active_merchant/billing/gateways/paybox_direct.rb +207 -0
  67. data/lib/active_merchant/billing/gateways/payflow.rb +253 -0
  68. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
  69. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  70. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  71. data/lib/active_merchant/billing/gateways/payflow_express.rb +222 -0
  72. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  73. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  74. data/lib/active_merchant/billing/gateways/payment_express.rb +235 -0
  75. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  76. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +351 -0
  77. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
  78. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  79. data/lib/active_merchant/billing/gateways/paypal_express.rb +177 -0
  80. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
  81. data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
  82. data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
  83. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  84. data/lib/active_merchant/billing/gateways/qbms.rb +295 -0
  85. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  86. data/lib/active_merchant/billing/gateways/quickpay.rb +218 -0
  87. data/lib/active_merchant/billing/gateways/realex.rb +311 -0
  88. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  89. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  90. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  91. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  92. data/lib/active_merchant/billing/gateways/sage_pay.rb +320 -0
  93. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  94. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  95. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  96. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +193 -0
  97. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  98. data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
  99. data/lib/active_merchant/billing/gateways/smart_ps.rb +271 -0
  100. data/lib/active_merchant/billing/gateways/stripe.rb +212 -0
  101. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  102. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  103. data/lib/active_merchant/billing/gateways/trust_commerce.rb +423 -0
  104. data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
  105. data/lib/active_merchant/billing/gateways/verifi.rb +233 -0
  106. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  107. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  108. data/lib/active_merchant/billing/gateways/worldpay.rb +280 -0
  109. data/lib/active_merchant/billing/integrations.rb +17 -0
  110. data/lib/active_merchant/billing/integrations/action_view_helper.rb +68 -0
  111. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  112. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  113. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  114. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  115. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  116. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  117. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  118. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  119. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  120. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  121. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  122. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  123. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  124. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  125. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  126. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  127. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  128. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  129. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  130. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  131. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  132. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  133. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  134. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  135. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  136. data/lib/active_merchant/billing/integrations/helper.rb +96 -0
  137. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  138. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  139. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  140. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  141. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  142. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  143. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  144. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  145. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  146. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  147. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  148. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  149. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  150. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  151. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  152. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  153. data/lib/active_merchant/billing/integrations/quickpay.rb +21 -0
  154. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  155. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  156. data/lib/active_merchant/billing/integrations/return.rb +42 -0
  157. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  158. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  159. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +111 -0
  160. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  161. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  162. data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
  163. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  164. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  165. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  166. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  167. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  168. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  169. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
  170. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  171. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  172. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  173. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  174. data/lib/active_merchant/billing/response.rb +32 -0
  175. data/lib/active_merchant/common.rb +14 -0
  176. data/lib/active_merchant/common/connection.rb +177 -0
  177. data/lib/active_merchant/common/country.rb +328 -0
  178. data/lib/active_merchant/common/error.rb +26 -0
  179. data/lib/active_merchant/common/post_data.rb +24 -0
  180. data/lib/active_merchant/common/posts_data.rb +63 -0
  181. data/lib/active_merchant/common/requires_parameters.rb +16 -0
  182. data/lib/active_merchant/common/utils.rb +22 -0
  183. data/lib/active_merchant/common/validateable.rb +81 -0
  184. data/lib/active_merchant/version.rb +3 -0
  185. data/lib/activemerchant.rb +1 -0
  186. data/lib/certs/cacert.pem +7815 -0
  187. data/lib/support/gateway_support.rb +58 -0
  188. data/lib/support/outbound_hosts.rb +25 -0
  189. metadata +276 -0
@@ -0,0 +1,222 @@
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
+ commit(:credit, build_capture_or_credit_request(money, authorization, options))
72
+ end
73
+
74
+ private
75
+ def build_request(action, body)
76
+ xml = Builder::XmlMarkup.new
77
+
78
+ xml.instruct!
79
+ xml.tag! 'env:Envelope', ENVELOPE_NAMESPACES do
80
+ xml.tag! 'env:Body' do
81
+ xml.tag! 'n1:SendAndCommit', SEND_AND_COMMIT_ATTRIBUTES do
82
+ xml.tag! 'SendAndCommitSource', SEND_AND_COMMIT_SOURCE_ATTRIBUTES do
83
+ add_credentials(xml)
84
+ add_transaction_type(xml, action)
85
+ xml << body
86
+ end
87
+ end
88
+ end
89
+ end
90
+ xml.target!
91
+ end
92
+
93
+ def build_sale_or_authorization_request(money, credit_card, options)
94
+ xml = Builder::XmlMarkup.new
95
+
96
+ add_amount(xml, money)
97
+ add_credit_card(xml, credit_card)
98
+ add_customer_data(xml, options)
99
+ add_invoice(xml, options)
100
+
101
+ xml.target!
102
+ end
103
+
104
+ def build_capture_or_credit_request(money, identification, options)
105
+ xml = Builder::XmlMarkup.new
106
+
107
+ add_identification(xml, identification)
108
+ add_amount(xml, money)
109
+ add_customer_data(xml, options)
110
+
111
+ xml.target!
112
+ end
113
+
114
+ def add_credentials(xml)
115
+ xml.tag! 'ExactID', @options[:login]
116
+ xml.tag! 'Password', @options[:password]
117
+ end
118
+
119
+ def add_transaction_type(xml, action)
120
+ xml.tag! 'Transaction_Type', TRANSACTIONS[action]
121
+ end
122
+
123
+ def add_identification(xml, identification)
124
+ authorization_num, transaction_tag = identification.split(';')
125
+
126
+ xml.tag! 'Authorization_Num', authorization_num
127
+ xml.tag! 'Transaction_Tag', transaction_tag
128
+ end
129
+
130
+ def add_amount(xml, money)
131
+ xml.tag! 'DollarAmount', amount(money)
132
+ end
133
+
134
+ def add_credit_card(xml, credit_card)
135
+ xml.tag! 'Card_Number', credit_card.number
136
+ xml.tag! 'Expiry_Date', expdate(credit_card)
137
+ xml.tag! 'CardHoldersName', credit_card.name
138
+
139
+ if credit_card.verification_value?
140
+ xml.tag! 'CVD_Presence_Ind', '1'
141
+ xml.tag! 'VerificationStr2', credit_card.verification_value
142
+ end
143
+ end
144
+
145
+ def add_customer_data(xml, options)
146
+ xml.tag! 'Customer_Ref', options[:customer]
147
+ xml.tag! 'Client_IP', options[:ip]
148
+ xml.tag! 'Client_Email', options[:email]
149
+ end
150
+
151
+ def add_address(xml, options)
152
+ if address = options[:billing_address] || options[:address]
153
+ xml.tag! 'ZipCode', address[:zip]
154
+ end
155
+ end
156
+
157
+ def add_invoice(xml, options)
158
+ xml.tag! 'Reference_No', options[:order_id]
159
+ xml.tag! 'Reference_3', options[:description]
160
+ end
161
+
162
+ def expdate(credit_card)
163
+ "#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}"
164
+ end
165
+
166
+ def commit(action, request)
167
+ response = parse(ssl_post(URL, build_request(action, request), POST_HEADERS))
168
+
169
+ Response.new(successful?(response), message_from(response), response,
170
+ :test => test?,
171
+ :authorization => authorization_from(response),
172
+ :avs_result => { :code => response[:avs] },
173
+ :cvv_result => response[:cvv2]
174
+ )
175
+ end
176
+
177
+ def successful?(response)
178
+ response[:transaction_approved] == SUCCESS
179
+ end
180
+
181
+ def authorization_from(response)
182
+ if response[:authorization_num] && response[:transaction_tag]
183
+ "#{response[:authorization_num]};#{response[:transaction_tag]}"
184
+ else
185
+ ''
186
+ end
187
+ end
188
+
189
+ def message_from(response)
190
+ if response[:faultcode] && response[:faultstring]
191
+ response[:faultstring]
192
+ elsif response[:error_number] != '0'
193
+ response[:error_description]
194
+ else
195
+ result = response[:exact_message] || ''
196
+ result << " - #{response[:bank_message]}" unless response[:bank_message].blank?
197
+ result
198
+ end
199
+ end
200
+
201
+ def parse(xml)
202
+ response = {}
203
+ xml = REXML::Document.new(xml)
204
+
205
+ if root = REXML::XPath.first(xml, "//types:TransactionResult")
206
+ parse_elements(response, root)
207
+ elsif root = REXML::XPath.first(xml, "//soap:Fault")
208
+ parse_elements(response, root)
209
+ end
210
+
211
+ response.delete_if{ |k,v| SENSITIVE_FIELDS.include?(k) }
212
+ end
213
+
214
+ def parse_elements(response, root)
215
+ root.elements.to_a.each do |node|
216
+ response[node.name.gsub(/EXact/, 'Exact').underscore.to_sym] = (node.text || '').strip
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
222
+
@@ -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
+