I have a simple custom button Stripe Checkout setup at the moment which is charging payments ok but I cannot seem to get the customers email address to pass back to Stripe.
Heres my current code:
JS
var handler = StripeCheckout.configure({
key: 'myPublicKey',
image: '/images/RoadPreview.jpg',
locale: 'auto',
token: function(token, args){
$form.append(jQuery('<input type="hidden" name="stripeToken" />').val(token.id));
$form.append(jQuery('<input type="hidden" name="stripeEmail" />').val(token.email));
$form.get(0).submit();
}
});
jQuery('#roadFlow').on('click', function(e) {
var token = function(res){
var $input = jQuery('<input type=hidden name=stripeToken />').val(res.id);
jQuery('form').append($input).submit();
};
// Open Checkout with further options
handler.open({
name: 'Road Bike - Flow',
description: 'Make a £500 deposit to Order Now',
billingAddress: true,
shippingAddress: true,
currency: "gbp",
amount: 50000,
token: token
});
e.preventDefault();
});
jQuery(window).on('popstate', function() {
handler.close();
});
PHP
<?php
require_once('stripeConfig.php');
\Stripe\Stripe::setApiKey("mySecretKey");
$token = $_POST['stripeToken'];
$email = $_POST['stripeEmail'];
$customer = \Stripe\Customer::create(array(
'id' => $name,
'email' => $email,
'card' => $token
));
$charge = \Stripe\Charge::create(array(
'customer' => $customer->id,
'amount' => 50000,
'description' => "Dassi Road - Flow",
"receipt_email" => $email,
'currency' => 'gbp'
));
echo '<h1>Successfully Paid!</h1>';
?>
Button
<form action="charge.php" method="post"><button type="submit" id="roadFlow">Order Now</button>
Any ideas as to where I'm going wrong?
You're overriding the token callback that you defined in the StripeCheckout.configure() call when you call handler.open(), and the overriding function does not add the stripeEmail field.
This should work:
var handler = StripeCheckout.configure({
key: 'myPublicKey',
image: '/images/RoadPreview.jpg',
locale: 'auto',
token: function(token, args){
$form.append(jQuery('<input type="hidden" name="stripeToken" />').val(token.id));
$form.append(jQuery('<input type="hidden" name="stripeEmail" />').val(token.email));
$form.get(0).submit();
}
});
jQuery('#roadFlow').on('click', function(e) {
// Open Checkout with further options
handler.open({
name: 'Road Bike - Flow',
description: 'Make a £500 deposit to Order Now',
billingAddress: true,
shippingAddress: true,
currency: "gbp",
amount: 50000
});
e.preventDefault();
});
jQuery(window).on('popstate', function() {
handler.close();
});
Related
What do I have to change in my code to immigrate from legacy stripe checkout to the new checkout?? I am confused with their wording. And most examples I find are old (2015-1016...and are the "old way")
Stripe wants me to upgrade to new checkout because of SCA
This is my working stripe checkout, I have a button that opens the checkout box
<script>
var handler = StripeCheckout.configure({
key: '<? echo $stripe_p_key;?>',
image: 'https://stripe.com/img/documentation/checkout/marketplace.png',
locale: 'auto',
token: function(token) {
var $form = $('#f2');
var token = token.id;
showloader('loaderid');
$form.prepend($('<input type="hidden" style="display:none" name="stripeToken">').val(token));
$form.prepend($('<input type="hidden" style="display:none" name="cc_currency">').val('<? echo $dialog_waehrung_kreditkarte;?>'));
$form.get(0).submit();
}
});
document.getElementById('customButton').addEventListener('click', function(e) {
// Open Checkout with further options:
handler.open({
name: '',
description: '<? echo $dialog_titel;?>',
zipCode: true,
currency: '<? echo $dialog_waehrung_kreditkarte;?>',
email: '<? echo $dialog_email_kreditkarte;?>',
amount: <? echo $dialog_preis_kreditkarte;?>
});
e.preventDefault();
});
// Close Checkout on page navigation:
window.addEventListener('popstate', function() {
handler.close();
});
</script>
then I charge the card in the next step
Stripe::setApiKey($params['private_live_key']);
$pubkey = $params['public_live_key'];
try {
$charge = Stripe_Charge::create(array(
"amount" => $amount_cents,
"currency" => $_SESSION['cc_currency'],
"source" => $_SESSION['stripeToken'],
"description" => $description,
"expand" =>array("balance_transaction")
)
);
If no error is thrown I forward the customer to his download page.
I want a very simple way, I do not need customers, bills, recruing payments or whatever..just single payments. I do not want customers address or such things. Payment and goodbye...
Stripe says I have to change this process.
But their example is confusing for me:
https://stripe.com/docs/payments/checkout/migration#api-products
(I did never create a customer for exampley...why should I?)
Can someone tell me what I have to do to migrate to the new checkout version?
Basic setup (you can build it up from here)
Back-end:
Update your Stripe PHP Library.
Change from \Stripe\Charge to \Stripe\PaymentIntent following this format:
$charge = \Stripe\Charge::create([
'source' => $token_id,
'amount' => $amount,
'currency' => 'usd',
]);
$intent = \Stripe\PaymentIntent::create([
'payment_method_data' => [
'type' => 'card',
'card' => ['token' => $token_id],
],
'amount' => $amount,
'currency' => 'usd',
'confirmation_method' => 'manual',
'confirm' => true,
]);
Front-end:
Update your Stripe JS to use v3.
<script src='https://js.stripe.com/v3/' type='text/javascript'></script>
Update JS code that handles your payment form:
document.addEventListener("DOMContentLoaded", function(event) {
var stripe = Stripe('xxxxxxxxxx'); // test publishable API key
var elements = stripe.elements();
var card = elements.create('card');
// Add an instance of the card UI component into the `card-element` <div>
card.mount('#card-element');
// Handle events and errors
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
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();
}
function createToken() {
stripe.createToken(card).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);
}
});
};
// Create a token when the form is submitted.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(e) {
e.preventDefault();
createToken();
});
});
Edit your HTML form:
<form action="process_payment.php" method="post" id="payment-form">
<div class="form-row">
<label for="card-element">
Credit or debit card
</label>
<div id="card-element"><!-- Your form goes here --></div>
</div>
<!-- Used to display form errors -->
<div id="card-errors" role="alert"></div>
</div>
<button type="submit">Pay</button>
</form>
With the new SCA regulations coming in as you mentioned in your comment, you need to use Payment methods and Payment intents now.
Basically from taking a look at your sample code you will need to rewrite pretty much everything (if you haven't already)
Their current docs are here -> https://stripe.com/docs/payments/checkout
The reason for Payment Intents and Payment methods is due to SCA - https://stripe.com/docs/strong-customer-authentication
They have a migration guide too which can be found on the side bar.
However from their examples this is how you would create your new payment intent
$intent = \Stripe\PaymentIntent::create([
'amount' => 1099,
'currency' => 'gbp',
]);
Here is also their guide for migrating from the charges API - it has a tab for stripe.js V2 if you've been using it https://stripe.com/docs/payments/payment-intents/migration
I agree. We have been using Stripe Checkout for about a year. The original implementation was dead easy. Trying to migrate to SCA compliant code is just a mess. Their online Chat is useless, and from the response in Chat, they bascially don't care if you stay with them or go.
We're going to revert to PayPal which we used before and look for an alternative payment processor.
I have a multistep form, in the step 3 there is a button "Pay" that when is clicked it shows a Stripe modal using the jQuery below:
<form action="{{ route('registration.charge') }}" method="post" id="paymentForm">
{{csrf_field()}}
<input type="hidden" name="stripeToken" id="stripeToken"/>
<input type="submit" href="" id="payment" class="btn btn-primary float-right"
value="Pay"/>
</form>
Charge method to handle the Stripe charge:
public function charge(Request $request)
{
Stripe::setApiKey(config('services.stripe.secret'));
$source = $request->stripeToken;
Charge::create([
'currency' => 'eur',
'description' => 'Example charge',
'amount' => 2500,
'source' => $source,
]);
}
Route:
Route::post('/charge', [
'uses' => 'RegistrationController#charge',
'as' => 'registration.charge'
]);
When the user clicks in pay the stripe modal appears the user fills the form and click in Pay button the Stripe validates and send the token and the user is redirected to another page (http://proj.test/charge) because of the charge().
Do you know how to instead of redirecting the user to (http://proj.test/charge) change Stripe code to use Ajax so the user remains on the same page? So that is possible to show in that some page a success message, for example, informing that the payment was completed.
Stripe code:
let stripe = StripeCheckout.configure({
key: "{{config('services.stripe.key')}}",
image: "",
locale: "auto",
token: (token) => {
document.getElementById('stripeToken').value = token.id;
document.getElementById('paymentForm').submit();
}
});
document.getElementById('payment').addEventListener('click', function(e){
stripe.open({
name: 'test',
description: 'test',
amount: 1000
});
e.preventDefault();
});
Like this is not working, it appears the " console.log("Ajax Error!");" and then the user is redirected to "http://proj.test/charge".
let stripe = StripeCheckout.configure({
key: "{{config('services.stripe.key')}}",
image: "",
locale: "auto",
token: (token) => {
document.querySelector('#stripeToken').value = token.id;
document.querySelector('#paymentForm').submit();
$.ajax({
type: "POST",
url: '{{route('conferences.charge')}}',
data: {tokenid: token.id, email: token.email},
success: function(data) {
if (data == 'success') {
console.log("success");
}
else {
console.log("error");
console.log("Ajax Error!");
}
},
error: function(data) {
console.log(data);
}
});
}
});
document.getElementById('payment').addEventListener('click', function(e){
stripe.open({
name: 'test',
description: 'test',
amount: '{{session('total')}}'
});
e.preventDefault();
});
RegistrationController returning code 200:
public function charge(Request $request)
{
Stripe::setApiKey(config('services.stripe.secret'));
$source = $request->stripeToken;
$selectedRtypes = Session::get('selectedRtypes');
$amount = (collect($selectedRtypes)->first()['total']) * 100;
try{
Charge::create([
'currency' => 'eur',
'description' => 'Example charge',
'amount' => $amount,
'source' => $source,
]);
}
catch(\Exception $e){
return response()->json(['status' => $e->getMessage()], 422);
}
return response()->json([
'success' => true,
'message' => 'success',
], 200);
}
So this could probably be achieved in different ways.
Here is a solution from a VUE script that uses jquery to get the form
send: function () {
Stripe.setPublishableKey("stripekey")
const $form = $('#payment-form')
Stripe.card.createToken($form, (status, response) => {
if (response.error) {
return
}
this.payment_token = response.id
this.post('<your controller charge>', this.getFormData())
})
},
post: function (url, data) {
axios.post(url, data).then(response => {
// handle success here
}).catch(error => {
// handle error here
})
},
getFormData: function () {
return {
'payment_token': this.payment_token
}
},
But what I think you are looking for is
send: function () {
Stripe.setPublishableKey("stripekey")
const $form = $('#payment-form')
Stripe.card.createToken($form, (status, response) => {
if (response.error) {
return
}
let stripeToken = response.id
})
}
This uses the stripe javascript sdk
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
I have the following fairly basic implementation of Stripe. It successfully creates a new customer but it won´t charge and return the "SUCCESS ERROR" message in the console. The token seems to be created correctly so my guess is i am missing something in the charge.php.
NOTE: I have not used composer to install stripe but load the init.php in config.php (could that be the problem?). Also is the neccessary even though i use ajax?(removing it won´t solve the problem though)
Index.php
<?php require_once('stripe/config.php'); ?>
<form action="charge.php" method="post">
<script src="https://checkout.stripe.com/checkout.js"></script>
<button id="customButton">Purchase</button>
<script>
var handler = StripeCheckout.configure({
key: 'pk_test_*******************',
token: function(token) {
// Use the token to create the charge with a server-side script.
// You can access the token ID with `token.id`
console.log(token)
$.ajax({
url: 'stripe/charge.php',
type: 'post',
data: {tokenid: token.id, email: token.email},
success: function(data) {
if (data == 'success') {
console.log("Card successfully charged!");
}
else {
console.log("Success Error!");
}
},
error: function(data) {
console.log("Ajax Error!");
console.log(data);
}
}); // end ajax call
}
});
$('#customButton').on('click', function(e) {
// Open Checkout with further options
handler.open({
name: 'shipping free',
description: '2 widgets',
amount: 2000
});
e.preventDefault();
});
// Close Checkout on page navigation
$(window).on('popstate', function() {
handler.close();
});
</script>
</form>
CONFIG.PHP
<?php require_once('init.php');
$stripe = array(
secret_key => 'sk_test_************************',
publishable_key => 'pk_test_************************'
);
Stripe::setApiKey($stripe['secret_key']);
?>
CHARGE.PHP
<?php require_once('/config.php');
$tokenid = $_POST['tokenid'];
$email = $_POST['email'];
$customer = \Stripe\Customer::create(array(
'email' => $email,
'card' => $tokenid
));
$charge = \Stripe\Charge::create(array(
'email' => $email,
'card' => $tokenid
'amount' => 5000,
'currency' => 'usd',
));
echo '<h1>Successfully charged $50.00!</h1>';
?>
In this line, 'card' => $tokenid. you are missing comma(,).
Add comma in that line.
$charge = \Stripe\Charge::create(array(
'email' => $email,
'card' => $tokenid,
'amount' => 5000,
'currency' => 'usd',
));
Using Stripe, I want to store a customer email address from the email they supplied in Checkout. Unfortunately, posting stripeEmail in my charge.php file returns null.
How can I return the email from checkout so I can use it to send a receipt?
Here's my form code:
<script src="https://checkout.stripe.com/v2/checkout.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"></script>
<form action="charge.php" method="post">
<input type="hidden" id="amount" name="chargeAmount"/>
<button data-charge-amount="300000" data-charge-name="Name" data-charge-description="Description">Select Pledge Level</button>
<button data-charge-amount="123123" data-charge-name="Name2" data-charge-description="Description2">Donate</button>
</form>
<script>
$('button').click(function(){
var token = function(res){
var $theToken = $('<input type=hidden name=stripeToken />').val(res.id);
$('form').append($theToken).submit();
};
var amount = $(this).data("chargeAmount");
var name = $(this).data("chargeName");
var description = $(this).data("chargeDescription");
$('input#amount').val(amount);
StripeCheckout.open({
key: 'pk_test_xxxxxxxxxxxxxxxxxxxxxxxx',
address: true,
amount: amount,
currency: 'usd',
name: name,
description: description,
panelLabel: 'Pledge',
token: token,
});
return false;
});
</script>
Here is my charge.php code:
<?php
require_once('./config.php');
$token = $_POST['stripeToken'];
$amount = $_POST['chargeAmount'];
$customer = \Stripe\Customer::create(array(
'email' => $email,
'card' => $token,
));
$charge = \Stripe\Charge::create(array(
'customer' => $customer->id,
'amount' => $amount,
'currency' => 'usd',
));
?>
Here is my config.php code:
<?php
require_once('./stripe-php-2.1.2/init.php');
$stripe = array(
"secret_key" => "sk_test_xxxxxxxxxxxxxxxxxxxxxxxx",
"publishable_key" => "pk_test_xxxxxxxxxxxxxxxxxxxxxxxx"
);
\Stripe\Stripe::setApiKey($stripe['secret_key']);
?>
Any help would be much appreciated.
THANKS!
The issue here is that you're using Custom Checkout which means that Checkout won't post the data to your server automatically but instead give it in the token callback. In your case you're only retrieving the token id here which is why you are not seeing the email.
Update your code so that the token callback also retrieves the email and send it in the stripeEmail parameter:
var token = function(res){
var $theToken = $('<input type="hidden" name="stripeToken" />').val(res.id);
var $theEmail = $('<input type="hidden" name="stripeEmail" />').val(res.email);
$('form').append($theToken).append($theEmail).submit();
};
I just spent all night on this problem! #Koopajah helped a ton, so here's my entire solution in case anyone else happens to run across this.
Here's the form:
<form action="/charge.php" method="post">
<input
type="submit"
id="payMe"
class="btn btn-default btn-lg btn-success"
value=" Pay "
data-key="xxxxxxx"
data-amount="199"
data-currency="usd"
data-name="Stuff"
data-description="20 Whozits ($19.99)"
data-image="images/image.jpg"
data-bitcoin="true"
/>
<script src="https://checkout.stripe.com/v2/checkout.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<script>
$(document).ready(function() {
$('#payMe').on('click', function(event) {
event.preventDefault();
var $button = $(this),
$form = $button.parents('form');
var opts = $.extend({}, $button.data(), {
token: function(result) {
var $theToken = $('<input>').attr({ type: 'hidden', name: 'stripeToken', value: result.id })
var $theEmail = $('<input>').attr({ type: 'hidden', name: 'stripeEmail', value: result.email })
$form.append($theToken).append($theEmail).submit();
}
});
StripeCheckout.open(opts);
});
});
</script>
</form>
And here's charge.php:
<?php
require_once('vendor/autoload.php');
$stripe = array(
"secret_key" => "xxxx",
"publishable_key" => "xxxx"
);
\Stripe\Stripe::setApiKey($stripe['secret_key']);
$token = $_POST['stripeToken'];
$email = $_POST['stripeEmail'];
\Stripe\Customer::create(array(
"source" => $token,
"email" => $email,
"description" => "It Worked!"
));
try {
$charge = \Stripe\Charge::create(array(
"amount" => 199, // amount in cents, again
"currency" => "usd",
"source" => $_POST['stripeToken'],
"description" => "Cat Facts"));
} catch(\Stripe\Error\Card $e) {
$error = $e->getMessage();
}
?>
I have had a very similar issue but am using node.js. I modified koopajah's answer and placed it in a charge.js file
const token = req.body.stripeToken;<br>
const email = req.body.stripeEmail;
and then I used this email variable like so...
return stripe.charges.create({
// ensures we send a number, and not a string
amount: parseInt(process.env.STRIPE_COST, 10),
currency: process.env.STRIPE_CCY,
source: token,
description: 'My product', // 👈 remember to change this!
receipt_email: email, // that line sends a receipt email to the customer, you can customise that email inside stripe
metadata: {},
});
I hope this is a useful answer to someone.
I was previously charging users a fixed amount, say, "$20," but I wanted to create a donation box that would accept variables. I understand that there is "StripeCheckout.open," but does anyone know how it would look?
That being said, I am currently using the code below to charge a user a fixed amount, though I'm desperate to find out how to set a variable amount that can be charged.
<?php
require_once('config.php');
$token = $_POST['stripeToken'];
$customer = Stripe_Customer::create(array(
'email' => 'customer#example.com',
'card' => $token
));
$charge = Stripe_Charge::create(array(
'customer' => $customer->id,
'amount' => variable,
'currency' => 'cad'
));
?>
Ok, you probably should use V2 instead of V1, and what you want to do is something like this:
$('#sendPledgeBtn').click(function(){
var token = function(res){
var $input = $('<input type=hidden name=stripeToken />').val(res.id);
var tokenId = $input.val();
var email = res.email;
setTimeout(function(){
$.ajax({
url:'make-payment.php',
cache: false,
data:{ email : email, token:tokenId },
type:'POST'
})
.done(function(data){
// If Payment Success
$('#sendPledgeBtn').html('Thank You').addClass('disabled');
})
.error(function(){
$('#sendPledgeBtn').html('Error, Unable to Process Payment').addClass('disabled');
});
},500);
$('form:first-child').append($input).submit();
};
StripeCheckout.open({
key: 'pk_live_XXXXXXXXX', // Your Key
address: false,
amount: $('#amount').val(),
currency: 'usd',
name: 'Canted Pictures',
description: 'Donation',
panelLabel: 'Checkout',
token: token
});
return false;
});