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,30 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ module PaypalExpressCommon
4
+ def self.included(base)
5
+ if base.respond_to?(:class_attribute)
6
+ base.class_attribute :test_redirect_url
7
+ base.class_attribute :live_redirect_url
8
+ else
9
+ base.class_inheritable_accessor :test_redirect_url
10
+ base.class_inheritable_accessor :live_redirect_url
11
+ end
12
+ base.live_redirect_url = 'https://www.paypal.com/cgi-bin/webscr'
13
+ end
14
+
15
+ def redirect_url
16
+ test? ? test_redirect_url : live_redirect_url
17
+ end
18
+
19
+ def redirect_url_for(token, options = {})
20
+ options = {:review => true, :mobile => false}.update(options)
21
+
22
+ cmd = options[:mobile] ? '_express-checkout-mobile' : '_express-checkout'
23
+ url = "#{redirect_url}?cmd=#{cmd}&token=#{token}"
24
+ url += '&useraction=commit' unless options[:review]
25
+
26
+ url
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,162 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PayscoutGateway < Gateway
4
+ self.live_url = self.test_url = 'https://secure.payscout.com/api/transact.php'
5
+
6
+ self.supported_countries = ['US']
7
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
8
+ self.default_currency = 'USD'
9
+ self.homepage_url = 'http://www.payscout.com/'
10
+ self.display_name = 'Payscout'
11
+
12
+ def initialize(options = {})
13
+ requires!(options, :username, :password)
14
+ super
15
+ end
16
+
17
+ def authorize(money, creditcard, options = {})
18
+ post = {}
19
+ add_invoice(post, options)
20
+ add_creditcard(post, creditcard)
21
+ add_currency(post, money, options)
22
+ add_address(post, options)
23
+
24
+ commit('auth', money, post)
25
+ end
26
+
27
+ def purchase(money, creditcard, options = {})
28
+ post = {}
29
+ add_invoice(post, options)
30
+ add_creditcard(post, creditcard)
31
+ add_currency(post, money, options)
32
+ add_address(post, options)
33
+
34
+ commit('sale', money, post)
35
+ end
36
+
37
+ def capture(money, authorization, options = {})
38
+ post = {}
39
+ post[:transactionid] = authorization
40
+
41
+ commit('capture', money, post)
42
+ end
43
+
44
+
45
+ def refund(money, authorization, options = {})
46
+ post = {}
47
+ post[:transactionid] = authorization
48
+
49
+ commit('refund', money, post)
50
+ end
51
+
52
+ def void(authorization, options = {})
53
+ post = {}
54
+ post[:transactionid] = authorization
55
+
56
+ commit('void', nil, post)
57
+ end
58
+
59
+ private
60
+
61
+ def add_address(post, options)
62
+ if address = options[:billing_address] || options[:address]
63
+ post[:address1] = address[:address1].to_s
64
+ post[:address2] = address[:address2].to_s
65
+ post[:city] = address[:city].to_s
66
+ post[:state] = (address[:state].blank? ? 'n/a' : address[:state])
67
+ post[:zip] = address[:zip].to_s
68
+ post[:country] = address[:country].to_s
69
+ post[:phone] = address[:phone].to_s
70
+ post[:fax] = address[:fax].to_s
71
+ post[:email] = address[:email].to_s
72
+ end
73
+
74
+ if address = options[:shipping_address]
75
+ post[:shipping_firstname] = address[:first_name].to_s
76
+ post[:shipping_lastname] = address[:last_name].to_s
77
+ post[:shipping_company] = address[:company].to_s
78
+ post[:shipping_address1] = address[:address1].to_s
79
+ post[:shipping_address2] = address[:address2].to_s
80
+ post[:shipping_city] = address[:city].to_s
81
+ post[:shipping_country] = address[:country].to_s
82
+ post[:shipping_state] = (address[:state].blank? ? 'n/a' : address[:state])
83
+ post[:shipping_zip] = address[:zip].to_s
84
+ post[:shipping_email] = address[:email].to_s
85
+ end
86
+ end
87
+
88
+ def add_currency(post, money, options)
89
+ post[:currency] = options[:currency] || currency(money)
90
+ end
91
+
92
+ def add_invoice(post, options)
93
+ post[:orderdescription] = options[:description]
94
+ post[:orderid] = options[:order_id]
95
+ end
96
+
97
+ def add_creditcard(post, creditcard)
98
+ post[:ccnumber] = creditcard.number
99
+ post[:cvv] = creditcard.verification_value if creditcard.verification_value?
100
+ post[:ccexp] = expdate(creditcard)
101
+ post[:firstname] = creditcard.first_name
102
+ post[:lastname] = creditcard.last_name
103
+ end
104
+
105
+ def parse(body)
106
+ Hash[body.split('&').map{|x|x.split('=')}]
107
+ end
108
+
109
+ def commit(action, money, parameters)
110
+ parameters[:amount] = amount(money) unless action == 'void'
111
+ url = (test? ? self.test_url : self.live_url)
112
+ data = ssl_post(url, post_data(action, parameters))
113
+
114
+ response = parse(data)
115
+ response[:action] = action
116
+
117
+ message = message_from(response)
118
+ test_mode = (test? || message =~ /TESTMODE/)
119
+ Response.new(success?(response), message, response,
120
+ :test => test_mode,
121
+ :authorization => response['transactionid'],
122
+ :fraud_review => fraud_review?(response),
123
+ :avs_result => { :code => response['avsresponse'] },
124
+ :cvv_result => response['cvvresponse']
125
+ )
126
+ end
127
+
128
+ def message_from(response)
129
+ case response['response']
130
+ when '1'
131
+ 'The transaction has been approved'
132
+ when '2'
133
+ 'The transaction has been declined'
134
+ when '3'
135
+ response['responsetext']
136
+ else
137
+ 'There was an error processing the transaction'
138
+ end
139
+ end
140
+
141
+ def fraud_review?(response)
142
+ false
143
+ end
144
+
145
+ def success?(response)
146
+ (response['response'] == '1')
147
+ end
148
+
149
+ def post_data(action, parameters = {})
150
+ post = {}
151
+
152
+ post[:username] = @options[:username]
153
+ post[:password] = @options[:password]
154
+ post[:type] = action
155
+
156
+ request = post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
157
+ request
158
+ end
159
+ end
160
+ end
161
+ end
162
+
@@ -0,0 +1,199 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PaystationGateway < Gateway
4
+
5
+ self.live_url = self.test_url = "https://www.paystation.co.nz/direct/paystation.dll"
6
+
7
+ # an "error code" of "0" means "No error - transaction successful"
8
+ SUCCESSFUL_RESPONSE_CODE = '0'
9
+
10
+ # an "error code" of "34" means "Future Payment Stored OK"
11
+ SUCCESSFUL_FUTURE_PAYMENT = '34'
12
+
13
+ # TODO: check this with paystation
14
+ self.supported_countries = ['NZ']
15
+
16
+ # TODO: check this with paystation (amex and diners need to be enabled)
17
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club ]
18
+
19
+ self.homepage_url = 'http://paystation.co.nz'
20
+ self.display_name = 'Paystation'
21
+
22
+ self.default_currency = 'NZD'
23
+ self.money_format = :cents
24
+
25
+ def initialize(options = {})
26
+ requires!(options, :paystation_id, :gateway_id)
27
+ super
28
+ end
29
+
30
+ def authorize(money, credit_card, options = {})
31
+ post = new_request
32
+
33
+ add_invoice(post, options)
34
+ add_amount(post, money, options)
35
+
36
+ add_credit_card(post, credit_card)
37
+
38
+ add_authorize_flag(post, options)
39
+
40
+ commit(post)
41
+ end
42
+
43
+ def capture(money, authorization_token, options = {})
44
+ post = new_request
45
+
46
+ add_invoice(post, options)
47
+ add_amount(post, money, options)
48
+
49
+ add_authorization_token(post, authorization_token, options[:credit_card_verification])
50
+
51
+ commit(post)
52
+ end
53
+
54
+ def purchase(money, payment_source, options = {})
55
+ post = new_request
56
+
57
+ add_invoice(post, options)
58
+ add_amount(post, money, options)
59
+
60
+ if payment_source.is_a?(String)
61
+ add_token(post, payment_source)
62
+ else
63
+ add_credit_card(post, payment_source)
64
+ end
65
+
66
+ add_customer_data(post, options) if options.has_key?(:customer)
67
+
68
+ commit(post)
69
+ end
70
+
71
+ def store(credit_card, options = {})
72
+ post = new_request
73
+
74
+ add_invoice(post, options)
75
+ add_credit_card(post, credit_card)
76
+ store_credit_card(post, options)
77
+
78
+ commit(post)
79
+ end
80
+
81
+ private
82
+
83
+ def new_request
84
+ {
85
+ :pi => @options[:paystation_id], # paystation account id
86
+ :gi => @options[:gateway_id], # paystation gateway id
87
+ "2p" => "t", # two-party transaction type
88
+ :nr => "t", # -- redirect??
89
+ :df => "yymm" # date format: optional sometimes, required others
90
+ }
91
+ end
92
+
93
+ def add_customer_data(post, options)
94
+ post[:mc] = options[:customer]
95
+ end
96
+
97
+ def add_invoice(post, options)
98
+ requires!(options, :order_id)
99
+
100
+ post[:ms] = options[:order_id] # "Merchant Session", must be unique per request
101
+ post[:mo] = options[:invoice] # "Order Details", displayed in Paystation Admin
102
+ post[:mr] = options[:description] # "Merchant Reference Code", seen from Paystation Admin
103
+ end
104
+
105
+ def add_credit_card(post, credit_card)
106
+
107
+ post[:cn] = credit_card.number
108
+ post[:ct] = credit_card.brand
109
+ post[:ex] = format_date(credit_card.month, credit_card.year)
110
+ post[:cc] = credit_card.verification_value if credit_card.verification_value?
111
+
112
+ end
113
+
114
+ # bill a token (stored via "store") rather than a Credit Card
115
+ def add_token(post, token)
116
+ post[:fp] = "t" # turn on "future payments" - what paystation calls Token Billing
117
+ post[:ft] = token
118
+ end
119
+
120
+ def store_credit_card(post, options)
121
+
122
+ post[:fp] = "t" # turn on "future payments" - what paystation calls Token Billing
123
+ post[:fs] = "t" # tells paystation to store right now, not bill
124
+ post[:ft] = options[:token] if options[:token] # specify a token to use that, or let Paystation generate one
125
+
126
+ end
127
+
128
+ def add_authorize_flag(post, options)
129
+ post[:pa] = "t" # tells Paystation that this is a pre-auth authorisation payment (account must be in pre-auth mode)
130
+ end
131
+
132
+ def add_authorization_token(post, auth_token, verification_value = nil)
133
+ post[:cp] = "t" # Capture Payment flag – tells Paystation this transaction should be treated as a capture payment
134
+ post[:cx] = auth_token
135
+ post[:cc] = verification_value
136
+ end
137
+
138
+ def add_amount(post, money, options)
139
+
140
+ post[:am] = amount(money)
141
+ post[:cu] = options[:currency] || currency(money)
142
+
143
+ end
144
+
145
+ def parse(xml_response)
146
+ response = {}
147
+
148
+ xml = REXML::Document.new(xml_response)
149
+
150
+ # for normal payments, the root node is <Response>
151
+ # for "future payments", it's <PaystationFuturePaymentResponse>
152
+ xml.elements.each("#{xml.root.name}/*") do |element|
153
+ response[element.name.underscore.to_sym] = element.text
154
+ end
155
+
156
+ response
157
+ end
158
+
159
+ def commit(post)
160
+
161
+ post[:tm] = "T" if test? # test mode
162
+
163
+ pstn_prefix_params = post.collect { |key, value| "pstn_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
164
+
165
+ # need include paystation param as "initiator flag for payment engine"
166
+ data = ssl_post(self.live_url, "#{pstn_prefix_params}&paystation=_empty")
167
+ response = parse(data)
168
+ message = message_from(response)
169
+
170
+ PaystationResponse.new(success?(response), message, response,
171
+ :test => (response[:tm] && response[:tm].downcase == "t"),
172
+ :authorization => response[:paystation_transaction_id]
173
+ )
174
+ end
175
+
176
+ def success?(response)
177
+ (response[:ec] == SUCCESSFUL_RESPONSE_CODE) || (response[:ec] == SUCCESSFUL_FUTURE_PAYMENT)
178
+ end
179
+
180
+ def message_from(response)
181
+ response[:em]
182
+ end
183
+
184
+ def format_date(month, year)
185
+ "#{format(year, :two_digits)}#{format(month, :two_digits)}"
186
+ end
187
+
188
+ end
189
+
190
+ class PaystationResponse < Response
191
+ # add a method to response so we can easily get the token
192
+ # for Validate transactions
193
+ def token
194
+ @params["future_payment_token"]
195
+ end
196
+ end
197
+ end
198
+ end
199
+
@@ -0,0 +1,247 @@
1
+ # encoding: utf-8
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class PayuInGateway < Gateway
6
+ self.test_url = "https://test.payu.in/_payment"
7
+ self.live_url = "https://secure.payu.in/_payment"
8
+
9
+ TEST_INFO_URL = "https://test.payu.in/merchant/postservice.php?form=2"
10
+ LIVE_INFO_URL = "https://info.payu.in/merchant/postservice.php?form=2"
11
+
12
+ self.supported_countries = ['IN']
13
+ self.default_currency = 'INR'
14
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
15
+
16
+ self.homepage_url = 'https://www.payu.in/'
17
+ self.display_name = 'PayU India'
18
+
19
+ def initialize(options={})
20
+ requires!(options, :key, :salt)
21
+ super
22
+ end
23
+
24
+ def purchase(money, payment, options={})
25
+ requires!(options, :order_id)
26
+
27
+ post = {}
28
+ add_invoice(post, money, options)
29
+ add_payment(post, payment)
30
+ add_addresses(post, options)
31
+ add_customer_data(post, options)
32
+ add_auth(post)
33
+
34
+ MultiResponse.run do |r|
35
+ r.process{commit(url("purchase"), post)}
36
+ if(r.params["enrolled"].to_s == "0")
37
+ r.process{commit(r.params["post_uri"], r.params["form_post_vars"])}
38
+ else
39
+ r.process{handle_3dsecure(r)}
40
+ end
41
+ end
42
+ end
43
+
44
+ def refund(money, authorization, options={})
45
+ raise ArgumentError, "Amount is required" unless money
46
+
47
+ post = {}
48
+
49
+ post[:command] = "cancel_refund_transaction"
50
+ post[:var1] = authorization
51
+ post[:var2] = generate_unique_id
52
+ post[:var3] = amount(money)
53
+
54
+ add_auth(post, :command, :var1)
55
+
56
+ commit(url("refund"), post)
57
+ end
58
+
59
+ def supports_scrubbing?
60
+ true
61
+ end
62
+
63
+ def scrub(transcript)
64
+ transcript.
65
+ gsub(/(ccnum=)[^&\n"]*(&|\n|"|$)/, '\1[FILTERED]\2').
66
+ gsub(/(ccvv=)[^&\n"]*(&|\n|"|$)/, '\1[FILTERED]\2').
67
+ gsub(/(card_hash=)[^&\n"]*(&|\n|"|$)/, '\1[FILTERED]\2').
68
+ gsub(/(ccnum":")[^"]*(")/, '\1[FILTERED]\2').
69
+ gsub(/(ccvv":")[^"]*(")/, '\1[FILTERED]\2')
70
+ end
71
+
72
+ private
73
+
74
+ PAYMENT_DIGEST_KEYS = %w(
75
+ txnid amount productinfo firstname email
76
+ udf1 udf2 udf3 udf4 udf5
77
+ bogus bogus bogus bogus bogus
78
+ )
79
+ def add_auth(post, *digest_keys)
80
+ post[:key] = @options[:key]
81
+ post[:txn_s2s_flow] = 1
82
+
83
+ digest_keys = PAYMENT_DIGEST_KEYS if digest_keys.empty?
84
+ digest = Digest::SHA2.new(512)
85
+ digest << @options[:key] << "|"
86
+ digest_keys.each do |key|
87
+ digest << (post[key.to_sym] || "") << "|"
88
+ end
89
+ digest << @options[:salt]
90
+ post[:hash] = digest.hexdigest
91
+ end
92
+
93
+ def add_customer_data(post, options)
94
+ post[:email] = clean(options[:email] || "unknown@example.com", nil, 50)
95
+ post[:phone] = clean((options[:billing_address] && options[:billing_address][:phone]) || "11111111111", :numeric, 50)
96
+ end
97
+
98
+ def add_addresses(post, options)
99
+ if options[:billing_address]
100
+ post[:address1] = clean(options[:billing_address][:address1], :text, 100)
101
+ post[:address2] = clean(options[:billing_address][:address2], :text, 100)
102
+ post[:city] = clean(options[:billing_address][:city], :text, 50)
103
+ post[:state] = clean(options[:billing_address][:state], :text, 50)
104
+ post[:country] = clean(options[:billing_address][:country], :text, 50)
105
+ post[:zipcode] = clean(options[:billing_address][:zip], :numeric, 20)
106
+ end
107
+
108
+ if options[:shipping_address]
109
+ if options[:shipping_address][:name]
110
+ first, *rest = options[:shipping_address][:name].split(/\s+/)
111
+ post[:shipping_firstname] = clean(first, :name, 60)
112
+ post[:shipping_lastname] = clean(rest.join(" "), :name, 20)
113
+ end
114
+ post[:shipping_address1] = clean(options[:shipping_address][:address1], :text, 100)
115
+ post[:shipping_address2] = clean(options[:shipping_address][:address2], :text, 100)
116
+ post[:shipping_city] = clean(options[:shipping_address][:city], :text, 50)
117
+ post[:shipping_state] = clean(options[:shipping_address][:state], :text, 50)
118
+ post[:shipping_country] = clean(options[:shipping_address][:country], :text, 50)
119
+ post[:shipping_zipcode] = clean(options[:shipping_address][:zip], :numeric, 20)
120
+ post[:shipping_phone] = clean(options[:shipping_address][:phone], :numeric, 50)
121
+ end
122
+ end
123
+
124
+ def add_invoice(post, money, options)
125
+ post[:amount] = amount(money)
126
+
127
+ post[:txnid] = clean(options[:order_id], :alphanumeric, 25)
128
+ post[:productinfo] = clean(options[:description] || "Purchase", nil, 100)
129
+
130
+ post[:surl] = "http://example.com"
131
+ post[:furl] = "http://example.com"
132
+ end
133
+
134
+ BRAND_MAP = {
135
+ visa: "VISA",
136
+ master: "MAST",
137
+ american_express: "AMEX",
138
+ diners_club: "DINR"
139
+ }
140
+
141
+ def add_payment(post, payment)
142
+ post[:pg] = "CC"
143
+ post[:firstname] = clean(payment.first_name, :name, 60)
144
+ post[:lastname] = clean(payment.last_name, :name, 20)
145
+
146
+ post[:bankcode] = BRAND_MAP[payment.brand.to_sym]
147
+ post[:ccnum] = payment.number
148
+ post[:ccvv] = payment.verification_value
149
+ post[:ccname] = payment.name
150
+ post[:ccexpmon] = format(payment.month, :two_digits)
151
+ post[:ccexpyr] = format(payment.year, :four_digits)
152
+ end
153
+
154
+ def clean(value, format, maxlength)
155
+ value ||= ""
156
+ value = case format
157
+ when :alphanumeric
158
+ value.gsub(/[^A-Za-z0-9]/, "")
159
+ when :name
160
+ value.gsub(/[^A-Za-z ]/, "")
161
+ when :numeric
162
+ value.gsub(/[^0-9]/, "")
163
+ when :text
164
+ value.gsub(/[^A-Za-z0-9@\-_\/\. ]/, "")
165
+ when nil
166
+ value
167
+ else
168
+ raise "Unknown format #{format} for #{value}"
169
+ end
170
+ value[0...maxlength]
171
+ end
172
+
173
+ def parse(body)
174
+ top = JSON.parse(body)
175
+
176
+ if result = top.delete("result")
177
+ result.split("&").inject({}) do |hash, string|
178
+ key, value = string.split("=")
179
+ hash[CGI.unescape(key).downcase] = CGI.unescape(value || "")
180
+ hash
181
+ end.each do |key, value|
182
+ if top[key]
183
+ top["result_#{key}"] = value
184
+ else
185
+ top[key] = value
186
+ end
187
+ end
188
+ end
189
+
190
+ if response = top.delete("response")
191
+ top.merge!(response)
192
+ end
193
+
194
+ top
195
+ rescue JSON::ParserError
196
+ {
197
+ "error" => "Invalid response received from the PayU API. (The raw response was `#{body}`)."
198
+ }
199
+ end
200
+
201
+ def commit(url, parameters)
202
+ response = parse(ssl_post(url, post_data(parameters), "Accept-Encoding" => "identity"))
203
+
204
+ Response.new(
205
+ success_from(response),
206
+ message_from(response),
207
+ response,
208
+ authorization: authorization_from(response),
209
+ test: test?
210
+ )
211
+ end
212
+
213
+ def url(action)
214
+ case action
215
+ when "purchase"
216
+ (test? ? test_url : live_url)
217
+ else
218
+ (test? ? TEST_INFO_URL : LIVE_INFO_URL)
219
+ end
220
+ end
221
+
222
+ def success_from(response)
223
+ if response["result_status"]
224
+ (response["status"] == "success" && response["result_status"] == "success")
225
+ else
226
+ (response["status"] == "success" || response["status"].to_s == "1")
227
+ end
228
+ end
229
+
230
+ def message_from(response)
231
+ (response["error_message"] || response["error"] || response["msg"])
232
+ end
233
+
234
+ def authorization_from(response)
235
+ response["mihpayid"]
236
+ end
237
+
238
+ def post_data(parameters = {})
239
+ PostData.new.merge!(parameters).to_post_data
240
+ end
241
+
242
+ def handle_3dsecure(response)
243
+ Response.new(false, "3D-secure enrolled cards are not supported.")
244
+ end
245
+ end
246
+ end
247
+ end