twitter-bootstrap 如何使用 Bootstrap 设置条纹元素输入的样式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46039315/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 01:02:38  来源:igfitidea点击:

How can I style a Stripe Elements input with Bootstrap?

twitter-bootstrapstripe-paymentsstripe.js

提问by michael

I'm building a simple website that will process payments with Stripe. I'm using Bootstrap for my styling. When I use Stripe Elements to insert the payment fields, they aren't styled with Bootstrap. How can I apply Bootstrap's styling to the Elements payment fields?

我正在构建一个简单的网站,将使用 Stripe 处理付款。我正在使用 Bootstrap 进行造型。当我使用 Stripe Elements 插入付款字段时,它们没有使用 Bootstrap 设置样式。如何将 Bootstrap 的样式应用于 Elements 付款字段?

回答by Brian Gottier

Alright, so I had to figure this out, because I was using Stripe.js v2, and the security vulnerability was explained to me by Stripe tech support, so I felt obligated to switch to Stripe.js v3 "Elements". What they said was that any javascript on the same page as your credit card form elements could obtain the values of the sensitive credit card data. I suppose this could happen if a person was pulling in external scripts ... and I suppose it must have happened, or they wouldn't care about it. Anyway, this is how I got my Stripe.js v3 elements working with Bootstrap 4 input groups. It's a full working example, you'd just need to change out the public key.

好吧,所以我必须弄清楚这一点,因为我使用的是 Stripe.js v2,并且 Stripe 技术支持向我解释了安全漏洞,所以我觉得有必要切换到 Stripe.js v3 “Elements”。他们说的是,与您的信用卡表单元素位于同一页面上的任何 javascript 都可以获取敏感信用卡数据的值。我想这可能发生在一个人拉入外部脚本的情况下……我想它一定发生了,否则他们不会关心它。无论如何,这就是我如何让我的 Stripe.js v3 元素与 Bootstrap 4 输入组一起工作。这是一个完整的工作示例,您只需要更改公钥。

Default jQuery Based Example

默认基于 jQuery 的示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Stripe.js v3 with Bootstrap 4 Test</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <style>
        /* Blue outline on focus */
        .StripeElement--focus {
            border-color: #80BDFF;
            outline:0;
            box-shadow: 0 0 0 .2rem rgba(0,123,255,.25);
            transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
        }
        /* Can't see what I type without this */
        #card-number.form-control,
        #card-cvc.form-control,
        #card-exp.form-control {
            display:inline-block;
        }
    </style>
</head>
<body>

    <div class="container-fluid">
        <h1 class="mt-5">Stripe.js v3 with Bootstrap 4 (beta) Test</h1>
        <div id="card-errors" role="alert"></div>
        <div class="card">
            <div class="card-body">
                <form id="payment-form">
                    <label for="name">Name on Card</label>
                    <div class="input-group mb-2">
                        <div class="input-group-prepend">
                            <span class="input-group-text">A</span>
                        </div>
                        <input type="text" class="form-control" id="name">
                        <div class="input-group-append">
                            <span class="input-group-text">B</span>
                        </div>
                    </div>
                    <label for="card-number">Credit Card Number</label>
                    <div class="input-group mb-2">
                        <div class="input-group-prepend">
                            <span class="input-group-text">C</span>
                        </div>
                        <span id="card-number" class="form-control">
                            <!-- Stripe Card Element -->
                        </span>
                        <div class="input-group-append">
                            <span class="input-group-text">D</span>
                        </div>
                    </div>
                    <label for="card-cvc">CVC Number</label>
                    <div class="input-group mb-2">
                        <div class="input-group-prepend">
                            <span class="input-group-text">E</span>
                        </div>
                        <span id="card-cvc" class="form-control">
                            <!-- Stripe CVC Element -->
                        </span>
                    </div>
                    <label for="card-exp">Expiration</label>
                    <div class="input-group mb-2">
                        <span id="card-exp" class="form-control">
                            <!-- Stripe Card Expiry Element -->
                        </span>
                        <div class="input-group-append">
                            <span class="input-group-text">F</span>
                        </div>
                    </div>
                    <button id="payment-submit" class="btn btn-primary mt-1">Submit Payment</button>
                </form>
            </div>
        </div>
    </div>

<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="https://js.stripe.com/v3/"></script>
<script>
    $(document).ready(function(){

        // Create a Stripe client
        var stripe = Stripe('pk_test_XxXxXxXxXxXxXxXxXxXxXxXx');

        // Create an instance of Elements
        var elements = stripe.elements();

        // Try to match bootstrap 4 styling
        var style = {
            base: {
                'lineHeight': '1.35',
                'fontSize': '1.11rem',
                'color': '#495057',
                'fontFamily': 'apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif'
            }
        };

        // Card number
        var card = elements.create('cardNumber', {
            'placeholder': '',
            'style': style
        });
        card.mount('#card-number');

        // CVC
        var cvc = elements.create('cardCvc', {
            'placeholder': '',
            'style': style
        });
        cvc.mount('#card-cvc');

        // Card expiry
        var exp = elements.create('cardExpiry', {
            'placeholder': '',
            'style': style
        });
        exp.mount('#card-exp');

        // Submit
        $('#payment-submit').on('click', function(e){
            e.preventDefault();
            var cardData = {
                'name': $('#name').val()
            };
            stripe.createToken(card, cardData).then(function(result) {
                console.log(result);
                if(result.error && result.error.message){
                    alert(result.error.message);
                }else{
                    alert(result.token.id);
                }
            });
        });

    });
</script>
</body>
</html>

I tested only in Firefox, Chrome, and Chrome on Android. Seems to work fine. Let me know if you experience any issues.

我仅在 Android 上的 Firefox、Chrome 和 Chrome 中进行了测试。似乎工作正常。如果您遇到任何问题,请告诉我。

Optional Vue.js Based Example

可选的基于 Vue.js 的示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Stripe.js v3 with Bootstrap 4 and Vue.js</title>
    <link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
    <link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css"/>
    <style>
        /* This background color not essential for the example */
        html, body {
            background:#999;
        }

        /* Padding for Stripe Element containers */
        .stripe-element-container {
            padding-top: .55rem;
            padding-bottom: .50rem;
        }

        /* Blue outline on focus */
        .StripeElement--focus {
            border-color: #80BDFF;
            outline:0;
            box-shadow: 0 0 0 .2rem rgba(0,123,255,.25);
            transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
        }

        /* Can't see what I type without this */
        #card-number.form-control,
        #card-cvc.form-control,
        #card-exp.form-control {
            display:inline-block;
        }
    </style>
</head>
<body>
    <div id="app">
        <stripe-form inline-template>
            <div class="container-fluid">
                <div class="row">
                    <div class="col-md-4 offset-md-4 pt-5">
                        <div class="card">
                            <div class="card-header">
                                <h3 class="mb-0">Pay Now</h3>
                            </div>
                            <div class="card-body">
                                <div v-bind:class="{alert: activeError, 'alert-danger': activeError}" role="alert" v-html="errorText"></div>

                                <form>

                                    <div class="form-group mb-4">
                                        <label for="name">Name on Card</label>
                                        <input type="text" class="form-control" v-model="ccName" />
                                    </div>

                                    <div class="form-group">
                                        <label for="card-number">Credit Card Number</label>
                                        <span id="card-number" class="form-control stripe-element-container">
                                            <!-- Stripe Card Element -->
                                        </span>
                                    </div>

                                    <div class="form-group">
                                        <label for="card-cvc">CVC Number</label>
                                        <span id="card-cvc" class="form-control stripe-element-container">
                                            <!-- Stripe CVC Element -->
                                        </span>
                                    </div>

                                    <div class="form-group">
                                        <label for="card-exp">Expiration</label>
                                        <span id="card-exp" class="form-control stripe-element-container">
                                            <!-- Stripe Card Expiry Element -->
                                        </span>
                                    </div>

                                    <button @click.prevent="paymentSubmit" class="btn btn-primary mt-1 float-right">Submit Payment</button>

                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </stripe-form>
        <modal></modal>
    </div>

<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="https://unpkg.com/babel-polyfill@latest/dist/polyfill.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>
<script src="https://js.stripe.com/v3/"></script>
<script>

// Your Stripe public key
const stripePublicKey = 'pk_test_XxXxXxXxXxXxXxXxXxXxXxXx';

/**
 * Class allows firing of events and 
 * listening of events between components
 */
window.Events = new class {

    constructor(){
        this.vue = new Vue();
    }

    fire( event, data = null ){
        this.vue.$emit( event, data );
    }

    listenFor( event, callback ){
        this.vue.$on( event, callback );
    }
}

/**
 * See: https://bootstrap-vue.js.org/docs/components/modal/
 */
Vue.component('modal', {

    template: `
        <div>
            <b-modal ref="myModalRef" ok-only ok-title="Close" v-bind:title="title">
                <p class="mb-0">{{ body }}</p>
            </b-modal>
        </div>
    `,

    data: function(){
        return {
            title: '',
            body: ''
        }
    },

    methods: {
        showModal () {
          this.$refs.myModalRef.show()
        }
        /* This not needed for this example
        ,
        hideModal () {
          this.$refs.myModalRef.hide()
        }
        */
    },

    created(){
        Events.listenFor('modalShow', ( data ) => {
            this.title = data.title;
            this.body = data.message;
            this.showModal();
        });
    }

});

Vue.component('stripe-form', {

    data: function(){
        return { 
            activeError: false,
            errorText: '',
            ccName: '',
            stripe: null,
            card: null,
            cvc: null,
            exp: null
        }
    },

    methods: {
        paymentSubmit: function(){
            let cardData = {
                'name': this.ccName
            };
            // Ensure the name field is not empty
            if( cardData.name.trim() == '' ){
                // Show an error
                this.activeError = true;
                this.errorText = '<b>Submission Error:</b><br />Name is required.';
                // Abort !!
                return;
            }
            this.stripe.createToken( this.card, cardData).then( (result) => {
                if(result.error && result.error.message){

                    // Show any errors
                    this.activeError = true;
                    this.errorText = '<b>Submission Error:</b><br />' + result.error.message;

                }else{

                    /**
                     * Success message in modal.
                     * This is normally where you'd post to your server, 
                     * and have it actually attempt the credit card transaction
                     * using the token ID that was just received.
                     */
                    Events.fire('modalShow', {
                        'title': 'Success',
                        'message': result.token.id
                    });

                    // Clear the form
                    this.activeError = false;
                    this.errorText = '';
                    this.ccName = '';
                    // Stripe elements must be cleared in a special way
                    this.card.clear();
                    this.cvc.clear();
                    this.exp.clear();
                }
            });
        }
    },

    mounted: function(){
        // Create a Stripe client
        this.stripe = Stripe( stripePublicKey );

        // Create an instance of Elements
        const elements = this.stripe.elements();

        /**
         * Try to match bootstrap 4 styling.
         * --------------------------------
         * fontSize was in rem units, but Stripe says that it should be in pixels.
         */
        const style = {
            base: {
                'fontSize': '16px',
                'color': '#495057',
                'fontFamily': 'apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif'
            }
        };

        // Card number
        this.card = elements.create('cardNumber', {
            'placeholder': '',
            'style': style
        });
        this.card.mount('#card-number');

        // CVC
        this.cvc = elements.create('cardCvc', {
            'placeholder': '',
            'style': style
        });
        this.cvc.mount('#card-cvc');

        // Card expiry
        this.exp = elements.create('cardExpiry', {
            'placeholder': '',
            'style': style
        });
        this.exp.mount('#card-exp');
    }

});

new Vue({ el: '#app' });

</script>
</body>
</html>

This Vue.js example could benefit from some work, but may help get you started.

这个 Vue.js 示例可以从一些工作中受益,但可以帮助您入门。

回答by michael

After digging around the docs a bit more, I found that https://stripe.com/docs/stripe.js#the-element-containersays "You should style the container you mount an Element to as if it were an on your page."

在对文档进行了更多挖掘之后,我发现 https://stripe.com/docs/stripe.js#the-element-container说“您应该将安装 Element 的容器设置为样式,就好像它是您的页。”

By adding Bootstrap's form-controlclass to the <div>I'm mounting the Element in, the field looks almost like any other Bootstrap-styled input field:

通过将 Bootstrap 的form-control类添加到<div>I'm mount the Element 中,该字段看起来几乎与任何其他 Bootstrap 样式的输入字段一样:

<div id="card-element" class="form-control"></div>

For some reason, the height of the field doesn't quite match, but through trial and error, I got it with:

出于某种原因,场的高度不太匹配,但通过反复试验,我得到了它:

var stripe = Stripe('your_key');
var elements = stripe.elements();
var card = elements.create('card', { style:
  {
    base: {
      lineHeight: '1.429'
    }
  }
});
card.mount('#card-element');

回答by Abram

This is all that was required for us using

这就是我们使用所需的全部内容

  <div class="form-group">
    <label for="card-element">Credit or debit card</label>
    <div id="card-element" class="form-control" style='height: 2.4em; padding-top: .7em;'>
      <!-- A Stripe Element will be inserted here. -->
    </div>
  </div>

enter image description here

在此处输入图片说明

回答by Louie Bacaj

Adding another Answer since I felt the simplest one on here was slightly incomplete. Added the error display and the JavaScript used to send the token to the back-end in case you want to do that.

添加另一个答案,因为我觉得这里最简单的答案有点不完整。添加了错误显示和用于将令牌发送到后端的 JavaScript,以防万一。

This HTML (which is right from their default docs with Bootstrap 4 elements added)

这个 HTML(来自他们的默认文档,添加了 Bootstrap 4 元素)

<form action="/charge" method="post" id="payment-form">
  <div class="form-group">
    <label for="card-element">
        Credit or debit card
    </label>
    <div id="card-element" class="form-control">
        <!-- A Stripe Element will be inserted here. -->
    </div>

    <!-- Used to display Element errors. -->
    <div id="card-errors" role="alert"></div>
  </div>

  <button>Submit Payment</button>
</form>

And This is the JavaScript (again right from their default docs but I use jQuery here but you dont have to)

这是 JavaScript(同样来自他们的默认文档,但我在这里使用 jQuery,但您不必这样做)

<script src="https://js.stripe.com/v3/"></script>
<script>
(function ($) {
    // Set your publishable key: remember to change this to your live publishable key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    var stripe = Stripe('yourPublishableKeyHere');
    var elements = stripe.elements();

    // Custom styling can be passed to options when creating an Element.
    var style = {
      base: {
        // Add your base input styles here. For example:
        fontSize: '16px',
        color: '#32325d',
      },
    };

    // Create an instance of the card Element.
    var card = elements.create('card', {style: style});

    // Add an instance of the card Element into the `card-element` <div>.
    card.mount('#card-element');


    // Create a token or display an error when the form is submitted.
    var form = document.getElementById('payment-form');
    form.addEventListener('submit', function(event) {
      event.preventDefault();

      stripe.createToken(card).then(function(result) {
        if (result.error) {
          // Inform the customer that there was an error.
          var errorElement = document.getElementById('card-errors');
          errorElement.textContent = result.error.message;
        } else {
          // Send the token to your server.
          stripeTokenHandler(result.token);
        }
      });
    });

    function stripeTokenHandler(token) {
      // Insert the token ID into the form so it gets submitted to the server
      var form = document.getElementById('payment-form');
      var hiddenInput = document.createElement('input');
      hiddenInput.setAttribute('type', 'hidden');
      hiddenInput.setAttribute('name', 'stripeToken');
      hiddenInput.setAttribute('value', token.id);
      form.appendChild(hiddenInput);

      // Submit the form
      form.submit();
    }
})(jQuery);
</script>