11

Usually, we use a theme which was provided stripe like the following.

style: {
  paymentRequestButton: {
    theme: "light-outline"
  }
}

They have also provided some theme's like 'dark' | 'light' | 'light-outline'

My question is can we create a custom theme for this button.? eg: a blue colour theme

Or is there any workaround or script hack for changing the color of the button.?

Jithin Raj P R
  • 6,667
  • 8
  • 38
  • 69
  • You can easily abandon Stripe's all-in-one payment widget and design your own form so that it is anything you want it to be. If this is an acceptable alternative, I'll give you an example when I get home in a couple hours. – Brian Gottier Nov 30 '17 at 01:36
  • @BrianGottier if we designed our own form how can we attach Payment Request Button inside it? And I hope by custom you mean a design holding the card details also.. – Jithin Raj P R Nov 30 '17 at 03:06
  • Sorry, Even though I'm up to date on my browsers, I can't see what a Payment Request Button is because Stripe says it doesn't work with my browser. You might want to think about that before implementing something that all people can't use. – Brian Gottier Nov 30 '17 at 04:32
  • @BrianGottier actually it works fine if you use a live stripe key, and it's only a secondary option in the form and for us also. But my client has seen it and he thinks its a neat feature and he is against to remove it *(i think you know how they are LOL)*. By the way please do post the custom design I will take a look at it. – Jithin Raj P R Nov 30 '17 at 05:13

3 Answers3

9

It is not possible to custom style the payment request button. However, you can use Stripe's payment request API with a custom button. The documentation only hints at this. Also, this should still be 100% PCI-compliant, as your application still never sees or touches any credit card information. I have a CodePen you can refer to as an example.

Essentially, just create whatever kind of button you want on your page. Then, bind the click event to paymentRequest.show, where paymentRequest is an instance of Stripe's PaymentRequest. For example:

let stripe = Stripe('pk_test_abc123');
let paymentRequest = stripe.paymentRequest({
    ...
});
let button = document.getElementById('awesome-custom-button');
button.addEventListener('click', paymentRequest.show);

Then, when you get the token, simply call ev.complete('success') before the end of the delegate function. For example:

paymentRequest.on('token', function (ev) {
    // do whatever with the token
    ev.complete('success');
});

The only slight hangup is that Apple dictates that the Apple Pay button must be styled a certain way, according to their HIG. The Stripe Elements payment request button handles this out of the box, but since you're no longer using the Elements button with this approach, you simply need to change your custom button manually. There's a number of ways you can do that. In my example code, I'm using Bootstrap and Fontawesome, so in the canMakePayment delegate function:

if (result.applePay) {
    button.className = 'btn btn-dark';
    button.style.backgroundColor = '#000';
    button.querySelector('.default').style.display = 'none';
    button.querySelector('.applepay').style.display = 'inline';
}

In my button HTML, I have a span with a "default" class that contains the normal button content and another span with an "applepay" class that is hidden initially and contains the following HTML:

<span class="fa-lg">
    <i class="fab fa-apple-pay" data-fa-transform="grow-12"></i>
</span>
<span class="sr-only">Purchase with Apple Pay</span>
Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • Nice idea *Chirs* I hope I had this answer when I was working on the stripe. – Jithin Raj P R Apr 12 '18 at 05:06
  • This works and is a high quality answer. The one thing I would say is that Apple seems very particular about it's branding/logo so the much appreciated codepen should display a clickable apple pay image vs a custom button. "Do not create your own version of the Apple Pay mark." https://developer.apple.com/apple-pay/marketing/ – Ronnie Royston Jun 20 '18 at 17:35
  • 1
    If you load the CodePen on an Apple device, you should see the Apple Pay version. Otherwise, you can simply comment out the `if (result.applePay)` conditional to just have it always apply the styling changes, allowing you to see what it looks like on any device. The logo comes from Font Awesome, but to my eyes, it looks virtually identical to the Apple Pay button examples in their HIG. – Chris Pratt Jun 20 '18 at 18:06
  • when I open this code pen in my iphone chrome and safari browser, it broke I cant see the buttons instead i get the message :/ I implemented the same login locally, still no success – Usman Iqbal Feb 26 '20 at 05:45
6

I've been trying to do this as well, but the reference docs here at the very bottom seem to indicate the answer is "no".

Looks like beyond a type, and theme the only thing you can set is a height: https://stripe.com/docs/stripe-js/reference#element-options

(Screenshot of relevant section below, in case it changes)

enter image description here

Henrik Joreteg
  • 1,698
  • 16
  • 18
  • 1
    Thank you for your response. I did notice this content doc, I was actually wondering if there any workaround or script hack for changing this.? Do you have any info on this.? – Jithin Raj P R Nov 28 '17 at 05:46
0

Reading Step 3 of Payment Request Button implementation steps, it is obvious the element has id: #payment-request-button.

Haven't worked with Stripe and I don't know if it's a <button> or a more complex HTML markup structure and I also read somewhere in their docs they do not guarantee maintaining the HTML structure of their elements.

Anyway, here are a few things to keep in mind when aiming this type of intervention: most importantly, develop in steps:

  1. Find a solution that works for the time being. Ideally, it should be something that degrades/fails gracefully and silently (no public facing errors)
  2. Maximize ability to withstand minor modifications in markup from Stripe

Also, keep your source files so you can easily adapt your solution to any markup breaking changes from Stripe so you can provide a fix when it stops working.

If you rely on CSS (recommended), you should inspect the currently rendered markup and find out what are the currently applying selectors. Simply writing stronger selectors should be enough. If styles are being applied via JavaScript by Stripe, chances are you will need to use !important in your CSS. Of course, you should avoid it as much as possible, or at least thoroughly test on as many devices as you can get your hands on.
As a rule of thumb, !important is quite bad in CSS. It's a very powerful hammer and most times it breaks delicate things (i.e.: responsiveness on touch devices).

Alternatively, if you rely on JavaScript to do the styling, you might want to play around with setTimeout() and determine the proper amount of miliseconds to wait before triggering your changes after the prButton.mount() method was called. Test on multiple devices. I advise against this method as it's more error prone and more difficult to control: you want to time your changes just after the element was built but (ideally) before it gets rendered. Of course, there are workarounds, such as hide or fade it until your changes are applied.


Note: This is not an easy task and nobody (except Stripe themselves, by providing a proper method) can guarantee you a bullet-proof solution so I thought laying out the principles on how to approach it might have more value on short and long term than trying to get Stripe working on a test/dev account and provide a particular solution which might stop working the next day, when Stripe change their markup.

tao
  • 82,996
  • 16
  • 114
  • 150
  • The Button is generated in a `Iframe` so as you know `CSS` styling in out of the box. The only way is `script` as you said it can create errors.So its a knockdown for me. I hope Stripe consider giving us options to style them. Anyway nice try bro, I appreciate the effort. – Jithin Raj P R Dec 05 '17 at 05:47
  • In that case your only option is to use JavaScript. In step 3 (which I already linked) insert a test after `prButton.mount()`. Something like... `document.getElementById('payment-request-button').style.borderColor = 'red';document.getElementById('payment-request-button').style.borderWidth = '2px'`. Should work. – tao Dec 05 '17 at 05:56
  • But, are you sure Stripe do not allow you to add classes to your button and custom CSS to your snippet/iframe? I don't remember where - as I've been through a lot of related resources, but I think it's possible. Is [`this`](https://www.tipsandtricks-hq.com/customizing-the-payment-button-styles-of-the-stripe-payments-plugin-9071) of any help? – tao Dec 05 '17 at 06:02
  • Let me look into that, I will get back to you soon.[am in the middle of something else now.] – Jithin Raj P R Dec 05 '17 at 06:02
  • Am trying the button which i marked in red Bro not the other buttons - [Image](https://drive.google.com/a/autozonecentre.com/file/d/16aWRMohRhZgsf1cVpA6r7lDoKTOCI5qA/view?usp=drivesdk), here is the [page](https://stripe.com/docs/payment-request-api) – Jithin Raj P R Dec 05 '17 at 06:11
  • All you need to do is `console.log(prButton)` after `mount()` and pay attention to details. I'm sure the entire contents of the ` – tao Dec 05 '17 at 06:17
  • This answer is not full, its just the path to the answer, once I finish the answer I will put it here. As for the bounty, i think you deserve it better than other answers. Thank you. – Jithin Raj P R Dec 06 '17 at 05:47