gonow-activemerchant 1.15.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 (189) hide show
  1. data/CHANGELOG +690 -0
  2. data/CONTRIBUTORS +237 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +165 -0
  5. data/gem-public_cert.pem +20 -0
  6. data/lib/active_merchant.rb +47 -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 +57 -0
  10. data/lib/active_merchant/billing/check.rb +68 -0
  11. data/lib/active_merchant/billing/credit_card.rb +178 -0
  12. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  13. data/lib/active_merchant/billing/credit_card_methods.rb +125 -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 +170 -0
  17. data/lib/active_merchant/billing/gateways.rb +18 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net.rb +664 -0
  19. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +858 -0
  20. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
  21. data/lib/active_merchant/billing/gateways/beanstream.rb +139 -0
  22. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +282 -0
  23. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  24. data/lib/active_merchant/billing/gateways/blue_pay.rb +11 -0
  25. data/lib/active_merchant/billing/gateways/bogus.rb +132 -0
  26. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  27. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  28. data/lib/active_merchant/billing/gateways/braintree_blue.rb +293 -0
  29. data/lib/active_merchant/billing/gateways/braintree_orange.rb +17 -0
  30. data/lib/active_merchant/billing/gateways/braspag.rb +188 -0
  31. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -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 +134 -0
  36. data/lib/active_merchant/billing/gateways/epay.rb +268 -0
  37. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/eway_managed.rb +231 -0
  39. data/lib/active_merchant/billing/gateways/exact.rb +222 -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 +156 -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 +209 -0
  57. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  58. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  59. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  60. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  61. data/lib/active_merchant/billing/gateways/ogone.rb +292 -0
  62. data/lib/active_merchant/billing/gateways/orbital.rb +321 -0
  63. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -0
  64. data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
  65. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  66. data/lib/active_merchant/billing/gateways/paybox_direct.rb +207 -0
  67. data/lib/active_merchant/billing/gateways/payflow.rb +253 -0
  68. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
  69. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  70. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  71. data/lib/active_merchant/billing/gateways/payflow_express.rb +222 -0
  72. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  73. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  74. data/lib/active_merchant/billing/gateways/payment_express.rb +235 -0
  75. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  76. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +351 -0
  77. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
  78. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  79. data/lib/active_merchant/billing/gateways/paypal_express.rb +177 -0
  80. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
  81. data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
  82. data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
  83. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  84. data/lib/active_merchant/billing/gateways/qbms.rb +295 -0
  85. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  86. data/lib/active_merchant/billing/gateways/quickpay.rb +218 -0
  87. data/lib/active_merchant/billing/gateways/realex.rb +311 -0
  88. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  89. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  90. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  91. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  92. data/lib/active_merchant/billing/gateways/sage_pay.rb +320 -0
  93. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  94. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  95. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  96. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +193 -0
  97. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  98. data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
  99. data/lib/active_merchant/billing/gateways/smart_ps.rb +271 -0
  100. data/lib/active_merchant/billing/gateways/stripe.rb +212 -0
  101. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  102. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  103. data/lib/active_merchant/billing/gateways/trust_commerce.rb +423 -0
  104. data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
  105. data/lib/active_merchant/billing/gateways/verifi.rb +233 -0
  106. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  107. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  108. data/lib/active_merchant/billing/gateways/worldpay.rb +280 -0
  109. data/lib/active_merchant/billing/integrations.rb +17 -0
  110. data/lib/active_merchant/billing/integrations/action_view_helper.rb +68 -0
  111. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  112. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  113. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  114. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  115. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  116. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  117. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  118. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  119. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  120. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  121. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  122. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  123. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  124. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  125. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  126. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  127. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  128. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  129. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  130. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  131. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  132. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  133. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  134. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  135. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  136. data/lib/active_merchant/billing/integrations/helper.rb +96 -0
  137. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  138. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  139. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  140. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  141. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  142. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  143. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  144. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  145. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  146. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  147. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  148. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  149. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  150. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  151. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  152. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  153. data/lib/active_merchant/billing/integrations/quickpay.rb +21 -0
  154. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  155. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  156. data/lib/active_merchant/billing/integrations/return.rb +42 -0
  157. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  158. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  159. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +111 -0
  160. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  161. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  162. data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
  163. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  164. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  165. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  166. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  167. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  168. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  169. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
  170. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  171. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  172. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  173. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  174. data/lib/active_merchant/billing/response.rb +32 -0
  175. data/lib/active_merchant/common.rb +14 -0
  176. data/lib/active_merchant/common/connection.rb +177 -0
  177. data/lib/active_merchant/common/country.rb +328 -0
  178. data/lib/active_merchant/common/error.rb +26 -0
  179. data/lib/active_merchant/common/post_data.rb +24 -0
  180. data/lib/active_merchant/common/posts_data.rb +63 -0
  181. data/lib/active_merchant/common/requires_parameters.rb +16 -0
  182. data/lib/active_merchant/common/utils.rb +22 -0
  183. data/lib/active_merchant/common/validateable.rb +81 -0
  184. data/lib/active_merchant/version.rb +3 -0
  185. data/lib/activemerchant.rb +1 -0
  186. data/lib/certs/cacert.pem +7815 -0
  187. data/lib/support/gateway_support.rb +58 -0
  188. data/lib/support/outbound_hosts.rb +25 -0
  189. metadata +276 -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,212 @@
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
+ def purchase(money, creditcard, options = {})
39
+ post = {}
40
+
41
+ add_amount(post, money, options)
42
+ add_creditcard(post, creditcard, options)
43
+ add_customer(post, options)
44
+ add_customer_data(post, options)
45
+ add_flags(post, options)
46
+
47
+ raise ArgumentError.new("Customer or Credit Card required.") if !post[:card] && !post[:customer]
48
+
49
+ commit('charges', post)
50
+ end
51
+
52
+ def authorize(money, creditcard, options = {})
53
+ purchase(money, creditcard, options.merge(:uncaptured => true))
54
+ end
55
+
56
+ def capture(money, identification, options = {})
57
+ commit("charges/#{CGI.escape(identification)}/capture", {})
58
+ end
59
+
60
+ def void(identification, options={})
61
+ commit("charges/#{CGI.escape(identification)}/refund", {})
62
+ end
63
+
64
+ def refund(money, identification, options = {})
65
+ post = {}
66
+
67
+ post[:amount] = amount(money) if money
68
+
69
+ commit("charges/#{CGI.escape(identification)}/refund", post)
70
+ end
71
+
72
+ def store(creditcard, options={})
73
+ post = {}
74
+ add_creditcard(post, creditcard, options)
75
+ add_customer_data(post, options)
76
+
77
+ if options[:customer]
78
+ commit("customers/#{CGI.escape(options[:customer])}", post)
79
+ else
80
+ commit('customers', post)
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ def add_amount(post, money, options)
87
+ post[:amount] = amount(money)
88
+ post[:currency] = (options[:currency] || currency(money)).downcase
89
+ end
90
+
91
+ def add_customer_data(post, options)
92
+ post[:description] = options[:email] || options[:description]
93
+ end
94
+
95
+ def add_address(post, options)
96
+ return unless post[:card] && post[:card].kind_of?(Hash)
97
+ if address = options[:billing_address] || options[:address]
98
+ post[:card][:address_line1] = address[:address1] if address[:address1]
99
+ post[:card][:address_line2] = address[:address2] if address[:address2]
100
+ post[:card][:address_country] = address[:country] if address[:country]
101
+ post[:card][:address_zip] = address[:zip] if address[:zip]
102
+ post[:card][:address_state] = address[:state] if address[:state]
103
+ end
104
+ end
105
+
106
+ def add_creditcard(post, creditcard, options)
107
+ if creditcard.respond_to?(:number)
108
+ card = {}
109
+ card[:number] = creditcard.number
110
+ card[:exp_month] = creditcard.month
111
+ card[:exp_year] = creditcard.year
112
+ card[:cvc] = creditcard.verification_value if creditcard.verification_value?
113
+ card[:name] = creditcard.name if creditcard.name
114
+ post[:card] = card
115
+
116
+ add_address(post, options)
117
+ elsif creditcard.kind_of?(String)
118
+ post[:card] = creditcard
119
+ end
120
+ end
121
+
122
+ def add_customer(post, options)
123
+ post[:customer] = options[:customer] if options[:customer] && !post[:card]
124
+ end
125
+
126
+ def add_flags(post, options)
127
+ post[:uncaptured] = true if options[:uncaptured]
128
+ end
129
+
130
+ def parse(body)
131
+ JSON.parse(body)
132
+ end
133
+
134
+ def post_data(params)
135
+ params.map do |key, value|
136
+ next if value.blank?
137
+ if value.is_a?(Hash)
138
+ h = {}
139
+ value.each do |k, v|
140
+ h["#{key}[#{k}]"] = v unless v.blank?
141
+ end
142
+ post_data(h)
143
+ else
144
+ "#{key}=#{CGI.escape(value.to_s)}"
145
+ end
146
+ end.compact.join("&")
147
+ end
148
+
149
+ def headers
150
+ @@ua ||= JSON.dump({
151
+ :bindings_version => ActiveMerchant::VERSION,
152
+ :lang => 'ruby',
153
+ :lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
154
+ :platform => RUBY_PLATFORM,
155
+ :publisher => 'active_merchant',
156
+ :uname => (RUBY_PLATFORM =~ /linux|darwin/i ? `uname -a 2>/dev/null`.strip : nil)
157
+ })
158
+
159
+ {
160
+ "Authorization" => "Basic " + ActiveSupport::Base64.encode64(@api_key.to_s + ":").strip,
161
+ "User-Agent" => "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
162
+ "X-Stripe-Client-User-Agent" => @@ua
163
+ }
164
+ end
165
+
166
+ def commit(url, parameters, method=:post)
167
+ raw_response = response = nil
168
+ success = false
169
+ begin
170
+ raw_response = ssl_request(method, LIVE_URL + url, post_data(parameters), headers)
171
+ response = parse(raw_response)
172
+ success = !response.key?("error")
173
+ rescue ResponseError => e
174
+ raw_response = e.response.body
175
+ response = response_error(raw_response)
176
+ rescue JSON::ParserError
177
+ response = json_error(raw_response)
178
+ end
179
+
180
+ card = response["card"] || {}
181
+ avs_code = AVS_CODE_TRANSLATOR["line1: #{card["address_line1_check"]}, zip: #{card["address_zip_check"]}"]
182
+ cvc_code = CVC_CODE_TRANSLATOR[card["cvc_check"]]
183
+ Response.new(success,
184
+ success ? "Transaction approved" : response["error"]["message"],
185
+ response,
186
+ :test => !response["livemode"],
187
+ :authorization => response["id"],
188
+ :avs_result => { :code => avs_code },
189
+ :cvv_result => cvc_code
190
+ )
191
+ end
192
+
193
+ def response_error(raw_response)
194
+ begin
195
+ parse(raw_response)
196
+ rescue JSON::ParserError
197
+ json_error(raw_response)
198
+ end
199
+ end
200
+
201
+ def json_error(raw_response)
202
+ msg = 'Invalid response received from the Stripe API. Please contact support@stripe.com if you continue to receive this message.'
203
+ msg += " (The raw response returned by the API was #{raw_response.inspect})"
204
+ {
205
+ "error" => {
206
+ "message" => msg
207
+ }
208
+ }
209
+ end
210
+ end
211
+ end
212
+ end