fishman-activemerchant 1.18.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 (188) hide show
  1. data/CHANGELOG +733 -0
  2. data/CONTRIBUTORS +257 -0
  3. data/MIT-LICENSE +20 -0
  4. data/gem-public_cert.pem +20 -0
  5. data/lib/active_merchant.rb +47 -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 +260 -0
  11. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  12. data/lib/active_merchant/billing/credit_card_methods.rb +125 -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 +693 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +858 -0
  19. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
  20. data/lib/active_merchant/billing/gateways/beanstream.rb +139 -0
  21. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +282 -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 +303 -0
  28. data/lib/active_merchant/billing/gateways/braintree_orange.rb +17 -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/cyber_source.rb +430 -0
  32. data/lib/active_merchant/billing/gateways/data_cash.rb +597 -0
  33. data/lib/active_merchant/billing/gateways/efsnet.rb +235 -0
  34. data/lib/active_merchant/billing/gateways/elavon.rb +134 -0
  35. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  36. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  37. data/lib/active_merchant/billing/gateways/eway_managed.rb +264 -0
  38. data/lib/active_merchant/billing/gateways/exact.rb +222 -0
  39. data/lib/active_merchant/billing/gateways/federated_canada.rb +168 -0
  40. data/lib/active_merchant/billing/gateways/first_pay.rb +177 -0
  41. data/lib/active_merchant/billing/gateways/garanti.rb +262 -0
  42. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +250 -0
  43. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  44. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  45. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +55 -0
  46. data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
  47. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  48. data/lib/active_merchant/billing/gateways/iridium.rb +258 -0
  49. data/lib/active_merchant/billing/gateways/jetpay.rb +276 -0
  50. data/lib/active_merchant/billing/gateways/linkpoint.rb +454 -0
  51. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +156 -0
  52. data/lib/active_merchant/billing/gateways/merchant_ware.rb +289 -0
  53. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  54. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
  55. data/lib/active_merchant/billing/gateways/moneris.rb +209 -0
  56. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  57. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  58. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  59. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  60. data/lib/active_merchant/billing/gateways/ogone.rb +292 -0
  61. data/lib/active_merchant/billing/gateways/optimal_payment.rb +274 -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 +354 -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 +184 -0
  80. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
  81. data/lib/active_merchant/billing/gateways/paypal_express_de.rb +14 -0
  82. data/lib/active_merchant/billing/gateways/paystation.rb +201 -0
  83. data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
  84. data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
  85. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  86. data/lib/active_merchant/billing/gateways/qbms.rb +297 -0
  87. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  88. data/lib/active_merchant/billing/gateways/quickpay.rb +297 -0
  89. data/lib/active_merchant/billing/gateways/realex.rb +311 -0
  90. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  91. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  92. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  93. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  94. data/lib/active_merchant/billing/gateways/sage_pay.rb +320 -0
  95. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  96. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  97. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  98. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +193 -0
  99. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  100. data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
  101. data/lib/active_merchant/billing/gateways/smart_ps.rb +271 -0
  102. data/lib/active_merchant/billing/gateways/stripe.rb +212 -0
  103. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  104. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  105. data/lib/active_merchant/billing/gateways/trust_commerce.rb +423 -0
  106. data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
  107. data/lib/active_merchant/billing/gateways/verifi.rb +233 -0
  108. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  109. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  110. data/lib/active_merchant/billing/gateways/worldpay.rb +280 -0
  111. data/lib/active_merchant/billing/integrations.rb +17 -0
  112. data/lib/active_merchant/billing/integrations/action_view_helper.rb +68 -0
  113. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  114. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  115. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  116. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  117. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  118. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  119. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  120. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  121. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  122. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  123. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  124. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  125. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  126. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  127. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  128. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  129. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  130. data/lib/active_merchant/billing/integrations/dwolla.rb +30 -0
  131. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +28 -0
  132. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +50 -0
  133. data/lib/active_merchant/billing/integrations/dwolla/return.rb +38 -0
  134. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  135. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  136. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  137. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  138. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  139. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  140. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  141. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  142. data/lib/active_merchant/billing/integrations/helper.rb +96 -0
  143. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  144. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  145. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  146. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  147. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  148. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  149. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  150. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  151. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  152. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  153. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  154. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  155. data/lib/active_merchant/billing/integrations/payflow_link.rb +21 -0
  156. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +58 -0
  157. data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +78 -0
  158. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  159. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  160. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  161. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  162. data/lib/active_merchant/billing/integrations/quickpay.rb +21 -0
  163. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  164. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  165. data/lib/active_merchant/billing/integrations/return.rb +42 -0
  166. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  167. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  168. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +111 -0
  169. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  170. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  171. data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
  172. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  173. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  174. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  175. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  176. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  177. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  178. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
  179. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  180. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  181. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  182. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  183. data/lib/active_merchant/billing/response.rb +32 -0
  184. data/lib/active_merchant/version.rb +3 -0
  185. data/lib/activemerchant.rb +1 -0
  186. data/lib/support/gateway_support.rb +58 -0
  187. data/lib/support/outbound_hosts.rb +25 -0
  188. metadata +335 -0
@@ -0,0 +1,258 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ # For more information on the Iridium Gateway please download the
4
+ # documentation from their Merchant Management System.
5
+ #
6
+ # The login and password are not the username and password you use to
7
+ # login to the Iridium Merchant Management System. Instead, you will
8
+ # use the API username and password you were issued separately.
9
+ class IridiumGateway < Gateway
10
+
11
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
12
+ self.supported_countries = ['GB', 'ES']
13
+ self.default_currency = 'EUR'
14
+ self.money_format = :cents
15
+
16
+ # The card types supported by the payment gateway
17
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
18
+
19
+ # The homepage URL of the gateway
20
+ self.homepage_url = 'http://www.iridiumcorp.co.uk/'
21
+
22
+ # The name of the gateway
23
+ self.display_name = 'Iridium'
24
+
25
+ CURRENCY_CODES = {
26
+ "AUD" => '036',
27
+ "CAD" => '124',
28
+ "EUR" => '978',
29
+ "GBP" => '826',
30
+ "MXN" => '484',
31
+ "NZD" => '554',
32
+ "USD" => '840',
33
+ }
34
+
35
+ def initialize(options = {})
36
+ requires!(options, :login, :password)
37
+ @options = options
38
+ @test_url = 'https://gw1.iridiumcorp.net/'
39
+ @live_url = 'https://gw1.iridiumcorp.net/'
40
+ super
41
+ end
42
+
43
+ def authorize(money, creditcard, options = {})
44
+ commit(build_purchase_request('PREAUTH', money, creditcard, options), options)
45
+ end
46
+
47
+ def purchase(money, payment_source, options = {})
48
+ setup_address_hash(options)
49
+
50
+ if payment_source.respond_to?(:number)
51
+ commit(build_purchase_request('SALE', money, payment_source, options), options)
52
+ else
53
+ commit(build_reference_request('SALE', money, payment_source, options), options)
54
+ end
55
+ end
56
+
57
+ def capture(money, authorization, options = {})
58
+ commit(build_reference_request('COLLECTION', money, authorization, options), options)
59
+ end
60
+
61
+ def credit(money, authorization, options={})
62
+ deprecated CREDIT_DEPRECATION_MESSAGE
63
+ refund(money, authorization, options)
64
+ end
65
+
66
+ def refund(money, authorization, options={})
67
+ commit(build_reference_request('REFUND', money, authorization, options), options)
68
+ end
69
+
70
+ def void(authorization, options={})
71
+ commit(build_reference_request('VOID', nil, authorization, options), options)
72
+ end
73
+
74
+ private
75
+
76
+ def build_purchase_request(type, money, creditcard, options)
77
+ options.merge!(:action => 'CardDetailsTransaction')
78
+ build_request(options) do |xml|
79
+ add_purchase_data(xml, type, money, options)
80
+ add_creditcard(xml, creditcard)
81
+ add_customerdetails(xml, creditcard, options[:billing_address], options)
82
+ end
83
+ end
84
+
85
+ def build_reference_request(type, money, authorization, options)
86
+ options.merge!(:action => 'CrossReferenceTransaction')
87
+ order_id, cross_reference, auth_id = authorization.split(";")
88
+ build_request(options) do |xml|
89
+ if money
90
+ details = {'CurrencyCode' => currency_code(options[:currency] || default_currency), 'Amount' => amount(money)}
91
+ else
92
+ details = {'CurrencyCode' => currency_code(default_currency), 'Amount' => '0'}
93
+ end
94
+ xml.tag! 'TransactionDetails', details do
95
+ xml.tag! 'MessageDetails', {'TransactionType' => type, 'CrossReference' => cross_reference}
96
+ xml.tag! 'OrderID', (options[:order_id] || order_id)
97
+ end
98
+ end
99
+ end
100
+
101
+ def build_request(options)
102
+ requires!(options, :action)
103
+ xml = Builder::XmlMarkup.new :indent => 2
104
+ xml.instruct!(:xml, :version => '1.0', :encoding => 'utf-8')
105
+ xml.tag! 'soap:Envelope', { 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/',
106
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
107
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'} do
108
+ xml.tag! 'soap:Body' do
109
+ xml.tag! options[:action], {'xmlns' => "https://www.thepaymentgateway.net/"} do
110
+ xml.tag! 'PaymentMessage' do
111
+ add_merchant_data(xml, options)
112
+ yield(xml)
113
+ end
114
+ end
115
+ end
116
+ end
117
+ xml.target!
118
+ end
119
+
120
+ def setup_address_hash(options)
121
+ options[:billing_address] = options[:billing_address] || options[:address] || {}
122
+ options[:shipping_address] = options[:shipping_address] || {}
123
+ end
124
+
125
+ def add_purchase_data(xml, type, money, options)
126
+ requires!(options, :order_id)
127
+ xml.tag! 'TransactionDetails', {'Amount' => amount(money), 'CurrencyCode' => currency_code(options[:currency] || currency(money))} do
128
+ xml.tag! 'MessageDetails', {'TransactionType' => type}
129
+ xml.tag! 'OrderID', options[:order_id]
130
+ xml.tag! 'TransactionControl' do
131
+ xml.tag! 'ThreeDSecureOverridePolicy', 'FALSE'
132
+ xml.tag! 'EchoAVSCheckResult', 'TRUE'
133
+ xml.tag! 'EchoCV2CheckResult', 'TRUE'
134
+ end
135
+ end
136
+ end
137
+
138
+ def add_customerdetails(xml, creditcard, address, options, shipTo = false)
139
+ xml.tag! 'CustomerDetails' do
140
+ if address
141
+ unless address[:country].blank?
142
+ country_code = Country.find(address[:country]).code(:numeric)
143
+ end
144
+ xml.tag! 'BillingAddress' do
145
+ xml.tag! 'Address1', address[:address1]
146
+ xml.tag! 'Address2', address[:address2]
147
+ xml.tag! 'City', address[:city]
148
+ xml.tag! 'State', address[:state]
149
+ xml.tag! 'PostCode', address[:zip]
150
+ xml.tag! 'CountryCode', country_code if country_code
151
+ end
152
+ xml.tag! 'PhoneNumber', address[:phone]
153
+ end
154
+
155
+ xml.tag! 'EmailAddress', options[:email]
156
+ xml.tag! 'CustomerIPAddress', options[:ip] || "127.0.0.1"
157
+ end
158
+ end
159
+
160
+ def add_creditcard(xml, creditcard)
161
+ xml.tag! 'CardDetails' do
162
+ xml.tag! 'CardName', creditcard.name
163
+ xml.tag! 'CV2', creditcard.verification_value if creditcard.verification_value
164
+ xml.tag! 'CardNumber', creditcard.number
165
+ xml.tag! 'ExpiryDate', { 'Month' => creditcard.month.to_s.rjust(2, "0"), 'Year' => creditcard.year.to_s[/\d\d$/] }
166
+ end
167
+ end
168
+
169
+ def add_merchant_data(xml, options)
170
+ xml.tag! 'MerchantAuthentication', {"MerchantID" => @options[:login], "Password" => @options[:password]}
171
+ end
172
+
173
+ def commit(request, options)
174
+ requires!(options, :action)
175
+ response = parse(ssl_post(test? ? @test_url : @live_url, request,
176
+ {"SOAPAction" => "https://www.thepaymentgateway.net/#{options[:action]}",
177
+ "Content-Type" => "text/xml; charset=utf-8" }))
178
+
179
+ success = response[:transaction_result][:status_code] == "0"
180
+ message = response[:transaction_result][:message]
181
+ authorization = success ? [ options[:order_id], response[:transaction_output_data][:cross_reference], response[:transaction_output_data][:auth_code] ].compact.join(";") : nil
182
+
183
+ Response.new(success, message, response,
184
+ :test => test?,
185
+ :authorization => authorization)
186
+ end
187
+
188
+ def parse(xml)
189
+ reply = {}
190
+ xml = REXML::Document.new(xml)
191
+ if (root = REXML::XPath.first(xml, "//CardDetailsTransactionResponse")) or
192
+ (root = REXML::XPath.first(xml, "//CrossReferenceTransactionResponse"))
193
+ root.elements.to_a.each do |node|
194
+ case node.name
195
+ when 'Message'
196
+ reply[:message] = reply(node.text)
197
+ else
198
+ parse_element(reply, node)
199
+ end
200
+ end
201
+ elsif root = REXML::XPath.first(xml, "//soap:Fault")
202
+ parse_element(reply, root)
203
+ reply[:message] = "#{reply[:faultcode]}: #{reply[:faultstring]}"
204
+ end
205
+ reply
206
+ end
207
+
208
+ def parse_element(reply, node)
209
+ case node.name
210
+ when "CrossReferenceTransactionResult"
211
+ reply[:transaction_result] = {}
212
+ node.attributes.each do |a,b|
213
+ reply[:transaction_result][a.underscore.to_sym] = b
214
+ end
215
+ node.elements.each{|e| parse_element(reply[:transaction_result], e) } if node.has_elements?
216
+
217
+ when "CardDetailsTransactionResult"
218
+ reply[:transaction_result] = {}
219
+ node.attributes.each do |a,b|
220
+ reply[:transaction_result][a.underscore.to_sym] = b
221
+ end
222
+ node.elements.each{|e| parse_element(reply[:transaction_result], e) } if node.has_elements?
223
+
224
+ when "TransactionOutputData"
225
+ reply[:transaction_output_data] = {}
226
+ node.attributes.each{|a,b| reply[:transaction_output_data][a.underscore.to_sym] = b }
227
+ node.elements.each{|e| parse_element(reply[:transaction_output_data], e) } if node.has_elements?
228
+ when "CustomVariables"
229
+ reply[:custom_variables] = {}
230
+ node.attributes.each{|a,b| reply[:custom_variables][a.underscore.to_sym] = b }
231
+ node.elements.each{|e| parse_element(reply[:custom_variables], e) } if node.has_elements?
232
+ when "GatewayEntryPoints"
233
+ reply[:gateway_entry_points] = {}
234
+ node.attributes.each{|a,b| reply[:gateway_entry_points][a.underscore.to_sym] = b }
235
+ node.elements.each{|e| parse_element(reply[:gateway_entry_points], e) } if node.has_elements?
236
+ else
237
+ k = node.name.underscore.to_sym
238
+ if node.has_elements?
239
+ reply[k] = {}
240
+ node.elements.each{|e| parse_element(reply[k], e) }
241
+ else
242
+ if node.has_attributes?
243
+ reply[k] = {}
244
+ node.attributes.each{|a,b| reply[k][a.underscore.to_sym] = b }
245
+ else
246
+ reply[k] = node.text
247
+ end
248
+ end
249
+ end
250
+ reply
251
+ end
252
+
253
+ def currency_code(currency)
254
+ CURRENCY_CODES[currency]
255
+ end
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,276 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class JetpayGateway < Gateway
4
+ TEST_URL = 'https://test1.jetpay.com/jetpay'
5
+ LIVE_URL = 'https://gateway17.jetpay.com/jetpay'
6
+
7
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
8
+ self.supported_countries = ['US']
9
+
10
+ # The card types supported by the payment gateway
11
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
12
+
13
+ # The homepage URL of the gateway
14
+ self.homepage_url = 'http://www.jetpay.com/'
15
+
16
+ # The name of the gateway
17
+ self.display_name = 'JetPay'
18
+
19
+ # all transactions are in cents
20
+ self.money_format = :cents
21
+
22
+ ACTION_CODE_MESSAGES = {
23
+ "001" => "Refer to card issuer.",
24
+ "002" => "Refer to card issuer, special condition.",
25
+ "003" => "Pick up card.",
26
+ "200" => "Deny - Pick up card.",
27
+ "005" => "Do not honor.",
28
+ "100" => "Deny.",
29
+ "006" => "Error.",
30
+ "181" => "Format error.",
31
+ "007" => "Pickup card, special condition.",
32
+ "104" => "Deny - New card issued.",
33
+ "110" => "Invalid amount.",
34
+ "014" => "Invalid account number (no such number).",
35
+ "111" => "Invalid account.",
36
+ "015" => "No such issuer.",
37
+ "103" => "Deny - Invalid manual Entry 4DBC.",
38
+ "182" => "Please wait.",
39
+ "109" => "Invalid merchant.",
40
+ "041" => "Pick up card (lost card).",
41
+ "043" => "Pick up card (stolen card).",
42
+ "051" => "Insufficient funds.",
43
+ "052" => "No checking account.",
44
+ "105" => "Deny - Account Cancelled.",
45
+ "054" => "Expired Card.",
46
+ "101" => "Expired Card.",
47
+ "183" => "Invalid currency code.",
48
+ "057" => "Transaction not permitted to cardholder.",
49
+ "115" => "Service not permitted.",
50
+ "062" => "Restricted card.",
51
+ "189" => "Deny - Cancelled or Closed Merchant/SE.",
52
+ "188" => "Deny - Expiration date required.",
53
+ "125" => "Invalid effective date.",
54
+ "122" => "Invalid card (CID) security code.",
55
+ "400" => "Reversal accepted.",
56
+ "992" => "DECLINE/TIMEOUT.",
57
+ "107" => "Please Call Issuer.",
58
+ "025" => "Transaction Not Found.",
59
+ "981" => "AVS Error.",
60
+ "913" => "Invalid Card Type.",
61
+ "996" => "Terminal ID Not Found.",
62
+ nil => "No response returned (missing credentials?)."
63
+ }
64
+
65
+ def initialize(options = {})
66
+ requires!(options, :login)
67
+ @options = options
68
+ super
69
+ end
70
+
71
+ def purchase(money, credit_card, options = {})
72
+ commit(money, build_sale_request(money, credit_card, options))
73
+ end
74
+
75
+ def authorize(money, credit_card, options = {})
76
+ commit(money, build_authonly_request(money, credit_card, options))
77
+ end
78
+
79
+ def capture(money, reference, options = {})
80
+ commit(money, build_capture_request('CAPT', reference.split(";").first))
81
+ end
82
+
83
+ def void(reference, options = {})
84
+ transaction_id, approval, amount = reference.split(";")
85
+ commit(amount.to_i, build_void_request(amount.to_i, transaction_id, approval))
86
+ end
87
+
88
+ def credit(money, transaction_id_or_card, options = {})
89
+ if transaction_id_or_card.is_a?(String)
90
+ deprecated CREDIT_DEPRECATION_MESSAGE
91
+ refund(money, transaction_id_or_card, options)
92
+ else
93
+ commit(money, build_credit_request('CREDIT', money, nil, transaction_id_or_card))
94
+ end
95
+ end
96
+
97
+ def refund(money, reference, options = {})
98
+ transaction_id = reference.split(";").first
99
+ credit_card = options[:credit_card]
100
+ commit(money, build_credit_request('CREDIT', money, transaction_id, credit_card))
101
+ end
102
+
103
+
104
+ private
105
+
106
+ def build_xml_request(transaction_type, transaction_id = nil, &block)
107
+ xml = Builder::XmlMarkup.new
108
+ xml.tag! 'JetPay' do
109
+ # The basic values needed for any request
110
+ xml.tag! 'TerminalID', @options[:login]
111
+ xml.tag! 'TransactionType', transaction_type
112
+ xml.tag! 'TransactionID', transaction_id.nil? ? generate_unique_id.slice(0, 18) : transaction_id
113
+
114
+ if block_given?
115
+ yield xml
116
+ else
117
+ xml.target!
118
+ end
119
+ end
120
+ end
121
+
122
+ def build_sale_request(money, credit_card, options)
123
+ build_xml_request('SALE') do |xml|
124
+ add_credit_card(xml, credit_card)
125
+ add_addresses(xml, options)
126
+ add_customer_data(xml, options)
127
+ add_invoice_data(xml, options)
128
+ xml.tag! 'TotalAmount', amount(money)
129
+
130
+ xml.target!
131
+ end
132
+ end
133
+
134
+ def build_authonly_request(money, credit_card, options)
135
+ build_xml_request('AUTHONLY') do |xml|
136
+ add_credit_card(xml, credit_card)
137
+ add_addresses(xml, options)
138
+ add_customer_data(xml, options)
139
+ add_invoice_data(xml, options)
140
+ xml.tag! 'TotalAmount', amount(money)
141
+
142
+ xml.target!
143
+ end
144
+ end
145
+
146
+ def build_capture_request(transaction_type, transaction_id)
147
+ build_xml_request(transaction_type, transaction_id)
148
+ end
149
+
150
+ def build_void_request(money, transaction_id, approval)
151
+ build_xml_request('VOID', transaction_id) do |xml|
152
+ xml.tag! 'Approval', approval
153
+ xml.tag! 'TotalAmount', amount(money)
154
+
155
+ xml.target!
156
+ end
157
+ end
158
+
159
+ # `transaction_id` may be nil for unlinked credit transactions.
160
+ def build_credit_request(transaction_type, money, transaction_id, card)
161
+ build_xml_request(transaction_type, transaction_id) do |xml|
162
+ add_credit_card(xml, card) if card
163
+ xml.tag! 'TotalAmount', amount(money)
164
+
165
+ xml.target!
166
+ end
167
+ end
168
+
169
+ def commit(money, request)
170
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request))
171
+
172
+ success = success?(response)
173
+ Response.new(success,
174
+ success ? 'APPROVED' : message_from(response),
175
+ response,
176
+ :test => test?,
177
+ :authorization => authorization_from(response, money),
178
+ :avs_result => { :code => response[:avs] },
179
+ :cvv_result => response[:cvv2]
180
+ )
181
+ end
182
+
183
+ def parse(body)
184
+ return {} if body.blank?
185
+
186
+ xml = REXML::Document.new(body)
187
+
188
+ response = {}
189
+ xml.root.elements.to_a.each do |node|
190
+ parse_element(response, node)
191
+ end
192
+ response
193
+ end
194
+
195
+ def parse_element(response, node)
196
+ if node.has_elements?
197
+ node.elements.each{|element| parse_element(response, element) }
198
+ else
199
+ response[node.name.underscore.to_sym] = node.text
200
+ end
201
+ end
202
+
203
+ def format_exp(value)
204
+ format(value, :two_digits)
205
+ end
206
+
207
+ def success?(response)
208
+ response[:action_code] == "000"
209
+ end
210
+
211
+ def message_from(response)
212
+ ACTION_CODE_MESSAGES[response[:action_code]]
213
+ end
214
+
215
+ def authorization_from(response, money)
216
+ original_amount = amount(money) if money
217
+ [ response[:transaction_id], response[:approval], original_amount ].join(";")
218
+ end
219
+
220
+ def add_credit_card(xml, credit_card)
221
+ xml.tag! 'CardNum', credit_card.number
222
+ xml.tag! 'CardExpMonth', format_exp(credit_card.month)
223
+ xml.tag! 'CardExpYear', format_exp(credit_card.year)
224
+
225
+ if credit_card.first_name || credit_card.last_name
226
+ xml.tag! 'CardName', [credit_card.first_name,credit_card.last_name].compact.join(' ')
227
+ end
228
+
229
+ unless credit_card.verification_value.nil? || (credit_card.verification_value.length == 0)
230
+ xml.tag! 'CVV2', credit_card.verification_value
231
+ end
232
+ end
233
+
234
+ def add_addresses(xml, options)
235
+ if billing_address = options[:billing_address] || options[:address]
236
+ xml.tag! 'BillingAddress', [billing_address[:address1], billing_address[:address2]].compact.join(" ")
237
+ xml.tag! 'BillingCity', billing_address[:city]
238
+ xml.tag! 'BillingStateProv', billing_address[:state]
239
+ xml.tag! 'BillingPostalCode', billing_address[:zip]
240
+ xml.tag! 'BillingCountry', lookup_country_code(billing_address[:country])
241
+ xml.tag! 'BillingPhone', billing_address[:phone]
242
+ end
243
+
244
+ if shipping_address = options[:shipping_address]
245
+ xml.tag! 'ShippingInfo' do
246
+ xml.tag! 'ShippingName', shipping_address[:name]
247
+
248
+ xml.tag! 'ShippingAddr' do
249
+ xml.tag! 'Address', [shipping_address[:address1], shipping_address[:address2]].compact.join(" ")
250
+ xml.tag! 'City', shipping_address[:city]
251
+ xml.tag! 'StateProv', shipping_address[:state]
252
+ xml.tag! 'PostalCode', shipping_address[:zip]
253
+ xml.tag! 'Country', lookup_country_code(shipping_address[:country])
254
+ end
255
+ end
256
+ end
257
+ end
258
+
259
+ def add_customer_data(xml, options)
260
+ xml.tag! 'Email', options[:email] if options[:email]
261
+ xml.tag! 'UserIPAddress', options[:ip] if options[:ip]
262
+ end
263
+
264
+ def add_invoice_data(xml, options)
265
+ xml.tag! 'OrderNumber', options[:order_id] if options[:order_id]
266
+ xml.tag! 'TaxAmount', amount(options[:tax]) if options[:tax]
267
+ end
268
+
269
+ def lookup_country_code(code)
270
+ country = Country.find(code) rescue nil
271
+ country && country.code(:alpha3)
272
+ end
273
+ end
274
+ end
275
+ end
276
+