Issue with Payment method selection when I add Braintree Drop-in UI in Spree Store

467 views Asked by At

I'm trying to implement extension to accommodate drop-in UI of braintree when customer selects Braintree as a payment method. If I add braintree js code into _gateway.html.erb then all the other payment methods stop working. If I select any other method except braintree and click "Save and continue" then nothing happens. "Save and continue" button just gets disabled.

I've overwritten spree/frontend/app/views/spree/checkout/_gateway.html.erb.

<% if payment_method.name == "Braintree" %>

 <div id="dropin"></div>

<% else %>
<div class="well clearfix">

  <%= image_tag 'credit_cards/credit_card.gif', :id => 'credit-card-image', :class => 'pull-right', :width => '170', :height => '28' %>
  <% param_prefix = "payment_source[#{payment_method.id}]" %>

  <p class="field">
    <%= label_tag "name_on_card_#{payment_method.id}" do %>
      <%= Spree.t(:name_on_card) %><abbr class="required" title="required">*</abbr>
    <% end %>
    <%= text_field_tag "#{param_prefix}[name]", "#{@order.billing_firstname} #{@order.billing_lastname}", { id: "name_on_card_#{payment_method.id}", :class => 'form-control required'} %>
  </p>

  <p class="field" data-hook="card_number">
    <%= label_tag "card_number" do %>
      <%= Spree.t(:card_number) %><abbr class="required" title="required">*</abbr>
    <% end %>
    <% options_hash = Rails.env.production? ? {:autocomplete => 'off'} : {} %>
    <%= text_field_tag "#{param_prefix}[number]", '', options_hash.merge(:id => 'card_number', :class => 'form-control required cardNumber', :size => 19, :maxlength => 19, :autocomplete => "off") %>
    &nbsp;
    <span id="card_type" style="display:none;">
      ( <span id="looks_like" ><%= Spree.t(:card_type_is) %> <span id="type"></span></span>
        <span id="unrecognized"><%= Spree.t(:unrecognized_card_type) %></span>
      )
    </span>
  </p>
  <div class="row">
    <div class="col-md-8 field" data-hook="card_expiration">
      <%= label_tag "card_expiry" do %>
        <%= Spree.t(:expiration) %><abbr class="required" title="required">*</abbr>
      <% end %>
      <%= text_field_tag "#{param_prefix}[expiry]", '', :id => 'card_expiry', :class => "form-control required cardExpiry", :placeholder => "MM / YY" %>
    </div>
    <div class="col-md-4 field" data-hook="card_code">
      <%= label_tag "card_code" do %>
        <%= Spree.t(:card_code) %><abbr class="required" title="required">*</abbr>
      <% end %>
      <%= text_field_tag "#{param_prefix}[verification_value]", '', options_hash.merge(:id => 'card_code', :class => 'form-control required cardCode', :size => 5) %>
      <%= link_to "(#{Spree.t(:what_is_this)})", spree.content_path('cvv'), :target => '_blank', "data-hook" => "cvv_link", :id => "cvv_link" %>
    </div>
  </div>

  <%= hidden_field_tag "#{param_prefix}[cc_type]", '', :id => "cc_type", :class => 'ccType' %>
</div>

<% end %>
<%= @client_token = Braintree::ClientToken.generate %>
<script type="text/javascript">
braintree.setup("<%=@client_token%>", 'dropin', {
      container: 'dropin'
    });
</script>
1

There are 1 answers

0
cdeist On

I work at Braintree. If you don't specify the form option inside the call to braintree.setup, braintree.js will attach its behavior to the closest parent form element. Since it looks like the parent form of your braintree container is the same form used by the other checkout flows, braintree.js will indeed hijack the call made by the submit button (regardless of the payment flow being used). I recommend creating two separate form elements, and passing the id of the one used by braintree to the braintree.setup call.

braintree.setup("<%=@client_token%>", 'dropin', {
    container: ‘dropin’,
    form: ‘braintree_checkout'
});