aktivemerchant 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +1596 -0
  3. data/CONTRIBUTORS +511 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +18 -0
  6. data/lib/active_merchant.rb +108 -0
  7. data/lib/active_merchant/billing.rb +13 -0
  8. data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
  9. data/lib/active_merchant/billing/avs_result.rb +98 -0
  10. data/lib/active_merchant/billing/base.rb +72 -0
  11. data/lib/active_merchant/billing/check.rb +76 -0
  12. data/lib/active_merchant/billing/compatibility.rb +120 -0
  13. data/lib/active_merchant/billing/credit_card.rb +352 -0
  14. data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
  15. data/lib/active_merchant/billing/credit_card_methods.rb +160 -0
  16. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  17. data/lib/active_merchant/billing/gateway.rb +268 -0
  18. data/lib/active_merchant/billing/gateways.rb +17 -0
  19. data/lib/active_merchant/billing/gateways/adyen.rb +209 -0
  20. data/lib/active_merchant/billing/gateways/alfabank.rb +117 -0
  21. data/lib/active_merchant/billing/gateways/app55.rb +176 -0
  22. data/lib/active_merchant/billing/gateways/authorize_net.rb +419 -0
  23. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
  24. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -0
  25. data/lib/active_merchant/billing/gateways/balanced.rb +256 -0
  26. data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
  27. data/lib/active_merchant/billing/gateways/banwire.rb +105 -0
  28. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +314 -0
  29. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +15 -0
  30. data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
  31. data/lib/active_merchant/billing/gateways/beanstream.rb +188 -0
  32. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +393 -0
  33. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  34. data/lib/active_merchant/billing/gateways/blue_pay.rb +506 -0
  35. data/lib/active_merchant/billing/gateways/bogus.rb +140 -0
  36. data/lib/active_merchant/billing/gateways/borgun.rb +210 -0
  37. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  38. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  39. data/lib/active_merchant/billing/gateways/braintree_blue.rb +515 -0
  40. data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
  41. data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
  42. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  43. data/lib/active_merchant/billing/gateways/card_stream.rb +220 -0
  44. data/lib/active_merchant/billing/gateways/cashnet.rb +191 -0
  45. data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
  46. data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
  47. data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
  48. data/lib/active_merchant/billing/gateways/checkout.rb +213 -0
  49. data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
  50. data/lib/active_merchant/billing/gateways/conekta.rb +209 -0
  51. data/lib/active_merchant/billing/gateways/cyber_source.rb +709 -0
  52. data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
  53. data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
  54. data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
  55. data/lib/active_merchant/billing/gateways/epay.rb +275 -0
  56. data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
  57. data/lib/active_merchant/billing/gateways/eway.rb +214 -0
  58. data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
  59. data/lib/active_merchant/billing/gateways/eway_rapid.rb +524 -0
  60. data/lib/active_merchant/billing/gateways/exact.rb +218 -0
  61. data/lib/active_merchant/billing/gateways/fat_zebra.rb +173 -0
  62. data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
  63. data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
  64. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  65. data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
  66. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +355 -0
  67. data/lib/active_merchant/billing/gateways/garanti.rb +257 -0
  68. data/lib/active_merchant/billing/gateways/global_transport.rb +183 -0
  69. data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
  70. data/lib/active_merchant/billing/gateways/hps.rb +288 -0
  71. data/lib/active_merchant/billing/gateways/iats_payments.rb +251 -0
  72. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
  73. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  74. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  75. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
  76. data/lib/active_merchant/billing/gateways/inspire.rb +213 -0
  77. data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
  78. data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
  79. data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
  80. data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
  81. data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
  82. data/lib/active_merchant/billing/gateways/litle.rb +346 -0
  83. data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
  84. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
  85. data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
  86. data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
  87. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
  88. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
  89. data/lib/active_merchant/billing/gateways/mercury.rb +333 -0
  90. data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
  91. data/lib/active_merchant/billing/gateways/migs.rb +265 -0
  92. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  93. data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
  94. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
  95. data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
  96. data/lib/active_merchant/billing/gateways/moneris_us.rb +291 -0
  97. data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
  98. data/lib/active_merchant/billing/gateways/nab_transact.rb +280 -0
  99. data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
  100. data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
  101. data/lib/active_merchant/billing/gateways/netbilling.rb +190 -0
  102. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  103. data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
  104. data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
  105. data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
  106. data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
  107. data/lib/active_merchant/billing/gateways/optimal_payment.rb +313 -0
  108. data/lib/active_merchant/billing/gateways/orbital.rb +803 -0
  109. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
  110. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
  111. data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
  112. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +261 -0
  113. data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
  114. data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
  115. data/lib/active_merchant/billing/gateways/pay_u_latam.rb +462 -0
  116. data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
  117. data/lib/active_merchant/billing/gateways/payex.rb +412 -0
  118. data/lib/active_merchant/billing/gateways/payflow.rb +304 -0
  119. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +209 -0
  120. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  121. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  122. data/lib/active_merchant/billing/gateways/payflow_express.rb +224 -0
  123. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  124. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  125. data/lib/active_merchant/billing/gateways/payment_express.rb +353 -0
  126. data/lib/active_merchant/billing/gateways/paymill.rb +281 -0
  127. data/lib/active_merchant/billing/gateways/paypal.rb +117 -0
  128. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +670 -0
  129. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
  130. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
  131. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  132. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
  133. data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
  134. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  135. data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
  136. data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
  137. data/lib/active_merchant/billing/gateways/payway.rb +207 -0
  138. data/lib/active_merchant/billing/gateways/pin.rb +197 -0
  139. data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
  140. data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
  141. data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
  142. data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
  143. data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
  144. data/lib/active_merchant/billing/gateways/quickpay.rb +367 -0
  145. data/lib/active_merchant/billing/gateways/realex.rb +298 -0
  146. data/lib/active_merchant/billing/gateways/redsys.rb +391 -0
  147. data/lib/active_merchant/billing/gateways/sage.rb +175 -0
  148. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +87 -0
  149. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +114 -0
  150. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
  151. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +102 -0
  152. data/lib/active_merchant/billing/gateways/sage_pay.rb +398 -0
  153. data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
  154. data/lib/active_merchant/billing/gateways/secure_net.rb +252 -0
  155. data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
  156. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
  157. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
  158. data/lib/active_merchant/billing/gateways/skip_jack.rb +452 -0
  159. data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
  160. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  161. data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
  162. data/lib/active_merchant/billing/gateways/stripe.rb +411 -0
  163. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
  164. data/lib/active_merchant/billing/gateways/tns.rb +227 -0
  165. data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
  166. data/lib/active_merchant/billing/gateways/transax.rb +23 -0
  167. data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
  168. data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
  169. data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
  170. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
  171. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +254 -0
  172. data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
  173. data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
  174. data/lib/active_merchant/billing/gateways/vindicia.rb +385 -0
  175. data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
  176. data/lib/active_merchant/billing/gateways/wepay.rb +189 -0
  177. data/lib/active_merchant/billing/gateways/wirecard.rb +421 -0
  178. data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
  179. data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
  180. data/lib/active_merchant/billing/model.rb +30 -0
  181. data/lib/active_merchant/billing/payment_token.rb +21 -0
  182. data/lib/active_merchant/billing/rails.rb +3 -0
  183. data/lib/active_merchant/billing/response.rb +91 -0
  184. data/lib/active_merchant/country.rb +332 -0
  185. data/lib/active_merchant/empty.rb +20 -0
  186. data/lib/active_merchant/errors.rb +29 -0
  187. data/lib/active_merchant/offsite_payments_shim.rb +19 -0
  188. data/lib/active_merchant/version.rb +3 -0
  189. data/lib/activemerchant.rb +1 -0
  190. data/lib/support/gateway_support.rb +71 -0
  191. data/lib/support/outbound_hosts.rb +25 -0
  192. data/lib/support/ssl_verify.rb +93 -0
  193. metadata +400 -0
@@ -0,0 +1,188 @@
1
+ require File.dirname(__FILE__) + '/beanstream/beanstream_core'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ # This class implements the Canadian {Beanstream}[http://www.beanstream.com] payment gateway.
6
+ # It is also named TD Canada Trust Online Mart payment gateway.
7
+ # To learn more about the specification of Beanstream gateway, please read the OM_Direct_Interface_API.pdf,
8
+ # which you can get from your Beanstream account or get from me by email.
9
+ #
10
+ # == Supported transaction types by Beanstream:
11
+ # * +P+ - Purchase
12
+ # * +PA+ - Pre Authorization
13
+ # * +PAC+ - Pre Authorization Completion
14
+ #
15
+ # == Secure Payment Profiles:
16
+ # BeanStream supports payment profiles (vaults). This allows you to store cc information with BeanStream and process subsequent transactions with a customer id.
17
+ # Secure Payment Profiles must be enabled on your account (must be done over the phone).
18
+ # Your API Access Passcode must be set in Administration => account settings => order settings.
19
+ # To learn more about storing credit cards with the Beanstream gateway, documentation can be found at http://developer.beanstream.com/documentation/classic-apis
20
+ #
21
+ # To store a credit card using Beanstream's Legato Javascript Library (http://developer.beanstream.com/documentation/legato) you must pass the singleUseToken in
22
+ # the store method's option parameter. Example: @gateway.store("gt6-0c78c25b-3637-4ba0-90e2-26105287f198")
23
+ #
24
+ # == Notes
25
+ # * Adding of order products information is not implemented.
26
+ # * Ensure that country and province data is provided as a code such as "CA", "US", "QC".
27
+ # * login is the Beanstream merchant ID, username and password should be enabled in your Beanstream account and passed in using the <tt>:user</tt> and <tt>:password</tt> options.
28
+ # * Test your app with your true merchant id and test credit card information provided in the api pdf document.
29
+ # * Beanstream does not allow Payment Profiles to be deleted with their API. The accounts are 'closed', but have to be deleted manually.
30
+ #
31
+ # Example authorization (Beanstream PA transaction type):
32
+ #
33
+ # twenty = 2000
34
+ # gateway = BeanstreamGateway.new(
35
+ # :login => '100200000',
36
+ # :user => 'xiaobozz',
37
+ # :password => 'password'
38
+ # )
39
+ #
40
+ # credit_card = CreditCard.new(
41
+ # :number => '4030000010001234',
42
+ # :month => 8,
43
+ # :year => 2011,
44
+ # :first_name => 'xiaobo',
45
+ # :last_name => 'zzz',
46
+ # :verification_value => 137
47
+ # )
48
+ # response = gateway.authorize(twenty, credit_card,
49
+ # :order_id => '1234',
50
+ # :billing_address => {
51
+ # :name => 'xiaobo zzz',
52
+ # :phone => '555-555-5555',
53
+ # :address1 => '1234 Levesque St.',
54
+ # :address2 => 'Apt B',
55
+ # :city => 'Montreal',
56
+ # :state => 'QC',
57
+ # :country => 'CA',
58
+ # :zip => 'H2C1X8'
59
+ # },
60
+ # :email => 'xiaobozzz@example.com',
61
+ # :subtotal => 800,
62
+ # :shipping => 100,
63
+ # :tax1 => 100,
64
+ # :tax2 => 100,
65
+ # :custom => 'reference one'
66
+ # )
67
+ class BeanstreamGateway < Gateway
68
+ include BeanstreamCore
69
+
70
+ def authorize(money, source, options = {})
71
+ post = {}
72
+ add_amount(post, money)
73
+ add_invoice(post, options)
74
+ add_source(post, source)
75
+ add_address(post, options)
76
+ add_transaction_type(post, :authorization)
77
+ add_customer_ip(post, options)
78
+ commit(post)
79
+ end
80
+
81
+ def purchase(money, source, options = {})
82
+ post = {}
83
+ add_amount(post, money)
84
+ add_invoice(post, options)
85
+ add_source(post, source)
86
+ add_address(post, options)
87
+ add_transaction_type(post, purchase_action(source))
88
+ add_customer_ip(post, options)
89
+ commit(post)
90
+ end
91
+
92
+ def void(authorization, options = {})
93
+ reference, amount, type = split_auth(authorization)
94
+
95
+ post = {}
96
+ add_reference(post, reference)
97
+ add_original_amount(post, amount)
98
+ add_transaction_type(post, void_action(type))
99
+ commit(post)
100
+ end
101
+
102
+ def recurring(money, source, options = {})
103
+ ActiveMerchant.deprecated RECURRING_DEPRECATION_MESSAGE
104
+
105
+ post = {}
106
+ add_amount(post, money)
107
+ add_invoice(post, options)
108
+ add_credit_card(post, source)
109
+ add_address(post, options)
110
+ add_transaction_type(post, purchase_action(source))
111
+ add_recurring_type(post, options)
112
+ commit(post)
113
+ end
114
+
115
+ def update_recurring(amount, source, options = {})
116
+ ActiveMerchant.deprecated RECURRING_DEPRECATION_MESSAGE
117
+
118
+ post = {}
119
+ add_recurring_amount(post, amount)
120
+ add_recurring_invoice(post, options)
121
+ add_credit_card(post, source)
122
+ add_address(post, options)
123
+ add_recurring_operation_type(post, :update)
124
+ add_recurring_service(post, options)
125
+ recurring_commit(post)
126
+ end
127
+
128
+ def cancel_recurring(options = {})
129
+ ActiveMerchant.deprecated RECURRING_DEPRECATION_MESSAGE
130
+
131
+ post = {}
132
+ add_recurring_operation_type(post, :cancel)
133
+ add_recurring_service(post, options)
134
+ recurring_commit(post)
135
+ end
136
+
137
+ def interac
138
+ @interac ||= BeanstreamInteracGateway.new(@options)
139
+ end
140
+
141
+ # To match the other stored-value gateways, like TrustCommerce,
142
+ # store and unstore need to be defined
143
+ def store(payment_method, options = {})
144
+ post = {}
145
+ add_address(post, options)
146
+
147
+ if payment_method.respond_to?(:number)
148
+ add_credit_card(post, payment_method)
149
+ else
150
+ post[:singleUseToken] = payment_method
151
+ end
152
+ add_secure_profile_variables(post, options)
153
+
154
+ commit(post, true)
155
+ end
156
+
157
+ #can't actually delete a secure profile with the supplicated API. This function sets the status of the profile to closed (C).
158
+ #Closed profiles will have to removed manually.
159
+ def delete(vault_id)
160
+ update(vault_id, false, {:status => "C"})
161
+ end
162
+
163
+ alias_method :unstore, :delete
164
+
165
+ # Update the values (such as CC expiration) stored at
166
+ # the gateway. The CC number must be supplied in the
167
+ # CreditCard object.
168
+ def update(vault_id, payment_method, options = {})
169
+ post = {}
170
+ add_address(post, options)
171
+ if payment_method.respond_to?(:number)
172
+ add_credit_card(post, payment_method)
173
+ else
174
+ post[:singleUseToken] = payment_method
175
+ end
176
+ options.merge!({:vault_id => vault_id, :operation => secure_profile_action(:modify)})
177
+ add_secure_profile_variables(post,options)
178
+ commit(post, true)
179
+ end
180
+
181
+ private
182
+ def build_response(*args)
183
+ Response.new(*args)
184
+ end
185
+ end
186
+ end
187
+ end
188
+
@@ -0,0 +1,393 @@
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', 'US']
67
+
68
+ # The card types supported by the payment gateway
69
+ base.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
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
+ super
87
+ end
88
+
89
+ def capture(money, authorization, options = {})
90
+ reference, _, _ = split_auth(authorization)
91
+
92
+ post = {}
93
+ add_amount(post, money)
94
+ add_reference(post, reference)
95
+ add_transaction_type(post, :capture)
96
+ commit(post)
97
+ end
98
+
99
+ def refund(money, source, options = {})
100
+ post = {}
101
+ reference, _, type = split_auth(source)
102
+ add_reference(post, reference)
103
+ add_transaction_type(post, refund_action(type))
104
+ add_amount(post, money)
105
+ commit(post)
106
+ end
107
+
108
+ def credit(money, source, options = {})
109
+ ActiveMerchant.deprecated Gateway::CREDIT_DEPRECATION_MESSAGE
110
+ refund(money, source, options)
111
+ end
112
+
113
+ private
114
+ def purchase_action(source)
115
+ if source.is_a?(Check)
116
+ :check_purchase
117
+ else
118
+ :purchase
119
+ end
120
+ end
121
+
122
+ def add_customer_ip(post, options)
123
+ post[:customerIP] = options[:ip] if options[:ip]
124
+ end
125
+
126
+ def void_action(original_transaction_type)
127
+ (original_transaction_type == TRANSACTIONS[:refund]) ? :void_refund : :void_purchase
128
+ end
129
+
130
+ def refund_action(type)
131
+ (type == TRANSACTIONS[:check_purchase]) ? :check_refund : :refund
132
+ end
133
+
134
+ def secure_profile_action(type)
135
+ PROFILE_OPERATIONS[type] || PROFILE_OPERATIONS[:new]
136
+ end
137
+
138
+ def split_auth(string)
139
+ string.split(";")
140
+ end
141
+
142
+ def add_amount(post, money)
143
+ post[:trnAmount] = amount(money)
144
+ end
145
+
146
+ def add_original_amount(post, amount)
147
+ post[:trnAmount] = amount
148
+ end
149
+
150
+ def add_reference(post, reference)
151
+ post[:adjId] = reference
152
+ end
153
+
154
+ def add_address(post, options)
155
+ prepare_address_for_non_american_countries(options)
156
+
157
+ if billing_address = options[:billing_address] || options[:address]
158
+ post[:ordName] = billing_address[:name]
159
+ post[:ordEmailAddress] = options[:email]
160
+ post[:ordPhoneNumber] = billing_address[:phone]
161
+ post[:ordAddress1] = billing_address[:address1]
162
+ post[:ordAddress2] = billing_address[:address2]
163
+ post[:ordCity] = billing_address[:city]
164
+ post[:ordProvince] = billing_address[:state]
165
+ post[:ordPostalCode] = billing_address[:zip]
166
+ post[:ordCountry] = billing_address[:country]
167
+ end
168
+ if shipping_address = options[:shipping_address]
169
+ post[:shipName] = shipping_address[:name]
170
+ post[:shipEmailAddress] = options[:email]
171
+ post[:shipPhoneNumber] = shipping_address[:phone]
172
+ post[:shipAddress1] = shipping_address[:address1]
173
+ post[:shipAddress2] = shipping_address[:address2]
174
+ post[:shipCity] = shipping_address[:city]
175
+ post[:shipProvince] = shipping_address[:state]
176
+ post[:shipPostalCode] = shipping_address[:zip]
177
+ post[:shipCountry] = shipping_address[:country]
178
+ post[:shippingMethod] = shipping_address[:shipping_method]
179
+ post[:deliveryEstimate] = shipping_address[:delivery_estimate]
180
+ end
181
+ end
182
+
183
+ def prepare_address_for_non_american_countries(options)
184
+ [ options[:billing_address], options[:shipping_address] ].compact.each do |address|
185
+ unless ['US', 'CA'].include?(address[:country])
186
+ address[:state] = '--'
187
+ address[:zip] = '000000' unless address[:zip]
188
+ end
189
+ end
190
+ end
191
+
192
+ def add_invoice(post, options)
193
+ post[:trnOrderNumber] = options[:order_id]
194
+ post[:trnComments] = options[:description]
195
+ post[:ordItemPrice] = amount(options[:subtotal])
196
+ post[:ordShippingPrice] = amount(options[:shipping])
197
+ post[:ordTax1Price] = amount(options[:tax1] || options[:tax])
198
+ post[:ordTax2Price] = amount(options[:tax2])
199
+ post[:ref1] = options[:custom]
200
+ end
201
+
202
+ def add_credit_card(post, credit_card)
203
+ if credit_card
204
+ post[:trnCardOwner] = credit_card.name
205
+ post[:trnCardNumber] = credit_card.number
206
+ post[:trnExpMonth] = format(credit_card.month, :two_digits)
207
+ post[:trnExpYear] = format(credit_card.year, :two_digits)
208
+ post[:trnCardCvd] = credit_card.verification_value
209
+ end
210
+ end
211
+
212
+ def add_check(post, check)
213
+ # The institution number of the consumer’s financial institution. Required for Canadian dollar EFT transactions.
214
+ post[:institutionNumber] = check.institution_number
215
+
216
+ # The bank transit number of the consumer’s bank account. Required for Canadian dollar EFT transactions.
217
+ post[:transitNumber] = check.transit_number
218
+
219
+ # The routing number of the consumer’s bank account. Required for US dollar EFT transactions.
220
+ post[:routingNumber] = check.routing_number
221
+
222
+ # The account number of the consumer’s bank account. Required for both Canadian and US dollar EFT transactions.
223
+ post[:accountNumber] = check.account_number
224
+ end
225
+
226
+ def add_secure_profile_variables(post, options = {})
227
+ post[:serviceVersion] = SP_SERVICE_VERSION
228
+ post[:responseFormat] = 'QS'
229
+ post[:cardValidation] = (options[:cardValidation].to_i == 1) || '0'
230
+
231
+ post[:operationType] = options[:operationType] || options[:operation] || secure_profile_action(:new)
232
+ post[:customerCode] = options[:billing_id] || options[:vault_id] || false
233
+ post[:status] = options[:status]
234
+ end
235
+
236
+ def add_recurring_amount(post, money)
237
+ post[:amount] = amount(money)
238
+ end
239
+
240
+ def add_recurring_invoice(post, options)
241
+ post[:rbApplyTax1] = options[:apply_tax1]
242
+ post[:rbApplyTax2] = options[:apply_tax2]
243
+ end
244
+
245
+ def add_recurring_operation_type(post, operation)
246
+ post[:operationType] = RECURRING_OPERATION[operation]
247
+ end
248
+
249
+ def add_recurring_service(post, options)
250
+ post[:serviceVersion] = '1.0'
251
+ post[:merchantId] = @options[:login]
252
+ post[:passCode] = @options[:recurring_api_key]
253
+ post[:rbAccountId] = options[:account_id]
254
+ end
255
+
256
+ def add_recurring_type(post, options)
257
+ # XXX requires!
258
+ post[:trnRecurring] = 1
259
+ period, increment = interval(options)
260
+ post[:rbBillingPeriod] = PERIODS[period]
261
+ post[:rbBillingIncrement] = increment
262
+
263
+ if options.include? :start_date
264
+ post[:rbCharge] = 0
265
+ post[:rbFirstBilling] = options[:start_date].strftime('%m%d%Y')
266
+ end
267
+
268
+ if count = options[:occurrences] || options[:payments]
269
+ post[:rbExpiry] = (options[:start_date] || Date.current).advance(period => count).strftime('%m%d%Y')
270
+ end
271
+ end
272
+
273
+ def interval(options)
274
+ if options.include? :periodicity
275
+ requires!(options, [:periodicity, *PERIODICITIES.keys])
276
+ PERIODICITIES[options[:periodicity]]
277
+ elsif options.include? :interval
278
+ interval = options[:interval]
279
+ if interval.respond_to? :parts
280
+ parts = interval.parts
281
+ raise ArgumentError.new("Cannot recur with mixed interval (#{interval}). Use only one of: days, weeks, months or years") if parts.length > 1
282
+ parts.first
283
+ elsif interval.kind_of? Hash
284
+ requires!(interval, :unit)
285
+ unit, length = interval.values_at(:unit, :length)
286
+ length ||= 1
287
+ [unit, length]
288
+ end
289
+ end
290
+ end
291
+
292
+ def parse(body)
293
+ results = {}
294
+ if !body.nil?
295
+ body.split(/&/).each do |pair|
296
+ key, val = pair.split(/\=/)
297
+ results[key.to_sym] = val.nil? ? nil : CGI.unescape(val)
298
+ end
299
+ end
300
+
301
+ # Clean up the message text if there is any
302
+ if results[:messageText]
303
+ results[:messageText].gsub!(/<LI>/, "")
304
+ results[:messageText].gsub!(/(\.)?<br>/, ". ")
305
+ results[:messageText].strip!
306
+ end
307
+
308
+ results
309
+ end
310
+
311
+ def recurring_parse(data)
312
+ REXML::Document.new(data).root.elements.to_a.inject({}) do |response, element|
313
+ response[element.name.to_sym] = element.text
314
+ response
315
+ end
316
+ end
317
+
318
+ def commit(params, use_profile_api = false)
319
+ post(post_data(params,use_profile_api),use_profile_api)
320
+ end
321
+
322
+ def recurring_commit(params)
323
+ recurring_post(post_data(params, false))
324
+ end
325
+
326
+ def post(data, use_profile_api=nil)
327
+ response = parse(ssl_post((use_profile_api ? SECURE_PROFILE_URL : self.live_url), data))
328
+ response[:customer_vault_id] = response[:customerCode] if response[:customerCode]
329
+ build_response(success?(response), message_from(response), response,
330
+ :test => test? || response[:authCode] == "TEST",
331
+ :authorization => authorization_from(response),
332
+ :cvv_result => CVD_CODES[response[:cvdId]],
333
+ :avs_result => { :code => (AVS_CODES.include? response[:avsId]) ? AVS_CODES[response[:avsId]] : response[:avsId] }
334
+ )
335
+ end
336
+
337
+ def recurring_post(data)
338
+ response = recurring_parse(ssl_post(RECURRING_URL, data))
339
+ build_response(recurring_success?(response), recurring_message_from(response), response)
340
+ end
341
+
342
+ def authorization_from(response)
343
+ "#{response[:trnId]};#{response[:trnAmount]};#{response[:trnType]}"
344
+ end
345
+
346
+ def message_from(response)
347
+ response[:messageText] || response[:responseMessage]
348
+ end
349
+
350
+ def recurring_message_from(response)
351
+ response[:message]
352
+ end
353
+
354
+ def success?(response)
355
+ response[:responseType] == 'R' || response[:trnApproved] == '1' || response[:responseCode] == '1'
356
+ end
357
+
358
+ def recurring_success?(response)
359
+ response[:code] == '1'
360
+ end
361
+
362
+ def add_source(post, source)
363
+ if source.is_a?(String) or source.is_a?(Integer)
364
+ post[:customerCode] = source
365
+ else
366
+ card_brand(source) == "check" ? add_check(post, source) : add_credit_card(post, source)
367
+ end
368
+ end
369
+
370
+ def add_transaction_type(post, action)
371
+ post[:trnType] = TRANSACTIONS[action]
372
+ end
373
+
374
+ def post_data(params, use_profile_api)
375
+ params[:requestType] = 'BACKEND'
376
+ if use_profile_api
377
+ params[:merchantId] = @options[:login]
378
+ params[:passCode] = @options[:secure_profile_api_key]
379
+ else
380
+ params[:username] = @options[:user] if @options[:user]
381
+ params[:password] = @options[:password] if @options[:password]
382
+ params[:merchant_id] = @options[:login]
383
+ end
384
+ params[:vbvEnabled] = '0'
385
+ params[:scEnabled] = '0'
386
+
387
+ params.reject{|k, v| v.blank?}.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
388
+ end
389
+
390
+ end
391
+ end
392
+ end
393
+