cpcdev
cpcdev

Reputation: 1214

Using Custom Separate Form Fields with Stripe

I'm using the Stripe API (PHP) to create a checkout form that uses custom fields. I'm trying to create the Stripe token but it is not working:

var stripe = Stripe('pk_test_yzxdfxfsd9mafsfasfFnFhfsaP1zt');
var elements = stripe.elements();

var cardNumber = elements.create('cardNumber');
cardNumber.mount('#card-number');
var cardExpiry = elements.create('cardExpiry');
cardExpiry.mount('#card-expiry');
var cardCvc = elements.create('cardCvc');
cardCvc.mount('#card-cvc');


stripe.createToken({
    number: $('.card-number').val(),
    cvc: $('.card-cvc').val(),
    exp_month: '04',
    exp_year: '21',
}).then(function(result) {
    if (result.error) {
        // Inform the user if 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);
    }
});

I've tried to pass in values for the card manually like shown above but I get the error:

Stripe Elements must be mounted in a DOM element that can contain child nodes. `input` elements are not permitted to have child nodes. Try using a `div` element instead.

Here is the HTML for the form:

<div>
    <span class="checkoutFormLabel">Card Number</span>
</div>
<div>
    <input type="text" name="card_num" id="card-number" class="full_width" />
</div>

<div>
    <span class="checkoutFormLabel">Name on Card</span>
</div>
<div>
    <input type="text" name="name_on_card" class="full_width" />
</div>


<div>
    <span class="checkoutFormLabel">Expiration</span>
</div>
<div>
    <input type="text" name="expiryDate" id="card-expiry" placeholder="MM/YY" class="full_width" />
</div>

<span class="checkoutFormLabel">CVC</span>
        <input type="text" name="cvc" class="full_width" id="card-cvc" style="width:100px;" />

How can I fix my stripe checkout form to work with custom form fields like I have set up above?

Thanks!

Upvotes: 3

Views: 4450

Answers (2)

Paul Asjes
Paul Asjes

Reputation: 5847

computercarguy is right, to expand a little:

One of the main purposes of Stripe Elements is to abstract the problem of PCI compliance away from you. By having inputs on your page that collect raw card numbers, you become subject to the full scope of PCI compliance. This means you are responsible for making sure the card details are secure, which includes submitting a 40+ page report annually proving that you are compliant.

The Stripe Elements are generated in an iframe which is hosted on a Stripe domain, meaning that raw card details never actually touch your systems, making you automatically PCI compliant through Stripe. This also prevents third parties (and you) from being able to access the private information.

Stripe Elements primarily accepts the card element you created with elements.create, it returns a tokenized version of the card which you can then use to make charges via your backend.

If you do decide that you'd want to handle raw card details yourself (and be fully PCI compliant) then you should collect the details, pass them to your backend and tokenize via the Stripe API instead. But again, this isn't really recommended as it opens up a large can of PCI worms.

Upvotes: 5

computercarguy
computercarguy

Reputation: 2454

Looking at the Stripe documentation, I don't think you are going to be able to do that. Stripe gives you a very specific set of parameters createToken will accept, and that's it.

Then again, the error give you the hint that the card-number element isn't just an input type, but a div which probably includes an input. In fact, I'd wager that the createToken method is wanting to pull out that information itself, rather than risk you giving it false information. I've tried to dive into the StripeElement card element, and it's extremely complex, has things well hidden, and is designed to make people think twice about trying to fool it.

I'd say to quit trying to reinvent the wheel and use the StripeElement they give you and use it as intended. By the time you've uncovered all the things createToken is likely looking for to validate it has the correct form element, with all of it's security in place, you'll have wasted a bunch of time you could have spent adding functionality or fixing bugs in the rest of your app.

How do I know this? I did the same thing as you did, and after hours & hours of not getting anywhere, I gave up and just used the well engineered, seemingly secure, and easy to use element that took minutes to make work.

Upvotes: 3

Related Questions