start_activemerchant 1.50.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 (218) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +1769 -0
  3. data/CONTRIBUTORS +540 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +226 -0
  6. data/lib/active_merchant.rb +67 -0
  7. data/lib/active_merchant/billing.rb +15 -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 +404 -0
  14. data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
  15. data/lib/active_merchant/billing/credit_card_methods.rb +195 -0
  16. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  17. data/lib/active_merchant/billing/gateway.rb +291 -0
  18. data/lib/active_merchant/billing/gateways.rb +14 -0
  19. data/lib/active_merchant/billing/gateways/allied_wallet.rb +203 -0
  20. data/lib/active_merchant/billing/gateways/app55.rb +176 -0
  21. data/lib/active_merchant/billing/gateways/authorize_net.rb +510 -0
  22. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
  23. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -0
  24. data/lib/active_merchant/billing/gateways/axcessms.rb +181 -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 +192 -0
  32. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +389 -0
  33. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +58 -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 +211 -0
  37. data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  39. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  40. data/lib/active_merchant/billing/gateways/braintree_blue.rb +574 -0
  41. data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
  42. data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
  43. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  44. data/lib/active_merchant/billing/gateways/card_stream.rb +238 -0
  45. data/lib/active_merchant/billing/gateways/cashnet.rb +202 -0
  46. data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
  47. data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
  48. data/lib/active_merchant/billing/gateways/cenpos.rb +262 -0
  49. data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
  50. data/lib/active_merchant/billing/gateways/checkout.rb +216 -0
  51. data/lib/active_merchant/billing/gateways/checkout_v2.rb +200 -0
  52. data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
  53. data/lib/active_merchant/billing/gateways/conekta.rb +210 -0
  54. data/lib/active_merchant/billing/gateways/cyber_source.rb +720 -0
  55. data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
  56. data/lib/active_merchant/billing/gateways/dibs.rb +206 -0
  57. data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
  58. data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
  59. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  60. data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
  61. data/lib/active_merchant/billing/gateways/eway.rb +214 -0
  62. data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
  63. data/lib/active_merchant/billing/gateways/eway_rapid.rb +522 -0
  64. data/lib/active_merchant/billing/gateways/exact.rb +227 -0
  65. data/lib/active_merchant/billing/gateways/ezic.rb +206 -0
  66. data/lib/active_merchant/billing/gateways/fat_zebra.rb +213 -0
  67. data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
  68. data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
  69. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  70. data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
  71. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +413 -0
  72. data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
  73. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
  74. data/lib/active_merchant/billing/gateways/garanti.rb +261 -0
  75. data/lib/active_merchant/billing/gateways/global_transport.rb +179 -0
  76. data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
  77. data/lib/active_merchant/billing/gateways/hps.rb +287 -0
  78. data/lib/active_merchant/billing/gateways/iats_payments.rb +277 -0
  79. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
  80. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  81. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  82. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
  83. data/lib/active_merchant/billing/gateways/inspire.rb +219 -0
  84. data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
  85. data/lib/active_merchant/billing/gateways/ipp.rb +175 -0
  86. data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
  87. data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
  88. data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
  89. data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
  90. data/lib/active_merchant/billing/gateways/litle.rb +345 -0
  91. data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
  92. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
  93. data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
  94. data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
  95. data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
  96. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
  97. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
  98. data/lib/active_merchant/billing/gateways/mercury.rb +326 -0
  99. data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
  100. data/lib/active_merchant/billing/gateways/migs.rb +280 -0
  101. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  102. data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
  103. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
  104. data/lib/active_merchant/billing/gateways/monei.rb +307 -0
  105. data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
  106. data/lib/active_merchant/billing/gateways/moneris_us.rb +298 -0
  107. data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
  108. data/lib/active_merchant/billing/gateways/nab_transact.rb +290 -0
  109. data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
  110. data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
  111. data/lib/active_merchant/billing/gateways/netbilling.rb +224 -0
  112. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  113. data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
  114. data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
  115. data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
  116. data/lib/active_merchant/billing/gateways/omise.rb +319 -0
  117. data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
  118. data/lib/active_merchant/billing/gateways/optimal_payment.rb +314 -0
  119. data/lib/active_merchant/billing/gateways/orbital.rb +834 -0
  120. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
  121. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
  122. data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
  123. data/lib/active_merchant/billing/gateways/pay_conex.rb +246 -0
  124. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +277 -0
  125. data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
  126. data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
  127. data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
  128. data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
  129. data/lib/active_merchant/billing/gateways/payex.rb +412 -0
  130. data/lib/active_merchant/billing/gateways/payflow.rb +308 -0
  131. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +220 -0
  132. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  133. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  134. data/lib/active_merchant/billing/gateways/payflow_express.rb +224 -0
  135. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  136. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  137. data/lib/active_merchant/billing/gateways/payment_express.rb +353 -0
  138. data/lib/active_merchant/billing/gateways/paymill.rb +282 -0
  139. data/lib/active_merchant/billing/gateways/paypal.rb +129 -0
  140. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +679 -0
  141. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
  142. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
  143. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  144. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
  145. data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
  146. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  147. data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
  148. data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
  149. data/lib/active_merchant/billing/gateways/payu_in.rb +247 -0
  150. data/lib/active_merchant/billing/gateways/payway.rb +207 -0
  151. data/lib/active_merchant/billing/gateways/pin.rb +207 -0
  152. data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
  153. data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
  154. data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
  155. data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
  156. data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
  157. data/lib/active_merchant/billing/gateways/quickbooks.rb +280 -0
  158. data/lib/active_merchant/billing/gateways/quickpay.rb +26 -0
  159. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +188 -0
  160. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +240 -0
  161. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +227 -0
  162. data/lib/active_merchant/billing/gateways/qvalent.rb +179 -0
  163. data/lib/active_merchant/billing/gateways/realex.rb +298 -0
  164. data/lib/active_merchant/billing/gateways/redsys.rb +406 -0
  165. data/lib/active_merchant/billing/gateways/s5.rb +226 -0
  166. data/lib/active_merchant/billing/gateways/sage.rb +173 -0
  167. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +89 -0
  168. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +115 -0
  169. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
  170. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  171. data/lib/active_merchant/billing/gateways/sage_pay.rb +399 -0
  172. data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
  173. data/lib/active_merchant/billing/gateways/secure_net.rb +263 -0
  174. data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
  175. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
  176. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
  177. data/lib/active_merchant/billing/gateways/skip_jack.rb +451 -0
  178. data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
  179. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  180. data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
  181. data/lib/active_merchant/billing/gateways/stripe.rb +489 -0
  182. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
  183. data/lib/active_merchant/billing/gateways/tns.rb +227 -0
  184. data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
  185. data/lib/active_merchant/billing/gateways/transax.rb +23 -0
  186. data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
  187. data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
  188. data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
  189. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
  190. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +259 -0
  191. data/lib/active_merchant/billing/gateways/vanco.rb +280 -0
  192. data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
  193. data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
  194. data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
  195. data/lib/active_merchant/billing/gateways/wepay.rb +205 -0
  196. data/lib/active_merchant/billing/gateways/wirecard.rb +420 -0
  197. data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
  198. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +204 -0
  199. data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
  200. data/lib/active_merchant/billing/model.rb +30 -0
  201. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +24 -0
  202. data/lib/active_merchant/billing/payment_token.rb +21 -0
  203. data/lib/active_merchant/billing/rails.rb +3 -0
  204. data/lib/active_merchant/billing/response.rb +92 -0
  205. data/lib/active_merchant/connection.rb +172 -0
  206. data/lib/active_merchant/country.rb +332 -0
  207. data/lib/active_merchant/empty.rb +20 -0
  208. data/lib/active_merchant/errors.rb +35 -0
  209. data/lib/active_merchant/network_connection_retries.rb +79 -0
  210. data/lib/active_merchant/post_data.rb +24 -0
  211. data/lib/active_merchant/posts_data.rb +84 -0
  212. data/lib/active_merchant/version.rb +3 -0
  213. data/lib/activemerchant.rb +1 -0
  214. data/lib/certs/cacert.pem +3866 -0
  215. data/lib/support/gateway_support.rb +71 -0
  216. data/lib/support/outbound_hosts.rb +28 -0
  217. data/lib/support/ssl_verify.rb +93 -0
  218. metadata +387 -0
@@ -0,0 +1,143 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class SallieMaeGateway < Gateway
4
+ self.live_url = self.test_url = 'https://trans.salliemae.com/cgi-bin/process.cgi'
5
+
6
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
7
+ self.supported_countries = ['US']
8
+
9
+ # The card types supported by the payment gateway
10
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
11
+
12
+ # The homepage URL of the gateway
13
+ self.homepage_url = 'http://www.salliemae.com/'
14
+
15
+ # The name of the gateway
16
+ self.display_name = 'Sallie Mae'
17
+
18
+ def initialize(options = {})
19
+ requires!(options, :login)
20
+ super
21
+ end
22
+
23
+ def test?
24
+ @options[:login] == "TEST0"
25
+ end
26
+
27
+ def authorize(money, creditcard, options = {})
28
+ post = PostData.new
29
+ add_invoice(post, options)
30
+ add_creditcard(post, creditcard)
31
+ add_address(post, creditcard, options)
32
+ add_customer_data(post, options)
33
+
34
+ commit(:authonly, money, post)
35
+ end
36
+
37
+ def purchase(money, creditcard, options = {})
38
+ post = PostData.new
39
+ add_invoice(post, options)
40
+ add_creditcard(post, creditcard)
41
+ add_address(post, creditcard, options)
42
+ add_customer_data(post, options)
43
+
44
+ commit(:sale, money, post)
45
+ end
46
+
47
+ def capture(money, authorization, options = {})
48
+ post = PostData.new
49
+ post[:postonly] = authorization
50
+ commit(:capture, money, post)
51
+ end
52
+
53
+ private
54
+
55
+ def add_customer_data(post, options)
56
+ if address = options[:billing_address] || options[:shipping_address] || options[:address]
57
+ post[:ci_phone] = address[:phone].to_s
58
+ end
59
+
60
+ post[:ci_email] = options[:email].to_s unless options[:email].blank?
61
+ post[:ci_IP] = options[:ip].to_s unless options[:ip].blank?
62
+ end
63
+
64
+ def add_address(post, creditcard, options)
65
+ if address = options[:billing_address] || options[:address]
66
+ post[:ci_billaddr1] = address[:address1].to_s
67
+ post[:ci_billaddr2] = address[:address2].to_s unless address[:address2].blank?
68
+ post[:ci_billcity] = address[:city].to_s
69
+ post[:ci_billstate] = address[:state].to_s
70
+ post[:ci_billzip] = address[:zip].to_s
71
+ end
72
+
73
+ if shipping_address = options[:shipping_address] || options[:address]
74
+ post[:ci_shipaddr1] = shipping_address[:address1].to_s
75
+ post[:ci_shipaddr2] = shipping_address[:address2].to_s unless shipping_address[:address2].blank?
76
+ post[:ci_shipcity] = shipping_address[:city].to_s
77
+ post[:ci_shipstate] = shipping_address[:state].to_s
78
+ post[:ci_shipzip] = shipping_address[:zip].to_s
79
+ end
80
+ end
81
+
82
+ def add_invoice(post, options)
83
+ memo = "OrderID: #{options[:order_id]}\nDescription: #{options[:description]}"
84
+ post[:ci_memo] = memo
85
+ end
86
+
87
+ def add_creditcard(post, creditcard)
88
+ post[:ccnum] = creditcard.number.to_s
89
+ post[:ccname] = creditcard.name.to_s
90
+ post[:cvv2] = creditcard.verification_value.to_s if creditcard.verification_value?
91
+ post[:expmon] = creditcard.month.to_s
92
+ post[:expyear] = creditcard.year.to_s
93
+ end
94
+
95
+ def parse(body)
96
+ h = {}
97
+ body.gsub!("<html><body><plaintext>", "")
98
+ body.
99
+ split("\r\n").
100
+ map do |i|
101
+ a = i.split("=")
102
+ h[a.first] = a.last unless a.first.nil?
103
+ end
104
+ h
105
+ end
106
+
107
+ def commit(action, money, parameters)
108
+ parameters[:acctid] = @options[:login].to_s
109
+ parameters[:subid] = @options[:sub_id].to_s unless @options[:sub_id].blank?
110
+ parameters[:amount] = amount(money)
111
+
112
+ case action
113
+ when :sale
114
+ parameters[:action] = "ns_quicksale_cc"
115
+ when :authonly
116
+ parameters[:action] = "ns_quicksale_cc"
117
+ parameters[:authonly] = 1
118
+ when :capture
119
+ parameters[:action] = "ns_quicksale_cc"
120
+ end
121
+
122
+ response = parse(ssl_post(self.live_url, parameters.to_post_data) || "")
123
+ Response.new(successful?(response), message_from(response), response,
124
+ :test => test?,
125
+ :authorization => response["refcode"]
126
+ )
127
+ end
128
+
129
+ def successful?(response)
130
+ response["Status"] == "Accepted"
131
+ end
132
+
133
+ def message_from(response)
134
+ if successful?(response)
135
+ "Accepted"
136
+ else
137
+ response["Reason"].split(":")[2].capitalize unless response["Reason"].nil?
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+
@@ -0,0 +1,263 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class SecureNetGateway < Gateway
4
+
5
+ API_VERSION = "4.0"
6
+
7
+ TRANSACTIONS = {
8
+ :auth_only => "0000",
9
+ :auth_capture => "0100",
10
+ :prior_auth_capture => "0200",
11
+ :void => "0400",
12
+ :credit => "0500"
13
+ }
14
+
15
+ XML_ATTRIBUTES = {
16
+ 'xmlns' => "http://gateway.securenet.com/API/Contracts",
17
+ 'xmlns:i' => "http://www.w3.org/2001/XMLSchema-instance"
18
+ }
19
+ NIL_ATTRIBUTE = { 'i:nil' => "true" }
20
+
21
+ self.supported_countries = ['US']
22
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
23
+ self.homepage_url = 'http://www.securenet.com/'
24
+ self.display_name = 'SecureNet'
25
+
26
+ self.test_url = 'https://certify.securenet.com/API/gateway.svc/webHttp/ProcessTransaction'
27
+ self.live_url = 'https://gateway.securenet.com/api/Gateway.svc/webHttp/ProcessTransaction'
28
+
29
+ APPROVED, DECLINED = 1, 2
30
+
31
+ CARD_CODE_ERRORS = %w( N S )
32
+ AVS_ERRORS = %w( A E N R W Z )
33
+
34
+ def initialize(options = {})
35
+ requires!(options, :login, :password)
36
+ super
37
+ end
38
+
39
+ def authorize(money, creditcard, options = {})
40
+ commit(build_sale_or_authorization(creditcard, options, :auth_only, money))
41
+ end
42
+
43
+ def purchase(money, creditcard, options = {})
44
+ commit(build_sale_or_authorization(creditcard, options, :auth_capture, money))
45
+ end
46
+
47
+ def capture(money, authorization, options = {})
48
+ commit(build_capture_refund_void(authorization, options, :prior_auth_capture, money))
49
+ end
50
+
51
+ def void(authorization, options = {})
52
+ commit(build_capture_refund_void(authorization, options, :void))
53
+ end
54
+
55
+ def refund(money, authorization, options = {})
56
+ commit(build_capture_refund_void(authorization, options, :credit, money))
57
+ end
58
+
59
+ def credit(money, authorization, options = {})
60
+ ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
61
+ refund(money, authorization, options)
62
+ end
63
+
64
+
65
+ private
66
+ def commit(request)
67
+ xml = build_request(request)
68
+ url = test? ? self.test_url : self.live_url
69
+ data = ssl_post(url, xml, "Content-Type" => "text/xml")
70
+ response = parse(data)
71
+
72
+ Response.new(success?(response), message_from(response), response,
73
+ :test => test?,
74
+ :authorization => build_authorization(response),
75
+ :avs_result => { :code => response[:avs_result_code] },
76
+ :cvv_result => response[:card_code_response_code]
77
+ )
78
+ end
79
+
80
+ def build_request(request)
81
+ xml = Builder::XmlMarkup.new
82
+
83
+ xml.instruct!
84
+ xml.tag!("TRANSACTION", XML_ATTRIBUTES) do
85
+ xml << request
86
+ end
87
+
88
+ xml.target!
89
+ end
90
+
91
+ def build_sale_or_authorization(creditcard, options, action, money)
92
+ xml = Builder::XmlMarkup.new
93
+
94
+ xml.tag! 'AMOUNT', amount(money)
95
+ add_credit_card(xml, creditcard)
96
+ add_params_in_required_order(xml, action, creditcard, options)
97
+ add_more_required_params(xml, options)
98
+
99
+ xml.target!
100
+ end
101
+
102
+ def build_capture_refund_void(authorization, options, action, money = nil)
103
+ xml = Builder::XmlMarkup.new
104
+
105
+ transaction_id, amount_in_ref, last_four = split_authorization(authorization)
106
+
107
+ xml.tag! 'AMOUNT', amount(money) || amount_in_ref
108
+ xml.tag!("CARD") do
109
+ xml.tag! 'CARDNUMBER', last_four
110
+ end
111
+
112
+ add_params_in_required_order(xml, action, nil, options)
113
+ xml.tag! 'REF_TRANSID', transaction_id
114
+ add_more_required_params(xml, options)
115
+
116
+ xml.target!
117
+ end
118
+
119
+ def add_credit_card(xml, creditcard)
120
+ xml.tag!("CARD") do
121
+ xml.tag! 'CARDCODE', creditcard.verification_value if creditcard.verification_value?
122
+ xml.tag! 'CARDNUMBER', creditcard.number
123
+ xml.tag! 'EXPDATE', expdate(creditcard)
124
+ end
125
+ end
126
+
127
+ def add_customer_data(xml, options)
128
+ if options.has_key? :customer
129
+ xml.tag! 'CUSTOMERID', options[:customer]
130
+ end
131
+
132
+ if options.has_key? :ip
133
+ xml.tag! 'CUSTOMERIP', options[:ip]
134
+ end
135
+ end
136
+
137
+ def add_address(xml, creditcard, options)
138
+ return unless creditcard
139
+
140
+ if address = options[:billing_address] || options[:address]
141
+ xml.tag!("CUSTOMER_BILL") do
142
+ xml.tag! 'ADDRESS', address[:address1].to_s
143
+ xml.tag! 'CITY', address[:city].to_s
144
+ xml.tag! 'COMPANY', address[:company].to_s
145
+ xml.tag! 'COUNTRY', address[:country].to_s
146
+ if options.has_key? :email
147
+ xml.tag! 'EMAIL', options[:email]
148
+ xml.tag! 'EMAILRECEIPT', 'FALSE'
149
+ end
150
+ xml.tag! 'FIRSTNAME', creditcard.first_name
151
+ xml.tag! 'LASTNAME', creditcard.last_name
152
+ xml.tag! 'PHONE', address[:phone].to_s
153
+ xml.tag! 'STATE', address[:state].blank? ? 'n/a' : address[:state]
154
+ xml.tag! 'ZIP', address[:zip].to_s
155
+ end
156
+ end
157
+
158
+ if address = options[:shipping_address]
159
+ xml.tag!("CUSTOMER_SHIP") do
160
+ xml.tag! 'ADDRESS', address[:address1].to_s
161
+ xml.tag! 'CITY', address[:city].to_s
162
+ xml.tag! 'COMPANY', address[:company].to_s
163
+ xml.tag! 'COUNTRY', address[:country].to_s
164
+
165
+ if address[:name]
166
+ names = address[:name].split
167
+ last_name = names.pop
168
+ first_name = names.join(" ")
169
+ xml.tag! 'FIRSTNAME', first_name
170
+ xml.tag! 'LASTNAME', last_name
171
+ else
172
+ xml.tag! 'FIRSTNAME', address[:first_name].to_s
173
+ xml.tag! 'LASTNAME', address[:last_name].to_s
174
+ end
175
+
176
+ xml.tag! 'STATE', address[:state].blank? ? 'n/a' : address[:state]
177
+ xml.tag! 'ZIP', address[:zip].to_s
178
+ end
179
+ else
180
+ xml.tag!('CUSTOMER_SHIP', NIL_ATTRIBUTE) do
181
+ end
182
+ end
183
+
184
+ end
185
+
186
+ def add_merchant_key(xml, options)
187
+ xml.tag!("MERCHANT_KEY") do
188
+ xml.tag! 'GROUPID', 0
189
+ xml.tag! 'SECUREKEY', @options[:password]
190
+ xml.tag! 'SECURENETID', @options[:login]
191
+ end
192
+ end
193
+
194
+ # SecureNet requires some of the xml params to be in a certain order. http://cl.ly/image/3K260E0p0a0n/content.png
195
+ def add_params_in_required_order(xml, action, creditcard, options)
196
+ xml.tag! 'CODE', TRANSACTIONS[action]
197
+ add_customer_data(xml, options)
198
+ add_address(xml, creditcard, options)
199
+ xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
200
+ xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
201
+ xml.tag! 'INVOICEDESC', options[:invoice_description] if options[:invoice_description]
202
+ xml.tag! 'INVOICENUM', options[:invoice_number] if options[:invoice_number]
203
+ add_merchant_key(xml, options)
204
+ xml.tag! 'METHOD', 'CC'
205
+ xml.tag! 'NOTE', options[:description] if options[:description]
206
+ xml.tag! 'ORDERID', truncate(options[:order_id], 25)
207
+ xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
208
+ end
209
+
210
+ def add_more_required_params(xml, options)
211
+ xml.tag! 'RETAIL_LANENUM', '0'
212
+ xml.tag! 'TEST', 'TRUE' if test?
213
+ xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0
214
+ xml.tag! 'TRANSACTION_SERVICE', 0
215
+ end
216
+
217
+ def success?(response)
218
+ response[:response_code].to_i == APPROVED
219
+ end
220
+
221
+ def message_from(response)
222
+ if response[:response_code].to_i == DECLINED
223
+ return CVVResult.messages[ response[:card_code_response_code] ] if CARD_CODE_ERRORS.include?(response[:card_code_response_code])
224
+ return AVSResult.messages[ response[:avs_result_code] ] if AVS_ERRORS.include?(response[:avs_result_code])
225
+ end
226
+
227
+ return response[:response_reason_text].nil? ? '' : response[:response_reason_text][0..-1]
228
+ end
229
+
230
+ def parse(xml)
231
+ response = {}
232
+ xml = REXML::Document.new(xml)
233
+ root = REXML::XPath.first(xml, "//GATEWAYRESPONSE")
234
+ if root
235
+ root.elements.to_a.each do |node|
236
+ recurring_parse_element(response, node)
237
+ end
238
+ end
239
+
240
+ response
241
+ end
242
+
243
+ def recurring_parse_element(response, node)
244
+ if node.has_elements?
245
+ node.elements.each{|e| recurring_parse_element(response, e) }
246
+ else
247
+ response[node.name.underscore.to_sym] = node.text
248
+ end
249
+ end
250
+
251
+ def split_authorization(authorization)
252
+ transaction_id, amount, last_four = authorization.split("|")
253
+ [transaction_id, amount, last_four]
254
+ end
255
+
256
+ def build_authorization(response)
257
+ [response[:transactionid], response[:transactionamount], response[:last4_digits]].join("|")
258
+ end
259
+
260
+ end
261
+ end
262
+ end
263
+
@@ -0,0 +1,201 @@
1
+ require 'active_merchant/billing/gateways/authorize_net'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class SecurePayGateway < Gateway
6
+ API_VERSION = '3.1'
7
+
8
+ self.live_url = self.test_url = 'https://www.securepay.com/AuthSpayAdapter/process.aspx'
9
+
10
+ class_attribute :duplicate_window
11
+
12
+ APPROVED, DECLINED, ERROR, FRAUD_REVIEW = 1, 2, 3, 4
13
+
14
+ RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT, AUTHORIZATION_CODE = 0, 2, 3, 4
15
+ AVS_RESULT_CODE, TRANSACTION_ID, CARD_CODE_RESPONSE_CODE, CARDHOLDER_AUTH_CODE = 5, 6, 38, 39
16
+
17
+ self.default_currency = 'USD'
18
+
19
+ self.supported_countries = %w(US CA GB AU)
20
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
21
+ self.homepage_url = 'http://www.securepay.com/'
22
+ self.display_name = 'SecurePay'
23
+
24
+ CARD_CODE_ERRORS = %w( N S )
25
+ AVS_ERRORS = %w( A E N R W Z )
26
+ AVS_REASON_CODES = %w(27 45)
27
+ TRANSACTION_ALREADY_ACTIONED = %w(310 311)
28
+
29
+ def initialize(options = {})
30
+ requires!(options, :login, :password)
31
+ super
32
+ end
33
+
34
+ def purchase(money, paysource, options = {})
35
+ post = {}
36
+ add_currency_code(post, money, options)
37
+ add_invoice(post, options)
38
+ add_payment_source(post, paysource, options)
39
+ add_address(post, options)
40
+ add_customer_data(post, options)
41
+ add_duplicate_window(post)
42
+
43
+ commit('AUTH_CAPTURE', money, post)
44
+ end
45
+
46
+ private
47
+
48
+ def commit(action, money, parameters)
49
+ parameters[:amount] = amount(money) unless action == 'VOID'
50
+
51
+ url = (test? ? self.test_url : self.live_url)
52
+ data = ssl_post(url, post_data(action, parameters))
53
+
54
+ response = parse(data)
55
+ response[:action] = action
56
+
57
+ message = message_from(response)
58
+
59
+ Response.new(success?(response), message, response,
60
+ :test => test?,
61
+ :authorization => response[:transaction_id],
62
+ :fraud_review => fraud_review?(response),
63
+ :avs_result => { :code => response[:avs_result_code] },
64
+ :cvv_result => response[:card_code]
65
+ )
66
+ end
67
+
68
+ def success?(response)
69
+ response[:response_code] == APPROVED && TRANSACTION_ALREADY_ACTIONED.exclude?(response[:response_reason_code])
70
+ end
71
+
72
+ def fraud_review?(response)
73
+ response[:response_code] == FRAUD_REVIEW
74
+ end
75
+
76
+ def parse(body)
77
+ fields = split(body)
78
+
79
+ results = {
80
+ :response_code => fields[RESPONSE_CODE].to_i,
81
+ :response_reason_code => fields[RESPONSE_REASON_CODE],
82
+ :response_reason_text => fields[RESPONSE_REASON_TEXT],
83
+ :avs_result_code => fields[AVS_RESULT_CODE],
84
+ :transaction_id => fields[TRANSACTION_ID],
85
+ :card_code => fields[CARD_CODE_RESPONSE_CODE],
86
+ :authorization_code => fields[AUTHORIZATION_CODE],
87
+ :cardholder_authentication_code => fields[CARDHOLDER_AUTH_CODE]
88
+ }
89
+ results
90
+ end
91
+
92
+ def post_data(action, parameters = {})
93
+ post = {}
94
+
95
+ post[:version] = API_VERSION
96
+ post[:login] = @options[:login]
97
+ post[:tran_key] = @options[:password]
98
+ post[:relay_response] = "FALSE"
99
+ post[:type] = action
100
+ post[:delim_data] = "TRUE"
101
+ post[:delim_char] = ","
102
+ post[:encap_char] = "$"
103
+ post[:solution_ID] = application_id if application_id.present? && application_id != "ActiveMerchant"
104
+
105
+ request = post.merge(parameters).collect { |key, value| "x_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
106
+ request
107
+ end
108
+
109
+ def add_currency_code(post, money, options)
110
+ post[:currency_code] = options[:currency] || currency(money)
111
+ end
112
+
113
+ def add_invoice(post, options)
114
+ post[:invoice_num] = options[:order_id]
115
+ post[:description] = options[:description]
116
+ end
117
+
118
+ def add_creditcard(post, creditcard, options={})
119
+ post[:card_num] = creditcard.number
120
+ post[:card_code] = creditcard.verification_value if creditcard.verification_value?
121
+ post[:exp_date] = expdate(creditcard)
122
+ post[:first_name] = creditcard.first_name
123
+ post[:last_name] = creditcard.last_name
124
+ end
125
+
126
+ def add_payment_source(params, source, options={})
127
+ add_creditcard(params, source, options)
128
+ end
129
+
130
+ def add_customer_data(post, options)
131
+ if options.has_key? :email
132
+ post[:email] = options[:email]
133
+ post[:email_customer] = false
134
+ end
135
+
136
+ if options.has_key? :customer
137
+ post[:cust_id] = options[:customer] if Float(options[:customer]) rescue nil
138
+ end
139
+
140
+ if options.has_key? :ip
141
+ post[:customer_ip] = options[:ip]
142
+ end
143
+
144
+ if options.has_key? :cardholder_authentication_value
145
+ post[:cardholder_authentication_value] = options[:cardholder_authentication_value]
146
+ end
147
+
148
+ if options.has_key? :authentication_indicator
149
+ post[:authentication_indicator] = options[:authentication_indicator]
150
+ end
151
+ end
152
+
153
+ # x_duplicate_window won't be sent by default, because sending it changes the response.
154
+ # "If this field is present in the request with or without a value, an enhanced duplicate transaction response will be sent."
155
+ # (as of 2008-12-30) http://www.authorize.net/support/AIM_guide_SCC.pdf
156
+ def add_duplicate_window(post)
157
+ post[:duplicate_window] = duplicate_window if duplicate_window
158
+ end
159
+
160
+ def add_address(post, options)
161
+ if address = options[:billing_address] || options[:address]
162
+ post[:address] = address[:address1].to_s
163
+ post[:company] = address[:company].to_s
164
+ post[:phone] = address[:phone].to_s
165
+ post[:zip] = address[:zip].to_s
166
+ post[:city] = address[:city].to_s
167
+ post[:country] = address[:country].to_s
168
+ post[:state] = address[:state].blank? ? 'n/a' : address[:state]
169
+ end
170
+
171
+ if address = options[:shipping_address]
172
+ post[:ship_to_first_name] = address[:first_name].to_s
173
+ post[:ship_to_last_name] = address[:last_name].to_s
174
+ post[:ship_to_address] = address[:address1].to_s
175
+ post[:ship_to_company] = address[:company].to_s
176
+ post[:ship_to_phone] = address[:phone].to_s
177
+ post[:ship_to_zip] = address[:zip].to_s
178
+ post[:ship_to_city] = address[:city].to_s
179
+ post[:ship_to_country] = address[:country].to_s
180
+ post[:ship_to_state] = address[:state].blank? ? 'n/a' : address[:state]
181
+ end
182
+ end
183
+
184
+ def message_from(results)
185
+ if results[:response_code] == DECLINED
186
+ return CVVResult.messages[ results[:card_code] ] if CARD_CODE_ERRORS.include?(results[:card_code])
187
+ if AVS_REASON_CODES.include?(results[:response_reason_code]) && AVS_ERRORS.include?(results[:avs_result_code])
188
+ return AVSResult.messages[ results[:avs_result_code] ]
189
+ end
190
+ end
191
+
192
+ (results[:response_reason_text] ? results[:response_reason_text].chomp('.') : '')
193
+ end
194
+
195
+ def split(response)
196
+ response.split(',')
197
+ end
198
+ end
199
+ end
200
+ end
201
+