J'ai dû résoudre ce problème, car j'utilisais Stripe.js v2, et le support technique de Stripe m'a expliqué la faille de sécurité. Je me suis donc senti obligé de passer à Stripe.js v3 "Elements". Ce qu'ils ont dit, c'est que tout javascript sur la même page que les éléments de votre formulaire de carte de crédit pouvait obtenir les valeurs des données sensibles de la carte de crédit. Je suppose que cela pourrait se produire si une personne tirait des scripts externes ... et je suppose que cela a dû se produire, sinon ils ne s'en seraient pas souciés. Quoi qu'il en soit, voici comment j'ai fait fonctionner mes éléments Stripe.js v3 avec les groupes d'entrée de Bootstrap 4. C'est un exemple complet qui fonctionne, vous devez juste changer la clé publique.
Exemple par défaut basé sur 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>
J'ai testé uniquement dans Firefox, Chrome, et Chrome sur Android. Il semble que cela fonctionne bien. Faites-moi savoir si vous rencontrez des problèmes.
Exemple facultatif basé sur 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/vue@2.5.13/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>
Cet exemple de Vue.js pourrait bénéficier d'un peu de travail, mais il peut vous aider à démarrer.