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,389 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module BeanstreamCore
4
+ RECURRING_URL = 'https://www.beanstream.com/scripts/recurring_billing.asp'
5
+ SECURE_PROFILE_URL = 'https://www.beanstream.com/scripts/payment_profile.asp'
6
+
7
+ SP_SERVICE_VERSION = '1.1'
8
+
9
+ TRANSACTIONS = {
10
+ :authorization => 'PA',
11
+ :purchase => 'P',
12
+ :capture => 'PAC',
13
+ :refund => 'R',
14
+ :void => 'VP',
15
+ :check_purchase => 'D',
16
+ :check_refund => 'C',
17
+ :void_purchase => 'VP',
18
+ :void_refund => 'VR'
19
+ }
20
+
21
+ PROFILE_OPERATIONS = {
22
+ :new => 'N',
23
+ :modify => 'M'
24
+ }
25
+
26
+ CVD_CODES = {
27
+ '1' => 'M',
28
+ '2' => 'N',
29
+ '3' => 'I',
30
+ '4' => 'S',
31
+ '5' => 'U',
32
+ '6' => 'P'
33
+ }
34
+
35
+ AVS_CODES = {
36
+ '0' => 'R',
37
+ '5' => 'I',
38
+ '9' => 'I'
39
+ }
40
+
41
+ PERIODS = {
42
+ :days => 'D',
43
+ :weeks => 'W',
44
+ :months => 'M',
45
+ :years => 'Y'
46
+ }
47
+
48
+ PERIODICITIES = {
49
+ :daily => [:days, 1],
50
+ :weekly => [:weeks, 1],
51
+ :biweekly => [:weeks, 2],
52
+ :monthly => [:months, 1],
53
+ :bimonthly => [:months, 2],
54
+ :yearly => [:years, 1]
55
+ }
56
+
57
+ RECURRING_OPERATION = {
58
+ :update => 'M',
59
+ :cancel => 'C'
60
+ }
61
+
62
+ def self.included(base)
63
+ base.default_currency = 'CAD'
64
+
65
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
66
+ base.supported_countries = ['CA']
67
+
68
+ # The card types supported by the payment gateway
69
+ base.supported_cardtypes = [:visa, :master, :american_express]
70
+
71
+ # The homepage URL of the gateway
72
+ base.homepage_url = 'http://www.beanstream.com/'
73
+ base.live_url = 'https://www.beanstream.com/scripts/process_transaction.asp'
74
+
75
+ # The name of the gateway
76
+ base.display_name = 'Beanstream.com'
77
+ end
78
+
79
+ # Only <tt>:login</tt> is required by default,
80
+ # which is the merchant's merchant ID. If you'd like to perform void,
81
+ # capture or refund transactions then you'll also need to add a username
82
+ # and password to your account under administration -> account settings ->
83
+ # order settings -> Use username/password validation
84
+ def initialize(options = {})
85
+ requires!(options, :login)
86
+ @options = options
87
+ super
88
+ end
89
+
90
+ def capture(money, authorization, options = {})
91
+ reference, amount, type = split_auth(authorization)
92
+
93
+ post = {}
94
+ add_amount(post, money)
95
+ add_reference(post, reference)
96
+ add_transaction_type(post, :capture)
97
+ commit(post)
98
+ end
99
+
100
+ def refund(money, source, options = {})
101
+ post = {}
102
+ reference, amount, type = split_auth(source)
103
+ add_reference(post, reference)
104
+ add_transaction_type(post, refund_action(type))
105
+ add_amount(post, money)
106
+ commit(post)
107
+ end
108
+
109
+ def credit(money, source, options = {})
110
+ deprecated Gateway::CREDIT_DEPRECATION_MESSAGE
111
+ refund(money, source, options)
112
+ end
113
+
114
+ private
115
+ def purchase_action(source)
116
+ if source.is_a?(Check)
117
+ :check_purchase
118
+ else
119
+ :purchase
120
+ end
121
+ end
122
+
123
+ def void_action(original_transaction_type)
124
+ (original_transaction_type == TRANSACTIONS[:refund]) ? :void_refund : :void_purchase
125
+ end
126
+
127
+ def refund_action(type)
128
+ (type == TRANSACTIONS[:check_purchase]) ? :check_refund : :refund
129
+ end
130
+
131
+ def secure_profile_action(type)
132
+ PROFILE_OPERATIONS[type] || PROFILE_OPERATIONS[:new]
133
+ end
134
+
135
+ def split_auth(string)
136
+ string.split(";")
137
+ end
138
+
139
+ def add_amount(post, money)
140
+ post[:trnAmount] = amount(money)
141
+ end
142
+
143
+ def add_original_amount(post, amount)
144
+ post[:trnAmount] = amount
145
+ end
146
+
147
+ def add_reference(post, reference)
148
+ post[:adjId] = reference
149
+ end
150
+
151
+ def add_address(post, options)
152
+ prepare_address_for_non_american_countries(options)
153
+
154
+ if billing_address = options[:billing_address] || options[:address]
155
+ post[:ordName] = billing_address[:name]
156
+ post[:ordEmailAddress] = options[:email]
157
+ post[:ordPhoneNumber] = billing_address[:phone]
158
+ post[:ordAddress1] = billing_address[:address1]
159
+ post[:ordAddress2] = billing_address[:address2]
160
+ post[:ordCity] = billing_address[:city]
161
+ post[:ordProvince] = billing_address[:state]
162
+ post[:ordPostalCode] = billing_address[:zip]
163
+ post[:ordCountry] = billing_address[:country]
164
+ end
165
+ if shipping_address = options[:shipping_address]
166
+ post[:shipName] = shipping_address[:name]
167
+ post[:shipEmailAddress] = options[:email]
168
+ post[:shipPhoneNumber] = shipping_address[:phone]
169
+ post[:shipAddress1] = shipping_address[:address1]
170
+ post[:shipAddress2] = shipping_address[:address2]
171
+ post[:shipCity] = shipping_address[:city]
172
+ post[:shipProvince] = shipping_address[:state]
173
+ post[:shipPostalCode] = shipping_address[:zip]
174
+ post[:shipCountry] = shipping_address[:country]
175
+ post[:shippingMethod] = shipping_address[:shipping_method]
176
+ post[:deliveryEstimate] = shipping_address[:delivery_estimate]
177
+ end
178
+ end
179
+
180
+ def prepare_address_for_non_american_countries(options)
181
+ [ options[:billing_address], options[:shipping_address] ].compact.each do |address|
182
+ unless ['US', 'CA'].include?(address[:country])
183
+ address[:state] = '--'
184
+ address[:zip] = '000000' unless address[:zip]
185
+ end
186
+ end
187
+ end
188
+
189
+ def add_invoice(post, options)
190
+ post[:trnOrderNumber] = options[:order_id]
191
+ post[:trnComments] = options[:description]
192
+ post[:ordItemPrice] = amount(options[:subtotal])
193
+ post[:ordShippingPrice] = amount(options[:shipping])
194
+ post[:ordTax1Price] = amount(options[:tax1] || options[:tax])
195
+ post[:ordTax2Price] = amount(options[:tax2])
196
+ post[:ref1] = options[:custom]
197
+ end
198
+
199
+ def add_credit_card(post, credit_card)
200
+ if credit_card
201
+ post[:trnCardOwner] = credit_card.name
202
+ post[:trnCardNumber] = credit_card.number
203
+ post[:trnExpMonth] = format(credit_card.month, :two_digits)
204
+ post[:trnExpYear] = format(credit_card.year, :two_digits)
205
+ post[:trnCardCvd] = credit_card.verification_value
206
+ end
207
+ end
208
+
209
+ def add_check(post, check)
210
+ # The institution number of the consumer’s financial institution. Required for Canadian dollar EFT transactions.
211
+ post[:institutionNumber] = check.institution_number
212
+
213
+ # The bank transit number of the consumer’s bank account. Required for Canadian dollar EFT transactions.
214
+ post[:transitNumber] = check.transit_number
215
+
216
+ # The routing number of the consumer’s bank account. Required for US dollar EFT transactions.
217
+ post[:routingNumber] = check.routing_number
218
+
219
+ # The account number of the consumer’s bank account. Required for both Canadian and US dollar EFT transactions.
220
+ post[:accountNumber] = check.account_number
221
+ end
222
+
223
+ def add_secure_profile_variables(post, options = {})
224
+ post[:serviceVersion] = SP_SERVICE_VERSION
225
+ post[:responseFormat] = 'QS'
226
+ post[:cardValidation] = (options[:cardValidation].to_i == 1) || '0'
227
+
228
+ post[:operationType] = options[:operationType] || options[:operation] || secure_profile_action(:new)
229
+ post[:customerCode] = options[:billing_id] || options[:vault_id] || false
230
+ post[:status] = options[:status]
231
+ end
232
+
233
+ def add_recurring_amount(post, money)
234
+ post[:amount] = amount(money)
235
+ end
236
+
237
+ def add_recurring_invoice(post, options)
238
+ post[:rbApplyTax1] = options[:apply_tax1]
239
+ end
240
+
241
+ def add_recurring_operation_type(post, operation)
242
+ post[:operationType] = RECURRING_OPERATION[operation]
243
+ end
244
+
245
+ def add_recurring_service(post, options)
246
+ post[:serviceVersion] = '1.0'
247
+ post[:merchantId] = @options[:login]
248
+ post[:passCode] = @options[:recurring_api_key]
249
+ post[:rbAccountId] = options[:account_id]
250
+ end
251
+
252
+ def add_recurring_type(post, options)
253
+ # XXX requires!
254
+ post[:trnRecurring] = 1
255
+ period, increment = interval(options)
256
+ post[:rbBillingPeriod] = PERIODS[period]
257
+ post[:rbBillingIncrement] = increment
258
+
259
+ if options.include? :start_date
260
+ post[:rbCharge] = 0
261
+ post[:rbFirstBilling] = options[:start_date].strftime('%m%d%Y')
262
+ end
263
+
264
+ if count = options[:occurrences] || options[:payments]
265
+ post[:rbExpiry] = (options[:start_date] || Date.current).advance(period => count).strftime('%m%d%Y')
266
+ end
267
+ end
268
+
269
+ def interval(options)
270
+ if options.include? :periodicity
271
+ requires!(options, [:periodicity, *PERIODICITIES.keys])
272
+ PERIODICITIES[options[:periodicity]]
273
+ elsif options.include? :interval
274
+ interval = options[:interval]
275
+ if interval.respond_to? :parts
276
+ parts = interval.parts
277
+ raise ArgumentError.new("Cannot recur with mixed interval (#{interval}). Use only one of: days, weeks, months or years") if parts.length > 1
278
+ parts.first
279
+ elsif interval.kind_of? Hash
280
+ requires!(interval, :unit)
281
+ unit, length = interval.values_at(:unit, :length)
282
+ length ||= 1
283
+ [unit, length]
284
+ end
285
+ end
286
+ end
287
+
288
+ def parse(body)
289
+ results = {}
290
+ if !body.nil?
291
+ body.split(/&/).each do |pair|
292
+ key, val = pair.split(/=/)
293
+ results[key.to_sym] = val.nil? ? nil : CGI.unescape(val)
294
+ end
295
+ end
296
+
297
+ # Clean up the message text if there is any
298
+ if results[:messageText]
299
+ results[:messageText].gsub!(/<LI>/, "")
300
+ results[:messageText].gsub!(/(\.)?<br>/, ". ")
301
+ results[:messageText].strip!
302
+ end
303
+
304
+ results
305
+ end
306
+
307
+ def recurring_parse(data)
308
+ REXML::Document.new(data).root.elements.to_a.inject({}) do |response, element|
309
+ response[element.name.to_sym] = element.text
310
+ response
311
+ end
312
+ end
313
+
314
+ def commit(params, use_profile_api = false)
315
+ post(post_data(params,use_profile_api),use_profile_api)
316
+ end
317
+
318
+ def recurring_commit(params)
319
+ recurring_post(post_data(params, false))
320
+ end
321
+
322
+ def post(data, use_profile_api=nil)
323
+ response = parse(ssl_post((use_profile_api ? SECURE_PROFILE_URL : self.live_url), data))
324
+ response[:customer_vault_id] = response[:customerCode] if response[:customerCode]
325
+ build_response(success?(response), message_from(response), response,
326
+ :test => test? || response[:authCode] == "TEST",
327
+ :authorization => authorization_from(response),
328
+ :cvv_result => CVD_CODES[response[:cvdId]],
329
+ :avs_result => { :code => (AVS_CODES.include? response[:avsId]) ? AVS_CODES[response[:avsId]] : response[:avsId] }
330
+ )
331
+ end
332
+
333
+ def recurring_post(data)
334
+ response = recurring_parse(ssl_post(RECURRING_URL, data))
335
+ build_response(recurring_success?(response), recurring_message_from(response), response)
336
+ end
337
+
338
+ def authorization_from(response)
339
+ "#{response[:trnId]};#{response[:trnAmount]};#{response[:trnType]}"
340
+ end
341
+
342
+ def message_from(response)
343
+ response[:messageText] || response[:responseMessage]
344
+ end
345
+
346
+ def recurring_message_from(response)
347
+ response[:message]
348
+ end
349
+
350
+ def success?(response)
351
+ response[:responseType] == 'R' || response[:trnApproved] == '1' || response[:responseCode] == '1'
352
+ end
353
+
354
+ def recurring_success?(response)
355
+ response[:code] == '1'
356
+ end
357
+
358
+ def add_source(post, source)
359
+ if source.is_a?(String) or source.is_a?(Integer)
360
+ post[:customerCode] = source
361
+ else
362
+ card_brand(source) == "check" ? add_check(post, source) : add_credit_card(post, source)
363
+ end
364
+ end
365
+
366
+ def add_transaction_type(post, action)
367
+ post[:trnType] = TRANSACTIONS[action]
368
+ end
369
+
370
+ def post_data(params, use_profile_api)
371
+ params[:requestType] = 'BACKEND'
372
+ if use_profile_api
373
+ params[:merchantId] = @options[:login]
374
+ params[:passCode] = @options[:secure_profile_api_key]
375
+ else
376
+ params[:username] = @options[:user] if @options[:user]
377
+ params[:password] = @options[:password] if @options[:password]
378
+ params[:merchant_id] = @options[:login]
379
+ end
380
+ params[:vbvEnabled] = '0'
381
+ params[:scEnabled] = '0'
382
+
383
+ params.reject{|k, v| v.blank?}.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
384
+ end
385
+
386
+ end
387
+ end
388
+ end
389
+
@@ -0,0 +1,54 @@
1
+ require File.dirname(__FILE__) + '/beanstream/beanstream_core'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class BeanstreamInteracResponse < Response
6
+ def redirect
7
+ params['pageContents']
8
+ end
9
+ end
10
+
11
+ class BeanstreamInteracGateway < Gateway
12
+ include BeanstreamCore
13
+
14
+ # Confirm a transaction posted back from the bank to Beanstream.
15
+ # Confirming a transaction does not require any credentials,
16
+ # and in an application with many merchants sharing a funded
17
+ # URL the application may not yet know which merchant the
18
+ # post back is for until the response of the confirmation is
19
+ # received, which contains the order number.
20
+ def self.confirm(transaction)
21
+ gateway = new(:login => '')
22
+ gateway.confirm(transaction)
23
+ end
24
+
25
+ def purchase(money, options = {})
26
+ post = {}
27
+ add_amount(post, money)
28
+ add_invoice(post, options)
29
+ add_address(post, options)
30
+ add_interac_details(post, options)
31
+ add_transaction_type(post, :purchase)
32
+ commit(post)
33
+ end
34
+
35
+ # Confirm a transaction posted back from the bank to Beanstream.
36
+ def confirm(transaction)
37
+ post(transaction)
38
+ end
39
+
40
+ private
41
+
42
+ def add_interac_details(post, options)
43
+ address = options[:billing_address] || options[:address] || {}
44
+ post[:trnCardOwner] = address[:name]
45
+ post[:paymentMethod] = 'IO'
46
+ end
47
+
48
+ def build_response(*args)
49
+ BeanstreamInteracResponse.new(*args)
50
+ end
51
+ end
52
+ end
53
+ end
54
+
@@ -0,0 +1,492 @@
1
+ require 'digest/md5'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class BluePayGateway < Gateway
6
+ class_attribute :live_url, :rebilling_url, :ignore_http_status
7
+
8
+ self.live_url = 'https://secure.bluepay.com/interfaces/bp20post'
9
+ self.rebilling_url = 'https://secure.bluepay.com/interfaces/bp20rebadmin'
10
+
11
+ self.ignore_http_status = true
12
+
13
+ RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT = 0, 2, 3
14
+ AVS_RESULT_CODE, TRANSACTION_ID, CARD_CODE_RESPONSE_CODE = 5, 6, 38
15
+
16
+ CARD_CODE_ERRORS = %w( N S )
17
+ AVS_ERRORS = %w( A E N R W Z )
18
+ AVS_REASON_CODES = %w(27 45)
19
+
20
+ class_attribute :duplicate_window
21
+
22
+ self.supported_countries = ['US']
23
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
24
+ self.homepage_url = 'http://www.bluepay.com/'
25
+ self.display_name = 'BluePay'
26
+ self.money_format = :dollars
27
+
28
+
29
+ # Creates a new BluepayGateway
30
+ #
31
+ # The gateway requires that a valid Account ID and Secret Key be passed
32
+ # in the +options+ hash.
33
+ #
34
+ # ==== Options
35
+ #
36
+ # * <tt>:account_id</tt> -- The BluePay gateway Account ID (REQUIRED)
37
+ # * <tt>:secret_key</tt> -- The BluePay gateway Secret Key (REQUIRED)
38
+ # * <tt>:test</tt> -- set to true for TEST mode or false for LIVE mode
39
+ def initialize(options = {})
40
+ requires!(options, :login, :password)
41
+ @options = options
42
+ super
43
+ end
44
+
45
+ # Performs an authorization, which reserves the funds on the customer's credit card. This does not actually take funds from the customer
46
+ # This is referred to an AUTH transaction in BluePay
47
+ #
48
+ # ==== Parameters
49
+ #
50
+ # * <tt>money</tt> -- The amount to be authorized as an Integer value in cents.
51
+ # * <tt>payment_object</tt> -- This can either be one of three things:
52
+ # A CreditCard object,
53
+ # A Check object,
54
+ # or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction.
55
+ # * <tt>options</tt> -- A hash of optional parameters.
56
+ def authorize(money, payment_object, options = {})
57
+ post = {}
58
+ post[:MASTER_ID] = ''
59
+ if payment_object != nil && payment_object.class() != String
60
+ payment_object.class() == ActiveMerchant::Billing::Check ?
61
+ add_check(post, payment_object) :
62
+ add_creditcard(post, payment_object)
63
+ else
64
+ post[:MASTER_ID] = payment_object
65
+ end
66
+ add_invoice(post, options)
67
+ add_address(post, options)
68
+ add_customer_data(post, options)
69
+ if options[:rebill] != nil
70
+ post[:DO_REBILL] = '1'
71
+ post[:REB_AMOUNT] = amount(options[:rebill_amount])
72
+ post[:REB_FIRST_DATE] = options[:rebill_start_date]
73
+ post[:REB_EXPR] = options[:rebill_expression]
74
+ post[:REB_CYCLES] = options[:rebill_cycles]
75
+ end
76
+ post[:TRANS_TYPE] = 'AUTH'
77
+ commit('AUTH_ONLY', money, post)
78
+ end
79
+
80
+ # Perform a purchase, which is essentially an authorization and capture in a single operation.
81
+ # This is referred to a SALE transaction in BluePay
82
+ #
83
+ # ==== Parameters
84
+ #
85
+ # * <tt>money</tt> -- The amount to be purchased as an Integer value in cents.
86
+ # * <tt>payment_object</tt> -- This can either be one of three things:
87
+ # A CreditCard object,
88
+ # A Check object,
89
+ # or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction.
90
+ # * <tt>options</tt> -- A hash of optional parameters.,
91
+ def purchase(money, payment_object, options = {})
92
+ post = {}
93
+ post[:MASTER_ID] = ''
94
+ if payment_object != nil && payment_object.class() != String
95
+ payment_object.class() == ActiveMerchant::Billing::Check ?
96
+ add_check(post, payment_object) :
97
+ add_creditcard(post, payment_object)
98
+ else
99
+ post[:MASTER_ID] = payment_object
100
+ end
101
+ add_invoice(post, options)
102
+ add_address(post, options)
103
+ add_customer_data(post, options)
104
+ if options[:rebill] != nil
105
+ post[:DO_REBILL] = '1'
106
+ post[:REB_AMOUNT] = amount(options[:rebill_amount])
107
+ post[:REB_FIRST_DATE] = options[:rebill_start_date]
108
+ post[:REB_EXPR] = options[:rebill_expression]
109
+ post[:REB_CYCLES] = options[:rebill_cycles]
110
+ end
111
+ post[:TRANS_TYPE] = 'SALE'
112
+ commit('AUTH_CAPTURE', money, post)
113
+ end
114
+
115
+ # Captures the funds from an authorize transaction.
116
+ # This is referred to a CAPTURE transaction in BluePay
117
+ #
118
+ # ==== Parameters
119
+ #
120
+ # * <tt>money</tt> -- The amount to be captured as an Integer value in cents.
121
+ # * <tt>identification</tt> -- The Master ID, or token, returned from the previous authorize transaction.
122
+ def capture(money, identification, options = {})
123
+ post = {}
124
+ add_address(post, options)
125
+ add_customer_data(post, options)
126
+ post[:MASTER_ID] = identification
127
+ post[:TRANS_TYPE] = 'CAPTURE'
128
+ commit('PRIOR_AUTH_CAPTURE', money, post)
129
+ end
130
+
131
+ # Void a previous transaction
132
+ # This is referred to a VOID transaction in BluePay
133
+ #
134
+ # ==== Parameters
135
+ #
136
+ # * <tt>identification</tt> - The Master ID, or token, returned from a previous authorize transaction.
137
+ def void(identification, options = {})
138
+ post = {}
139
+ post[:MASTER_ID] = identification
140
+ post[:TRANS_TYPE] = 'VOID'
141
+ commit('VOID', nil, post)
142
+ end
143
+
144
+ # Performs a credit.
145
+ #
146
+ # This transaction indicates that money should flow from the merchant to the customer.
147
+ #
148
+ # ==== Parameters
149
+ #
150
+ # * <tt>money</tt> -- The amount to be credited to the customer as an Integer value in cents.
151
+ # * <tt>payment_object</tt> -- This can either be one of three things:
152
+ # A CreditCard object,
153
+ # A Check object,
154
+ # or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction.
155
+ # If the payment_object is a token, then the transaction type will reverse a previous capture or purchase transaction, returning the funds to the customer. If the amount is nil, a full credit will be processed. This is referred to a REFUND transaction in BluePay.
156
+ # If the payment_object is either a CreditCard or Check object, then the transaction type will be an unmatched credit placing funds in the specified account. This is referred to a CREDIT transaction in BluePay.
157
+ # * <tt>options</tt> -- A hash of parameters.
158
+ def refund(money, payment_object, options = {})
159
+ post = {}
160
+ post[:PAYMENT_ACCOUNT] = ''
161
+ if payment_object != nil && payment_object.class() != String
162
+ payment_object.class() == ActiveMerchant::Billing::Check ?
163
+ add_check(post, payment_object) :
164
+ add_creditcard(post, payment_object)
165
+ post[:TRANS_TYPE] = 'CREDIT'
166
+ else
167
+ post[:MASTER_ID] = payment_object
168
+ post[:TRANS_TYPE] = 'REFUND'
169
+ end
170
+
171
+ options[:first_name] ? post[:NAME1] = options[:first_name] : post[:NAME1] = ''
172
+ post[:NAME2] = options[:last_name] if options[:last_name]
173
+ post[:ZIP] = options[:zip] if options[:zip]
174
+ add_invoice(post, options)
175
+ add_address(post, options)
176
+ add_customer_data(post, options)
177
+ commit('CREDIT', money, post)
178
+ end
179
+
180
+ def credit(money, identification, options = {})
181
+ deprecated CREDIT_DEPRECATION_MESSAGE
182
+ refund(money, identification, options)
183
+ end
184
+
185
+ # Create a new recurring payment.
186
+ #
187
+ # ==== Parameters
188
+ #
189
+ # * <tt>money</tt> -- The amount to charge the customer at the time of the recurring payment setup, in cents. Set to zero if you do not want the customer to be charged at this time.
190
+ # * <tt>payment_object</tt> -- This can either be one of three things:
191
+ # A CreditCard object,
192
+ # A Check object,
193
+ # or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction.
194
+ # * <tt>options</tt> -- A hash of optional parameters.,
195
+
196
+ # ==== Options
197
+ #
198
+ # * <tt>:rebill_start_date</tt> is a string that tells the gateway when to start the rebill. (REQUIRED)
199
+ # Has two valid formats:
200
+ # "YYYY-MM-DD HH:MM:SS" Hours, minutes, and seconds are optional.
201
+ # "XX UNITS" Relative date as explained below. Marked from the time of the
202
+ # transaction (i.e.: 10 DAYS, 1 MONTH, 1 YEAR)
203
+ # * <tt>:rebill_expression</tt> is the period of time in-between rebillings. (REQUIRED)
204
+ # It uses the same "XX UNITS" format as rebill_start_date, explained above.
205
+ # Optional parameters include:
206
+ # * <tt>rebill_cycles</tt>: Number of times to rebill. Don't send or set to nil for infinite rebillings (or
207
+ # until canceled).
208
+ # * <tt>rebill_amount</tt>: Amount to rebill. Defaults to amount of transaction for rebillings.
209
+ #
210
+ # For example, to charge the customer $19.95 now and then charge $39.95 in 60 days every 3 months for 5 times, the options hash would be as follows:
211
+ # :rebill_start_date => '60 DAYS',
212
+ # :rebill_expression => '3 MONTHS',
213
+ # :rebill_cycles => '5',
214
+ # :rebill_amount => '39.95'
215
+ # A money object of 1995 cents would be passed into the 'money' parameter.
216
+ def recurring(money, payment_object, options = {})
217
+ requires!(options, :rebill_start_date, :rebill_expression)
218
+ options[:rebill] = '1'
219
+ money == nil ? authorize(money, payment_object, options) :
220
+ purchase(money, payment_object, options)
221
+ end
222
+
223
+ # View a recurring payment
224
+ #
225
+ # This will pull data associated with a current recurring billing
226
+ #
227
+ # ==== Parameters
228
+ #
229
+ # * <tt>rebill_id</tt> -- A string containing the rebill_id of the recurring billing that is already active (REQUIRED)
230
+ def status_recurring(rebill_id)
231
+ post = {}
232
+ requires!(rebill_id)
233
+ post[:REBILL_ID] = rebill_id
234
+ post[:TRANS_TYPE] = 'GET'
235
+ commit('rebill', 'nil', post)
236
+ end
237
+
238
+ # Update a recurring payment's details.
239
+ #
240
+ # This transaction updates an existing recurring billing
241
+ #
242
+ # ==== Options
243
+ #
244
+ # * <tt>:rebill_id</tt> -- The 12 digit rebill ID used to update a particular rebilling cycle. (REQUIRED)
245
+ # * <tt>:rebill_amount</tt> -- A string containing the new rebilling amount.
246
+ # * <tt>:rebill_next_date</tt> -- A string containing the new rebilling next date.
247
+ # * <tt>:rebill_expression</tt> -- A string containing the new rebilling expression.
248
+ # * <tt>:rebill_cycles</tt> -- A string containing the new rebilling cycles.
249
+ # * <tt>:rebill_next_amount</tt> -- A string containing the next rebilling amount to charge the customer. This ONLY affects the next scheduled charge; all other rebillings will continue at the regular (rebill_amount) amount.
250
+ # Take a look above at the recurring_payment method for similar examples on how to use.
251
+ def update_recurring(options = {})
252
+ post = {}
253
+ requires!(options, :rebill_id)
254
+ post[:REBILL_ID] = options[:rebill_id]
255
+ post[:TRANS_TYPE] = 'SET'
256
+ post[:REB_AMOUNT] = amount(options[:rebill_amount]) if !options[:rebill_amount].nil?
257
+ post[:NEXT_DATE] = options[:rebill_next_date] if !options[:rebill_next_date].nil?
258
+ post[:REB_EXPR] = options[:rebill_expression] if !options[:rebill_expression].nil?
259
+ post[:REB_CYCLES] = options[:rebill_cycles] if !options[:rebill_cycles].nil?
260
+ post[:NEXT_AMOUNT] = options[:rebill_next_amount] if !options[:rebill_next_amount].nil?
261
+ commit('rebill', 'nil', post)
262
+ end
263
+
264
+ # Cancel a recurring payment.
265
+ #
266
+ # This transaction cancels an existing recurring billing.
267
+ #
268
+ # ==== Parameters
269
+ #
270
+ # * <tt>rebill_id</tt> -- A string containing the rebill_id of the recurring billing that you wish to cancel/stop (REQUIRED)
271
+ def cancel_recurring(rebill_id)
272
+ post = {}
273
+ requires!(rebill_id)
274
+ post[:REBILL_ID] = rebill_id
275
+ post[:TRANS_TYPE] = 'SET'
276
+ post[:STATUS] = 'stopped'
277
+ commit('rebill', 'nil', post)
278
+ end
279
+
280
+ private
281
+
282
+ def commit(action, money, fields)
283
+ fields[:AMOUNT] = amount(money) unless (fields[:TRANS_TYPE] == 'VOID' or action == 'rebill')
284
+ test? == true || @options[:test] == true ? fields[:MODE] = 'TEST' : fields[:MODE] = 'LIVE'
285
+ action == 'rebill' ? begin url = rebilling_url; fields[:TAMPER_PROOF_SEAL] = calc_rebill_tps(fields) end : begin url = live_url; fields[:TAMPER_PROOF_SEAL] = calc_tps(amount(money), fields) end
286
+ fields[:ACCOUNT_ID] = @options[:login]
287
+ data = ssl_post url, post_data(action, fields)
288
+ response = parse(data)
289
+ message = message_from(response)
290
+ test_mode = test? || fields[:MODE] == 'TEST'
291
+ if (response.has_key?('TRANS_ID'))
292
+ response_id = response['TRANS_ID'].to_s()
293
+ elsif (response.has_key?('rebill_id'))
294
+ response_id = response['rebill_id'][0]
295
+ else
296
+ response_id = response[TRANSACTION_ID]
297
+ end
298
+ response.has_key?('AVS') ? avs = response['AVS'] : avs = ''
299
+ response[AVS_RESULT_CODE] != '' ? avs = response[AVS_RESULT_CODE] : avs = ''
300
+ response.has_key?('CVV2') ? cvv2 = response['CVV2'] : cvv2 = ''
301
+ response[CARD_CODE_RESPONSE_CODE] != '' ? cvv2 = response[CARD_CODE_RESPONSE_CODE] : cvv2 = ''
302
+ Response.new(success?(response), message, response,
303
+ :test => test_mode,
304
+ :authorization => response_id,
305
+ :fraud_review => fraud_review?(response),
306
+ :avs_result => { :code => avs },
307
+ :cvv_result => cvv2
308
+ )
309
+ end
310
+
311
+ def success?(response)
312
+ if (response['STATUS'] == '1' || message_from(response) =~ /approved/ || response.has_key?('rebill_id') || response[RESPONSE_REASON_TEXT] =~ /approved/)
313
+ return true
314
+ else
315
+ return false
316
+ end
317
+ end
318
+
319
+ def fraud_review?(response)
320
+ response['STATUS'] == 'E' || response['STATUS'] == '0' || response[RESPONSE_REASON_TEXT] =~ /being reviewed/
321
+ end
322
+
323
+ def get_rebill_id(response)
324
+ return response['REBID'] if response_has.key?('REBID')
325
+ end
326
+
327
+ def parse(body)
328
+ fields = CGI::parse(body)
329
+ if fields.has_key?('MESSAGE') or fields.has_key?('rebill_id')
330
+ if fields.has_key?('MESSAGE')
331
+ fields['MESSAGE'][0] == "Missing ACCOUNT_ID" ? message = "The merchant login ID or password is invalid" : message = fields['MESSAGE']
332
+ fields['MESSAGE'][0] =~ /Approved/ ? message = "This transaction has been approved" : message = fields['MESSAGE'] if message == fields['MESSAGE']
333
+ fields['MESSAGE'][0] =~ /Expired/ ? message = "The credit card has expired" : message = fields['MESSAGE'] if message == fields['MESSAGE']
334
+ fields.delete('MESSAGE')
335
+ end
336
+ fields.has_key?('STATUS') ? begin status = fields['STATUS']; fields.delete('STATUS') end : status = ''
337
+ fields.has_key?('AVS') ? begin avs = fields['AVS']; fields.delete('AVS') end : avs = ''
338
+ fields.has_key?('CVV2') ? begin cvv2 = fields['CVV2']; fields.delete('CVV2') end : cvv2 = ''
339
+ fields.has_key?('MASTER_ID') ? begin trans_id = fields['MASTER_ID']; fields.delete('MASTER_ID') end : trans_id = ''
340
+ fields[:avs_result_code] = avs
341
+ fields[:card_code] = cvv2
342
+ fields[:response_code] = status
343
+ fields[:response_reason_code] = ''
344
+ fields[:response_reason_text] = message
345
+ fields[:transaction_id] = trans_id
346
+ return fields
347
+ end
348
+ # parse response if using other old API
349
+ hash = Hash.new
350
+ fields = fields.first[0].split(",")
351
+ fields.each_index do |x|
352
+ hash[x] = fields[x].tr('$','')
353
+ end
354
+ hash
355
+ end
356
+
357
+ def add_invoice(post, options)
358
+ post[:ORDER_ID] = options[:order_id] if options.has_key? :order_id
359
+ post[:INVOICE_ID] = options[:invoice] if options.has_key? :invoice
360
+ post[:invoice_num] = options[:order_id] if options.has_key? :order_id
361
+ post[:MEMO] = options[:description] if options.has_key? :description
362
+ post[:description] = options[:description] if options.has_key? :description
363
+ end
364
+
365
+ def add_creditcard(post, creditcard)
366
+ post[:PAYMENT_TYPE] = 'CREDIT'
367
+ post[:PAYMENT_ACCOUNT] = creditcard.number
368
+ post[:CARD_CVV2] = creditcard.verification_value if
369
+ creditcard.verification_value?
370
+ post[:CARD_EXPIRE] = expdate(creditcard)
371
+ post[:NAME1] = creditcard.first_name
372
+ post[:NAME2] = creditcard.last_name
373
+ end
374
+
375
+ def add_check(post, check)
376
+ post[:PAYMENT_TYPE] = 'ACH'
377
+ post[:PAYMENT_ACCOUNT] = check.account_type + ":" + check.routing_number + ":" + check.account_number
378
+ post[:NAME1] = check.first_name
379
+ post[:NAME2] = check.last_name
380
+ end
381
+
382
+ def add_customer_data(post, options)
383
+ post[:EMAIL] = options[:email] if options.has_key? :email
384
+ post[:CUSTOM_ID] = options[:customer] if options.has_key? :customer
385
+ end
386
+
387
+ def add_duplicate_window(post)
388
+ unless duplicate_window.nil?
389
+ post[:duplicate_window] = duplicate_window
390
+ post[:DUPLICATE_OVERRIDE] = duplicate_window
391
+ end
392
+ end
393
+
394
+ def add_address(post, options)
395
+ if address = options[:billing_address] || options[:address]
396
+ post[:NAME1] = address[:first_name]
397
+ post[:NAME2] = address[:last_name]
398
+ post[:ADDR1] = address[:address1]
399
+ post[:ADDR2] = address[:address2]
400
+ post[:COMPANY_NAME] = address[:company]
401
+ post[:PHONE] = address[:phone]
402
+ post[:CITY] = address[:city]
403
+ post[:STATE] = address[:state].blank? ? 'n/a' : address[:state]
404
+ post[:ZIP] = address[:zip]
405
+ post[:COUNTRY] = address[:country]
406
+ end
407
+ if address = options[:shipping_address]
408
+ post[:NAME1] = address[:first_name]
409
+ post[:NAME2] = address[:last_name]
410
+ post[:ADDR1] = address[:address1]
411
+ post[:ADDR1] = address[:address1]
412
+ post[:COMPANY_NAME] = address[:company]
413
+ post[:PHONE] = address[:phone]
414
+ post[:ZIP] = address[:zip]
415
+ post[:CITY] = address[:city]
416
+ post[:COUNTRY] = address[:country]
417
+ post[:STATE] = address[:state].blank? ? 'n/a' : address[:state]
418
+ end
419
+ end
420
+
421
+ def post_data(action, parameters = {})
422
+ post = {}
423
+ post[:version] = '3.0'
424
+ post[:login] = ''
425
+ post[:tran_key] = ''
426
+ post[:relay_response] = "FALSE"
427
+ post[:type] = action
428
+ post[:delim_data] = "TRUE"
429
+ post[:delim_char] = ","
430
+ post[:encap_char] = "$"
431
+ post[:card_num] = '4111111111111111'
432
+ post[:exp_date] = '1212'
433
+ post[:solution_ID] = application_id if application_id.present? && application_id != "ActiveMerchant"
434
+ request = post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
435
+ request
436
+ end
437
+
438
+ def message_from(results)
439
+ if results[:response_code] == 2
440
+ return CVVResult.messages[ results[:card_code] ] if CARD_CODE_ERRORS.include?(results[:card_code])
441
+ if AVS_REASON_CODES.include?(results[:response_reason_code]) && AVS_ERRORS.include?(results[:avs_result_code])
442
+ return AVSResult.messages[ results[:avs_result_code] ]
443
+ end
444
+ return (results[:response_reason_text] ? results[:response_reason_text].chomp('.') : '')
445
+ end
446
+ if results.has_key?(:response_reason_text)
447
+ return results[:response_reason_text].to_s()
448
+ end
449
+ if !results.has_key?('STATUS')
450
+ return results[RESPONSE_REASON_TEXT] ? results[RESPONSE_REASON_TEXT].chomp('.') : ''
451
+ end
452
+ end
453
+
454
+ def expdate(creditcard)
455
+ year = sprintf("%.4i", creditcard.year)
456
+ month = sprintf("%.2i", creditcard.month)
457
+
458
+ "#{month}#{year[-2..-1]}"
459
+ end
460
+
461
+ def calc_tps(amount, post)
462
+ post[:NAME1] = '' if post[:NAME1].nil?
463
+ digest = Digest::MD5.hexdigest(@options[:password] +
464
+ @options[:login] + post[:TRANS_TYPE] +
465
+ amount.to_s() + post[:MASTER_ID].to_s() +
466
+ post[:NAME1].to_s() + post[:PAYMENT_ACCOUNT].to_s())
467
+ return digest
468
+ end
469
+
470
+
471
+ def calc_rebill_tps(post)
472
+ digest = Digest::MD5.hexdigest(@options[:password] +
473
+ @options[:login] + post[:TRANS_TYPE] + post[:REBILL_ID][0].to_s())
474
+ return digest
475
+ end
476
+
477
+ def handle_response(response)
478
+ if ignore_http_status then
479
+ return response.body
480
+ else
481
+ case response.code.to_i
482
+ when 200...300
483
+ response.body
484
+ else
485
+ raise ResponseError.new(response)
486
+ end
487
+ end
488
+ end
489
+
490
+ end
491
+ end
492
+ end