tomriley-active_merchant 1.4.2.3

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 (278) hide show
  1. data/CHANGELOG +442 -0
  2. data/CONTRIBUTERS +102 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README +134 -0
  5. data/Rakefile +153 -0
  6. data/active_merchant.gemspec +15 -0
  7. data/gem-public_cert.pem +20 -0
  8. data/init.rb +4 -0
  9. data/lib/active_merchant/billing/avs_result.rb +98 -0
  10. data/lib/active_merchant/billing/base.rb +57 -0
  11. data/lib/active_merchant/billing/check.rb +68 -0
  12. data/lib/active_merchant/billing/credit_card.rb +159 -0
  13. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  14. data/lib/active_merchant/billing/credit_card_methods.rb +125 -0
  15. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  16. data/lib/active_merchant/billing/expiry_date.rb +28 -0
  17. data/lib/active_merchant/billing/gateway.rb +158 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net.rb +646 -0
  19. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +702 -0
  20. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +233 -0
  21. data/lib/active_merchant/billing/gateways/beanstream.rb +102 -0
  22. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  23. data/lib/active_merchant/billing/gateways/bogus.rb +98 -0
  24. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  25. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
  26. data/lib/active_merchant/billing/gateways/cyber_source.rb +406 -0
  27. data/lib/active_merchant/billing/gateways/data_cash.rb +595 -0
  28. data/lib/active_merchant/billing/gateways/efsnet.rb +229 -0
  29. data/lib/active_merchant/billing/gateways/eway.rb +272 -0
  30. data/lib/active_merchant/billing/gateways/exact.rb +222 -0
  31. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  32. data/lib/active_merchant/billing/gateways/linkpoint.rb +396 -0
  33. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +154 -0
  34. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  35. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +214 -0
  36. data/lib/active_merchant/billing/gateways/moneris.rb +205 -0
  37. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  38. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  39. data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
  40. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  41. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
  42. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  43. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  44. data/lib/active_merchant/billing/gateways/payflow.rb +236 -0
  45. data/lib/active_merchant/billing/gateways/payflow_express.rb +138 -0
  46. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  47. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  48. data/lib/active_merchant/billing/gateways/payment_express.rb +230 -0
  49. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +325 -0
  50. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +38 -0
  51. data/lib/active_merchant/billing/gateways/paypal.rb +108 -0
  52. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  53. data/lib/active_merchant/billing/gateways/paypal_express.rb +130 -0
  54. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +20 -0
  55. data/lib/active_merchant/billing/gateways/plugnpay.rb +292 -0
  56. data/lib/active_merchant/billing/gateways/protx.rb +349 -0
  57. data/lib/active_merchant/billing/gateways/psigate.rb +214 -0
  58. data/lib/active_merchant/billing/gateways/psl_card.rb +306 -0
  59. data/lib/active_merchant/billing/gateways/quickpay.rb +213 -0
  60. data/lib/active_merchant/billing/gateways/realex.rb +200 -0
  61. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  62. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +110 -0
  63. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  64. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  65. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  66. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +157 -0
  67. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  68. data/lib/active_merchant/billing/gateways/skip_jack.rb +442 -0
  69. data/lib/active_merchant/billing/gateways/smart_ps.rb +254 -0
  70. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  71. data/lib/active_merchant/billing/gateways/transax.rb +26 -0
  72. data/lib/active_merchant/billing/gateways/trust_commerce.rb +418 -0
  73. data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
  74. data/lib/active_merchant/billing/gateways/verifi.rb +228 -0
  75. data/lib/active_merchant/billing/gateways/viaklix.rb +165 -0
  76. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  77. data/lib/active_merchant/billing/gateways.rb +3 -0
  78. data/lib/active_merchant/billing/integrations/action_view_helper.rb +79 -0
  79. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  80. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  81. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  82. data/lib/active_merchant/billing/integrations/bogus.rb +22 -0
  83. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +81 -0
  84. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +156 -0
  85. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  86. data/lib/active_merchant/billing/integrations/chronopay.rb +22 -0
  87. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  88. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  89. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +83 -0
  90. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  91. data/lib/active_merchant/billing/integrations/gestpay.rb +26 -0
  92. data/lib/active_merchant/billing/integrations/helper.rb +93 -0
  93. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  94. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  95. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  96. data/lib/active_merchant/billing/integrations/hi_trust.rb +26 -0
  97. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  98. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  99. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  100. data/lib/active_merchant/billing/integrations/nochex.rb +87 -0
  101. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  102. data/lib/active_merchant/billing/integrations/paypal/helper.rb +118 -0
  103. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  104. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  105. data/lib/active_merchant/billing/integrations/paypal.rb +40 -0
  106. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  107. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  108. data/lib/active_merchant/billing/integrations/quickpay.rb +18 -0
  109. data/lib/active_merchant/billing/integrations/return.rb +35 -0
  110. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  111. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  112. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  113. data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
  114. data/lib/active_merchant/billing/integrations.rb +22 -0
  115. data/lib/active_merchant/billing/response.rb +32 -0
  116. data/lib/active_merchant/lib/connection.rb +170 -0
  117. data/lib/active_merchant/lib/country.rb +319 -0
  118. data/lib/active_merchant/lib/error.rb +4 -0
  119. data/lib/active_merchant/lib/post_data.rb +22 -0
  120. data/lib/active_merchant/lib/posts_data.rb +47 -0
  121. data/lib/active_merchant/lib/requires_parameters.rb +16 -0
  122. data/lib/active_merchant/lib/utils.rb +18 -0
  123. data/lib/active_merchant/lib/validateable.rb +76 -0
  124. data/lib/active_merchant.rb +60 -0
  125. data/lib/certs/cacert.pem +7815 -0
  126. data/lib/support/gateway_support.rb +58 -0
  127. data/script/destroy +14 -0
  128. data/script/generate +14 -0
  129. data/test/fixtures.yml +330 -0
  130. data/test/remote/gateways/remote_authorize_net_cim_test.rb +459 -0
  131. data/test/remote/gateways/remote_authorize_net_test.rb +145 -0
  132. data/test/remote/gateways/remote_beanstream_interac_test.rb +53 -0
  133. data/test/remote/gateways/remote_beanstream_test.rb +150 -0
  134. data/test/remote/gateways/remote_braintree_test.rb +154 -0
  135. data/test/remote/gateways/remote_card_stream_test.rb +148 -0
  136. data/test/remote/gateways/remote_cyber_source_test.rb +144 -0
  137. data/test/remote/gateways/remote_data_cash_test.rb +357 -0
  138. data/test/remote/gateways/remote_efsnet_test.rb +81 -0
  139. data/test/remote/gateways/remote_eway_test.rb +74 -0
  140. data/test/remote/gateways/remote_exact_test.rb +60 -0
  141. data/test/remote/gateways/remote_instapay_test.rb +61 -0
  142. data/test/remote/gateways/remote_linkpoint_test.rb +112 -0
  143. data/test/remote/gateways/remote_merchant_e_solutions_test.rb +173 -0
  144. data/test/remote/gateways/remote_modern_payments_cim_test.rb +58 -0
  145. data/test/remote/gateways/remote_modern_payments_test.rb +43 -0
  146. data/test/remote/gateways/remote_moneris_test.rb +82 -0
  147. data/test/remote/gateways/remote_net_registry_test.rb +85 -0
  148. data/test/remote/gateways/remote_netbilling_test.rb +70 -0
  149. data/test/remote/gateways/remote_pay_junction_test.rb +143 -0
  150. data/test/remote/gateways/remote_pay_secure_test.rb +39 -0
  151. data/test/remote/gateways/remote_payflow_express_test.rb +50 -0
  152. data/test/remote/gateways/remote_payflow_test.rb +237 -0
  153. data/test/remote/gateways/remote_payflow_uk_test.rb +173 -0
  154. data/test/remote/gateways/remote_payment_express_test.rb +136 -0
  155. data/test/remote/gateways/remote_paypal_express_test.rb +49 -0
  156. data/test/remote/gateways/remote_paypal_test.rb +167 -0
  157. data/test/remote/gateways/remote_plugnpay_test.rb +72 -0
  158. data/test/remote/gateways/remote_protx_test.rb +219 -0
  159. data/test/remote/gateways/remote_psigate_test.rb +50 -0
  160. data/test/remote/gateways/remote_psl_card_test.rb +125 -0
  161. data/test/remote/gateways/remote_quickpay_test.rb +190 -0
  162. data/test/remote/gateways/remote_realex_test.rb +224 -0
  163. data/test/remote/gateways/remote_sage_bankcard_test.rb +109 -0
  164. data/test/remote/gateways/remote_sage_test.rb +87 -0
  165. data/test/remote/gateways/remote_sage_virtual_check_test.rb +62 -0
  166. data/test/remote/gateways/remote_secure_pay_au_test.rb +40 -0
  167. data/test/remote/gateways/remote_secure_pay_tech_test.rb +37 -0
  168. data/test/remote/gateways/remote_secure_pay_test.rb +28 -0
  169. data/test/remote/gateways/remote_skipjack_test.rb +105 -0
  170. data/test/remote/gateways/remote_trans_first_test.rb +34 -0
  171. data/test/remote/gateways/remote_transax_test.rb +112 -0
  172. data/test/remote/gateways/remote_trust_commerce_test.rb +152 -0
  173. data/test/remote/gateways/remote_usa_epay_test.rb +46 -0
  174. data/test/remote/gateways/remote_verifi_test.rb +107 -0
  175. data/test/remote/gateways/remote_viaklix_test.rb +43 -0
  176. data/test/remote/gateways/remote_wirecard_test.rb +111 -0
  177. data/test/remote/integrations/remote_gestpay_integration_test.rb +37 -0
  178. data/test/remote/integrations/remote_paypal_integration_test.rb +26 -0
  179. data/test/test_helper.rb +182 -0
  180. data/test/unit/avs_result_test.rb +59 -0
  181. data/test/unit/base_test.rb +55 -0
  182. data/test/unit/check_test.rb +88 -0
  183. data/test/unit/connection_test.rb +129 -0
  184. data/test/unit/country_code_test.rb +33 -0
  185. data/test/unit/country_test.rb +64 -0
  186. data/test/unit/credit_card_formatting_test.rb +19 -0
  187. data/test/unit/credit_card_methods_test.rb +170 -0
  188. data/test/unit/credit_card_test.rb +318 -0
  189. data/test/unit/cvv_result_test.rb +33 -0
  190. data/test/unit/expiry_date_test.rb +21 -0
  191. data/test/unit/gateways/authorize_net_cim_test.rb +638 -0
  192. data/test/unit/gateways/authorize_net_test.rb +290 -0
  193. data/test/unit/gateways/beanstream_interac_test.rb +51 -0
  194. data/test/unit/gateways/beanstream_test.rb +108 -0
  195. data/test/unit/gateways/bogus_test.rb +46 -0
  196. data/test/unit/gateways/braintree_test.rb +126 -0
  197. data/test/unit/gateways/card_stream_test.rb +90 -0
  198. data/test/unit/gateways/cyber_source_test.rb +188 -0
  199. data/test/unit/gateways/data_cash_test.rb +133 -0
  200. data/test/unit/gateways/efsnet_test.rb +123 -0
  201. data/test/unit/gateways/eway_test.rb +118 -0
  202. data/test/unit/gateways/exact_test.rb +156 -0
  203. data/test/unit/gateways/gateway_test.rb +48 -0
  204. data/test/unit/gateways/instapay_test.rb +102 -0
  205. data/test/unit/gateways/linkpoint_test.rb +167 -0
  206. data/test/unit/gateways/merchant_e_solutions_test.rb +169 -0
  207. data/test/unit/gateways/modern_payments_cim_test.rb +171 -0
  208. data/test/unit/gateways/moneris_test.rb +158 -0
  209. data/test/unit/gateways/net_registry_test.rb +416 -0
  210. data/test/unit/gateways/netbilling_test.rb +54 -0
  211. data/test/unit/gateways/pay_junction_test.rb +123 -0
  212. data/test/unit/gateways/pay_secure_test.rb +71 -0
  213. data/test/unit/gateways/payflow_express_test.rb +173 -0
  214. data/test/unit/gateways/payflow_express_uk_test.rb +86 -0
  215. data/test/unit/gateways/payflow_test.rb +305 -0
  216. data/test/unit/gateways/payflow_uk_test.rb +30 -0
  217. data/test/unit/gateways/payment_express_test.rb +195 -0
  218. data/test/unit/gateways/paypal_express_test.rb +382 -0
  219. data/test/unit/gateways/paypal_test.rb +520 -0
  220. data/test/unit/gateways/plugnpay_test.rb +86 -0
  221. data/test/unit/gateways/protx_test.rb +139 -0
  222. data/test/unit/gateways/psigate_test.rb +169 -0
  223. data/test/unit/gateways/psl_card_test.rb +64 -0
  224. data/test/unit/gateways/quickpay_test.rb +112 -0
  225. data/test/unit/gateways/realex_test.rb +151 -0
  226. data/test/unit/gateways/sage_bankcard_test.rb +162 -0
  227. data/test/unit/gateways/sage_virtual_check_test.rb +71 -0
  228. data/test/unit/gateways/secure_pay_au_test.rb +207 -0
  229. data/test/unit/gateways/secure_pay_tech_test.rb +44 -0
  230. data/test/unit/gateways/secure_pay_test.rb +87 -0
  231. data/test/unit/gateways/skip_jack_test.rb +133 -0
  232. data/test/unit/gateways/trans_first_test.rb +112 -0
  233. data/test/unit/gateways/trust_commerce_test.rb +90 -0
  234. data/test/unit/gateways/usa_epay_test.rb +128 -0
  235. data/test/unit/gateways/verifi_test.rb +96 -0
  236. data/test/unit/gateways/viaklix_test.rb +78 -0
  237. data/test/unit/gateways/wirecard_test.rb +250 -0
  238. data/test/unit/generators/test_gateway_generator.rb +46 -0
  239. data/test/unit/generators/test_generator_helper.rb +20 -0
  240. data/test/unit/generators/test_integration_generator.rb +53 -0
  241. data/test/unit/integrations/action_view_helper_test.rb +50 -0
  242. data/test/unit/integrations/bogus_module_test.rb +20 -0
  243. data/test/unit/integrations/chronopay_module_test.rb +13 -0
  244. data/test/unit/integrations/gestpay_module_test.rb +14 -0
  245. data/test/unit/integrations/helpers/bogus_helper_test.rb +28 -0
  246. data/test/unit/integrations/helpers/chronopay_helper_test.rb +67 -0
  247. data/test/unit/integrations/helpers/gestpay_helper_test.rb +100 -0
  248. data/test/unit/integrations/helpers/hi_trust_helper_test.rb +16 -0
  249. data/test/unit/integrations/helpers/nochex_helper_test.rb +53 -0
  250. data/test/unit/integrations/helpers/paypal_helper_test.rb +162 -0
  251. data/test/unit/integrations/helpers/quickpay_helper_test.rb +40 -0
  252. data/test/unit/integrations/helpers/two_checkout_helper_test.rb +92 -0
  253. data/test/unit/integrations/hi_trust_module_test.rb +13 -0
  254. data/test/unit/integrations/nochex_module_test.rb +13 -0
  255. data/test/unit/integrations/notifications/chronopay_notification_test.rb +66 -0
  256. data/test/unit/integrations/notifications/gestpay_notification_test.rb +60 -0
  257. data/test/unit/integrations/notifications/hi_trust_notification_test.rb +59 -0
  258. data/test/unit/integrations/notifications/nochex_notification_test.rb +51 -0
  259. data/test/unit/integrations/notifications/notification_test.rb +54 -0
  260. data/test/unit/integrations/notifications/paypal_notification_test.rb +85 -0
  261. data/test/unit/integrations/notifications/quickpay_notification_test.rb +69 -0
  262. data/test/unit/integrations/notifications/two_checkout_notification_test.rb +55 -0
  263. data/test/unit/integrations/paypal_module_test.rb +28 -0
  264. data/test/unit/integrations/quickpay_module_test.rb +9 -0
  265. data/test/unit/integrations/returns/chronopay_return_test.rb +11 -0
  266. data/test/unit/integrations/returns/gestpay_return_test.rb +10 -0
  267. data/test/unit/integrations/returns/hi_trust_return_test.rb +24 -0
  268. data/test/unit/integrations/returns/nochex_return_test.rb +10 -0
  269. data/test/unit/integrations/returns/paypal_return_test.rb +10 -0
  270. data/test/unit/integrations/returns/return_test.rb +11 -0
  271. data/test/unit/integrations/returns/two_checkout_return_test.rb +24 -0
  272. data/test/unit/integrations/two_checkout_module_test.rb +13 -0
  273. data/test/unit/post_data_test.rb +55 -0
  274. data/test/unit/posts_data_test.rb +48 -0
  275. data/test/unit/response_test.rb +28 -0
  276. data/test/unit/utils_test.rb +7 -0
  277. data/test/unit/validateable_test.rb +60 -0
  278. metadata +364 -0
@@ -0,0 +1,349 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class ProtxGateway < Gateway
4
+ cattr_accessor :simulate
5
+ self.simulate = false
6
+
7
+ TEST_URL = 'https://ukvpstest.protx.com/vspgateway/service'
8
+ LIVE_URL = 'https://ukvps.protx.com/vspgateway/service'
9
+ SIMULATOR_URL = 'https://ukvpstest.protx.com/VSPSimulator'
10
+
11
+ APPROVED = 'OK'
12
+ REGISTERED = 'REGISTERED'
13
+
14
+ TRANSACTIONS = {
15
+ :purchase => 'PAYMENT',
16
+ :credit => 'REFUND',
17
+ :authorization => 'DEFERRED',
18
+ :capture => 'RELEASE',
19
+ :void => 'VOID',
20
+ :abort => 'ABORT',
21
+ :repeat => 'REPEAT',
22
+ :authenticate => 'AUTHENTICATE',
23
+ :authorise => 'AUTHORISE'
24
+ }
25
+
26
+ CREDIT_CARDS = {
27
+ :visa => "VISA",
28
+ :master => "MC",
29
+ :delta => "DELTA",
30
+ :solo => "SOLO",
31
+ :switch => "MAESTRO",
32
+ :maestro => "MAESTRO",
33
+ :american_express => "AMEX",
34
+ :electron => "UKE",
35
+ :diners_club => "DC",
36
+ :jcb => "JCB"
37
+ }
38
+
39
+ ELECTRON = /^(424519|42496[23]|450875|48440[6-8]|4844[1-5][1-5]|4917[3-5][0-9]|491880)\d{10}(\d{3})?$/
40
+
41
+ AVS_CVV_CODE = {
42
+ "NOTPROVIDED" => nil,
43
+ "NOTCHECKED" => 'X',
44
+ "MATCHED" => 'Y',
45
+ "NOTMATCHED" => 'N'
46
+ }
47
+
48
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :switch, :solo, :maestro, :diners_club]
49
+ self.supported_countries = ['GB']
50
+ self.default_currency = 'GBP'
51
+
52
+ self.homepage_url = 'http://www.protx.com'
53
+ self.display_name = 'Protx'
54
+
55
+ def initialize(options = {})
56
+ requires!(options, :login)
57
+ @options = options
58
+ super
59
+ end
60
+
61
+ def test?
62
+ @options[:test] || super
63
+ end
64
+
65
+ def purchase(money, credit_card, options = {})
66
+ requires!(options, :order_id)
67
+ post = {}
68
+
69
+ add_amount(post, money, options)
70
+ add_invoice(post, options)
71
+ add_credit_card(post, credit_card)
72
+ add_address(post, options)
73
+ add_customer_data(post, options)
74
+
75
+ commit(:purchase, post)
76
+ end
77
+
78
+ def authorize(money, credit_card, options = {})
79
+ requires!(options, :order_id)
80
+ post = {}
81
+
82
+ add_amount(post, money, options)
83
+ add_invoice(post, options)
84
+ add_credit_card(post, credit_card)
85
+ add_address(post, options)
86
+ add_customer_data(post, options)
87
+
88
+ commit(:authorization, post)
89
+ end
90
+
91
+ def authenticate(money, credit_card, options = {})
92
+ requires!(options, :order_id)
93
+ post = {}
94
+
95
+ add_credit_card(post, credit_card)
96
+ add_address(post, options)
97
+ add_customer_data(post, options)
98
+ add_invoice(post, options)
99
+ add_amount(post, money, options)
100
+
101
+ commit(:authenticate, post)
102
+ end
103
+
104
+ # Identification is authorization for original payment or authorization. Supply an :order_id option
105
+ # that is a unique id for this repeat payment (don't just supply the original order id).
106
+ def repeat(money, identification, options = {})
107
+ requires!(options, :order_id)
108
+ post = {}
109
+
110
+ add_invoice(post, options)
111
+ add_related_reference(post, identification)
112
+ add_amount(post, money, options)
113
+
114
+ # If we're making the first payment, we AUTHORISE, otherwise we're REPEATING
115
+ # a PAYMENT or an existing AUTHORISE
116
+ if identification.split(';').last == 'authenticate'
117
+ commit(:authorise, post)
118
+ else
119
+ commit(:repeat, post)
120
+ end
121
+ end
122
+
123
+ # You can only capture a transaction once, even if you didn't capture the full amount the first time.
124
+ def capture(money, identification, options = {})
125
+ post = {}
126
+
127
+ add_reference(post, identification)
128
+ add_release_amount(post, money, options)
129
+
130
+ commit(:capture, post)
131
+ end
132
+
133
+ def void(identification, options = {})
134
+ post = {}
135
+
136
+ add_reference(post, identification)
137
+ action = abort_or_void_from(identification)
138
+
139
+ commit(action, post)
140
+ end
141
+
142
+ # Crediting requires a new order_id to passed in, as well as a description
143
+ def credit(money, identification, options = {})
144
+ requires!(options, :order_id, :description)
145
+
146
+ post = {}
147
+
148
+ add_credit_reference(post, identification)
149
+ add_amount(post, money, options)
150
+ add_invoice(post, options)
151
+
152
+ commit(:credit, post)
153
+ end
154
+
155
+ private
156
+ def add_reference(post, identification)
157
+ order_id, transaction_id, authorization, security_key = identification.split(';')
158
+
159
+ add_pair(post, :VendorTxCode, order_id)
160
+ add_pair(post, :VPSTxId, transaction_id)
161
+ add_pair(post, :TxAuthNo, authorization)
162
+ add_pair(post, :SecurityKey, security_key)
163
+ end
164
+
165
+ def add_credit_reference(post, identification)
166
+ order_id, transaction_id, authorization, security_key = identification.split(';')
167
+
168
+ add_pair(post, :RelatedVendorTxCode, order_id)
169
+ add_pair(post, :RelatedVPSTxId, transaction_id)
170
+ add_pair(post, :RelatedTxAuthNo, authorization)
171
+ add_pair(post, :RelatedSecurityKey, security_key)
172
+ end
173
+
174
+ def add_amount(post, money, options)
175
+ add_pair(post, :Amount, amount(money), :required => true)
176
+ add_pair(post, :Currency, options[:currency] || currency(money), :required => true)
177
+ end
178
+
179
+ # doesn't actually use the currency -- dodgy!
180
+ def add_release_amount(post, money, options)
181
+ add_pair(post, :ReleaseAmount, amount(money), :required => true)
182
+ end
183
+
184
+ def add_customer_data(post, options)
185
+ add_pair(post, :CustomerEMail, options[:email][0,255]) unless options[:email].blank?
186
+ add_pair(post, :BillingPhone, options[:phone].gsub(/[^0-9+]/, '')[0,20]) unless options[:phone].blank?
187
+ add_pair(post, :ClientIPAddress, options[:ip])
188
+ end
189
+
190
+ def add_address(post, options)
191
+ if billing_address = options[:billing_address] || options[:address]
192
+ first_name, last_name = parse_first_and_last_name(billing_address[:name])
193
+ add_pair(post, :BillingSurname, last_name)
194
+ add_pair(post, :BillingFirstnames, first_name)
195
+ add_pair(post, :BillingAddress1, billing_address[:address1])
196
+ add_pair(post, :BillingAddress2, billing_address[:address2])
197
+ add_pair(post, :BillingCity, billing_address[:city])
198
+ add_pair(post, :BillingState, billing_address[:state]) if billing_address[:country] == 'US'
199
+ add_pair(post, :BillingCountry, billing_address[:country])
200
+ add_pair(post, :BillingPostCode, billing_address[:zip])
201
+ end
202
+
203
+ if shipping_address = options[:shipping_address] || billing_address
204
+ first_name, last_name = parse_first_and_last_name(shipping_address[:name])
205
+ add_pair(post, :DeliverySurname, last_name)
206
+ add_pair(post, :DeliveryFirstnames, first_name)
207
+ add_pair(post, :DeliveryAddress1, shipping_address[:address1])
208
+ add_pair(post, :DeliveryAddress2, shipping_address[:address2])
209
+ add_pair(post, :DeliveryCity, shipping_address[:city])
210
+ add_pair(post, :DeliveryState, shipping_address[:state]) if shipping_address[:country] == 'US'
211
+ add_pair(post, :DeliveryCountry, shipping_address[:country])
212
+ add_pair(post, :DeliveryPostCode, shipping_address[:zip])
213
+ end
214
+ end
215
+
216
+ def add_invoice(post, options)
217
+ add_pair(post, :VendorTxCode, sanitize_order_id(options[:order_id]), :required => true)
218
+ add_pair(post, :Description, options[:description] || options[:order_id])
219
+ end
220
+
221
+ def add_credit_card(post, credit_card)
222
+ add_pair(post, :CardHolder, credit_card.name, :required => true)
223
+ add_pair(post, :CardNumber, credit_card.number, :required => true)
224
+
225
+ add_pair(post, :ExpiryDate, format_date(credit_card.month, credit_card.year), :required => true)
226
+
227
+ if requires_start_date_or_issue_number?(credit_card)
228
+ add_pair(post, :StartDate, format_date(credit_card.start_month, credit_card.start_year))
229
+ add_pair(post, :IssueNumber, credit_card.issue_number)
230
+ end
231
+ add_pair(post, :CardType, map_card_type(credit_card))
232
+
233
+ add_pair(post, :CV2, credit_card.verification_value)
234
+ end
235
+
236
+ def sanitize_order_id(order_id)
237
+ order_id.to_s.gsub(/[^-a-zA-Z0-9._]/, '')
238
+ end
239
+
240
+ def map_card_type(credit_card)
241
+ raise ArgumentError, "The credit card type must be provided" if card_brand(credit_card).blank?
242
+
243
+ card_type = card_brand(credit_card).to_sym
244
+
245
+ # Check if it is an electron card
246
+ if card_type == :visa && credit_card.number =~ ELECTRON
247
+ CREDIT_CARDS[:electron]
248
+ else
249
+ CREDIT_CARDS[card_type]
250
+ end
251
+ end
252
+
253
+ # MMYY format
254
+ def format_date(month, year)
255
+ return nil if year.blank? || month.blank?
256
+
257
+ year = sprintf("%.4i", year)
258
+ month = sprintf("%.2i", month)
259
+
260
+ "#{month}#{year[-2..-1]}"
261
+ end
262
+
263
+ def commit(action, parameters)
264
+ response = parse( ssl_post(url_for(action), post_data(action, parameters)) )
265
+
266
+ Response.new([APPROVED, REGISTERED].include?(response['Status']), message_from(response), response,
267
+ :test => test?,
268
+ :authorization => authorization_from(response, parameters, action),
269
+ :avs_result => {
270
+ :street_match => AVS_CVV_CODE[ response["AddressResult"] ],
271
+ :postal_match => AVS_CVV_CODE[ response["PostCodeResult"] ],
272
+ },
273
+ :cvv_result => AVS_CVV_CODE[ response["CV2Result"] ]
274
+ )
275
+ end
276
+
277
+ def authorization_from(response, params, action)
278
+ [ params[:VendorTxCode],
279
+ response["VPSTxId"],
280
+ response["TxAuthNo"],
281
+ response["SecurityKey"],
282
+ action ].join(";")
283
+ end
284
+
285
+ def add_related_reference(post, identification)
286
+ order_id, transaction_id, authorization, security_key = identification.split(';')
287
+ add_pair(post, :RelatedVendorTxCode, order_id)
288
+ add_pair(post, :RelatedVPSTxId, transaction_id)
289
+ add_pair(post, :RelatedTxAuthNo, authorization)
290
+ add_pair(post, :RelatedSecurityKey, security_key)
291
+ end
292
+
293
+ def abort_or_void_from(identification)
294
+ original_transaction = identification.split(';').last
295
+ original_transaction == 'authorization' ? :abort : :void
296
+ end
297
+
298
+ def url_for(action)
299
+ simulate ? build_simulator_url(action) : build_url(action)
300
+ end
301
+
302
+ def build_url(action)
303
+ endpoint = [ :purchase, :authorization, :authenticate ].include?(action) ? "vspdirect-register" : TRANSACTIONS[action].downcase
304
+ "#{test? ? TEST_URL : LIVE_URL}/#{endpoint}.vsp"
305
+ end
306
+
307
+ def build_simulator_url(action)
308
+ endpoint = [ :purchase, :authorization, :authenticate ].include?(action) ? "VSPDirectGateway.asp" : "VSPServerGateway.asp?Service=Vendor#{TRANSACTIONS[action].capitalize}Tx"
309
+ "#{SIMULATOR_URL}/#{endpoint}"
310
+ end
311
+
312
+ def message_from(response)
313
+ [APPROVED, REGISTERED].include?(response['Status']) ? 'Success' : (response['StatusDetail'] || 'Unspecified error') # simonr 20080207 can't actually get non-nil blanks, so this is shorter
314
+ end
315
+
316
+ def post_data(action, parameters = {})
317
+ parameters.update(
318
+ :Vendor => @options[:login],
319
+ :TxType => TRANSACTIONS[action],
320
+ :VPSProtocol => "2.23"
321
+ )
322
+
323
+ parameters.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
324
+ end
325
+
326
+ # Protx returns data in the following format
327
+ # Key1=value1
328
+ # Key2=value2
329
+ def parse(body)
330
+ result = {}
331
+ body.to_a.each { |pair| result[$1] = $2 if pair.strip =~ /\A([^=]+)=(.+)\Z/im }
332
+ result
333
+ end
334
+
335
+ def add_pair(post, key, value, options = {})
336
+ post[key] = value if !value.blank? || options[:required]
337
+ end
338
+
339
+ def parse_first_and_last_name(value)
340
+ name = value.to_s.split(' ')
341
+
342
+ last_name = name.pop || ''
343
+ first_name = name.join(' ')
344
+ [ first_name[0,20], last_name[0,20] ]
345
+ end
346
+ end
347
+ end
348
+ end
349
+
@@ -0,0 +1,214 @@
1
+ # This class implements the Psigate gateway for the ActiveMerchant module.
2
+ # Psigate = http://www.psigate.com/ The class is currently set up to use
3
+ # the psigate test server while rails is in testing or developement mode.
4
+ # The real server will be used while in production mode.
5
+ #
6
+ # Modifications by Sean O'Hara ( sohara at sohara dot com )
7
+ #
8
+ # Usage for a PreAuth (authorize) is as follows:
9
+ #
10
+ # twenty = 2000
11
+ # gateway = PsigateGateway.new(
12
+ # :login => 'teststore',
13
+ # :password => 'psigate1234'
14
+ # )
15
+ #
16
+ # creditcard = CreditCard.new(
17
+ # :number => '4242424242424242',
18
+ # :month => 8,
19
+ # :year => 2006,
20
+ # :first_name => 'Longbob',
21
+ # :last_name => 'Longsen'
22
+ # )
23
+ # response = @gateway.authorize(twenty, creditcard,
24
+ # :order_id => 1234,
25
+ # :billing_address => {
26
+ # :address1 => '123 fairweather Lane',
27
+ # :address2 => 'Apt B',
28
+ # :city => 'New York',
29
+ # :state => 'NY',
30
+ # :country => 'U.S.A.',
31
+ # :zip => '10010'
32
+ # },
33
+ # :email => 'jack@yahoo.com'
34
+ # )
35
+
36
+ require 'rexml/document'
37
+
38
+ module ActiveMerchant #:nodoc:
39
+ module Billing #:nodoc:
40
+
41
+ class PsigateGateway < Gateway
42
+ TEST_URL = 'https://dev.psigate.com:7989/Messenger/XMLMessenger'
43
+ LIVE_URL = 'https://secure.psigate.com:7934/Messenger/XMLMessenger'
44
+
45
+ self.supported_cardtypes = [:visa, :master, :american_express]
46
+ self.supported_countries = ['CA']
47
+ self.homepage_url = 'http://www.psigate.com/'
48
+ self.display_name = 'Psigate'
49
+
50
+ SUCCESS_MESSAGE = 'Success'
51
+ FAILURE_MESSAGE = 'The transaction was declined'
52
+
53
+ def initialize(options = {})
54
+ requires!(options, :login, :password)
55
+ @options = options
56
+ super
57
+ end
58
+
59
+ # Psigate PreAuth
60
+ def authorize(money, creditcard, options = {})
61
+ requires!(options, :order_id)
62
+ options.update({ :CardAction => "1" })
63
+ commit(money, creditcard, options)
64
+ end
65
+
66
+ # Psigate Sale
67
+ def purchase(money, creditcard, options = {})
68
+ requires!(options, :order_id)
69
+ options.update({ :CardAction => "0" })
70
+ commit(money, creditcard, options)
71
+ end
72
+
73
+ # Psigate PostAuth
74
+ def capture(money, authorization, options = {})
75
+ options.update({ :CardAction => "2", :order_id => authorization })
76
+ commit(money, nil, options)
77
+ end
78
+
79
+
80
+ # Psigate Credit
81
+ def credit(money, authorization, options = {})
82
+ options.update({ :CardAction => "3", :order_id => authorization })
83
+ commit(money, nil, options)
84
+ end
85
+
86
+ private
87
+
88
+ def commit(money, creditcard, options = {})
89
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, post_data(money, creditcard, options)))
90
+
91
+ Response.new(successful?(response), message_from(response), response,
92
+ :test => test?,
93
+ :authorization => response[:orderid],
94
+ :avs_result => { :code => response[:avsresult] },
95
+ :cvv_result => response[:cardidresult]
96
+ )
97
+ end
98
+
99
+ def successful?(response)
100
+ response[:approved] == "APPROVED"
101
+ end
102
+
103
+ def parse(xml)
104
+ response = {:message => "Global Error Receipt", :complete => false}
105
+
106
+ xml = REXML::Document.new(xml)
107
+ xml.elements.each('//Result/*') do |node|
108
+
109
+ response[node.name.downcase.to_sym] = normalize(node.text)
110
+
111
+ end unless xml.root.nil?
112
+
113
+ response
114
+ end
115
+
116
+ def post_data(money, creditcard, options)
117
+ xml = REXML::Document.new
118
+ xml << REXML::XMLDecl.new
119
+ root = xml.add_element("Order")
120
+
121
+ for key, value in parameters(money, creditcard, options)
122
+ root.add_element(key.to_s).text = value if value
123
+ end
124
+
125
+ xml.to_s
126
+ end
127
+
128
+ # Set up the parameters hash just once so we don't have to do it
129
+ # for every action.
130
+ def parameters(money, creditcard, options = {})
131
+ params = {
132
+ # General order paramters
133
+ :StoreID => @options[:login],
134
+ :Passphrase => @options[:password],
135
+ :TestResult => options[:test_result],
136
+ :OrderID => options[:order_id],
137
+ :UserID => options[:user_id],
138
+ :Phone => options[:phone],
139
+ :Fax => options[:fax],
140
+ :Email => options[:email],
141
+
142
+ # Credit Card paramaters
143
+ :PaymentType => "CC",
144
+ :CardAction => options[:CardAction],
145
+
146
+ # Financial paramters
147
+ :CustomerIP => options[:ip],
148
+ :SubTotal => amount(money),
149
+ :Tax1 => options[:tax1],
150
+ :Tax2 => options[:tax2],
151
+ :ShippingTotal => options[:shipping_total],
152
+ }
153
+
154
+ if creditcard
155
+ exp_month = sprintf("%.2i", creditcard.month) unless creditcard.month.blank?
156
+ exp_year = creditcard.year.to_s[2,2] unless creditcard.year.blank?
157
+ card_id_code = creditcard.verification_value.blank? ? nil : "1"
158
+
159
+ params.update(
160
+ :CardNumber => creditcard.number,
161
+ :CardExpMonth => exp_month,
162
+ :CardExpYear => exp_year,
163
+ :CardIDCode => card_id_code,
164
+ :CardIDNumber => creditcard.verification_value
165
+ )
166
+ end
167
+
168
+ if address = options[:billing_address] || options[:address]
169
+ params[:Bname] = address[:name] || creditcard.name
170
+ params[:Baddress1] = address[:address1] unless address[:address1].blank?
171
+ params[:Baddress2] = address[:address2] unless address[:address2].blank?
172
+ params[:Bcity] = address[:city] unless address[:city].blank?
173
+ params[:Bprovince] = address[:state] unless address[:state].blank?
174
+ params[:Bpostalcode] = address[:zip] unless address[:zip].blank?
175
+ params[:Bcountry] = address[:country] unless address[:country].blank?
176
+ params[:Bcompany] = address[:company] unless address[:company].blank?
177
+ end
178
+
179
+ if address = options[:shipping_address]
180
+ params[:Sname] = address[:name] || creditcard.name
181
+ params[:Saddress1] = address[:address1] unless address[:address1].blank?
182
+ params[:Saddress2] = address[:address2] unless address[:address2].blank?
183
+ params[:Scity] = address[:city] unless address[:city].blank?
184
+ params[:Sprovince] = address[:state] unless address[:state].blank?
185
+ params[:Spostalcode] = address[:zip] unless address[:zip].blank?
186
+ params[:Scountry] = address[:country] unless address[:country].blank?
187
+ params[:Scompany] = address[:company] unless address[:company].blank?
188
+ end
189
+
190
+ return params
191
+ end
192
+
193
+ def message_from(response)
194
+ if response[:approved] == "APPROVED"
195
+ return SUCCESS_MESSAGE
196
+ else
197
+ return FAILURE_MESSAGE if response[:errmsg].blank?
198
+ return response[:errmsg].gsub(/[^\w]/, ' ').split.join(" ").capitalize
199
+ end
200
+ end
201
+
202
+ # Make a ruby type out of the response string
203
+ def normalize(field)
204
+ case field
205
+ when "true" then true
206
+ when "false" then false
207
+ when "" then nil
208
+ when "null" then nil
209
+ else field
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end