Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

Allow user to specify style and placeholder_text of hosted_fields #276

Merged
merged 3 commits into from
Nov 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,14 @@ has each payment type disabled. It also adds a `before_create` callback to
default configuration that gets created by overriding the private
`build_default_configuration` method on `Spree::Store`.

### Hosted Fields Styling
You can style the Braintree credit card fields by using the `credit_card_fields_style` preference on the payment method. The `credit_card_fields_style` will be passed to the `style` key when initializing the credit card fields. You can find more information about styling hosted fields can be found [here.](https://developers.braintreepayments.com/guides/hosted-fields/styling/javascript/v3)

You can also use the `placeholder_text` preference on the payment method to set the placeholder text you'd like to use for each of the hosted fields. You'll pass the field name in as the key, and the placeholder text you'd like to use as the value. For example:
```ruby
{ number: "Enter card number", cvv: "Enter CVV", expirationDate: "mm/yy" }
```

### 3D Secure

This gem supports [3D Secure 2](https://developers.braintreepayments.com/guides/3d-secure/overview),
Expand Down
13 changes: 9 additions & 4 deletions app/assets/javascripts/solidus_paypal_braintree/hosted_form.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,22 @@ SolidusPaypalBraintree.HostedForm.prototype._createHostedFields = function () {

fields: {
number: {
selector: "#card_number" + this.paymentMethodId
selector: "#card_number" + this.paymentMethodId,
placeholder: placeholder_text["number"]
},

cvv: {
selector: "#card_code" + this.paymentMethodId
selector: "#card_code" + this.paymentMethodId,
placeholder: placeholder_text["cvv"]
},

expirationDate: {
selector: "#card_expiry" + this.paymentMethodId
selector: "#card_expiry" + this.paymentMethodId,
placeholder: placeholder_text["expirationDate"]
}
}
},

styles: credit_card_fields_style
};

return SolidusPaypalBraintree.PromiseShim.convertBraintreePromise(braintree.hostedFields.create, [opts]);
Expand Down
8 changes: 8 additions & 0 deletions app/models/solidus_paypal_braintree/gateway.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ class TokenGenerationDisabledError < StandardError; end
# Which checkout flow to use (vault/checkout)
preference(:paypal_flow, :string, default: 'vault')

# A hash that gets passed to the `style` key when initializing the credit card fields.
# See https://developers.braintreepayments.com/guides/hosted-fields/styling/javascript/v3
preference(:credit_card_fields_style, :hash, default: {})

# A hash that gets its keys passed to the associated braintree field placeholder tag.
# Example: { number: "Enter card number", cvv: "Enter CVV", expirationDate: "mm/yy" }
preference(:placeholder_text, :hash, default: {})

def partial_name
"paypal_braintree"
end
Expand Down
35 changes: 23 additions & 12 deletions app/views/spree/shared/_braintree_hosted_fields.html.erb
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
<% prefix = "payment_source[#{id}]" %>
<% if defined?(id) && !defined?(payment_method) %>
<% payment_method = Spree::PaymentMethod.find(id) %>
<% Spree::Deprecation.warn(
"passing id to _braintree_hosted_fields.html.erb is deprecated. Please pass the payment_method directly.",
caller
) %>
<% end %>

<% prefix = "payment_source[#{payment_method.id}]" %>

<div class="hosted-fields">
<div class="field" data-hook="card_number">
<%= label_tag "card_number#{id}", Spree::CreditCard.human_attribute_name(:number), class: "required" %>
<div class="input" id="card_number<%= id %>"></div>
<%= label_tag "card_number#{payment_method.id}", Spree::CreditCard.human_attribute_name(:number), class: "required" %>
<div class="input" id="card_number<%= payment_method.id %>"></div>
</div>

<div class="field" data-hook="card_expiration">
<%= label_tag "card_expiry#{id}", Spree::CreditCard.human_attribute_name(:expiration), class: "required" %>
<div class="input" id="card_expiry<%= id %>"></div>
<%= label_tag "card_expiry#{payment_method.id}", Spree::CreditCard.human_attribute_name(:expiration), class: "required" %>
<div class="input" id="card_expiry<%= payment_method.id %>"></div>
</div>

<div class="field" data-hook="card_code">
<%= label_tag "card_code#{id}", Spree::CreditCard.human_attribute_name(:card_code), class: "required" %>
<div class="input" id="card_code<%= id %>"></div>
<%= label_tag "card_code#{payment_method.id}", Spree::CreditCard.human_attribute_name(:card_code), class: "required" %>
<div class="input" id="card_code<%= payment_method.id %>"></div>

<a href="/content/cvv" class="info cvvLink" target="_blank">
(<%= I18n.t("spree.what_is_this") %>)
Expand All @@ -25,8 +33,11 @@
<input type="hidden" id="payment_method_nonce" name="<%= prefix %>[nonce]">
</div>

<% if current_store.braintree_configuration.three_d_secure? %>
<script>
var threeDSecureOptions = <%=raw braintree_3ds_options_for(current_order).to_json %>;
</script>
<% end -%>

<script>
<% if current_store.braintree_configuration.three_d_secure? %>
var threeDSecureOptions = <%= raw braintree_3ds_options_for(current_order).to_json %>;
<% end -%>
var credit_card_fields_style = <%= raw payment_method.preferred_credit_card_fields_style.to_json %>
var placeholder_text = <%= raw payment_method.preferred_placeholder_text.to_json %>
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
</div>

<div id="card_form<%= id %>" data-hook style="display: none;">
<%= render partial: "spree/shared/braintree_hosted_fields", locals: { id: id } %>
<%= render partial: "spree/shared/braintree_hosted_fields", locals: { payment_method: payment_method } %>
seand7565 marked this conversation as resolved.
Show resolved Hide resolved
</div>
</fieldset>
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
</div>

<div id="card_form<%= id %>" data-hook style="display: none;">
<%= render partial: "spree/shared/braintree_hosted_fields", locals: { id: id } %>
<%= render partial: "spree/shared/braintree_hosted_fields", locals: { payment_method: payment_method } %>
</div>
</fieldset>
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<% if current_store.braintree_configuration.credit_card? %>
<fieldset class="braintree-hosted-fields" data-braintree-hosted-fields data-id="<%= id %>">
<%= render "spree/shared/braintree_hosted_fields", id: id %>
<%= render "spree/shared/braintree_hosted_fields", payment_method: payment_method %>
</fieldset>
<% end %>

Expand Down
17 changes: 17 additions & 0 deletions spec/features/frontend/braintree_credit_card_checkout_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
credit_card: true,
three_d_secure: three_d_secure_enabled
)

braintree.update(
preferred_credit_card_fields_style: { input: { 'font-size': '30px' } },
preferred_placeholder_text: { number: "Enter Your Card Number" }
)
end

order = if SolidusSupport.solidus_gem_version >= Gem::Version.new('2.6.0')
Expand Down Expand Up @@ -53,6 +58,18 @@
expect(page).to have_selector("iframe#braintree-hosted-field-number")
expect(page).to have_selector("iframe[type='number']")
end

it "credit card field style variable is set" do
within_frame("braintree-hosted-field-number") do
expect(find("#credit-card-number").style("font-size")).to eq({ "font-size" => "30px" })
end
end

it "sets the placeholder text correctly" do
within_frame("braintree-hosted-field-number") do
expect(find("#credit-card-number")['placeholder']).to eq("Enter Your Card Number")
end
end
end

context "with valid credit card data", vcr: {
Expand Down