tlconnor-activemerchant 1.20.4

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 (195) hide show
  1. data/CHANGELOG +805 -0
  2. data/CONTRIBUTORS +274 -0
  3. data/MIT-LICENSE +20 -0
  4. data/gem-public_cert.pem +20 -0
  5. data/lib/active_merchant.rb +63 -0
  6. data/lib/active_merchant/billing.rb +9 -0
  7. data/lib/active_merchant/billing/avs_result.rb +98 -0
  8. data/lib/active_merchant/billing/base.rb +57 -0
  9. data/lib/active_merchant/billing/check.rb +68 -0
  10. data/lib/active_merchant/billing/credit_card.rb +264 -0
  11. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  12. data/lib/active_merchant/billing/credit_card_methods.rb +129 -0
  13. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  14. data/lib/active_merchant/billing/expiry_date.rb +34 -0
  15. data/lib/active_merchant/billing/gateway.rb +170 -0
  16. data/lib/active_merchant/billing/gateways.rb +18 -0
  17. data/lib/active_merchant/billing/gateways/authorize_net.rb +694 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +944 -0
  19. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
  20. data/lib/active_merchant/billing/gateways/beanstream.rb +167 -0
  21. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +388 -0
  22. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  23. data/lib/active_merchant/billing/gateways/blue_pay.rb +11 -0
  24. data/lib/active_merchant/billing/gateways/bogus.rb +142 -0
  25. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  26. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  27. data/lib/active_merchant/billing/gateways/braintree_blue.rb +308 -0
  28. data/lib/active_merchant/billing/gateways/braintree_orange.rb +21 -0
  29. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  30. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
  31. data/lib/active_merchant/billing/gateways/certo_direct.rb +279 -0
  32. data/lib/active_merchant/billing/gateways/cyber_source.rb +430 -0
  33. data/lib/active_merchant/billing/gateways/data_cash.rb +597 -0
  34. data/lib/active_merchant/billing/gateways/efsnet.rb +235 -0
  35. data/lib/active_merchant/billing/gateways/elavon.rb +135 -0
  36. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  37. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/eway_managed.rb +265 -0
  39. data/lib/active_merchant/billing/gateways/exact.rb +227 -0
  40. data/lib/active_merchant/billing/gateways/federated_canada.rb +168 -0
  41. data/lib/active_merchant/billing/gateways/first_pay.rb +177 -0
  42. data/lib/active_merchant/billing/gateways/garanti.rb +262 -0
  43. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +250 -0
  44. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  45. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  46. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +55 -0
  47. data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
  48. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  49. data/lib/active_merchant/billing/gateways/iridium.rb +258 -0
  50. data/lib/active_merchant/billing/gateways/jetpay.rb +276 -0
  51. data/lib/active_merchant/billing/gateways/linkpoint.rb +454 -0
  52. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +157 -0
  53. data/lib/active_merchant/billing/gateways/merchant_ware.rb +289 -0
  54. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  55. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
  56. data/lib/active_merchant/billing/gateways/moneris.rb +239 -0
  57. data/lib/active_merchant/billing/gateways/nab_transact.rb +244 -0
  58. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  59. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  60. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  61. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  62. data/lib/active_merchant/billing/gateways/ogone.rb +330 -0
  63. data/lib/active_merchant/billing/gateways/optimal_payment.rb +277 -0
  64. data/lib/active_merchant/billing/gateways/orbital.rb +344 -0
  65. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -0
  66. data/lib/active_merchant/billing/gateways/pay_junction.rb +397 -0
  67. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  68. data/lib/active_merchant/billing/gateways/paybox_direct.rb +207 -0
  69. data/lib/active_merchant/billing/gateways/payflow.rb +261 -0
  70. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +208 -0
  71. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  72. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  73. data/lib/active_merchant/billing/gateways/payflow_express.rb +222 -0
  74. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  75. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  76. data/lib/active_merchant/billing/gateways/payment_express.rb +235 -0
  77. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  78. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +354 -0
  79. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
  80. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  81. data/lib/active_merchant/billing/gateways/paypal_express.rb +229 -0
  82. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
  83. data/lib/active_merchant/billing/gateways/paystation.rb +201 -0
  84. data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
  85. data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
  86. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  87. data/lib/active_merchant/billing/gateways/qbms.rb +297 -0
  88. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  89. data/lib/active_merchant/billing/gateways/quickpay.rb +298 -0
  90. data/lib/active_merchant/billing/gateways/realex.rb +315 -0
  91. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  92. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  93. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  94. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  95. data/lib/active_merchant/billing/gateways/sage_pay.rb +320 -0
  96. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  97. data/lib/active_merchant/billing/gateways/samurai.rb +121 -0
  98. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  99. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  100. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +280 -0
  101. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  102. data/lib/active_merchant/billing/gateways/skip_jack.rb +458 -0
  103. data/lib/active_merchant/billing/gateways/smart_ps.rb +271 -0
  104. data/lib/active_merchant/billing/gateways/stripe.rb +244 -0
  105. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  106. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  107. data/lib/active_merchant/billing/gateways/trust_commerce.rb +423 -0
  108. data/lib/active_merchant/billing/gateways/usa_epay.rb +23 -0
  109. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1496 -0
  110. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +206 -0
  111. data/lib/active_merchant/billing/gateways/verifi.rb +233 -0
  112. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  113. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  114. data/lib/active_merchant/billing/gateways/worldpay.rb +280 -0
  115. data/lib/active_merchant/billing/integrations.rb +17 -0
  116. data/lib/active_merchant/billing/integrations/action_view_helper.rb +72 -0
  117. data/lib/active_merchant/billing/integrations/authorize_net_sim.rb +38 -0
  118. data/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb +228 -0
  119. data/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb +340 -0
  120. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  121. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  122. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  123. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  124. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  125. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  126. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  127. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  128. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  129. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  130. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  131. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  132. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  133. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  134. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  135. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  136. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  137. data/lib/active_merchant/billing/integrations/dwolla.rb +30 -0
  138. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +31 -0
  139. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +55 -0
  140. data/lib/active_merchant/billing/integrations/dwolla/return.rb +38 -0
  141. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  142. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  143. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  144. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  145. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  146. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  147. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  148. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  149. data/lib/active_merchant/billing/integrations/helper.rb +113 -0
  150. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  151. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  152. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  153. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  154. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  155. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  156. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  157. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  158. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  159. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  160. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  161. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  162. data/lib/active_merchant/billing/integrations/payflow_link.rb +21 -0
  163. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +100 -0
  164. data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +78 -0
  165. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  166. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  167. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  168. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  169. data/lib/active_merchant/billing/integrations/quickpay.rb +21 -0
  170. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  171. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  172. data/lib/active_merchant/billing/integrations/return.rb +42 -0
  173. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  174. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  175. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +127 -0
  176. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  177. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  178. data/lib/active_merchant/billing/integrations/two_checkout.rb +22 -0
  179. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  180. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  181. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  182. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  183. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  184. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  185. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
  186. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  187. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  188. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  189. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  190. data/lib/active_merchant/billing/response.rb +32 -0
  191. data/lib/active_merchant/version.rb +3 -0
  192. data/lib/activemerchant.rb +1 -0
  193. data/lib/support/gateway_support.rb +58 -0
  194. data/lib/support/outbound_hosts.rb +25 -0
  195. metadata +411 -0
@@ -0,0 +1,271 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'check.rb')
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class SmartPs < Gateway #:nodoc:
6
+
7
+ ##
8
+ # This is the base gateway for processors who use the smartPS processing system
9
+
10
+ def initialize(options = {})
11
+ requires!(options, :login, :password)
12
+ @options = options
13
+ super
14
+ end
15
+
16
+ # Pass :store => true in the options to store the
17
+ # payment info at the gateway and get a generated
18
+ # customer_vault_id in the response.
19
+ # Pass :store => some_number_or_string to specify the
20
+ # customer_vault_id the gateway should use (make sure it's
21
+ # unique).
22
+ def authorize(money, creditcard, options = {})
23
+ post = {}
24
+ add_invoice(post, options)
25
+ add_payment_source(post, creditcard,options)
26
+ add_address(post, options[:billing_address] || options[:address])
27
+ add_address(post, options[:shipping_address], "shipping")
28
+ add_customer_data(post, options)
29
+ add_currency(post, money, options)
30
+ add_taxes(post, options)
31
+ add_processor(post, options)
32
+ commit('auth', money, post)
33
+ end
34
+
35
+ def purchase(money, payment_source, options = {})
36
+ post = {}
37
+ add_invoice(post, options)
38
+ add_payment_source(post, payment_source, options)
39
+ add_address(post, options[:billing_address] || options[:address])
40
+ add_address(post, options[:shipping_address], "shipping")
41
+ add_customer_data(post, options)
42
+ add_currency(post, money, options)
43
+ add_taxes(post, options)
44
+ add_processor(post, options)
45
+ commit('sale', money, post)
46
+ end
47
+
48
+ def capture(money, authorization, options = {})
49
+ post ={}
50
+ post[:transactionid] = authorization
51
+ commit('capture', money, post)
52
+ end
53
+
54
+ def void(authorization, options = {})
55
+ post ={}
56
+ post[:transactionid] = authorization
57
+ commit('void', nil, post)
58
+ end
59
+
60
+ def credit(money, payment_source, options = {})
61
+ post = {}
62
+ add_invoice(post, options)
63
+ add_payment_source(post, payment_source, options)
64
+ add_address(post, options[:billing_address] || options[:address])
65
+ add_customer_data(post, options)
66
+ add_sku(post,options)
67
+ add_currency(post, money, options)
68
+ add_processor(post, options)
69
+ commit('credit', money, post)
70
+ end
71
+
72
+ def refund(money, auth, options = {})
73
+ post = {}
74
+ add_transaction(post, auth)
75
+ commit('refund', money, post)
76
+ end
77
+
78
+
79
+ # Update the values (such as CC expiration) stored at
80
+ # the gateway. The CC number must be supplied in the
81
+ # CreditCard object.
82
+ def update(vault_id, creditcard, options = {})
83
+ post = {}
84
+ post[:customer_vault] = "update_customer"
85
+ add_customer_vault_id(post, vault_id)
86
+ add_creditcard(post, creditcard, options)
87
+ add_address(post, options[:billing_address] || options[:address])
88
+ add_customer_data(post, options)
89
+
90
+ commit(nil, nil, post)
91
+ end
92
+
93
+ # Amend an existing transaction
94
+ def amend(auth, options = {})
95
+ post = {}
96
+ add_invoice(post, options)
97
+ add_transaction(post, auth)
98
+ commit('update', nil, post)
99
+ end
100
+
101
+
102
+ def delete(vault_id)
103
+ post = {}
104
+ post[:customer_vault] = "delete_customer"
105
+ add_customer_vault_id(post, vault_id)
106
+ commit(nil, nil, post)
107
+ end
108
+
109
+ # To match the other stored-value gateways, like TrustCommerce,
110
+ # store and unstore need to be defined
111
+ def store(payment_source, options = {})
112
+ post = {}
113
+ billing_id = options.delete(:billing_id).to_s || true
114
+ add_payment_source(post, payment_source, :store => billing_id)
115
+ add_address(post, options[:billing_address] || options[:address])
116
+ add_customer_data(post, options)
117
+ commit(nil, nil, post)
118
+ end
119
+
120
+ alias_method :unstore, :delete
121
+
122
+ private
123
+ def add_customer_data(post, options)
124
+ if options.has_key? :email
125
+ post[:email] = options[:email]
126
+ end
127
+
128
+ if options.has_key? :ip
129
+ post[:ipaddress] = options[:ip]
130
+ end
131
+ end
132
+
133
+ def add_address(post, address,prefix="")
134
+ prefix +="_" unless prefix.blank?
135
+ unless address.blank? or address.values.blank?
136
+ post[prefix+"address1"] = address[:address1].to_s
137
+ post[prefix+"address2"] = address[:address2].to_s unless address[:address2].blank?
138
+ post[prefix+"company"] = address[:company].to_s
139
+ post[prefix+"phone"] = address[:phone].to_s
140
+ post[prefix+"zip"] = address[:zip].to_s
141
+ post[prefix+"city"] = address[:city].to_s
142
+ post[prefix+"country"] = address[:country].to_s
143
+ post[prefix+"state"] = address[:state].blank? ? 'n/a' : address[:state]
144
+ end
145
+ end
146
+
147
+ def add_currency(post, money, options)
148
+ post[:currency] = options[:currency] || currency(money)
149
+ end
150
+
151
+ def add_taxes(post, options)
152
+ post[:tax] = amount(options[:tax])
153
+ end
154
+
155
+ def add_processor(post, options)
156
+ post[:processor] = options[:processor] unless options[:processor].nil?
157
+ end
158
+
159
+ def add_invoice(post, options)
160
+ post[:orderid] = options[:order_id].to_s.gsub(/[^\w.]/, '')
161
+ end
162
+
163
+ def add_payment_source(params, source, options={})
164
+ case determine_funding_source(source)
165
+ when :vault then add_customer_vault_id(params, source)
166
+ when :credit_card then add_creditcard(params, source, options)
167
+ when :check then add_check(params, source, options)
168
+ end
169
+ end
170
+
171
+ def add_customer_vault_id(params, vault_id)
172
+ params[:customer_vault_id] = vault_id
173
+ end
174
+
175
+ def add_creditcard(post, creditcard, options)
176
+ if options[:store]
177
+ post[:customer_vault] = "add_customer"
178
+ post[:customer_vault_id] = options[:store] unless options[:store] == true
179
+ end
180
+ post[:ccnumber] = creditcard.number
181
+ post[:cvv] = creditcard.verification_value if creditcard.verification_value?
182
+ post[:ccexp] = expdate(creditcard)
183
+ post[:firstname] = creditcard.first_name
184
+ post[:lastname] = creditcard.last_name
185
+ end
186
+
187
+ def add_check(post, check, options)
188
+ if options[:store]
189
+ post[:customer_vault] = "add_customer"
190
+ post[:customer_vault_id] = options[:store] unless options[:store] == true
191
+ end
192
+
193
+ post[:payment] = 'check' # Set transaction to ACH
194
+ post[:checkname] = check.name # The name on the customer's Checking Account
195
+ post[:checkaba] = check.routing_number # The customer's bank routing number
196
+ post[:checkaccount] = check.account_number # The customer's account number
197
+ post[:account_holder_type] = check.account_holder_type # The customer's type of ACH account
198
+ post[:account_type] = check.account_type # The customer's type of ACH account
199
+ end
200
+
201
+ def add_sku(post,options)
202
+ post["product_sku_#"] = options[:sku] || options["product_sku_#"]
203
+ end
204
+
205
+ def add_transaction(post, auth)
206
+ post[:transactionid] = auth
207
+ end
208
+
209
+ def parse(body)
210
+ results = {}
211
+ body.split(/&/).each do |pair|
212
+ key,val = pair.split(/=/)
213
+ results[key] = val
214
+ end
215
+
216
+ results
217
+ end
218
+
219
+ def commit(action, money, parameters)
220
+ parameters[:amount] = amount(money) if money
221
+ response = parse( ssl_post(api_url, post_data(action,parameters)) )
222
+ Response.new(response["response"] == "1", message_from(response), response,
223
+ :authorization => response["transactionid"],
224
+ :test => test?,
225
+ :cvv_result => response["cvvresponse"],
226
+ :avs_result => { :code => response["avsresponse"] }
227
+ )
228
+
229
+ end
230
+
231
+ def expdate(creditcard)
232
+ year = sprintf("%.04i", creditcard.year.to_i)
233
+ month = sprintf("%.02i", creditcard.month.to_i)
234
+
235
+ "#{month}#{year[-2..-1]}"
236
+ end
237
+
238
+
239
+ def message_from(response)
240
+ case response["responsetext"]
241
+ when "SUCCESS", "Approved", nil # This is dubious, but responses from UPDATE are nil.
242
+ "This transaction has been approved"
243
+ when "DECLINE"
244
+ "This transaction has been declined"
245
+ else
246
+ response["responsetext"]
247
+ end
248
+ end
249
+
250
+ def post_data(action, parameters = {})
251
+ post = {}
252
+ post[:username] = @options[:login]
253
+ post[:password] = @options[:password]
254
+ post[:type] = action if action
255
+
256
+ request = post.merge(parameters).map {|key,value| "#{key}=#{CGI.escape(value.to_s)}"}.join("&")
257
+ request
258
+ end
259
+
260
+ def determine_funding_source(source)
261
+ case
262
+ when source.is_a?(String) then :vault
263
+ when CreditCard.card_companies.keys.include?(card_brand(source)) then :credit_card
264
+ when card_brand(source) == 'check' then :check
265
+ else raise ArgumentError, "Unsupported funding source provided"
266
+ end
267
+ end
268
+ end
269
+ end
270
+ end
271
+
@@ -0,0 +1,244 @@
1
+ require 'json'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class StripeGateway < Gateway
6
+ LIVE_URL = 'https://api.stripe.com/v1/'
7
+
8
+ AVS_CODE_TRANSLATOR = {
9
+ 'line1: pass, zip: pass' => 'Y',
10
+ 'line1: pass, zip: fail' => 'A',
11
+ 'line1: pass, zip: unchecked' => 'B',
12
+ 'line1: fail, zip: pass' => 'Z',
13
+ 'line1: fail, zip: fail' => 'N',
14
+ 'line1: unchecked, zip: pass' => 'P',
15
+ 'line1: unchecked, zip: unchecked' => 'I'
16
+ }
17
+
18
+ CVC_CODE_TRANSLATOR = {
19
+ 'pass' => 'M',
20
+ 'fail' => 'N',
21
+ 'unchecked' => 'P'
22
+ }
23
+
24
+ self.supported_countries = ['US']
25
+ self.default_currency = 'USD'
26
+ self.money_format = :cents
27
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
28
+
29
+ self.homepage_url = 'https://stripe.com/'
30
+ self.display_name = 'Stripe'
31
+
32
+ def initialize(options = {})
33
+ requires!(options, :login)
34
+ @api_key = options[:login]
35
+ super
36
+ end
37
+
38
+ # To create a charge on a card or a token, call
39
+ #
40
+ # purchase(money, card_hash_or_token, { ... })
41
+ #
42
+ # To create a charge on a customer, call
43
+ #
44
+ # purchase(money, nil, { :customer => id, ... })
45
+ def purchase(money, creditcard, options = {})
46
+ post = {}
47
+
48
+ add_amount(post, money, options)
49
+ add_creditcard(post, creditcard, options)
50
+ add_customer(post, options)
51
+ post[:description] = options[:description] || options[:email]
52
+ add_flags(post, options)
53
+
54
+ meta = generate_meta(options)
55
+
56
+ raise ArgumentError.new("Customer or Credit Card required.") if !post[:card] && !post[:customer]
57
+
58
+ commit(:post, 'charges', post, meta)
59
+ end
60
+
61
+ def authorize(money, creditcard, options = {})
62
+ raise "Stripe does not support separate authorization and capture"
63
+ end
64
+
65
+ def capture(money, identification, options = {})
66
+ raise "Stripe does not support separate authorization and capture"
67
+ end
68
+
69
+ def void(identification, options = {})
70
+ commit(:post, "charges/#{CGI.escape(identification)}/refund", {})
71
+ end
72
+
73
+ def refund(money, identification, options = {})
74
+ meta = generate_meta(options)
75
+ post = {}
76
+
77
+ post[:amount] = amount(money) if money
78
+
79
+ commit(:post, "charges/#{CGI.escape(identification)}/refund", post, meta)
80
+ end
81
+
82
+ def store(creditcard, options = {})
83
+ post = {}
84
+ add_creditcard(post, creditcard, options)
85
+ post[:description] = options[:description]
86
+ post[:email] = options[:email]
87
+
88
+ meta = generate_meta(options)
89
+ path = if options[:customer]
90
+ "customers/#{CGI.escape(options[:customer])}"
91
+ else
92
+ 'customers'
93
+ end
94
+
95
+ commit(:post, path, post, meta)
96
+ end
97
+
98
+ def update(customer_id, creditcard, options = {})
99
+ options = options.merge(:customer => customer_id)
100
+ store(creditcard, options)
101
+ end
102
+
103
+ def unstore(customer_id, options = {})
104
+ meta = generate_meta(options)
105
+ commit(:delete, "customers/#{CGI.escape(customer_id)}", nil, meta)
106
+ end
107
+
108
+ private
109
+
110
+ def add_amount(post, money, options)
111
+ post[:amount] = amount(money)
112
+ post[:currency] = (options[:currency] || currency(money)).downcase
113
+ end
114
+
115
+ def add_customer_data(post, options)
116
+ post[:description] = options[:description]
117
+ post[:email] = options[:email]
118
+ end
119
+
120
+ def add_address(post, options)
121
+ return unless post[:card] && post[:card].kind_of?(Hash)
122
+ if address = options[:billing_address] || options[:address]
123
+ post[:card][:address_line1] = address[:address1] if address[:address1]
124
+ post[:card][:address_line2] = address[:address2] if address[:address2]
125
+ post[:card][:address_country] = address[:country] if address[:country]
126
+ post[:card][:address_zip] = address[:zip] if address[:zip]
127
+ post[:card][:address_state] = address[:state] if address[:state]
128
+ end
129
+ end
130
+
131
+ def add_creditcard(post, creditcard, options)
132
+ if creditcard.respond_to?(:number)
133
+ card = {}
134
+ card[:number] = creditcard.number
135
+ card[:exp_month] = creditcard.month
136
+ card[:exp_year] = creditcard.year
137
+ card[:cvc] = creditcard.verification_value if creditcard.verification_value?
138
+ card[:name] = creditcard.name if creditcard.name
139
+ post[:card] = card
140
+
141
+ add_address(post, options)
142
+ elsif creditcard.kind_of?(String)
143
+ post[:card] = creditcard
144
+ end
145
+ end
146
+
147
+ def add_customer(post, options)
148
+ post[:customer] = options[:customer] if options[:customer] && !post[:card]
149
+ end
150
+
151
+ def add_flags(post, options)
152
+ post[:uncaptured] = true if options[:uncaptured]
153
+ end
154
+
155
+ def parse(body)
156
+ JSON.parse(body)
157
+ end
158
+
159
+ def post_data(params)
160
+ return nil unless params
161
+
162
+ params.map do |key, value|
163
+ next if value.blank?
164
+ if value.is_a?(Hash)
165
+ h = {}
166
+ value.each do |k, v|
167
+ h["#{key}[#{k}]"] = v unless v.blank?
168
+ end
169
+ post_data(h)
170
+ else
171
+ "#{key}=#{CGI.escape(value.to_s)}"
172
+ end
173
+ end.compact.join("&")
174
+ end
175
+
176
+ def generate_meta(options)
177
+ {:ip => options[:ip]}
178
+ end
179
+
180
+ def headers(meta={})
181
+ @@ua ||= JSON.dump({
182
+ :bindings_version => ActiveMerchant::VERSION,
183
+ :lang => 'ruby',
184
+ :lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
185
+ :platform => RUBY_PLATFORM,
186
+ :publisher => 'active_merchant',
187
+ :uname => (RUBY_PLATFORM =~ /linux|darwin/i ? `uname -a 2>/dev/null`.strip : nil)
188
+ })
189
+
190
+ {
191
+ "Authorization" => "Basic " + Base64.encode64(@api_key.to_s + ":").strip,
192
+ "User-Agent" => "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
193
+ "X-Stripe-Client-User-Agent" => @@ua,
194
+ "X-Stripe-Client-User-Metadata" => meta.to_json
195
+ }
196
+ end
197
+
198
+ def commit(method, url, parameters=nil, meta={})
199
+ raw_response = response = nil
200
+ success = false
201
+ begin
202
+ raw_response = ssl_request(method, LIVE_URL + url, post_data(parameters), headers(meta))
203
+ response = parse(raw_response)
204
+ success = !response.key?("error")
205
+ rescue ResponseError => e
206
+ raw_response = e.response.body
207
+ response = response_error(raw_response)
208
+ rescue JSON::ParserError
209
+ response = json_error(raw_response)
210
+ end
211
+
212
+ card = response["card"] || response["active_card"] || {}
213
+ avs_code = AVS_CODE_TRANSLATOR["line1: #{card["address_line1_check"]}, zip: #{card["address_zip_check"]}"]
214
+ cvc_code = CVC_CODE_TRANSLATOR[card["cvc_check"]]
215
+ Response.new(success,
216
+ success ? "Transaction approved" : response["error"]["message"],
217
+ response,
218
+ :test => !response["livemode"],
219
+ :authorization => response["id"],
220
+ :avs_result => { :code => avs_code },
221
+ :cvv_result => cvc_code
222
+ )
223
+ end
224
+
225
+ def response_error(raw_response)
226
+ begin
227
+ parse(raw_response)
228
+ rescue JSON::ParserError
229
+ json_error(raw_response)
230
+ end
231
+ end
232
+
233
+ def json_error(raw_response)
234
+ msg = 'Invalid response received from the Stripe API. Please contact support@stripe.com if you continue to receive this message.'
235
+ msg += " (The raw response returned by the API was #{raw_response.inspect})"
236
+ {
237
+ "error" => {
238
+ "message" => msg
239
+ }
240
+ }
241
+ end
242
+ end
243
+ end
244
+ end