activemerchant-nsp 1.27.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (252) hide show
  1. data/CHANGELOG +952 -0
  2. data/CONTRIBUTORS +347 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +204 -0
  5. data/gem-public_cert.pem +20 -0
  6. data/lib/active_merchant.rb +63 -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 +56 -0
  10. data/lib/active_merchant/billing/check.rb +68 -0
  11. data/lib/active_merchant/billing/credit_card.rb +274 -0
  12. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  13. data/lib/active_merchant/billing/credit_card_methods.rb +143 -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 +176 -0
  17. data/lib/active_merchant/billing/gateways.rb +18 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net.rb +695 -0
  19. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +943 -0
  20. data/lib/active_merchant/billing/gateways/balanced.rb +462 -0
  21. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
  22. data/lib/active_merchant/billing/gateways/beanstream.rb +167 -0
  23. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +389 -0
  24. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  25. data/lib/active_merchant/billing/gateways/blue_pay.rb +492 -0
  26. data/lib/active_merchant/billing/gateways/bogus.rb +142 -0
  27. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  28. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  29. data/lib/active_merchant/billing/gateways/braintree_blue.rb +389 -0
  30. data/lib/active_merchant/billing/gateways/braintree_orange.rb +19 -0
  31. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  32. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
  33. data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
  34. data/lib/active_merchant/billing/gateways/cyber_source.rb +576 -0
  35. data/lib/active_merchant/billing/gateways/data_cash.rb +597 -0
  36. data/lib/active_merchant/billing/gateways/efsnet.rb +235 -0
  37. data/lib/active_merchant/billing/gateways/elavon.rb +137 -0
  38. data/lib/active_merchant/billing/gateways/epay.rb +276 -0
  39. data/lib/active_merchant/billing/gateways/eway.rb +287 -0
  40. data/lib/active_merchant/billing/gateways/eway_managed.rb +265 -0
  41. data/lib/active_merchant/billing/gateways/exact.rb +227 -0
  42. data/lib/active_merchant/billing/gateways/fat_zebra.rb +152 -0
  43. data/lib/active_merchant/billing/gateways/federated_canada.rb +168 -0
  44. data/lib/active_merchant/billing/gateways/first_pay.rb +177 -0
  45. data/lib/active_merchant/billing/gateways/garanti.rb +262 -0
  46. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +252 -0
  47. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  48. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  49. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +55 -0
  50. data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
  51. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  52. data/lib/active_merchant/billing/gateways/iridium.rb +257 -0
  53. data/lib/active_merchant/billing/gateways/itransact.rb +450 -0
  54. data/lib/active_merchant/billing/gateways/jetpay.rb +276 -0
  55. data/lib/active_merchant/billing/gateways/linkpoint.rb +451 -0
  56. data/lib/active_merchant/billing/gateways/litle.rb +290 -0
  57. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +157 -0
  58. data/lib/active_merchant/billing/gateways/merchant_ware.rb +289 -0
  59. data/lib/active_merchant/billing/gateways/metrics_global.rb +323 -0
  60. data/lib/active_merchant/billing/gateways/migs.rb +263 -0
  61. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  62. data/lib/active_merchant/billing/gateways/modern_payments.rb +38 -0
  63. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
  64. data/lib/active_merchant/billing/gateways/moneris.rb +250 -0
  65. data/lib/active_merchant/billing/gateways/moneris_us.rb +211 -0
  66. data/lib/active_merchant/billing/gateways/nab_transact.rb +257 -0
  67. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  68. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  69. data/lib/active_merchant/billing/gateways/netbilling.rb +196 -0
  70. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  71. data/lib/active_merchant/billing/gateways/ogone.rb +427 -0
  72. data/lib/active_merchant/billing/gateways/optimal_payment.rb +277 -0
  73. data/lib/active_merchant/billing/gateways/orbital.rb +351 -0
  74. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -0
  75. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +266 -0
  76. data/lib/active_merchant/billing/gateways/pay_junction.rb +397 -0
  77. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  78. data/lib/active_merchant/billing/gateways/paybox_direct.rb +201 -0
  79. data/lib/active_merchant/billing/gateways/payflow.rb +268 -0
  80. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +212 -0
  81. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  82. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  83. data/lib/active_merchant/billing/gateways/payflow_express.rb +224 -0
  84. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  85. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  86. data/lib/active_merchant/billing/gateways/payment_express.rb +282 -0
  87. data/lib/active_merchant/billing/gateways/paypal.rb +106 -0
  88. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +653 -0
  89. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
  90. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +245 -0
  91. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  92. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +43 -0
  93. data/lib/active_merchant/billing/gateways/paypal_express.rb +178 -0
  94. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  95. data/lib/active_merchant/billing/gateways/paystation.rb +201 -0
  96. data/lib/active_merchant/billing/gateways/payway.rb +214 -0
  97. data/lib/active_merchant/billing/gateways/plugnpay.rb +295 -0
  98. data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
  99. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  100. data/lib/active_merchant/billing/gateways/qbms.rb +297 -0
  101. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  102. data/lib/active_merchant/billing/gateways/quickpay.rb +298 -0
  103. data/lib/active_merchant/billing/gateways/realex.rb +313 -0
  104. data/lib/active_merchant/billing/gateways/sage.rb +148 -0
  105. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  106. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +115 -0
  107. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  108. data/lib/active_merchant/billing/gateways/sage_pay.rb +322 -0
  109. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  110. data/lib/active_merchant/billing/gateways/samurai.rb +121 -0
  111. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  112. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  113. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +284 -0
  114. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  115. data/lib/active_merchant/billing/gateways/skip_jack.rb +458 -0
  116. data/lib/active_merchant/billing/gateways/smart_ps.rb +273 -0
  117. data/lib/active_merchant/billing/gateways/stripe.rb +236 -0
  118. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  119. data/lib/active_merchant/billing/gateways/transax.rb +23 -0
  120. data/lib/active_merchant/billing/gateways/trust_commerce.rb +423 -0
  121. data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
  122. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1497 -0
  123. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +206 -0
  124. data/lib/active_merchant/billing/gateways/verifi.rb +233 -0
  125. data/lib/active_merchant/billing/gateways/viaklix.rb +194 -0
  126. data/lib/active_merchant/billing/gateways/vindicia.rb +359 -0
  127. data/lib/active_merchant/billing/gateways/wirecard.rb +313 -0
  128. data/lib/active_merchant/billing/gateways/worldpay.rb +271 -0
  129. data/lib/active_merchant/billing/integrations.rb +17 -0
  130. data/lib/active_merchant/billing/integrations/action_view_helper.rb +73 -0
  131. data/lib/active_merchant/billing/integrations/authorize_net_sim.rb +38 -0
  132. data/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb +228 -0
  133. data/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb +340 -0
  134. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  135. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  136. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  137. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  138. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  139. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  140. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  141. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  142. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  143. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  144. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  145. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  146. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  147. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  148. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  149. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  150. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  151. data/lib/active_merchant/billing/integrations/dotpay.rb +22 -0
  152. data/lib/active_merchant/billing/integrations/dotpay/helper.rb +77 -0
  153. data/lib/active_merchant/billing/integrations/dotpay/notification.rb +86 -0
  154. data/lib/active_merchant/billing/integrations/dotpay/return.rb +11 -0
  155. data/lib/active_merchant/billing/integrations/dwolla.rb +30 -0
  156. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +31 -0
  157. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +55 -0
  158. data/lib/active_merchant/billing/integrations/dwolla/return.rb +38 -0
  159. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  160. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  161. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  162. data/lib/active_merchant/billing/integrations/easy_pay.rb +30 -0
  163. data/lib/active_merchant/billing/integrations/easy_pay/common.rb +40 -0
  164. data/lib/active_merchant/billing/integrations/easy_pay/helper.rb +40 -0
  165. data/lib/active_merchant/billing/integrations/easy_pay/notification.rb +51 -0
  166. data/lib/active_merchant/billing/integrations/epay.rb +21 -0
  167. data/lib/active_merchant/billing/integrations/epay/helper.rb +55 -0
  168. data/lib/active_merchant/billing/integrations/epay/notification.rb +110 -0
  169. data/lib/active_merchant/billing/integrations/first_data.rb +38 -0
  170. data/lib/active_merchant/billing/integrations/first_data/helper.rb +63 -0
  171. data/lib/active_merchant/billing/integrations/first_data/notification.rb +56 -0
  172. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  173. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  174. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  175. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  176. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  177. data/lib/active_merchant/billing/integrations/helper.rb +117 -0
  178. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  179. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  180. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  181. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  182. data/lib/active_merchant/billing/integrations/maksuturva.rb +86 -0
  183. data/lib/active_merchant/billing/integrations/maksuturva/helper.rb +119 -0
  184. data/lib/active_merchant/billing/integrations/maksuturva/notification.rb +48 -0
  185. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  186. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  187. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  188. data/lib/active_merchant/billing/integrations/nelnet.rb +40 -0
  189. data/lib/active_merchant/billing/integrations/nelnet/helper.rb +34 -0
  190. data/lib/active_merchant/billing/integrations/nelnet/notification.rb +100 -0
  191. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  192. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  193. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  194. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  195. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  196. data/lib/active_merchant/billing/integrations/paxum.rb +44 -0
  197. data/lib/active_merchant/billing/integrations/paxum/common.rb +24 -0
  198. data/lib/active_merchant/billing/integrations/paxum/helper.rb +42 -0
  199. data/lib/active_merchant/billing/integrations/paxum/notification.rb +33 -0
  200. data/lib/active_merchant/billing/integrations/payflow_link.rb +21 -0
  201. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +100 -0
  202. data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +78 -0
  203. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  204. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  205. data/lib/active_merchant/billing/integrations/paypal/notification.rb +155 -0
  206. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  207. data/lib/active_merchant/billing/integrations/paypal_payments_advanced.rb +20 -0
  208. data/lib/active_merchant/billing/integrations/paypal_payments_advanced/helper.rb +15 -0
  209. data/lib/active_merchant/billing/integrations/pxpay.rb +31 -0
  210. data/lib/active_merchant/billing/integrations/pxpay/helper.rb +110 -0
  211. data/lib/active_merchant/billing/integrations/pxpay/notification.rb +157 -0
  212. data/lib/active_merchant/billing/integrations/pxpay/return.rb +25 -0
  213. data/lib/active_merchant/billing/integrations/quickpay.rb +21 -0
  214. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +71 -0
  215. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  216. data/lib/active_merchant/billing/integrations/return.rb +42 -0
  217. data/lib/active_merchant/billing/integrations/robokassa.rb +49 -0
  218. data/lib/active_merchant/billing/integrations/robokassa/common.rb +19 -0
  219. data/lib/active_merchant/billing/integrations/robokassa/helper.rb +50 -0
  220. data/lib/active_merchant/billing/integrations/robokassa/notification.rb +55 -0
  221. data/lib/active_merchant/billing/integrations/robokassa/return.rb +17 -0
  222. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  223. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  224. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +129 -0
  225. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  226. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  227. data/lib/active_merchant/billing/integrations/two_checkout.rb +44 -0
  228. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +91 -0
  229. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +139 -0
  230. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  231. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  232. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  233. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  234. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
  235. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  236. data/lib/active_merchant/billing/integrations/verkkomaksut.rb +20 -0
  237. data/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb +87 -0
  238. data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +59 -0
  239. data/lib/active_merchant/billing/integrations/web_pay.rb +45 -0
  240. data/lib/active_merchant/billing/integrations/web_pay/common.rb +50 -0
  241. data/lib/active_merchant/billing/integrations/web_pay/helper.rb +68 -0
  242. data/lib/active_merchant/billing/integrations/web_pay/notification.rb +51 -0
  243. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  244. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  245. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  246. data/lib/active_merchant/billing/response.rb +64 -0
  247. data/lib/active_merchant/version.rb +3 -0
  248. data/lib/activemerchant.rb +1 -0
  249. data/lib/support/gateway_support.rb +65 -0
  250. data/lib/support/outbound_hosts.rb +25 -0
  251. data/lib/support/ssl_verify.rb +93 -0
  252. metadata +482 -0
@@ -0,0 +1,257 @@
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
+ self.live_url = self.test_url = 'https://gw1.iridiumcorp.net/'
11
+
12
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
13
+ self.supported_countries = ['GB', 'ES']
14
+ self.default_currency = 'EUR'
15
+ self.money_format = :cents
16
+
17
+ # The card types supported by the payment gateway
18
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
19
+
20
+ # The homepage URL of the gateway
21
+ self.homepage_url = 'http://www.iridiumcorp.co.uk/'
22
+
23
+ # The name of the gateway
24
+ self.display_name = 'Iridium'
25
+
26
+ CURRENCY_CODES = {
27
+ "AUD" => '036',
28
+ "CAD" => '124',
29
+ "EUR" => '978',
30
+ "GBP" => '826',
31
+ "MXN" => '484',
32
+ "NZD" => '554',
33
+ "USD" => '840',
34
+ }
35
+
36
+ def initialize(options = {})
37
+ requires!(options, :login, :password)
38
+ @options = options
39
+ super
40
+ end
41
+
42
+ def authorize(money, creditcard, options = {})
43
+ commit(build_purchase_request('PREAUTH', money, creditcard, options), options)
44
+ end
45
+
46
+ def purchase(money, payment_source, options = {})
47
+ setup_address_hash(options)
48
+
49
+ if payment_source.respond_to?(:number)
50
+ commit(build_purchase_request('SALE', money, payment_source, options), options)
51
+ else
52
+ commit(build_reference_request('SALE', money, payment_source, options), options)
53
+ end
54
+ end
55
+
56
+ def capture(money, authorization, options = {})
57
+ commit(build_reference_request('COLLECTION', money, authorization, options), options)
58
+ end
59
+
60
+ def credit(money, authorization, options={})
61
+ deprecated CREDIT_DEPRECATION_MESSAGE
62
+ refund(money, authorization, options)
63
+ end
64
+
65
+ def refund(money, authorization, options={})
66
+ commit(build_reference_request('REFUND', money, authorization, options), options)
67
+ end
68
+
69
+ def void(authorization, options={})
70
+ commit(build_reference_request('VOID', nil, authorization, options), options)
71
+ end
72
+
73
+ private
74
+
75
+ def build_purchase_request(type, money, creditcard, options)
76
+ options.merge!(:action => 'CardDetailsTransaction')
77
+ build_request(options) do |xml|
78
+ add_purchase_data(xml, type, money, options)
79
+ add_creditcard(xml, creditcard)
80
+ add_customerdetails(xml, creditcard, options[:billing_address], options)
81
+ end
82
+ end
83
+
84
+ def build_reference_request(type, money, authorization, options)
85
+ options.merge!(:action => 'CrossReferenceTransaction')
86
+ order_id, cross_reference, auth_id = authorization.split(";")
87
+ build_request(options) do |xml|
88
+ if money
89
+ details = {'CurrencyCode' => currency_code(options[:currency] || default_currency), 'Amount' => amount(money)}
90
+ else
91
+ details = {'CurrencyCode' => currency_code(default_currency), 'Amount' => '0'}
92
+ end
93
+ xml.tag! 'TransactionDetails', details do
94
+ xml.tag! 'MessageDetails', {'TransactionType' => type, 'CrossReference' => cross_reference}
95
+ xml.tag! 'OrderID', (options[:order_id] || order_id)
96
+ end
97
+ end
98
+ end
99
+
100
+ def build_request(options)
101
+ requires!(options, :action)
102
+ xml = Builder::XmlMarkup.new :indent => 2
103
+ xml.instruct!(:xml, :version => '1.0', :encoding => 'utf-8')
104
+ xml.tag! 'soap:Envelope', { 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/',
105
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
106
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'} do
107
+ xml.tag! 'soap:Body' do
108
+ xml.tag! options[:action], {'xmlns' => "https://www.thepaymentgateway.net/"} do
109
+ xml.tag! 'PaymentMessage' do
110
+ add_merchant_data(xml, options)
111
+ yield(xml)
112
+ end
113
+ end
114
+ end
115
+ end
116
+ xml.target!
117
+ end
118
+
119
+ def setup_address_hash(options)
120
+ options[:billing_address] = options[:billing_address] || options[:address] || {}
121
+ options[:shipping_address] = options[:shipping_address] || {}
122
+ end
123
+
124
+ def add_purchase_data(xml, type, money, options)
125
+ requires!(options, :order_id)
126
+ xml.tag! 'TransactionDetails', {'Amount' => amount(money), 'CurrencyCode' => currency_code(options[:currency] || currency(money))} do
127
+ xml.tag! 'MessageDetails', {'TransactionType' => type}
128
+ xml.tag! 'OrderID', options[:order_id]
129
+ xml.tag! 'TransactionControl' do
130
+ xml.tag! 'ThreeDSecureOverridePolicy', 'FALSE'
131
+ xml.tag! 'EchoAVSCheckResult', 'TRUE'
132
+ xml.tag! 'EchoCV2CheckResult', 'TRUE'
133
+ end
134
+ end
135
+ end
136
+
137
+ def add_customerdetails(xml, creditcard, address, options, shipTo = false)
138
+ xml.tag! 'CustomerDetails' do
139
+ if address
140
+ unless address[:country].blank?
141
+ country_code = Country.find(address[:country]).code(:numeric)
142
+ end
143
+ xml.tag! 'BillingAddress' do
144
+ xml.tag! 'Address1', address[:address1]
145
+ xml.tag! 'Address2', address[:address2]
146
+ xml.tag! 'City', address[:city]
147
+ xml.tag! 'State', address[:state]
148
+ xml.tag! 'PostCode', address[:zip]
149
+ xml.tag! 'CountryCode', country_code if country_code
150
+ end
151
+ xml.tag! 'PhoneNumber', address[:phone]
152
+ end
153
+
154
+ xml.tag! 'EmailAddress', options[:email]
155
+ xml.tag! 'CustomerIPAddress', options[:ip] || "127.0.0.1"
156
+ end
157
+ end
158
+
159
+ def add_creditcard(xml, creditcard)
160
+ xml.tag! 'CardDetails' do
161
+ xml.tag! 'CardName', creditcard.name
162
+ xml.tag! 'CV2', creditcard.verification_value if creditcard.verification_value
163
+ xml.tag! 'CardNumber', creditcard.number
164
+ xml.tag! 'ExpiryDate', { 'Month' => creditcard.month.to_s.rjust(2, "0"), 'Year' => creditcard.year.to_s[/\d\d$/] }
165
+ end
166
+ end
167
+
168
+ def add_merchant_data(xml, options)
169
+ xml.tag! 'MerchantAuthentication', {"MerchantID" => @options[:login], "Password" => @options[:password]}
170
+ end
171
+
172
+ def commit(request, options)
173
+ requires!(options, :action)
174
+ response = parse(ssl_post(test? ? self.test_url : self.live_url, request,
175
+ {"SOAPAction" => "https://www.thepaymentgateway.net/#{options[:action]}",
176
+ "Content-Type" => "text/xml; charset=utf-8" }))
177
+
178
+ success = response[:transaction_result][:status_code] == "0"
179
+ message = response[:transaction_result][:message]
180
+ authorization = success ? [ options[:order_id], response[:transaction_output_data][:cross_reference], response[:transaction_output_data][:auth_code] ].compact.join(";") : nil
181
+
182
+ Response.new(success, message, response,
183
+ :test => test?,
184
+ :authorization => authorization)
185
+ end
186
+
187
+ def parse(xml)
188
+ reply = {}
189
+ xml = REXML::Document.new(xml)
190
+ if (root = REXML::XPath.first(xml, "//CardDetailsTransactionResponse")) or
191
+ (root = REXML::XPath.first(xml, "//CrossReferenceTransactionResponse"))
192
+ root.elements.to_a.each do |node|
193
+ case node.name
194
+ when 'Message'
195
+ reply[:message] = reply(node.text)
196
+ else
197
+ parse_element(reply, node)
198
+ end
199
+ end
200
+ elsif root = REXML::XPath.first(xml, "//soap:Fault")
201
+ parse_element(reply, root)
202
+ reply[:message] = "#{reply[:faultcode]}: #{reply[:faultstring]}"
203
+ end
204
+ reply
205
+ end
206
+
207
+ def parse_element(reply, node)
208
+ case node.name
209
+ when "CrossReferenceTransactionResult"
210
+ reply[:transaction_result] = {}
211
+ node.attributes.each do |a,b|
212
+ reply[:transaction_result][a.underscore.to_sym] = b
213
+ end
214
+ node.elements.each{|e| parse_element(reply[:transaction_result], e) } if node.has_elements?
215
+
216
+ when "CardDetailsTransactionResult"
217
+ reply[:transaction_result] = {}
218
+ node.attributes.each do |a,b|
219
+ reply[:transaction_result][a.underscore.to_sym] = b
220
+ end
221
+ node.elements.each{|e| parse_element(reply[:transaction_result], e) } if node.has_elements?
222
+
223
+ when "TransactionOutputData"
224
+ reply[:transaction_output_data] = {}
225
+ node.attributes.each{|a,b| reply[:transaction_output_data][a.underscore.to_sym] = b }
226
+ node.elements.each{|e| parse_element(reply[:transaction_output_data], e) } if node.has_elements?
227
+ when "CustomVariables"
228
+ reply[:custom_variables] = {}
229
+ node.attributes.each{|a,b| reply[:custom_variables][a.underscore.to_sym] = b }
230
+ node.elements.each{|e| parse_element(reply[:custom_variables], e) } if node.has_elements?
231
+ when "GatewayEntryPoints"
232
+ reply[:gateway_entry_points] = {}
233
+ node.attributes.each{|a,b| reply[:gateway_entry_points][a.underscore.to_sym] = b }
234
+ node.elements.each{|e| parse_element(reply[:gateway_entry_points], e) } if node.has_elements?
235
+ else
236
+ k = node.name.underscore.to_sym
237
+ if node.has_elements?
238
+ reply[k] = {}
239
+ node.elements.each{|e| parse_element(reply[k], e) }
240
+ else
241
+ if node.has_attributes?
242
+ reply[k] = {}
243
+ node.attributes.each{|a,b| reply[k][a.underscore.to_sym] = b }
244
+ else
245
+ reply[k] = node.text
246
+ end
247
+ end
248
+ end
249
+ reply
250
+ end
251
+
252
+ def currency_code(currency)
253
+ CURRENCY_CODES[currency]
254
+ end
255
+ end
256
+ end
257
+ end
@@ -0,0 +1,450 @@
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ # iTransact, Inc. is an authorized reseller of the PaymentClearing gateway. If your merchant service provider uses PaymentClearing.com to process payments, you can use this module.
6
+ #
7
+ #
8
+ # Please note, the username and API Access Key are not what you use to log into the Merchant Control Panel.
9
+ #
10
+ # ==== How to get your GatewayID and API Access Key
11
+ #
12
+ # 1. If you don't already have a Gateway Account, go to http://www.itransact.com/merchant/test.html to sign up.
13
+ # 2. Go to http://support.paymentclearing.com and login or register, if necessary.
14
+ # 3. Click on "Submit a Ticket."
15
+ # 4. Select "Merchant Support" as the department and click "Next"
16
+ # 5. Enter *both* your company name and GatewayID. Put "API Access Key" in the subject. In the body, you can request a username, but it may already be in use.
17
+ #
18
+ # ==== Initialization
19
+ #
20
+ # Once you have the username, API Access Key, and your GatewayId, you're ready
21
+ # to begin. You initialize the Gateway like so:
22
+ #
23
+ # gateway = ActiveMerchant::Billing::ItransactGateway.new(
24
+ # :login => "#{THE_USERNAME}",
25
+ # :password => "#{THE_API_ACCESS_KEY}",
26
+ # :gateway_id => "#{THE_GATEWAY_ID}"
27
+ # )
28
+ #
29
+ # ==== Important Notes
30
+ # 1. Recurring is not implemented
31
+ # 1. CreditTransactions are not implemented (these are credits not related to a previously run transaction).
32
+ # 1. TransactionStatus is not implemented
33
+ #
34
+ class ItransactGateway < Gateway
35
+ self.live_url = self.test_url = 'https://secure.paymentclearing.com/cgi-bin/rc/xmltrans2.cgi'
36
+
37
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
38
+ self.supported_countries = ['US']
39
+
40
+ # The card types supported by the payment gateway
41
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
42
+
43
+ # The homepage URL of the gateway
44
+ self.homepage_url = 'http://www.itransact.com/'
45
+
46
+ # The name of the gateway
47
+ self.display_name = 'iTransact'
48
+
49
+ #
50
+ # Creates a new instance of the iTransact Gateway.
51
+ #
52
+ # ==== Parameters
53
+ # * <tt>options</tt> - A Hash of options
54
+ #
55
+ # ==== Options Hash
56
+ # * <tt>:login</tt> - A String containing your PaymentClearing assigned API Access Username
57
+ # * <tt>:password</tt> - A String containing your PaymentClearing assigned API Access Key
58
+ # * <tt>:gateway_id</tt> - A String containing your PaymentClearing assigned GatewayID
59
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Run *all* transactions with the 'TestMode' element set to 'TRUE'.
60
+ #
61
+ def initialize(options = {})
62
+ requires!(options, :login, :password, :gateway_id)
63
+ @options = options
64
+ super
65
+ end
66
+
67
+ # Performs an authorize transaction. In PaymentClearing's documentation
68
+ # this is known as a "PreAuth" transaction.
69
+ #
70
+ # ==== Parameters
71
+ # * <tt>money</tt> - The amount to be captured. Should be an Integer amount in cents.
72
+ # * <tt>creditcard</tt> - The CreditCard details for the transaction
73
+ # * <tt>options</tt> - A Hash of options
74
+ #
75
+ # ==== Options Hash
76
+ # The standard options apply here (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address), as well as:
77
+ # * <tt>:order_items</tt> - An Array of Hash objects with the keys <tt>:description</tt>, <tt>:cost</tt> (in cents!), and <tt>:quantity</tt>. If this is provided, <tt>:description</tt> and <tt>money</tt> will be ignored.
78
+ # * <tt>:vendor_data</tt> - An Array of Hash objects with the keys being the name of the VendorData element and value being the value.
79
+ # * <tt>:send_customer_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'.
80
+ # * <tt>:send_merchant_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'.
81
+ # * <tt>:email_text</tt> - An Array of (up to ten (10)) String objects to be included in emails
82
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'.
83
+ #
84
+ # ==== Examples
85
+ # response = gateway.authorize(1000, creditcard,
86
+ # :order_id => '1212', :address => {...}, :email => 'test@test.com',
87
+ # :order_items => [
88
+ # {:description => 'Line Item 1', :cost => '8.98', :quantity => '6'},
89
+ # {:description => 'Line Item 2', :cost => '6.99', :quantity => '4'}
90
+ # ],
91
+ # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}],
92
+ # :send_customer_email => true,
93
+ # :send_merchant_email => true,
94
+ # :email_text => ['line1', 'line2', 'line3'],
95
+ # :test_mode => true
96
+ # )
97
+ #
98
+ def authorize(money, payment_source, options = {})
99
+ payload = Nokogiri::XML::Builder.new do |xml|
100
+ xml.AuthTransaction {
101
+ xml.Preauth
102
+ add_customer_data(xml, payment_source, options)
103
+ add_invoice(xml, money, options)
104
+ add_payment_source(xml, payment_source)
105
+ add_transaction_control(xml, options)
106
+ add_vendor_data(xml, options)
107
+ }
108
+ end.doc
109
+
110
+ commit(payload)
111
+ end
112
+
113
+ # Performs an authorize and capture in single transaction. In PaymentClearing's
114
+ # documentation this is known as an "Auth" or a "Sale" transaction
115
+ #
116
+ # ==== Parameters
117
+ # * <tt>money</tt> - The amount to be captured. Should be <tt>nil</tt> or an Integer amount in cents.
118
+ # * <tt>creditcard</tt> - The CreditCard details for the transaction
119
+ # * <tt>options</tt> - A Hash of options
120
+ #
121
+ # ==== Options Hash
122
+ # The standard options apply here (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address), as well as:
123
+ # * <tt>:order_items</tt> - An Array of Hash objects with the keys <tt>:description</tt>, <tt>:cost</tt> (in cents!), and <tt>:quantity</tt>. If this is provided, <tt>:description</tt> and <tt>money</tt> will be ignored.
124
+ # * <tt>:vendor_data</tt> - An Array of Hash objects with the keys being the name of the VendorData element and value being the value.
125
+ # * <tt>:send_customer_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'.
126
+ # * <tt>:send_merchant_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'.
127
+ # * <tt>:email_text</tt> - An Array of (up to ten (10)) String objects to be included in emails
128
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'.
129
+ #
130
+ # ==== Examples
131
+ # response = gateway.purchase(1000, creditcard,
132
+ # :order_id => '1212', :address => {...}, :email => 'test@test.com',
133
+ # :order_items => [
134
+ # {:description => 'Line Item 1', :cost => '8.98', :quantity => '6'},
135
+ # {:description => 'Line Item 2', :cost => '6.99', :quantity => '4'}
136
+ # ],
137
+ # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}],
138
+ # :send_customer_email => true,
139
+ # :send_merchant_email => true,
140
+ # :email_text => ['line1', 'line2', 'line3'],
141
+ # :test_mode => true
142
+ # )
143
+ #
144
+ def purchase(money, payment_source, options = {})
145
+ payload = Nokogiri::XML::Builder.new do |xml|
146
+ xml.AuthTransaction {
147
+ add_customer_data(xml, payment_source, options)
148
+ add_invoice(xml, money, options)
149
+ add_payment_source(xml, payment_source)
150
+ add_transaction_control(xml, options)
151
+ add_vendor_data(xml, options)
152
+ }
153
+ end.doc
154
+
155
+ commit(payload)
156
+ end
157
+
158
+ # Captures the funds from an authorize transaction. In PaymentClearing's
159
+ # documentation this is known as a "PostAuth" transaction.
160
+ #
161
+ # ==== Parameters
162
+ # * <tt>money</tt> - The amount to be captured. Should be an Integer amount in cents
163
+ # * <tt>authorization</tt> - The authorization returned from the previous capture or purchase request
164
+ # * <tt>options</tt> - A Hash of options, all are optional.
165
+ #
166
+ # ==== Options Hash
167
+ # The standard options apply here (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address), as well as:
168
+ # * <tt>:vendor_data</tt> - An Array of Hash objects with the keys being the name of the VendorData element and value being the value.
169
+ # * <tt>:send_customer_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'.
170
+ # * <tt>:send_merchant_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'.
171
+ # * <tt>:email_text</tt> - An Array of (up to ten (10)) String objects to be included in emails
172
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'.
173
+ #
174
+ # ==== Examples
175
+ # response = gateway.capture(1000, creditcard,
176
+ # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}],
177
+ # :send_customer_email => true,
178
+ # :send_merchant_email => true,
179
+ # :email_text => ['line1', 'line2', 'line3'],
180
+ # :test_mode => true
181
+ # )
182
+ #
183
+ def capture(money, authorization, options = {})
184
+ payload = Nokogiri::XML::Builder.new do |xml|
185
+ xml.PostAuthTransaction {
186
+ xml.OperationXID(authorization)
187
+ add_invoice(xml, money, options)
188
+ add_transaction_control(xml, options)
189
+ add_vendor_data(xml, options)
190
+ }
191
+ end.doc
192
+
193
+ commit(payload)
194
+ end
195
+
196
+ # This will reverse a previously run transaction which *has* *not* settled.
197
+ #
198
+ # ==== Parameters
199
+ # * <tt>money</tt> - This parameter is ignored -- the PaymentClearing gateway does not allow partial voids.
200
+ # * <tt>authorization</tt> - The authorization returned from the previous capture or purchase request
201
+ # * <tt>options</tt> - A Hash of options, all are optional
202
+ #
203
+ # ==== Options Hash
204
+ # The standard options (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address) are ignored.
205
+ # * <tt>:vendor_data</tt> - An Array of Hash objects with the keys being the name of the VendorData element and value being the value.
206
+ # * <tt>:send_customer_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'.
207
+ # * <tt>:send_merchant_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'.
208
+ # * <tt>:email_text</tt> - An Array of (up to ten (10)) String objects to be included in emails
209
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'.
210
+ #
211
+ # ==== Examples
212
+ # response = gateway.void(nil, '9999999999',
213
+ # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}],
214
+ # :send_customer_email => true,
215
+ # :send_merchant_email => true,
216
+ # :email_text => ['line1', 'line2', 'line3'],
217
+ # :test_mode => true
218
+ # )
219
+ #
220
+ def void(money, authorization, options = {})
221
+ payload = Nokogiri::XML::Builder.new do |xml|
222
+ xml.VoidTransaction {
223
+ xml.OperationXID(authorization)
224
+ add_transaction_control(xml, options)
225
+ add_vendor_data(xml, options)
226
+ }
227
+ end.doc
228
+
229
+ commit(payload)
230
+ end
231
+
232
+ # This will reverse a previously run transaction which *has* settled.
233
+ #
234
+ # ==== Parameters
235
+ # * <tt>money</tt> - The amount to be credited. Should be <tt>nil</tt> or an Integer amount in cents
236
+ # * <tt>authorization</tt> - The authorization returned from the previous capture or purchase request
237
+ # * <tt>options</tt> - A Hash of options, all are optional
238
+ #
239
+ # ==== Options Hash
240
+ # The standard options (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address) are ignored.
241
+ # * <tt>:vendor_data</tt> - An Array of Hash objects with the keys being the name of the VendorData element and value being the value.
242
+ # * <tt>:send_customer_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'.
243
+ # * <tt>:send_merchant_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'.
244
+ # * <tt>:email_text</tt> - An Array of (up to ten (10)) String objects to be included in emails
245
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'.
246
+ #
247
+ # ==== Examples
248
+ # response = gateway.credit(nil, '9999999999',
249
+ # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}],
250
+ # :send_customer_email => true,
251
+ # :send_merchant_email => true,
252
+ # :email_text => ['line1', 'line2', 'line3'],
253
+ # :test_mode => true
254
+ # )
255
+ #
256
+ def credit(money, authorization, options = {})
257
+ payload = Nokogiri::XML::Builder.new do |xml|
258
+ xml.TranCreditTransaction {
259
+ xml.OperationXID(authorization)
260
+ add_invoice(xml, money, options)
261
+ add_transaction_control(xml, options)
262
+ add_vendor_data(xml, options)
263
+ }
264
+ end.doc
265
+
266
+ commit(payload)
267
+ end
268
+
269
+ private
270
+
271
+ def add_customer_data(xml, payment_source, options)
272
+ billing_address = options[:billing_address] || options[:address]
273
+ shipping_address = options[:shipping_address] || options[:address]
274
+
275
+ xml.CustomerData {
276
+ xml.Email(options[:email]) unless options[:email].blank?
277
+ xml.CustId(options[:order_id]) unless options[:order_id].blank?
278
+ xml.BillingAddress {
279
+ xml.FirstName(payment_source.first_name || parse_first_name(billing_address[:name]))
280
+ xml.LastName(payment_source.last_name || parse_last_name(billing_address[:name]))
281
+ xml.Address1(billing_address[:address1])
282
+ xml.Address2(billing_address[:address2]) unless billing_address[:address2].blank?
283
+ xml.City(billing_address[:city])
284
+ xml.State(billing_address[:state])
285
+ xml.Zip(billing_address[:zip])
286
+ xml.Country(billing_address[:country])
287
+ xml.Phone(billing_address[:phone])
288
+ }
289
+ xml.ShippingAddress {
290
+ xml.FirstName(payment_source.first_name || parse_first_name(shipping_address[:name]))
291
+ xml.LastName(payment_source.last_name || parse_last_name(shipping_address[:name]))
292
+ xml.Address1(shipping_address[:address1])
293
+ xml.Address2(shipping_address[:address2]) unless shipping_address[:address2].blank?
294
+ xml.City(shipping_address[:city])
295
+ xml.State(shipping_address[:state])
296
+ xml.Zip(shipping_address[:zip])
297
+ xml.Country(shipping_address[:country])
298
+ xml.Phone(shipping_address[:phone])
299
+ } unless shipping_address.blank?
300
+ }
301
+ end
302
+
303
+ def add_invoice(xml, money, options)
304
+ xml.AuthCode options[:force] if options[:force]
305
+ if options[:order_items].blank?
306
+ xml.Total(amount(money)) unless(money.nil? || money < 0.01)
307
+ xml.Description(options[:description]) unless( options[:description].blank?)
308
+ else
309
+ xml.OrderItems {
310
+ options[:order_items].each do |item|
311
+ xml.Item {
312
+ xml.Description(item[:description])
313
+ xml.Cost(amount(item[:cost]))
314
+ xml.Qty(item[:quantity].to_s)
315
+ }
316
+ end
317
+ }
318
+ end
319
+ end
320
+
321
+ def add_payment_source(xml, source)
322
+ case determine_funding_source(source)
323
+ when :credit_card then add_creditcard(xml, source)
324
+ when :check then add_check(xml, source)
325
+ end
326
+ end
327
+
328
+ def determine_funding_source(payment_source)
329
+ case payment_source
330
+ when ActiveMerchant::Billing::CreditCard
331
+ :credit_card
332
+ when ActiveMerchant::Billing::Check
333
+ :check
334
+ end
335
+ end
336
+
337
+ def add_creditcard(xml, creditcard)
338
+ xml.AccountInfo {
339
+ xml.CardAccount {
340
+ xml.AccountNumber(creditcard.number.to_s)
341
+ xml.ExpirationMonth(creditcard.month.to_s.rjust(2,'0'))
342
+ xml.ExpirationYear(creditcard.year.to_s)
343
+ xml.CVVNumber(creditcard.verification_value.to_s) unless creditcard.verification_value.blank?
344
+ }
345
+ }
346
+ end
347
+
348
+ def add_check(xml, check)
349
+ xml.AccountInfo {
350
+ xml.ABA(check.routing_number.to_s)
351
+ xml.AccountNumber(check.account_number.to_s)
352
+ xml.AccountSource(check.account_type.to_s)
353
+ xml.AccountType(check.account_holder_type.to_s)
354
+ xml.CheckNumber(check.number.to_s)
355
+ }
356
+ end
357
+
358
+ def add_transaction_control(xml, options)
359
+ xml.TransactionControl {
360
+ # if there was a 'global' option set...
361
+ xml.TestMode(@options[:test_mode].upcase) if !@options[:test_mode].blank?
362
+ # allow the global option to be overridden...
363
+ xml.TestMode(options[:test_mode].upcase) if !options[:test_mode].blank?
364
+ xml.SendCustomerEmail(options[:send_customer_email].upcase) unless options[:send_customer_email].blank?
365
+ xml.SendMerchantEmail(options[:send_merchant_email].upcase) unless options[:send_merchant_email].blank?
366
+ xml.EmailText {
367
+ options[:email_text].each do |item|
368
+ xml.EmailTextItem(item)
369
+ end
370
+ } if options[:email_text]
371
+ }
372
+ end
373
+
374
+ def add_vendor_data(xml, options)
375
+ return if options[:vendor_data].blank?
376
+ xml.VendorData {
377
+ options[:vendor_data].each do |k,v|
378
+ xml.Element {
379
+ xml.Name(k)
380
+ xml.Key(v)
381
+ }
382
+ end
383
+ }
384
+ end
385
+
386
+ def commit(payload)
387
+ # Set the Content-Type header -- otherwise the URL decoding messes up
388
+ # the Base64 encoded payload signature!
389
+ response = parse(ssl_post(self.live_url, post_data(payload), 'Content-Type' => 'text/xml'))
390
+
391
+ Response.new(successful?(response), response[:error_message], response,
392
+ :test => test?,
393
+ :authorization => response[:xid],
394
+ :avs_result => { :code => response[:avs_response] },
395
+ :cvv_result => response[:cvv_response])
396
+ end
397
+
398
+ def post_data(payload)
399
+ payload_xml = payload.root.to_xml(:indent => 0)
400
+
401
+ payload_signature = sign_payload(payload_xml)
402
+
403
+ request = Nokogiri::XML::Builder.new do |xml|
404
+ xml.GatewayInterface {
405
+ xml.APICredentials {
406
+ xml.Username(@options[:login])
407
+ xml.PayloadSignature(payload_signature)
408
+ xml.TargetGateway(@options[:gateway_id])
409
+ }
410
+ }
411
+ end.doc
412
+
413
+ request.root.children.first.after payload.root
414
+ request.to_xml(:indent => 0)
415
+ end
416
+
417
+ def parse(raw_xml)
418
+ doc = REXML::Document.new(raw_xml)
419
+ response = Hash.new
420
+ transaction_result = doc.root.get_elements('TransactionResponse/TransactionResult/*')
421
+ transaction_result.each do |e|
422
+ response[e.name.to_s.underscore.to_sym] = e.text unless e.text.blank?
423
+ end
424
+ response
425
+ end
426
+
427
+ def successful?(response)
428
+ # Turns out the PaymentClearing gateway is not consistent...
429
+ response[:status].downcase =='ok'
430
+ end
431
+
432
+ def test_mode?(response)
433
+ # The '1' is a legacy thing; most of the time it should be 'TRUE'...
434
+ response[:test_mode] == 'TRUE' || response[:test_mode] == '1'
435
+ end
436
+
437
+ def message_from(response)
438
+ response[:error_message]
439
+ end
440
+
441
+ def sign_payload(payload)
442
+ key = @options[:password].to_s
443
+ digest=OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new(key), key, payload)
444
+ signature = Base64.encode64(digest)
445
+ signature.chomp!
446
+ end
447
+ end
448
+ end
449
+ end
450
+