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,406 @@
1
+ # coding: utf-8
2
+ require 'nokogiri'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ # = Redsys Merchant Gateway
7
+ #
8
+ # Gateway support for the Spanish "Redsys" payment gateway system. This is
9
+ # used by many banks in Spain and is particularly well supported by
10
+ # Catalunya Caixa's ecommerce department.
11
+ #
12
+ # Redsys requires an order_id be provided with each transaction and it must
13
+ # follow a specific format. The rules are as follows:
14
+ #
15
+ # * First 4 digits must be numerical
16
+ # * Remaining 8 digits may be alphanumeric
17
+ # * Max length: 12
18
+ #
19
+ # If an invalid order_id is provided, we do our best to clean it up.
20
+ #
21
+ # Much of the code for this library is based on the active_merchant_sermepa
22
+ # integration gateway which uses essentially the same API but with the
23
+ # banks own payment screen.
24
+ #
25
+ # Written by Samuel Lown for Cabify. For implementation questions, or
26
+ # test access details please get in touch: sam@cabify.com.
27
+ class RedsysGateway < Gateway
28
+ self.live_url = "https://sis.sermepa.es/sis/operaciones"
29
+ self.test_url = "https://sis-t.redsys.es:25443/sis/operaciones"
30
+
31
+ self.supported_countries = ['ES']
32
+ self.default_currency = 'EUR'
33
+ self.money_format = :cents
34
+
35
+ # Not all card types may be activated by the bank!
36
+ self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :diners_club]
37
+ self.homepage_url = "http://www.redsys.es/"
38
+ self.display_name = "Redsys"
39
+
40
+ CURRENCY_CODES = {
41
+ "ARS" => '032',
42
+ "AUD" => '036',
43
+ "BRL" => '986',
44
+ "BOB" => '068',
45
+ "CAD" => '124',
46
+ "CHF" => '756',
47
+ "CLP" => '152',
48
+ "COP" => '170',
49
+ "EUR" => '978',
50
+ "GBP" => '826',
51
+ "GTQ" => '320',
52
+ "JPY" => '392',
53
+ "MYR" => '458',
54
+ "MXN" => '484',
55
+ "NZD" => '554',
56
+ "PEN" => '604',
57
+ "RUB" => '643',
58
+ "SGD" => '702',
59
+ "USD" => '840',
60
+ "UYU" => '858'
61
+ }
62
+
63
+ # The set of supported transactions for this gateway.
64
+ # More operations are supported by the gateway itself, but
65
+ # are not supported in this library.
66
+ SUPPORTED_TRANSACTIONS = {
67
+ :purchase => 'A',
68
+ :authorize => '1',
69
+ :capture => '2',
70
+ :refund => '3',
71
+ :cancel => '9'
72
+ }
73
+
74
+ # These are the text meanings sent back by the acquirer when
75
+ # a card has been rejected. Syntax or general request errors
76
+ # are not covered here.
77
+ RESPONSE_TEXTS = {
78
+ 0 => "Transaction Approved",
79
+ 400 => "Cancellation Accepted",
80
+ 481 => "Cancellation Accepted",
81
+ 500 => "Reconciliation Accepted",
82
+ 900 => "Refund / Confirmation approved",
83
+
84
+ 101 => "Card expired",
85
+ 102 => "Card blocked temporarily or under susciption of fraud",
86
+ 104 => "Transaction not permitted",
87
+ 107 => "Contact the card issuer",
88
+ 109 => "Invalid identification by merchant or POS terminal",
89
+ 110 => "Invalid amount",
90
+ 114 => "Card cannot be used to the requested transaction",
91
+ 116 => "Insufficient credit",
92
+ 118 => "Non-registered card",
93
+ 125 => "Card not effective",
94
+ 129 => "CVV2/CVC2 Error",
95
+ 167 => "Contact the card issuer: suspected fraud",
96
+ 180 => "Card out of service",
97
+ 181 => "Card with credit or debit restrictions",
98
+ 182 => "Card with credit or debit restrictions",
99
+ 184 => "Authentication error",
100
+ 190 => "Refusal with no specific reason",
101
+ 191 => "Expiry date incorrect",
102
+
103
+ 201 => "Card expired",
104
+ 202 => "Card blocked temporarily or under suspicion of fraud",
105
+ 204 => "Transaction not permitted",
106
+ 207 => "Contact the card issuer",
107
+ 208 => "Lost or stolen card",
108
+ 209 => "Lost or stolen card",
109
+ 280 => "CVV2/CVC2 Error",
110
+ 290 => "Declined with no specific reason",
111
+
112
+ 480 => "Original transaction not located, or time-out exceeded",
113
+ 501 => "Original transaction not located, or time-out exceeded",
114
+ 502 => "Original transaction not located, or time-out exceeded",
115
+ 503 => "Original transaction not located, or time-out exceeded",
116
+
117
+ 904 => "Merchant not registered at FUC",
118
+ 909 => "System error",
119
+ 912 => "Issuer not available",
120
+ 913 => "Duplicate transmission",
121
+ 916 => "Amount too low",
122
+ 928 => "Time-out exceeded",
123
+ 940 => "Transaction cancelled previously",
124
+ 941 => "Authorization operation already cancelled",
125
+ 942 => "Original authorization declined",
126
+ 943 => "Different details from origin transaction",
127
+ 944 => "Session error",
128
+ 945 => "Duplicate transmission",
129
+ 946 => "Cancellation of transaction while in progress",
130
+ 947 => "Duplicate tranmission while in progress",
131
+ 949 => "POS Inoperative",
132
+ 950 => "Refund not possible",
133
+ 9064 => "Card number incorrect",
134
+ 9078 => "No payment method available",
135
+ 9093 => "Non-existent card",
136
+ 9218 => "Recursive transaction in bad gateway",
137
+ 9253 => "Check-digit incorrect",
138
+ 9256 => "Preauth not allowed for merchant",
139
+ 9257 => "Preauth not allowed for card",
140
+ 9261 => "Operating limit exceeded",
141
+ 9912 => "Issuer not available",
142
+ 9913 => "Confirmation error",
143
+ 9914 => "KO Confirmation"
144
+ }
145
+
146
+ # Creates a new instance
147
+ #
148
+ # Redsys requires a login and secret_key, and optionally also accepts a
149
+ # non-default terminal.
150
+ #
151
+ # ==== Options
152
+ #
153
+ # * <tt>:login</tt> -- The Redsys Merchant ID (REQUIRED)
154
+ # * <tt>:secret_key</tt> -- The Redsys Secret Key. (REQUIRED)
155
+ # * <tt>:terminal</tt> -- The Redsys Terminal. Defaults to 1. (OPTIONAL)
156
+ # * <tt>:test</tt> -- +true+ or +false+. Defaults to +false+. (OPTIONAL)
157
+ def initialize(options = {})
158
+ requires!(options, :login, :secret_key)
159
+ options[:terminal] ||= 1
160
+ super
161
+ end
162
+
163
+ def purchase(money, payment, options = {})
164
+ requires!(options, :order_id)
165
+
166
+ data = {}
167
+ add_action(data, :purchase)
168
+ add_amount(data, money, options)
169
+ add_order(data, options[:order_id])
170
+ add_payment(data, payment)
171
+ data[:description] = options[:description]
172
+ data[:store_in_vault] = options[:store]
173
+
174
+ commit data
175
+ end
176
+
177
+ def authorize(money, payment, options = {})
178
+ requires!(options, :order_id)
179
+
180
+ data = {}
181
+ add_action(data, :authorize)
182
+ add_amount(data, money, options)
183
+ add_order(data, options[:order_id])
184
+ add_payment(data, payment)
185
+ data[:description] = options[:description]
186
+ data[:store_in_vault] = options[:store]
187
+
188
+ commit data
189
+ end
190
+
191
+ def capture(money, authorization, options = {})
192
+ data = {}
193
+ add_action(data, :capture)
194
+ add_amount(data, money, options)
195
+ order_id, _, _ = split_authorization(authorization)
196
+ add_order(data, order_id)
197
+ data[:description] = options[:description]
198
+
199
+ commit data
200
+ end
201
+
202
+ def void(authorization, options = {})
203
+ data = {}
204
+ add_action(data, :cancel)
205
+ order_id, amount, currency = split_authorization(authorization)
206
+ add_amount(data, amount, :currency => currency)
207
+ add_order(data, order_id)
208
+ data[:description] = options[:description]
209
+
210
+ commit data
211
+ end
212
+
213
+ def refund(money, authorization, options = {})
214
+ data = {}
215
+ add_action(data, :refund)
216
+ add_amount(data, money, options)
217
+ order_id, _, _ = split_authorization(authorization)
218
+ add_order(data, order_id)
219
+ data[:description] = options[:description]
220
+
221
+ commit data
222
+ end
223
+
224
+ def verify(creditcard, options = {})
225
+ MultiResponse.run(:use_first_response) do |r|
226
+ r.process { authorize(100, creditcard, options) }
227
+ r.process(:ignore_result) { void(r.authorization, options) }
228
+ end
229
+ end
230
+
231
+ private
232
+
233
+ def add_action(data, action)
234
+ data[:action] = transaction_code(action)
235
+ end
236
+
237
+ def add_amount(data, money, options)
238
+ data[:amount] = amount(money).to_s
239
+ data[:currency] = currency_code(options[:currency] || currency(money))
240
+ end
241
+
242
+ def add_order(data, order_id)
243
+ data[:order_id] = clean_order_id(order_id)
244
+ end
245
+
246
+ def url
247
+ test? ? test_url : live_url
248
+ end
249
+
250
+ def add_payment(data, card)
251
+ if card.is_a?(String)
252
+ data[:credit_card_token] = card
253
+ else
254
+ name = [card.first_name, card.last_name].join(' ').slice(0, 60)
255
+ year = sprintf("%.4i", card.year)
256
+ month = sprintf("%.2i", card.month)
257
+ data[:card] = {
258
+ :name => name,
259
+ :pan => card.number,
260
+ :date => "#{year[2..3]}#{month}",
261
+ :cvv => card.verification_value
262
+ }
263
+ end
264
+ end
265
+
266
+ def commit(data)
267
+ headers = {
268
+ 'Content-Type' => 'application/x-www-form-urlencoded'
269
+ }
270
+ xml = build_xml_request(data)
271
+ parse(ssl_post(url, "entrada=#{CGI.escape(xml)}", headers))
272
+ end
273
+
274
+ def build_signature(data)
275
+ str = data[:amount] +
276
+ data[:order_id].to_s +
277
+ @options[:login].to_s +
278
+ data[:currency]
279
+
280
+ if card = data[:card]
281
+ str << card[:pan]
282
+ str << card[:cvv] if card[:cvv]
283
+ end
284
+
285
+ str << data[:action]
286
+ if data[:store_in_vault]
287
+ str << 'REQUIRED'
288
+ elsif data[:credit_card_token]
289
+ str << data[:credit_card_token]
290
+ end
291
+ str << @options[:secret_key]
292
+
293
+ Digest::SHA1.hexdigest(str)
294
+ end
295
+
296
+ def build_xml_request(data)
297
+ xml = Builder::XmlMarkup.new :indent => 2
298
+ xml.DATOSENTRADA do
299
+ # Basic elements
300
+ xml.DS_Version 0.1
301
+ xml.DS_MERCHANT_CURRENCY data[:currency]
302
+ xml.DS_MERCHANT_AMOUNT data[:amount]
303
+ xml.DS_MERCHANT_ORDER data[:order_id]
304
+ xml.DS_MERCHANT_TRANSACTIONTYPE data[:action]
305
+ xml.DS_MERCHANT_PRODUCTDESCRIPTION data[:description]
306
+ xml.DS_MERCHANT_TERMINAL @options[:terminal]
307
+ xml.DS_MERCHANT_MERCHANTCODE @options[:login]
308
+ xml.DS_MERCHANT_MERCHANTSIGNATURE build_signature(data)
309
+
310
+ # Only when card is present
311
+ if data[:card]
312
+ xml.DS_MERCHANT_TITULAR data[:card][:name]
313
+ xml.DS_MERCHANT_PAN data[:card][:pan]
314
+ xml.DS_MERCHANT_EXPIRYDATE data[:card][:date]
315
+ xml.DS_MERCHANT_CVV2 data[:card][:cvv]
316
+ xml.DS_MERCHANT_IDENTIFIER 'REQUIRED' if data[:store_in_vault]
317
+ elsif data[:credit_card_token]
318
+ xml.DS_MERCHANT_IDENTIFIER data[:credit_card_token]
319
+ end
320
+ end
321
+ xml.target!
322
+ end
323
+
324
+ def parse(data)
325
+ params = {}
326
+ success = false
327
+ message = ""
328
+ options = @options.merge(:test => test?)
329
+ xml = Nokogiri::XML(data)
330
+ code = xml.xpath("//RETORNOXML/CODIGO").text
331
+ if code == "0"
332
+ op = xml.xpath("//RETORNOXML/OPERACION")
333
+ op.children.each do |element|
334
+ params[element.name.downcase.to_sym] = element.text
335
+ end
336
+
337
+ if validate_signature(params)
338
+ message = response_text(params[:ds_response])
339
+ options[:authorization] = build_authorization(params)
340
+ success = is_success_response?(params[:ds_response])
341
+ else
342
+ message = "Response failed validation check"
343
+ end
344
+ else
345
+ # Some kind of programmer error with the request!
346
+ message = "#{code} ERROR"
347
+ end
348
+
349
+ Response.new(success, message, params, options)
350
+ end
351
+
352
+ def validate_signature(data)
353
+ str = data[:ds_amount] +
354
+ data[:ds_order].to_s +
355
+ data[:ds_merchantcode] +
356
+ data[:ds_currency] +
357
+ data[:ds_response] +
358
+ data[:ds_cardnumber].to_s +
359
+ data[:ds_transactiontype].to_s +
360
+ data[:ds_securepayment].to_s +
361
+ @options[:secret_key]
362
+
363
+ sig = Digest::SHA1.hexdigest(str)
364
+ data[:ds_signature].to_s.downcase == sig
365
+ end
366
+
367
+ def build_authorization(params)
368
+ [params[:ds_order], params[:ds_amount], params[:ds_currency]].join("|")
369
+ end
370
+
371
+ def split_authorization(authorization)
372
+ order_id, amount, currency = authorization.split("|")
373
+ [order_id, amount.to_i, currency]
374
+ end
375
+
376
+ def currency_code(currency)
377
+ return currency if currency =~ /^\d+$/
378
+ raise ArgumentError, "Unknown currency #{currency}" unless CURRENCY_CODES[currency]
379
+ CURRENCY_CODES[currency]
380
+ end
381
+
382
+ def transaction_code(type)
383
+ SUPPORTED_TRANSACTIONS[type]
384
+ end
385
+
386
+ def response_text(code)
387
+ code = code.to_i
388
+ code = 0 if code < 100
389
+ RESPONSE_TEXTS[code] || "Unkown code, please check in manual"
390
+ end
391
+
392
+ def is_success_response?(code)
393
+ (code.to_i < 100) || [400, 481, 500, 900].include?(code.to_i)
394
+ end
395
+
396
+ def clean_order_id(order_id)
397
+ cleansed = order_id.gsub(/[^\da-zA-Z]/, '')
398
+ if cleansed =~ /^\d{4}/
399
+ cleansed[0..11]
400
+ else
401
+ "%04d%s" % [rand(0..9999), cleansed[0...8]]
402
+ end
403
+ end
404
+ end
405
+ end
406
+ end
@@ -0,0 +1,226 @@
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class S5Gateway < Gateway
6
+ self.test_url = 'https://test.ctpe.io/payment/ctpe'
7
+ self.live_url = 'https://ctpe.io/payment/ctpe'
8
+
9
+ self.supported_countries = ['DK']
10
+ self.default_currency = 'EUR'
11
+ self.supported_cardtypes = [:visa, :master, :maestro]
12
+
13
+ self.homepage_url = 'http://www.s5.dk/'
14
+ self.display_name = 'S5'
15
+
16
+ SUPPORTED_TRANSACTIONS = {
17
+ 'sale' => 'CC.DB',
18
+ 'authonly' => 'CC.PA',
19
+ 'capture' => 'CC.CP',
20
+ 'refund' => 'CC.RF',
21
+ 'void' => 'CC.RV',
22
+ }
23
+
24
+ def initialize(options={})
25
+ requires!(options, :sender, :channel, :login, :password)
26
+ super
27
+ end
28
+
29
+ def purchase(money, payment, options={})
30
+ request = build_xml_request do |xml|
31
+ add_payment(xml, money, 'sale', options)
32
+ add_account(xml, payment)
33
+ add_customer(xml, payment, options)
34
+ add_recurrence_mode(xml, options)
35
+ end
36
+
37
+ commit(request)
38
+ end
39
+
40
+ def refund(money, authorization, options={})
41
+ request = build_xml_request do |xml|
42
+ add_identification(xml, authorization)
43
+ add_payment(xml, money, 'refund', options)
44
+ end
45
+
46
+ commit(request)
47
+ end
48
+
49
+ def authorize(money, payment, options={})
50
+ request = build_xml_request do |xml|
51
+ add_payment(xml, money, 'authonly', options)
52
+ add_account(xml, payment)
53
+ add_customer(xml, payment, options)
54
+ add_recurrence_mode(xml, options)
55
+ end
56
+
57
+ commit(request)
58
+ end
59
+
60
+ def capture(money, authorization, options={})
61
+ request = build_xml_request do |xml|
62
+ add_identification(xml, authorization)
63
+ add_payment(xml, money, 'capture', options)
64
+ end
65
+
66
+ commit(request)
67
+ end
68
+
69
+ def void(authorization, options={})
70
+ request = build_xml_request do |xml|
71
+ add_identification(xml, authorization)
72
+ add_payment(xml, nil, 'void', options)
73
+ end
74
+
75
+ commit(request)
76
+ end
77
+
78
+ def verify(credit_card, options={})
79
+ MultiResponse.run(:use_first_response) do |r|
80
+ r.process { authorize(100, credit_card, options) }
81
+ r.process(:ignore_result) { void(r.authorization, options) }
82
+ end
83
+ end
84
+
85
+ def supports_scrubbing?
86
+ true
87
+ end
88
+
89
+ def scrub(transcript)
90
+ transcript.
91
+ gsub(%r((pwd=).+?(/>))i, '\1[FILTERED]\2').
92
+ gsub(%r((<Number>).+?(</Number>))i, '\1[FILTERED]\2').
93
+ gsub(%r((<Verification>).+?(</Verification>))i, '\1[FILTERED]\2')
94
+ end
95
+
96
+ private
97
+
98
+ def add_identification(xml, authorization)
99
+ xml.Identification do
100
+ xml.ReferenceID authorization
101
+ end
102
+ end
103
+
104
+ def add_payment(xml, money, action, options)
105
+ xml.Payment(code: SUPPORTED_TRANSACTIONS[action]) do
106
+ xml.Memo "return_code=#{options[:memo]}" if options[:memo]
107
+ xml.Presentation do
108
+ xml.Amount amount(money)
109
+ xml.Currency options[:currency] || currency(money)
110
+ xml.Usage options[:description]
111
+ end
112
+ end
113
+ end
114
+
115
+ def add_account(xml, creditcard)
116
+ xml.Account do
117
+ xml.Number creditcard.number
118
+ xml.Holder "#{creditcard.first_name} #{creditcard.last_name}"
119
+ xml.Brand creditcard.brand
120
+ xml.Expiry(year: creditcard.year, month: creditcard.month)
121
+ xml.Verification creditcard.verification_value
122
+ end
123
+ end
124
+
125
+ def add_customer(xml, creditcard, options)
126
+ address = options[:billing_address]
127
+ xml.Customer do
128
+ xml.Contact do
129
+ xml.Email options[:email]
130
+ xml.Ip options[:ip]
131
+ xml.Phone address[:phone] if address
132
+ end
133
+ add_address(xml, address)
134
+ xml.Name do
135
+ xml.Given creditcard.first_name
136
+ xml.Family creditcard.last_name
137
+ xml.Company options[:company]
138
+ end
139
+ end
140
+ end
141
+
142
+ def add_address(xml, address)
143
+ return unless address
144
+
145
+ xml.Address do
146
+ xml.Street "#{address[:address1]} #{address[:address2]}"
147
+ xml.Zip address[:zip]
148
+ xml.City address[:city]
149
+ xml.State address[:state]
150
+ xml.Country address[:country]
151
+ end
152
+ end
153
+
154
+ def add_recurrence_mode(xml, options)
155
+ if options[:recurring] == true
156
+ xml.Recurrence(mode: "REPEATED")
157
+ else
158
+ xml.Recurrence(mode: "INITIAL")
159
+ end
160
+ end
161
+
162
+ def parse(body)
163
+ results = {}
164
+ xml = Nokogiri::XML(body)
165
+ resp = xml.xpath("//Response/Transaction/Identification")
166
+ resp.children.each do |element|
167
+ results[element.name.downcase.to_sym] = element.text
168
+ end
169
+ resp = xml.xpath("//Response/Transaction/Processing")
170
+ resp.children.each do |element|
171
+ results[element.name.downcase.to_sym] = element.text
172
+ end
173
+ results
174
+ end
175
+
176
+ def commit(xml)
177
+ url = (test? ? test_url : live_url)
178
+ headers = {
179
+ 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'
180
+ }
181
+
182
+ response = parse(ssl_post(url, post_data(xml), headers))
183
+
184
+ Response.new(
185
+ success_from(response),
186
+ message_from(response),
187
+ response,
188
+ authorization: authorization_from(response),
189
+ test: test?
190
+ )
191
+ end
192
+
193
+ def success_from(response)
194
+ response[:result] == 'ACK'
195
+ end
196
+
197
+ def message_from(response)
198
+ response[:return]
199
+ end
200
+
201
+ def authorization_from(response)
202
+ response[:uniqueid]
203
+ end
204
+
205
+ def post_data(xml)
206
+ "load=#{xml}"
207
+ end
208
+
209
+ def build_xml_request
210
+ builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
211
+ xml.Request(version: '1.0') do
212
+ xml.Header do
213
+ xml.Security(sender: @options[:sender])
214
+ end
215
+ xml.Transaction(mode: @options[:mode] || 'LIVE', channel: @options[:channel]) do
216
+ xml.User(login: @options[:login], pwd: @options[:password])
217
+ yield(xml)
218
+ end
219
+ end
220
+ end
221
+
222
+ builder.to_xml
223
+ end
224
+ end
225
+ end
226
+ end