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,262 @@
1
+ require "nokogiri"
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class CenposGateway < Gateway
6
+ self.display_name = "CenPOS"
7
+ self.homepage_url = "https://www.cenpos.com/"
8
+
9
+ self.live_url = "https://ww3.cenpos.net/6/transact.asmx"
10
+
11
+ self.supported_countries = %w(AD AI AG AR AU AT BS BB BE BZ BM BR BN BG CA HR CY CZ DK DM EE FI FR DE GR GD GY HK HU IS IN IL IT JP LV LI LT LU MY MT MX MC MS NL PA PL PT KN LC MF VC SM SG SK SI ZA ES SR SE CH TR GB US UY)
12
+ self.default_currency = "USD"
13
+ self.money_format = :dollars
14
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
15
+
16
+ def initialize(options={})
17
+ requires!(options, :merchant_id, :password, :user_id)
18
+ super
19
+ end
20
+
21
+ def purchase(amount, payment_method, options={})
22
+ post = {}
23
+ add_invoice(post, amount, options)
24
+ add_payment_method(post, payment_method)
25
+ add_customer_data(post, options)
26
+
27
+ commit("Sale", post)
28
+ end
29
+
30
+ def authorize(amount, payment_method, options={})
31
+ post = {}
32
+ add_invoice(post, amount, options)
33
+ add_payment_method(post, payment_method)
34
+ add_customer_data(post, options)
35
+
36
+ commit("Auth", post)
37
+ end
38
+
39
+ def capture(amount, authorization, options={})
40
+ post = {}
41
+ add_invoice(post, amount, options)
42
+ add_reference(post, authorization)
43
+ add_customer_data(post, options)
44
+
45
+ commit("SpecialForce", post)
46
+ end
47
+
48
+ def void(authorization, options={})
49
+ post = {}
50
+ add_void_required_elements(post)
51
+ add_reference(post, authorization)
52
+ add_remembered_amount(post, authorization)
53
+ add_tax(post, options)
54
+
55
+ commit("Void", post)
56
+ end
57
+
58
+ def refund(amount, authorization, options={})
59
+ post = {}
60
+ add_invoice(post, amount, options)
61
+ add_reference(post, authorization)
62
+ add_customer_data(post, options)
63
+
64
+ commit("SpecialReturn", post)
65
+ end
66
+
67
+ def credit(amount, payment_method, options={})
68
+ post = {}
69
+ add_invoice(post, amount, options)
70
+ add_payment_method(post, payment_method)
71
+
72
+ commit("Credit", post)
73
+ end
74
+
75
+ def verify(credit_card, options={})
76
+ MultiResponse.run(:use_first_response) do |r|
77
+ r.process { authorize(100, credit_card, options) }
78
+ r.process(:ignore_result) { void(r.authorization, options) }
79
+ end
80
+ end
81
+
82
+ def supports_scrubbing?
83
+ true
84
+ end
85
+
86
+ def scrub(transcript)
87
+ transcript.
88
+ gsub(%r((<acr1:CardNumber>)[^<]+(<))i, '\1[FILTERED]\2').
89
+ gsub(%r((<acr1:CardVerificationNumber>)[^<]+(<))i, '\1[FILTERED]\2').
90
+ gsub(%r((<acr:Password>)[^<]+(<))i, '\1[FILTERED]\2')
91
+ end
92
+
93
+ private
94
+
95
+ def add_invoice(post, money, options)
96
+ post[:Amount] = amount(money)
97
+ post[:CurrencyCode] = options[:currency] || currency(money)
98
+ post[:InvoiceNumber] = options[:order_id]
99
+ post[:InvoiceDetail] = options[:invoice_detail] if options[:invoice_detail]
100
+ post[:CustomerCode] = options[:customer_code] if options[:customer_code]
101
+ add_tax(post, options)
102
+ end
103
+
104
+ def add_payment_method(post, payment_method)
105
+ post[:NameOnCard] = payment_method.name
106
+ post[:CardNumber] = payment_method.number
107
+ post[:CardVerificationNumber] = payment_method.verification_value
108
+ post[:CardExpirationDate] = format(payment_method.month, :two_digits) + format(payment_method.year, :two_digits)
109
+ post[:CardLastFourDigits] = payment_method.last_digits
110
+ post[:MagneticData] = payment_method.track_data if payment_method.track_data
111
+ end
112
+
113
+ def add_customer_data(post, options)
114
+ if(billing_address = (options[:billing_address] || options[:address]))
115
+ post[:CustomerEmailAddress] = billing_address[:email]
116
+ post[:CustomerPhone] = billing_address[:phone]
117
+ post[:CustomerBillingAddress] = billing_address[:address1]
118
+ post[:CustomerCity] = billing_address[:city]
119
+ post[:CustomerState] = billing_address[:state]
120
+ post[:CustomerZipCode] = billing_address[:zip]
121
+ end
122
+ end
123
+
124
+ def add_void_required_elements(post)
125
+ post[:GeoLocationInformation] = nil
126
+ post[:IMEI] = nil
127
+ end
128
+
129
+ def add_tax(post, options)
130
+ post[:TaxAmount] = amount(options[:tax] || 0)
131
+ end
132
+
133
+ def add_reference(post, authorization)
134
+ reference_number, last_four_digits = split_authorization(authorization)
135
+ post[:ReferenceNumber] = reference_number
136
+ post[:CardLastFourDigits] = last_four_digits
137
+ end
138
+
139
+ def add_remembered_amount(post, authorization)
140
+ post[:Amount] = split_authorization(authorization).last
141
+ end
142
+
143
+ def commit(action, post)
144
+ post[:MerchantId] = @options[:merchant_id]
145
+ post[:Password] = @options[:password]
146
+ post[:UserId] = @options[:user_id]
147
+ post[:TransactionType] = action
148
+
149
+ data = build_request(post)
150
+ begin
151
+ raw = parse(ssl_post(self.live_url, data, headers))
152
+ rescue ActiveMerchant::ResponseError => e
153
+ if(e.response.code == "500" && e.response.body.start_with?("<s:Envelope"))
154
+ raw = {
155
+ message: "See transcript for detailed error description."
156
+ }
157
+ else
158
+ raise
159
+ end
160
+ end
161
+
162
+ succeeded = success_from(raw[:result])
163
+ Response.new(
164
+ succeeded,
165
+ message_from(succeeded, raw),
166
+ raw,
167
+ authorization: authorization_from(post, raw),
168
+ error_code: error_code_from(succeeded, raw),
169
+ test: test?
170
+ )
171
+ end
172
+
173
+ def headers
174
+ {
175
+ "Accept-Encoding" => "gzip,deflate",
176
+ "Content-Type" => "text/xml;charset=UTF-8",
177
+ "SOAPAction" => "http://tempuri.org/Transactional/ProcessCreditCard"
178
+ }
179
+ end
180
+
181
+ def build_request(post)
182
+ xml = Builder::XmlMarkup.new :indent => 8
183
+ xml.tag!("acr:MerchantId", post.delete(:MerchantId))
184
+ xml.tag!("acr:Password", post.delete(:Password))
185
+ xml.tag!("acr:UserId", post.delete(:UserId))
186
+ post.sort.each do |field, value|
187
+ xml.tag!("acr1:#{field}", value)
188
+ end
189
+ envelope(xml.target!)
190
+ end
191
+
192
+ def envelope(body)
193
+ <<-EOS
194
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:acr="http://schemas.datacontract.org/2004/07/Acriter.ABI.CenPOS.EPayment.VirtualTerminal.Common" xmlns:acr1="http://schemas.datacontract.org/2004/07/Acriter.ABI.CenPOS.EPayment.VirtualTerminal.v6.Common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
195
+ <soapenv:Header/>
196
+ <soapenv:Body>
197
+ <tem:ProcessCreditCard>
198
+ <tem:request>
199
+ #{body}
200
+ </tem:request>
201
+ </tem:ProcessCreditCard>
202
+ </soapenv:Body>
203
+ </soapenv:Envelope>
204
+ EOS
205
+ end
206
+
207
+ def parse(xml)
208
+ response = {}
209
+
210
+ doc = Nokogiri::XML(xml)
211
+ doc.remove_namespaces!
212
+ body = doc.xpath("//ProcessCreditCardResult")
213
+ body.children.each do |node|
214
+ if (node.elements.size == 0)
215
+ response[node.name.underscore.to_sym] = node.text
216
+ else
217
+ node.elements.each do |childnode|
218
+ name = "#{node.name.underscore}_#{childnode.name.underscore}"
219
+ response[name.to_sym] = childnode.text
220
+ end
221
+ end
222
+ end unless doc.root.nil?
223
+
224
+ response
225
+ end
226
+
227
+ def success_from(response)
228
+ response == "0"
229
+ end
230
+
231
+ def message_from(succeeded, response)
232
+ if succeeded
233
+ "Succeeded"
234
+ else
235
+ response[:message] || "Unable to read error message"
236
+ end
237
+ end
238
+
239
+ STANDARD_ERROR_CODE_MAPPING = {
240
+ "211" => STANDARD_ERROR_CODE[:invalid_number],
241
+ "252" => STANDARD_ERROR_CODE[:invalid_expiry_date],
242
+ "257" => STANDARD_ERROR_CODE[:invalid_cvc],
243
+ "333" => STANDARD_ERROR_CODE[:expired_card],
244
+ "1" => STANDARD_ERROR_CODE[:card_declined],
245
+ "99" => STANDARD_ERROR_CODE[:processing_error],
246
+ }
247
+
248
+ def authorization_from(request, response)
249
+ [ response[:reference_number], request[:CardLastFourDigits], request[:Amount] ].join("|")
250
+ end
251
+
252
+ def split_authorization(authorization)
253
+ reference_number, last_four_digits, original_amount = authorization.split("|")
254
+ [reference_number, last_four_digits, original_amount]
255
+ end
256
+
257
+ def error_code_from(succeeded, response)
258
+ succeeded ? nil : STANDARD_ERROR_CODE_MAPPING[response[:result]]
259
+ end
260
+ end
261
+ end
262
+ end
@@ -0,0 +1,278 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class CertoDirectGateway < Gateway
4
+ self.live_url = self.test_url = "https://secure.certodirect.com/gateway/process/v2"
5
+
6
+ self.supported_countries = [
7
+ "BE", "BG", "CZ", "DK", "DE", "EE", "IE", "ES", "FR",
8
+ "IT", "CY", "LV", "LT", "LU", "HU", "MT", "NL", "AT", "PL",
9
+ "PT", "RO", "SI", "SK", "FI", "SE", "GB"
10
+ ]
11
+
12
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
13
+ self.homepage_url = 'http://www.certodirect.com/'
14
+ self.display_name = 'CertoDirect'
15
+
16
+ # Creates a new CertoDirectGateway
17
+ #
18
+ # The gateway requires that a valid login and password be passed
19
+ # in the +options+ hash.
20
+ #
21
+ # ==== Options
22
+ #
23
+ # * <tt>:login</tt> -- The CertoDirect Shop ID (REQUIRED)
24
+ # * <tt>:password</tt> -- The CertoDirect Shop Password. (REQUIRED)
25
+ # * <tt>:test</tt> -- +true+ or +false+. If true, perform transactions against the test server.
26
+ # Otherwise, perform transactions against the production server.
27
+ def initialize(options = {})
28
+ requires!(options, :login, :password)
29
+ super
30
+ end
31
+
32
+ # Perform a purchase, which is essentially an authorization and capture in a single operation.
33
+ #
34
+ # ==== Parameters
35
+ #
36
+ # * <tt>money</tt> -- The amount to be purchased as an Integer value in cents.
37
+ # * <tt>credit_card</tt> -- The CreditCard details for the transaction.
38
+ # * <tt>options</tt> -- A hash of optional parameters.
39
+ def purchase(money, credit_card, options = {})
40
+ requires!(options, :email, :currency, :ip, :description)
41
+
42
+ commit(build_sale_request(money, credit_card, options))
43
+ end
44
+
45
+ # Refund a transaction.
46
+ #
47
+ # This transaction indicates to the gateway that
48
+ # money should flow from the merchant to the customer.
49
+ #
50
+ # ==== Parameters
51
+ #
52
+ # * <tt>money</tt> -- The amount to be credited to the customer as an Integer value in cents.
53
+ # * <tt>identification</tt> -- The ID of the original order against which the refund is being issued.
54
+ # * <tt>options</tt> -- A hash of parameters.
55
+ def refund(money, identification, options = {})
56
+ requires!(options, :reason)
57
+
58
+ commit(build_refund_request(money, identification, options))
59
+ end
60
+
61
+ # Performs an authorization, which reserves the funds on the customer's credit card, but does not
62
+ # charge the card.
63
+ #
64
+ # ==== Parameters
65
+ #
66
+ # * <tt>money</tt> -- The amount to be authorized as an Integer value in cents.
67
+ # * <tt>credit_card</tt> -- The CreditCard details for the transaction.
68
+ # * <tt>options</tt> -- A hash of optional parameters.
69
+ def authorize(money, credit_card, options = {})
70
+ requires!(options, :email, :currency, :ip, :description)
71
+
72
+ commit(build_authorize_request(money, credit_card, options))
73
+ end
74
+
75
+ # Captures the funds from an authorized transaction.
76
+ #
77
+ # ==== Parameters
78
+ #
79
+ # * <tt>money</tt> -- The amount to be captured as an Integer value in cents.
80
+ # * <tt>identification</tt> -- The authorization returned from the previous authorize request.
81
+ def capture(money, identification, options = {})
82
+ commit(build_capture_request(money, identification))
83
+ end
84
+
85
+ # Void a previous transaction
86
+ #
87
+ # ==== Parameters
88
+ #
89
+ # * <tt>money</tt> -- The amount to be captured as an Integer value in cents.
90
+ # * <tt>identification</tt> - The authorization returned from the previous authorize request.
91
+ def void(money, identification, options = {})
92
+ commit(build_void_request(money, identification))
93
+ end
94
+
95
+ # Create a recurring payment.
96
+ #
97
+ # ==== Parameters
98
+ #
99
+ # * <tt>options</tt> -- A hash of parameters.
100
+ #
101
+ # ==== Options
102
+ #
103
+ def recurring(identification, options={})
104
+ ActiveMerchant.deprecated RECURRING_DEPRECATION_MESSAGE
105
+
106
+ commit(build_recurring_request(identification, options))
107
+ end
108
+
109
+ private
110
+
111
+ def commit(request_xml)
112
+ begin
113
+ response = Hash.from_xml(ssl_post(self.live_url, request_xml, headers))
114
+ Response.new(success?(response),
115
+ message(response),
116
+ response,
117
+ :test => test?,
118
+ :authorization => authorization(response))
119
+ rescue ResponseError => e
120
+ raise e unless e.response.code == '403'
121
+ response = Hash.from_xml(e.response.body)['response']
122
+ Response.new(false, message(response), {}, :test => test?)
123
+ end
124
+ end
125
+
126
+ def build_sale_request(money, credit_card, options)
127
+ build_request_xml('Sale') do |xml|
128
+ add_order(xml, money, credit_card, options)
129
+ end
130
+ end
131
+
132
+ def build_authorize_request(money, credit_card, options)
133
+ build_request_xml('Authorize') do |xml|
134
+ add_order(xml, money, credit_card, options)
135
+ end
136
+ end
137
+
138
+ def build_refund_request(money, identification, options)
139
+ build_request_xml('Refund') do |xml|
140
+ add_reference_info(xml, money, identification, options)
141
+ xml.tag! 'reason', options[:reason]
142
+ end
143
+ end
144
+
145
+ def build_capture_request(money, identification)
146
+ build_request_xml('Capture') do |xml|
147
+ add_reference_info(xml, money, identification, options)
148
+ end
149
+ end
150
+
151
+ def build_void_request(money, identification)
152
+ build_request_xml('Void') do |xml|
153
+ add_reference_info(xml, money, identification, options)
154
+ end
155
+ end
156
+
157
+ def build_recurring_request(identification, options)
158
+ build_request_xml('Sale') do |xml|
159
+ xml.tag! 'order' do
160
+ xml.tag!('test', 'true') if test?
161
+ xml.tag! 'initial_order_id', identification, :type => 'integer'
162
+
163
+ add_order_details(xml, options[:amount], options) if has_any_order_details_key?(options)
164
+ add_address(xml, 'billing_address', options[:billing_address]) if options[:billing_address]
165
+ add_address(xml, 'shipping_address', options[:shipping_address]) if options[:shipping_address]
166
+ end
167
+ end
168
+ end
169
+
170
+ def build_request_xml(type, &block)
171
+ xml = Builder::XmlMarkup.new(:indent => 2)
172
+ xml.tag! 'transaction' do
173
+ xml.tag! 'type', type
174
+ yield(xml)
175
+ end
176
+ xml.target!
177
+ end
178
+
179
+ def add_order(xml, money, credit_card, options)
180
+ xml.tag! 'order' do
181
+ xml.tag!('test', 'true') if test?
182
+
183
+ xml.tag!('return_url', options[:return_url]) if options[:return_url]
184
+ xml.tag!('cancel_url', options[:cancel_url]) if options[:cancel_url]
185
+
186
+ xml.tag! 'payment_method_type', 'CreditCard'
187
+ xml.tag! 'payment_method' do
188
+ xml.tag! 'number', credit_card.number
189
+ xml.tag! 'exp_month', "%02i" % credit_card.month
190
+ xml.tag! 'exp_year', credit_card.year
191
+ xml.tag! 'holder', credit_card.name
192
+ xml.tag! 'verification_value', credit_card.verification_value
193
+ end
194
+
195
+ add_order_details(xml, money, options)
196
+ add_address(xml, 'billing_address', options[:billing_address]) if options[:billing_address]
197
+ add_address(xml, 'shipping_address', options[:shipping_address]) if options[:shipping_address]
198
+ end
199
+ end
200
+
201
+ def add_order_details(xml, money, options)
202
+ xml.tag! 'details' do
203
+ xml.tag!('amount', localized_amount(money, options[:currency]), :type => 'decimal') if money
204
+ xml.tag!('currency', options[:currency]) if options[:currency]
205
+ xml.tag!('email', options[:email]) if options[:email]
206
+ xml.tag!('ip', options[:ip]) if options[:ip]
207
+ xml.tag!('shipping', options[:shipping], :type => 'decimal') if options[:shipping]
208
+ xml.tag!('description', options[:description]) if options[:description]
209
+ end
210
+ end
211
+
212
+ def add_reference_info(xml, money, identification, options)
213
+ xml.tag! 'order_id', identification, :type => 'integer'
214
+ xml.tag! 'amount', localized_amount(money, options[:currency]), :type => 'decimal'
215
+ end
216
+
217
+ def add_address(xml, address_type, address)
218
+ xml.tag! address_type do
219
+ xml.tag! 'address', address[:address1]
220
+ xml.tag! 'city', address[:city]
221
+ xml.tag! 'country', address[:country]
222
+ xml.tag! 'first_name', address[:first_name]
223
+ xml.tag! 'last_name', address[:last_name]
224
+ xml.tag! 'state', address[:state]
225
+ xml.tag! 'phone', address[:phone]
226
+ xml.tag! 'zip', address[:zip]
227
+ end
228
+ end
229
+
230
+ def has_any_order_details_key?(options)
231
+ [ :currency, :amount, :email, :ip, :shipping, :description ].any? do |key|
232
+ options.has_key?(key)
233
+ end
234
+ end
235
+
236
+ def success?(response)
237
+ %w(completed forwarding).include?(state(response)) and
238
+ status(response) == 'success'
239
+ end
240
+
241
+ def error?(response)
242
+ response['errors']
243
+ end
244
+
245
+ def state(response)
246
+ response["transaction"].try(:[], "state")
247
+ end
248
+
249
+ def status(response)
250
+ response['transaction'].try(:[], 'response').try(:[], 'status')
251
+ end
252
+
253
+ def authorization(response)
254
+ error?(response) ? nil : response["transaction"]["order"]['id'].to_s
255
+ end
256
+
257
+ def message(response)
258
+ return response['errors'].join('; ') if error?(response)
259
+
260
+ if state(response) == 'completed'
261
+ response["transaction"]["response"]["message"]
262
+ else
263
+ response['transaction']['message']
264
+ end
265
+ end
266
+
267
+ def headers
268
+ { 'authorization' => basic_auth,
269
+ 'Accept' => 'application/xml',
270
+ 'Content-Type' => 'application/xml' }
271
+ end
272
+
273
+ def basic_auth
274
+ 'Basic ' + ["#{@options[:login]}:#{@options[:password]}"].pack('m').delete("\r\n")
275
+ end
276
+ end
277
+ end
278
+ end