activemerchant 1.133.0 → 1.137.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +240 -0
  3. data/lib/active_merchant/billing/check.rb +2 -2
  4. data/lib/active_merchant/billing/compatibility.rb +4 -4
  5. data/lib/active_merchant/billing/credit_card.rb +11 -8
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +59 -6
  8. data/lib/active_merchant/billing/gateway.rb +9 -0
  9. data/lib/active_merchant/billing/gateways/adyen.rb +162 -43
  10. data/lib/active_merchant/billing/gateways/airwallex.rb +26 -12
  11. data/lib/active_merchant/billing/gateways/alelo.rb +23 -5
  12. data/lib/active_merchant/billing/gateways/authorize_net.rb +43 -35
  13. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +10 -6
  14. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +1 -3
  15. data/lib/active_merchant/billing/gateways/axcessms.rb +6 -2
  16. data/lib/active_merchant/billing/gateways/banwire.rb +4 -2
  17. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -3
  18. data/lib/active_merchant/billing/gateways/blue_pay.rb +13 -5
  19. data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -5
  20. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +65 -20
  21. data/lib/active_merchant/billing/gateways/braintree_blue.rb +226 -73
  22. data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
  23. data/lib/active_merchant/billing/gateways/card_connect.rb +5 -2
  24. data/lib/active_merchant/billing/gateways/card_stream.rb +4 -6
  25. data/lib/active_merchant/billing/gateways/cashnet.rb +1 -1
  26. data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
  27. data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +316 -0
  28. data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
  29. data/lib/active_merchant/billing/gateways/cecabank.rb +7 -240
  30. data/lib/active_merchant/billing/gateways/checkout_v2.rb +238 -34
  31. data/lib/active_merchant/billing/gateways/commerce_hub.rb +63 -6
  32. data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
  33. data/lib/active_merchant/billing/gateways/cyber_source.rb +185 -47
  34. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +102 -58
  35. data/lib/active_merchant/billing/gateways/d_local.rb +26 -15
  36. data/lib/active_merchant/billing/gateways/data_cash.rb +21 -17
  37. data/lib/active_merchant/billing/gateways/datatrans.rb +279 -0
  38. data/lib/active_merchant/billing/gateways/decidir.rb +53 -18
  39. data/lib/active_merchant/billing/gateways/decidir_plus.rb +4 -1
  40. data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
  41. data/lib/active_merchant/billing/gateways/ebanx.rb +40 -36
  42. data/lib/active_merchant/billing/gateways/efsnet.rb +6 -2
  43. data/lib/active_merchant/billing/gateways/elavon.rb +99 -33
  44. data/lib/active_merchant/billing/gateways/element.rb +36 -7
  45. data/lib/active_merchant/billing/gateways/epay.rb +6 -2
  46. data/lib/active_merchant/billing/gateways/evo_ca.rb +6 -2
  47. data/lib/active_merchant/billing/gateways/eway.rb +4 -2
  48. data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -2
  49. data/lib/active_merchant/billing/gateways/exact.rb +6 -2
  50. data/lib/active_merchant/billing/gateways/fat_zebra.rb +31 -3
  51. data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -2
  52. data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
  53. data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
  54. data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
  55. data/lib/active_merchant/billing/gateways/first_pay.rb +6 -172
  56. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -2
  57. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +7 -3
  58. data/lib/active_merchant/billing/gateways/flex_charge.rb +347 -0
  59. data/lib/active_merchant/billing/gateways/garanti.rb +4 -2
  60. data/lib/active_merchant/billing/gateways/global_collect.rb +45 -37
  61. data/lib/active_merchant/billing/gateways/hi_pay.rb +286 -0
  62. data/lib/active_merchant/billing/gateways/hps.rb +1 -1
  63. data/lib/active_merchant/billing/gateways/iats_payments.rb +7 -2
  64. data/lib/active_merchant/billing/gateways/inspire.rb +6 -4
  65. data/lib/active_merchant/billing/gateways/instapay.rb +7 -4
  66. data/lib/active_merchant/billing/gateways/ipg.rb +9 -5
  67. data/lib/active_merchant/billing/gateways/iridium.rb +15 -5
  68. data/lib/active_merchant/billing/gateways/itransact.rb +6 -2
  69. data/lib/active_merchant/billing/gateways/iveri.rb +3 -3
  70. data/lib/active_merchant/billing/gateways/ixopay.rb +2 -2
  71. data/lib/active_merchant/billing/gateways/jetpay.rb +4 -2
  72. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -2
  73. data/lib/active_merchant/billing/gateways/kushki.rb +72 -12
  74. data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -2
  75. data/lib/active_merchant/billing/gateways/litle.rb +33 -50
  76. data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
  77. data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
  78. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +8 -5
  79. data/lib/active_merchant/billing/gateways/merchant_ware.rb +11 -4
  80. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +11 -4
  81. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +19 -3
  82. data/lib/active_merchant/billing/gateways/mercury.rb +6 -2
  83. data/lib/active_merchant/billing/gateways/metrics_global.rb +8 -6
  84. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +1 -0
  85. data/lib/active_merchant/billing/gateways/migs.rb +6 -2
  86. data/lib/active_merchant/billing/gateways/mit.rb +8 -3
  87. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +18 -10
  88. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  89. data/lib/active_merchant/billing/gateways/moneris.rb +9 -3
  90. data/lib/active_merchant/billing/gateways/money_movers.rb +6 -2
  91. data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -4
  92. data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
  93. data/lib/active_merchant/billing/gateways/netbanx.rb +1 -3
  94. data/lib/active_merchant/billing/gateways/netbilling.rb +6 -2
  95. data/lib/active_merchant/billing/gateways/network_merchants.rb +6 -2
  96. data/lib/active_merchant/billing/gateways/nmi.rb +18 -6
  97. data/lib/active_merchant/billing/gateways/ogone.rb +6 -2
  98. data/lib/active_merchant/billing/gateways/openpay.rb +4 -2
  99. data/lib/active_merchant/billing/gateways/opp.rb +1 -2
  100. data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -2
  101. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +1 -3
  102. data/lib/active_merchant/billing/gateways/orbital.rb +83 -24
  103. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +7 -4
  104. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -2
  105. data/lib/active_merchant/billing/gateways/pay_hub.rb +4 -2
  106. data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -2
  107. data/lib/active_merchant/billing/gateways/pay_secure.rb +6 -2
  108. data/lib/active_merchant/billing/gateways/pay_trace.rb +31 -18
  109. data/lib/active_merchant/billing/gateways/payeezy.rb +19 -8
  110. data/lib/active_merchant/billing/gateways/payex.rb +4 -2
  111. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  112. data/lib/active_merchant/billing/gateways/payflow.rb +1 -3
  113. data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
  114. data/lib/active_merchant/billing/gateways/paymentez.rb +23 -11
  115. data/lib/active_merchant/billing/gateways/paysafe.rb +12 -11
  116. data/lib/active_merchant/billing/gateways/payscout.rb +7 -4
  117. data/lib/active_merchant/billing/gateways/paystation.rb +7 -3
  118. data/lib/active_merchant/billing/gateways/payway.rb +6 -2
  119. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +2 -2
  120. data/lib/active_merchant/billing/gateways/pin.rb +22 -4
  121. data/lib/active_merchant/billing/gateways/plexo.rb +49 -10
  122. data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
  123. data/lib/active_merchant/billing/gateways/priority.rb +6 -5
  124. data/lib/active_merchant/billing/gateways/psigate.rb +6 -2
  125. data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
  126. data/lib/active_merchant/billing/gateways/qbms.rb +6 -2
  127. data/lib/active_merchant/billing/gateways/quantum.rb +6 -2
  128. data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -5
  129. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
  130. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +6 -2
  131. data/lib/active_merchant/billing/gateways/rapyd.rb +148 -46
  132. data/lib/active_merchant/billing/gateways/reach.rb +11 -4
  133. data/lib/active_merchant/billing/gateways/redsys.rb +2 -10
  134. data/lib/active_merchant/billing/gateways/redsys_rest.rb +507 -0
  135. data/lib/active_merchant/billing/gateways/s5.rb +3 -3
  136. data/lib/active_merchant/billing/gateways/safe_charge.rb +36 -16
  137. data/lib/active_merchant/billing/gateways/sage.rb +12 -4
  138. data/lib/active_merchant/billing/gateways/sage_pay.rb +79 -5
  139. data/lib/active_merchant/billing/gateways/sallie_mae.rb +6 -2
  140. data/lib/active_merchant/billing/gateways/secure_net.rb +6 -2
  141. data/lib/active_merchant/billing/gateways/secure_pay.rb +8 -6
  142. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -4
  143. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +6 -2
  144. data/lib/active_merchant/billing/gateways/securion_pay.rb +24 -10
  145. data/lib/active_merchant/billing/gateways/shift4.rb +17 -20
  146. data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
  147. data/lib/active_merchant/billing/gateways/simetrik.rb +17 -11
  148. data/lib/active_merchant/billing/gateways/skip_jack.rb +6 -2
  149. data/lib/active_merchant/billing/gateways/smart_ps.rb +7 -4
  150. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +4 -2
  151. data/lib/active_merchant/billing/gateways/spreedly_core.rb +2 -4
  152. data/lib/active_merchant/billing/gateways/stripe.rb +53 -21
  153. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +199 -50
  154. data/lib/active_merchant/billing/gateways/sum_up.rb +223 -0
  155. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +4 -2
  156. data/lib/active_merchant/billing/gateways/telr.rb +3 -4
  157. data/lib/active_merchant/billing/gateways/trans_first.rb +1 -2
  158. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +8 -16
  159. data/lib/active_merchant/billing/gateways/transact_pro.rb +1 -1
  160. data/lib/active_merchant/billing/gateways/trust_commerce.rb +6 -2
  161. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -8
  162. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +6 -2
  163. data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
  164. data/lib/active_merchant/billing/gateways/vantiv_express.rb +587 -0
  165. data/lib/active_merchant/billing/gateways/verifi.rb +6 -2
  166. data/lib/active_merchant/billing/gateways/viaklix.rb +6 -2
  167. data/lib/active_merchant/billing/gateways/visanet_peru.rb +2 -2
  168. data/lib/active_merchant/billing/gateways/vpos.rb +3 -3
  169. data/lib/active_merchant/billing/gateways/wirecard.rb +7 -3
  170. data/lib/active_merchant/billing/gateways/wompi.rb +5 -0
  171. data/lib/active_merchant/billing/gateways/worldpay.rb +140 -73
  172. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +13 -10
  173. data/lib/active_merchant/billing/gateways/xpay.rb +242 -0
  174. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  175. data/lib/active_merchant/billing/response.rb +2 -2
  176. data/lib/active_merchant/connection.rb +3 -17
  177. data/lib/active_merchant/country.rb +1 -0
  178. data/lib/active_merchant/errors.rb +10 -0
  179. data/lib/active_merchant/version.rb +1 -1
  180. data/lib/support/gateway_support.rb +2 -2
  181. data/lib/support/ssl_verify.rb +4 -4
  182. data/lib/support/ssl_version.rb +6 -6
  183. metadata +30 -9
@@ -0,0 +1,286 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class HiPayGateway < Gateway
4
+ # to add more check => payment_product_list: https://developer.hipay.com/api-explorer/api-online-payments#/payments/generateHostedPaymentPage
5
+ PAYMENT_PRODUCT = {
6
+ 'visa' => 'visa',
7
+ 'master' => 'mastercard'
8
+ }
9
+
10
+ DEVICE_CHANEL = {
11
+ app: 1,
12
+ browser: 2,
13
+ three_ds_requestor_initiaded: 3
14
+ }
15
+
16
+ self.test_url = 'https://stage-secure-gateway.hipay-tpp.com/rest'
17
+ self.live_url = 'https://secure-gateway.hipay-tpp.com/rest'
18
+
19
+ self.supported_countries = %w[FR]
20
+ self.default_currency = 'EUR'
21
+ self.money_format = :dollars
22
+ self.supported_cardtypes = %i[visa master american_express]
23
+
24
+ self.homepage_url = 'https://hipay.com/'
25
+ self.display_name = 'HiPay'
26
+
27
+ def initialize(options = {})
28
+ requires!(options, :username, :password)
29
+ @username = options[:username]
30
+ @password = options[:password]
31
+ super
32
+ end
33
+
34
+ def purchase(money, payment_method, options = {})
35
+ authorize(money, payment_method, options.merge({ operation: 'Sale' }))
36
+ end
37
+
38
+ def authorize(money, payment_method, options = {})
39
+ MultiResponse.run do |r|
40
+ if payment_method.is_a?(CreditCard)
41
+ response = r.process { tokenize(payment_method, options) }
42
+ card_token = response.params['token']
43
+ elsif payment_method.is_a?(String)
44
+ _transaction_ref, card_token, payment_product = payment_method.split('|') if payment_method.split('|').size == 3
45
+ card_token, payment_product = payment_method.split('|') if payment_method.split('|').size == 2
46
+ end
47
+
48
+ payment_product = payment_method.is_a?(CreditCard) ? PAYMENT_PRODUCT[payment_method.brand] : PAYMENT_PRODUCT[payment_product&.downcase]
49
+
50
+ post = {
51
+ payment_product: payment_product,
52
+ operation: options[:operation] || 'Authorization',
53
+ cardtoken: card_token
54
+ }
55
+ add_address(post, options)
56
+ add_product_data(post, options)
57
+ add_invoice(post, money, options)
58
+ add_3ds(post, options)
59
+ r.process { commit('order', post) }
60
+ end
61
+ end
62
+
63
+ def capture(money, authorization, options)
64
+ reference_operation(money, authorization, options.merge({ operation: 'capture' }))
65
+ end
66
+
67
+ def store(payment_method, options = {})
68
+ tokenize(payment_method, options.merge({ multiuse: '1' }))
69
+ end
70
+
71
+ def unstore(authorization, options = {})
72
+ _transaction_ref, card_token, _payment_product = authorization.split('|') if authorization.split('|').size == 3
73
+ card_token, _payment_product = authorization.split('|') if authorization.split('|').size == 2
74
+ commit('unstore', { card_token: card_token }, options, :delete)
75
+ end
76
+
77
+ def refund(money, authorization, options)
78
+ reference_operation(money, authorization, options.merge({ operation: 'refund' }))
79
+ end
80
+
81
+ def void(authorization, options)
82
+ reference_operation(nil, authorization, options.merge({ operation: 'cancel' }))
83
+ end
84
+
85
+ def supports_scrubbing?
86
+ true
87
+ end
88
+
89
+ def scrub(transcript)
90
+ transcript.
91
+ gsub(%r((Authorization: Basic )[\w =]+), '\1[FILTERED]').
92
+ gsub(%r((card_number=)\w+), '\1[FILTERED]\2').
93
+ gsub(%r((cvc=)\w+), '\1[FILTERED]\2')
94
+ end
95
+
96
+ private
97
+
98
+ def reference_operation(money, authorization, options)
99
+ post = {}
100
+ post[:operation] = options[:operation]
101
+ post[:currency] = (options[:currency] || currency(money))
102
+ post[:amount] = amount(money) if options[:operation] == 'refund' || options[:operation] == 'capture'
103
+ commit(options[:operation], post, { transaction_reference: authorization.split('|').first })
104
+ end
105
+
106
+ def add_product_data(post, options)
107
+ post[:orderid] = options[:order_id] if options[:order_id]
108
+ post[:description] = options[:description]
109
+ end
110
+
111
+ def add_invoice(post, money, options)
112
+ post[:currency] = (options[:currency] || currency(money))
113
+ post[:amount] = amount(money)
114
+ end
115
+
116
+ def add_credit_card(post, credit_card)
117
+ post[:card_number] = credit_card.number
118
+ post[:card_expiry_month] = credit_card.month
119
+ post[:card_expiry_year] = credit_card.year
120
+ post[:card_holder] = credit_card.name
121
+ post[:cvc] = credit_card.verification_value
122
+ end
123
+
124
+ def add_address(post, options)
125
+ return unless billing_address = options[:billing_address]
126
+
127
+ post[:streetaddress] = billing_address[:address1] if billing_address[:address1]
128
+ post[:streetaddress2] = billing_address[:address2] if billing_address[:address2]
129
+ post[:city] = billing_address[:city] if billing_address[:city]
130
+ post[:recipient_info] = billing_address[:company] if billing_address[:company]
131
+ post[:state] = billing_address[:state] if billing_address[:state]
132
+ post[:country] = billing_address[:country] if billing_address[:country]
133
+ post[:zipcode] = billing_address[:zip] if billing_address[:zip]
134
+ post[:country] = billing_address[:country] if billing_address[:country]
135
+ post[:phone] = billing_address[:phone] if billing_address[:phone]
136
+ end
137
+
138
+ def tokenize(payment_method, options = {})
139
+ post = {}
140
+ add_credit_card(post, payment_method)
141
+ post[:multi_use] = options[:multiuse] ? '1' : '0'
142
+ post[:generate_request_id] = '0'
143
+ commit('store', post, options)
144
+ end
145
+
146
+ def add_3ds(post, options)
147
+ return unless options.has_key?(:execute_threed)
148
+
149
+ browser_info_3ds = options[:three_ds_2][:browser_info]
150
+
151
+ browser_info_hash = {
152
+ java_enabled: browser_info_3ds[:java],
153
+ javascript_enabled: (browser_info_3ds[:javascript] || false),
154
+ ipaddr: options[:ip],
155
+ http_accept: '*\\/*',
156
+ http_user_agent: browser_info_3ds[:user_agent],
157
+ language: browser_info_3ds[:language],
158
+ color_depth: browser_info_3ds[:depth],
159
+ screen_height: browser_info_3ds[:height],
160
+ screen_width: browser_info_3ds[:width],
161
+ timezone: browser_info_3ds[:timezone]
162
+ }
163
+
164
+ browser_info_hash['device_fingerprint'] = options[:device_fingerprint] if options[:device_fingerprint]
165
+ post[:browser_info] = browser_info_hash.to_json
166
+ post.to_json
167
+
168
+ post[:accept_url] = options[:accept_url] if options[:accept_url]
169
+ post[:decline_url] = options[:decline_url] if options[:decline_url]
170
+ post[:pending_url] = options[:pending_url] if options[:pending_url]
171
+ post[:exception_url] = options[:exception_url] if options[:exception_url]
172
+ post[:cancel_url] = options[:cancel_url] if options[:cancel_url]
173
+ post[:notify_url] = browser_info_3ds[:notification_url] if browser_info_3ds[:notification_url]
174
+ post[:authentication_indicator] = DEVICE_CHANEL[options[:three_ds_2][:channel]] || 0
175
+ end
176
+
177
+ def parse(body)
178
+ return {} if body.blank?
179
+
180
+ JSON.parse(body)
181
+ end
182
+
183
+ def commit(action, post, options = {}, method = :post)
184
+ raw_response = begin
185
+ ssl_request(method, url(action, options), post_data(post), request_headers)
186
+ rescue ResponseError => e
187
+ e.response.body
188
+ end
189
+
190
+ response = parse(raw_response)
191
+
192
+ Response.new(
193
+ success_from(action, response),
194
+ message_from(action, response),
195
+ response,
196
+ authorization: authorization_from(action, response),
197
+ test: test?,
198
+ error_code: error_code_from(action, response)
199
+ )
200
+ end
201
+
202
+ def error_code_from(action, response)
203
+ (response['code'] || response.dig('reason', 'code')).to_s unless success_from(action, response)
204
+ end
205
+
206
+ def success_from(action, response)
207
+ case action
208
+ when 'order'
209
+ response['state'] == 'completed' || (response['state'] == 'forwarding' && response['status'] == '140')
210
+ when 'capture'
211
+ response['status'] == '118' && response['message'] == 'Captured'
212
+ when 'refund'
213
+ response['status'] == '124' && response['message'] == 'Refund Requested'
214
+ when 'cancel'
215
+ response['status'] == '175' && response['message'] == 'Authorization Cancellation requested'
216
+ when 'store'
217
+ response.include? 'token'
218
+ when 'unstore'
219
+ response['code'] == '204'
220
+ else
221
+ false
222
+ end
223
+ end
224
+
225
+ def message_from(action, response)
226
+ response['message']
227
+ end
228
+
229
+ def authorization_from(action, response)
230
+ authorization_string(response['transactionReference'], response['token'], response['brand'])
231
+ end
232
+
233
+ def authorization_string(*args)
234
+ args.flatten.compact.reject(&:empty?).join('|')
235
+ end
236
+
237
+ def post_data(params)
238
+ params.map { |k, v| "#{k}=#{CGI.escape(v.to_s)}" }.join('&')
239
+ end
240
+
241
+ def url(action, options = {})
242
+ case action
243
+ when 'store'
244
+ "#{token_url}/create"
245
+ when 'unstore'
246
+ token_url
247
+ when 'capture', 'refund', 'cancel'
248
+ endpoint = "maintenance/transaction/#{options[:transaction_reference]}"
249
+ base_url(endpoint)
250
+ else
251
+ base_url(action)
252
+ end
253
+ end
254
+
255
+ def base_url(endpoint)
256
+ "#{test? ? test_url : live_url}/v1/#{endpoint}"
257
+ end
258
+
259
+ def token_url
260
+ "https://#{'stage-' if test?}secure2-vault.hipay-tpp.com/rest/v2/token"
261
+ end
262
+
263
+ def basic_auth
264
+ Base64.strict_encode64("#{@username}:#{@password}")
265
+ end
266
+
267
+ def request_headers
268
+ {
269
+ 'Accept' => 'application/json',
270
+ 'Content-Type' => 'application/x-www-form-urlencoded',
271
+ 'Authorization' => "Basic #{basic_auth}"
272
+ }
273
+ end
274
+
275
+ def handle_response(response)
276
+ case response.code.to_i
277
+ # to get the response code after unstore(delete instrument), because the body is nil
278
+ when 200...300
279
+ response.body || { code: response.code }.to_json
280
+ else
281
+ raise ResponseError.new(response)
282
+ end
283
+ end
284
+ end
285
+ end
286
+ end
@@ -330,7 +330,7 @@ module ActiveMerchant #:nodoc:
330
330
  } do
331
331
  xml.SOAP :Body do
332
332
  xml.hps :PosRequest do
333
- xml.hps 'Ver1.0'.to_sym do
333
+ xml.hps :"Ver1.0" do
334
334
  xml.hps :Header do
335
335
  xml.hps :SecretAPIKey, @options[:secret_api_key]
336
336
  xml.hps :DeveloperID, @options[:developer_id] if @options[:developer_id]
@@ -185,8 +185,13 @@ module ActiveMerchant #:nodoc:
185
185
  end
186
186
 
187
187
  def commit(action, parameters)
188
- response = parse(ssl_post(url(action), post_data(action, parameters),
189
- { 'Content-Type' => 'application/soap+xml; charset=utf-8' }))
188
+ response = parse(
189
+ ssl_post(
190
+ url(action),
191
+ post_data(action, parameters),
192
+ { 'Content-Type' => 'application/soap+xml; charset=utf-8' }
193
+ )
194
+ )
190
195
 
191
196
  Response.new(
192
197
  success_from(response),
@@ -172,11 +172,14 @@ module ActiveMerchant #:nodoc:
172
172
 
173
173
  response = parse(ssl_post(self.live_url, post_data(action, parameters)))
174
174
 
175
- Response.new(response['response'] == '1', message_from(response), response,
175
+ Response.new(
176
+ response['response'] == '1',
177
+ message_from(response), response,
176
178
  authorization: response['transactionid'],
177
179
  test: test?,
178
180
  cvv_result: response['cvvresponse'],
179
- avs_result: { code: response['avsresponse'] })
181
+ avs_result: { code: response['avsresponse'] }
182
+ )
180
183
  end
181
184
 
182
185
  def message_from(response)
@@ -196,8 +199,7 @@ module ActiveMerchant #:nodoc:
196
199
  post[:password] = @options[:password]
197
200
  post[:type] = action if action
198
201
 
199
- request = post.merge(parameters).map { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&')
200
- request
202
+ post.merge(parameters).map { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&')
201
203
  end
202
204
 
203
205
  def determine_funding_source(source)
@@ -140,10 +140,14 @@ module ActiveMerchant #:nodoc:
140
140
  data = ssl_post self.live_url, post_data(action, parameters)
141
141
  response = parse(data)
142
142
 
143
- Response.new(response[:success], response[:message], response,
143
+ Response.new(
144
+ response[:success],
145
+ response[:message],
146
+ response,
144
147
  authorization: response[:transaction_id],
145
148
  avs_result: { code: response[:avs_result] },
146
- cvv_result: response[:cvv_result])
149
+ cvv_result: response[:cvv_result]
150
+ )
147
151
  end
148
152
 
149
153
  def post_data(action, parameters = {})
@@ -151,8 +155,7 @@ module ActiveMerchant #:nodoc:
151
155
  post[:acctid] = @options[:login]
152
156
  post[:merchantpin] = @options[:password] if @options[:password]
153
157
  post[:action] = action
154
- request = post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&')
155
- request
158
+ post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&')
156
159
  end
157
160
  end
158
161
  end
@@ -18,7 +18,7 @@ module ActiveMerchant #:nodoc:
18
18
  ACTION_REQUEST_ITEMS = %w(vault unstore)
19
19
 
20
20
  def initialize(options = {})
21
- requires!(options, :store_id, :user_id, :password, :pem, :pem_password)
21
+ requires!(options, :user_id, :password, :pem, :pem_password)
22
22
  @credentials = options
23
23
  @hosted_data_id = nil
24
24
  super
@@ -86,8 +86,7 @@ module ActiveMerchant #:nodoc:
86
86
  transcript.
87
87
  gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
88
88
  gsub(%r((<v1:CardNumber>).+(</v1:CardNumber>)), '\1[FILTERED]\2').
89
- gsub(%r((<v1:CardCodeValue>).+(</v1:CardCodeValue>)), '\1[FILTERED]\2').
90
- gsub(%r((<v1:StoreId>).+(</v1:StoreId>)), '\1[FILTERED]\2')
89
+ gsub(%r((<v1:CardCodeValue>).+(</v1:CardCodeValue>)), '\1[FILTERED]\2')
91
90
  end
92
91
 
93
92
  private
@@ -273,7 +272,7 @@ module ActiveMerchant #:nodoc:
273
272
  xml.tag!('v1:SubTotal', options[:sub_total]) if options[:sub_total]
274
273
  xml.tag!('v1:ValueAddedTax', options[:value_added_tax]) if options[:value_added_tax]
275
274
  xml.tag!('v1:DeliveryAmount', options[:delivery_amount]) if options[:delivery_amount]
276
- xml.tag!('v1:ChargeTotal', money)
275
+ xml.tag!('v1:ChargeTotal', amount(money))
277
276
  xml.tag!('v1:Currency', CURRENCY_CODES[options[:currency]])
278
277
  xml.tag!('v1:numberOfInstallments', options[:number_of_installments]) if options[:number_of_installments]
279
278
  end
@@ -317,7 +316,10 @@ module ActiveMerchant #:nodoc:
317
316
  end
318
317
 
319
318
  def encoded_credentials
320
- Base64.encode64("WS#{@credentials[:store_id]}._.#{@credentials[:user_id]}:#{@credentials[:password]}").delete("\n")
319
+ # We remove 'WS' and add it back on the next line because the ipg docs are a little confusing.
320
+ # Some merchants will likely add it to their user_id and others won't.
321
+ user_id = @credentials[:user_id].sub(/^WS/, '')
322
+ Base64.encode64("WS#{user_id}:#{@credentials[:password]}").delete("\n")
321
323
  end
322
324
 
323
325
  def envelope_namespaces
@@ -344,6 +346,8 @@ module ActiveMerchant #:nodoc:
344
346
  end
345
347
 
346
348
  def override_store_id(options)
349
+ raise ArgumentError, 'store_id must be provieded' if @credentials[:store_id].blank? && options[:store_id].blank?
350
+
347
351
  @credentials[:store_id] = options[:store_id] if options[:store_id].present?
348
352
  end
349
353
 
@@ -376,22 +376,32 @@ module ActiveMerchant #:nodoc:
376
376
 
377
377
  def commit(request, options)
378
378
  requires!(options, :action)
379
- response = parse(ssl_post(test? ? self.test_url : self.live_url, request,
380
- { 'SOAPAction' => 'https://www.thepaymentgateway.net/' + options[:action],
381
- 'Content-Type' => 'text/xml; charset=utf-8' }))
379
+ response = parse(
380
+ ssl_post(
381
+ test? ? self.test_url : self.live_url, request,
382
+ {
383
+ 'SOAPAction' => 'https://www.thepaymentgateway.net/' + options[:action],
384
+ 'Content-Type' => 'text/xml; charset=utf-8'
385
+ }
386
+ )
387
+ )
382
388
 
383
389
  success = response[:transaction_result][:status_code] == '0'
384
390
  message = response[:transaction_result][:message]
385
391
  authorization = success ? [options[:order_id], response[:transaction_output_data][:cross_reference], response[:transaction_output_data][:auth_code]].compact.join(';') : nil
386
392
 
387
- Response.new(success, message, response,
393
+ Response.new(
394
+ success,
395
+ message,
396
+ response,
388
397
  test: test?,
389
398
  authorization: authorization,
390
399
  avs_result: {
391
400
  street_match: AVS_CODE[ response[:transaction_output_data][:address_numeric_check_result] ],
392
401
  postal_match: AVS_CODE[ response[:transaction_output_data][:post_code_check_result] ]
393
402
  },
394
- cvv_result: CVV_CODE[ response[:transaction_output_data][:cv2_check_result] ])
403
+ cvv_result: CVV_CODE[ response[:transaction_output_data][:cv2_check_result] ]
404
+ )
395
405
  end
396
406
 
397
407
  def parse(xml)
@@ -387,11 +387,15 @@ module ActiveMerchant #:nodoc:
387
387
  # the Base64 encoded payload signature!
388
388
  response = parse(ssl_post(self.live_url, post_data(payload), 'Content-Type' => 'text/xml'))
389
389
 
390
- Response.new(successful?(response), response[:error_message], response,
390
+ Response.new(
391
+ successful?(response),
392
+ response[:error_message],
393
+ response,
391
394
  test: test?,
392
395
  authorization: response[:xid],
393
396
  avs_result: { code: response[:avs_response] },
394
- cvv_result: response[:cvv_response])
397
+ cvv_result: response[:cvv_response]
398
+ )
395
399
  end
396
400
 
397
401
  def post_data(payload)
@@ -218,10 +218,10 @@ module ActiveMerchant #:nodoc:
218
218
  end
219
219
  end
220
220
 
221
- if !node.elements.empty?
222
- node.elements.each { |e| parse_element(parsed, e) }
223
- else
221
+ if node.elements.empty?
224
222
  parsed[underscore(node.name)] = node.text
223
+ else
224
+ node.elements.each { |e| parse_element(parsed, e) }
225
225
  end
226
226
  end
227
227
 
@@ -286,8 +286,8 @@ module ActiveMerchant #:nodoc:
286
286
  response =
287
287
  begin
288
288
  parse(ssl_post(url, request, headers(request)))
289
- rescue StandardError => error
290
- parse(error.response.body)
289
+ rescue StandardError => e
290
+ parse(e.response.body)
291
291
  end
292
292
 
293
293
  Response.new(
@@ -284,13 +284,15 @@ module ActiveMerchant #:nodoc:
284
284
  response = parse(ssl_post(url, request))
285
285
 
286
286
  success = success?(response)
287
- Response.new(success,
287
+ Response.new(
288
+ success,
288
289
  success ? 'APPROVED' : message_from(response),
289
290
  response,
290
291
  test: test?,
291
292
  authorization: authorization_from(response, money, token),
292
293
  avs_result: { code: response[:avs] },
293
- cvv_result: response[:cvv2])
294
+ cvv_result: response[:cvv2]
295
+ )
294
296
  end
295
297
 
296
298
  def url
@@ -295,14 +295,16 @@ module ActiveMerchant #:nodoc:
295
295
  response = parse(ssl_post(url, request))
296
296
 
297
297
  success = success?(response)
298
- Response.new(success,
298
+ Response.new(
299
+ success,
299
300
  success ? 'APPROVED' : message_from(response),
300
301
  response,
301
302
  test: test?,
302
303
  authorization: authorization_from(response, money, token),
303
304
  avs_result: AVSResult.new(code: response[:avs]),
304
305
  cvv_result: CVVResult.new(response[:cvv2]),
305
- error_code: success ? nil : error_code_from(response))
306
+ error_code: success ? nil : error_code_from(response)
307
+ )
306
308
  end
307
309
 
308
310
  def url