lib/active_merchant/billing/gateways/adyen.rb in activemerchant-1.86.0 vs lib/active_merchant/billing/gateways/adyen.rb in activemerchant-1.87.0

- old
+ new

@@ -5,11 +5,11 @@ # we recommend setting up merchant-specific endpoints. # https://docs.adyen.com/developers/api-manual#apiendpoints self.test_url = 'https://pal-test.adyen.com/pal/servlet/Payment/v18' self.live_url = 'https://pal-live.adyen.com/pal/servlet/Payment/v18' - self.supported_countries = ['AT','AU','BE','BG','BR','CH','CY','CZ','DE','DK','EE','ES','FI','FR','GB','GI','GR','HK','HU','IE','IS','IT','LI','LT','LU','LV','MC','MT','MX','NL','NO','PL','PT','RO','SE','SG','SK','SI','US'] + self.supported_countries = ['AT', 'AU', 'BE', 'BG', 'BR', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GI', 'GR', 'HK', 'HU', 'IE', 'IS', 'IT', 'LI', 'LT', 'LU', 'LV', 'MC', 'MT', 'MX', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SG', 'SK', 'SI', 'US'] self.default_currency = 'USD' self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb, :dankort, :maestro, :discover] self.money_format = :cents @@ -32,12 +32,12 @@ super end def purchase(money, payment, options={}) MultiResponse.run do |r| - r.process{authorize(money, payment, options)} - r.process{capture(money, r.authorization, options)} + r.process { authorize(money, payment, options) } + r.process { capture(money, r.authorization, options) } end end def authorize(money, payment, options={}) requires!(options, :order_id) @@ -101,10 +101,42 @@ gsub(%r(("cavv\\?":\\?")[^"]*)i, '\1[FILTERED]') end private + AVS_MAPPING = { + '0' => 'R', # Unknown + '1' => 'A', # Address matches, postal code doesn't + '2' => 'N', # Neither postal code nor address match + '3' => 'R', # AVS unavailable + '4' => 'E', # AVS not supported for this card type + '5' => 'U', # No AVS data provided + '6' => 'Z', # Postal code matches, address doesn't match + '7' => 'D', # Both postal code and address match + '8' => 'U', # Address not checked, postal code unknown + '9' => 'B', # Address matches, postal code unknown + '10' => 'N', # Address doesn't match, postal code unknown + '11' => 'U', # Postal code not checked, address unknown + '12' => 'B', # Address matches, postal code not checked + '13' => 'U', # Address doesn't match, postal code not checked + '14' => 'P', # Postal code matches, address unknown + '15' => 'P', # Postal code matches, address not checked + '16' => 'N', # Postal code doesn't match, address unknown + '17' => 'U', # Postal code doesn't match, address not checked + '18' => 'I' # Neither postal code nor address were checked + } + + CVC_MAPPING = { + '0' => 'P', # Unknown + '1' => 'M', # Matches + '2' => 'N', # Does not match + '3' => 'P', # Not checked + '4' => 'S', # No CVC/CVV provided, but was required + '5' => 'U', # Issuer not certifed by CVC/CVV + '6' => 'P' # No CVC/CVV provided + } + NETWORK_TOKENIZATION_CARD_SOURCE = { 'apple_pay' => 'applepay', 'android_pay' => 'androidpay', 'google_pay' => 'paywithgoogle' } @@ -182,11 +214,11 @@ holderName: credit_card.name, number: credit_card.number, cvc: credit_card.verification_value } - card.delete_if{|k,v| v.blank? } + card.delete_if { |k, v| v.blank? } card[:holderName] ||= 'Not Provided' if credit_card.is_a?(NetworkTokenizationCreditCard) requires!(card, :expiryMonth, :expiryYear, :holderName, :number) post[:card] = card end @@ -231,25 +263,34 @@ JSON.parse(body) end def commit(action, parameters) begin - raw_response = ssl_post("#{url}/#{action.to_s}", post_data(action, parameters), request_headers) + raw_response = ssl_post("#{url}/#{action}", post_data(action, parameters), request_headers) response = parse(raw_response) rescue ResponseError => e raw_response = e.response.body response = parse(raw_response) end - success = success_from(action, response) Response.new( success, message_from(action, response), response, authorization: authorization_from(action, parameters, response), test: test?, - error_code: success ? nil : error_code_from(response) + error_code: success ? nil : error_code_from(response), + avs_result: AVSResult.new(:code => avs_code_from(response)), + cvv_result: CVVResult.new(cvv_result_from(response)) ) + end + + def avs_code_from(response) + AVS_MAPPING[response['additionalData']['avsResult'][0..1].strip] if response.dig('additionalData', 'avsResult') + end + + def cvv_result_from(response) + CVC_MAPPING[response['additionalData']['cvcResult'][0]] if response.dig('additionalData', 'cvcResult') end def url if test? test_url