diff --git a/lib/active_merchant/billing/gateways/worldpay.rb b/lib/active_merchant/billing/gateways/worldpay.rb index 9d77455b005..db893f56528 100644 --- a/lib/active_merchant/billing/gateways/worldpay.rb +++ b/lib/active_merchant/billing/gateways/worldpay.rb @@ -573,6 +573,8 @@ def add_payment_method(xml, amount, payment_method, options) add_amount_for_pay_as_order(xml, amount, payment_method, options) when :network_token add_network_tokenization_card(xml, payment_method, options) + when :encrypted_wallet + add_encrypted_wallet(xml, payment_method, options) else add_card_or_token(xml, payment_method, options) end @@ -612,6 +614,23 @@ def add_network_tokenization_card(xml, payment_method, options) end end + def add_encrypted_wallet(xml, payment_method, options) + source = payment_method.source == :apple_pay ? 'APPLEPAY' : 'PAYWITHGOOGLE' + + xml.paymentDetails do + xml.tag! "#{source}-SSL" do + xml.header do + xml.ephemeralPublicKey payment_method.payment_data.dig(:header, :ephemeralPublicKey) + xml.publicKeyHash payment_method.payment_data.dig(:header, :publicKeyHash) + xml.transactionId payment_method.payment_data.dig(:header, :transactionId) + end + xml.signature payment_method.payment_data[:signature] + xml.version payment_method.payment_data[:version] + xml.data payment_method.payment_data[:data] + end + end + end + def add_card_or_token(xml, payment_method, options) xml.paymentDetails credit_fund_transfer_attribute(options) do if options[:payment_type] == :token @@ -981,7 +1000,15 @@ def payment_details(payment_method, options = {}) when String token_type_and_details(payment_method) else - type = network_token?(payment_method) || options[:wallet_type] == :google_pay ? :network_token : :credit + type = if network_token?(payment_method) || options[:wallet_type] == :google_pay + if network_token?(payment_method) && payment_method.payment_data + :encrypted_wallet + else + :network_token + end + else + :credit + end { payment_type: type } end diff --git a/test/unit/gateways/worldpay_test.rb b/test/unit/gateways/worldpay_test.rb index f2dc5f177c5..b6770bf7160 100644 --- a/test/unit/gateways/worldpay_test.rb +++ b/test/unit/gateways/worldpay_test.rb @@ -164,7 +164,7 @@ def test_payment_type_for_network_card def test_payment_type_returns_network_token_if_the_payment_method_responds_to_source_payment_cryptogram_and_eci payment_method = mock - payment_method.stubs(source: nil, payment_cryptogram: nil, eci: nil) + payment_method.stubs(source: nil, payment_cryptogram: nil, eci: nil, payment_data: nil) result = @gateway.send(:payment_details, payment_method) assert_equal({ payment_type: :network_token }, result) end @@ -219,6 +219,56 @@ def test_successful_authorize_without_name assert_equal 'R50704213207145707', response.authorization end + def test_successful_authorize_encrypted_apple_pay + apple_pay = ActiveMerchant::Billing::NetworkTokenizationCreditCard.new({ + source: :apple_pay, + payment_data: { + version: 'EC_v1', + data: 'QlzLxRFnNP9/GTaMhBwgmZ2ywntbr9', + signature: 'signature', + header: { + ephemeralPublicKey: 'ephemeralPublicKey', + publicKeyHash: 'publicKeyHash', + transactionId: 'transactionId' + } + } + }) + + stub_comms do + @gateway.authorize(@amount, apple_pay, @options) + end.check_request do |_endpoint, data, _headers| + assert_match(/APPLEPAY-SSL/, data) + assert_match(%r(EC_v1), data) + assert_match(%r(transactionId), data) + assert_match(%r(QlzLxRFnNP9/GTaMhBwgmZ2ywntbr9), data) + end.respond_with(successful_authorize_response) + end + + def test_successful_authorize_encrypted_google_pay + google_pay = ActiveMerchant::Billing::NetworkTokenizationCreditCard.new({ + source: :google_pay, + payment_data: { + version: 'EC_v1', + data: 'QlzLxRFnNP9/GTaMhBwgmZ2ywntbr9', + signature: 'signature', + header: { + ephemeralPublicKey: 'ephemeralPublicKey', + publicKeyHash: 'publicKeyHash', + transactionId: 'transactionId' + } + } + }) + + stub_comms do + @gateway.authorize(@amount, google_pay, @options) + end.check_request do |_endpoint, data, _headers| + assert_match(/PAYWITHGOOGLE-SSL/, data) + assert_match(%r(EC_v1), data) + assert_match(%r(transactionId), data) + assert_match(%r(QlzLxRFnNP9/GTaMhBwgmZ2ywntbr9), data) + end.respond_with(successful_authorize_response) + end + def test_successful_authorize_by_reference response = stub_comms do @gateway.authorize(@amount, @options[:order_id].to_s, @options)