activemerchant 1.133.0 → 1.137.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 (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