STRIPE: How Do I get this checkout form to work - php

I've been having a bunch of trouble with getting Stripe to work for me and have googled a bunch of examples but cant seem to get it to make charges.
I'm using Stripes, simple checkout form, and it is definitely generating a stripe token because I can see it in the stripe logs. I then have the form execute charge.php which receives the stripe token as a POST variable and this is def working because I can echo the token.
The problem is that it then does nothing and doesn't throw any error nor charge the card.
The code is as follows:
Checkout page:
<form action="charge.php" method="POST">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="test key"
data-amount="2000"
data-name="Demo Site"
data-description="2 widgets ($20.00)"
data-image="/128x128.png">
</script>
</form>
The Actual PHP script which charges: charge.php
<?php
require('Absolute Link to site /lib/Stripe.php');
// Set your secret key: remember to change this to your live secret key in production
// See your keys here https://dashboard.stripe.com/account
Stripe::setApiKey("test key");
// Get the credit card details submitted by the form
$token = $_POST['stripeToken'];
// Create the charge on Stripe's servers - this will charge the user's card
try {
$charge = Stripe_Charge::create(array(
"amount" => 1000, // amount in cents, again
"currency" => "aud",
"card" => $token,
"description" => "VIP Basic"
));
} catch(Stripe_CardError $e) {
// The card has been declined
}
?>
I emailed stripe support and they say the charge.php code works on their end and to check whether the libs are being called correctly. There aren't any warnings and nothing in the error_log.
Does anyone have any ideas? It should be the simplest thing in the world and i'm tearing my hair out over it and just cant see it.

The problem could be with the card not accepting aud, you should try visa or mastercard. If you are seeing the generated token in the dashboard try the below ajax method. include stripe.js and jquery.
<input type="text" id="card_number">
<input type="text" id="cvc">
<input type="text" id="ex_month">
<input type="text" id="ex_year">
<button id="paynow">Pay Now</button>
$('#paynow').click(function(){
Stripe.setPublishableKey('pk_test_Bwg5tfiOULnNK8DvS60zJ2Sm');
Stripe.card.createToken({
number: $("#card_number").val(),
cvc: $("#cvc").val(),
exp_month: $("#ex_month")val(),
exp_year: $("#ex_year").val()
}, stripeResponseHandler);
function stripeResponseHandler(status, error){
if(response.error){
alert(response.error.message);
}
else {
$.ajax({
url: 'charge.php',
type:'POST',
data:{token:response.id},
cache:false,
success: function(data){
alert(data);
}
});
}
}
});

Your code looks correct and should work, so the issue is most likely that the card is being declined, but you aren't handling the error. Add some code to this part:
} catch(Stripe_CardError $e) {
// The card has been declined
}
Echo out the error, etc, and you'll probably discover the problem.

Related

Either you do not have a card saved to your Wallet or the current domain is not registered for Apple Pay

I'm trying to set up Apple Pay using Stripe on my website.
I'm following the instructions here https://stripe.com/docs/stripe-js/elements/payment-request-button
I've already registered my domain on Stripe, seen here
Then i added test card to my wallet on my macbook, seen here
When i run ngrok on my localhost, ngrok shows me this
ngrok (Ctrl+C to quit)
Hello World! https://ngrok.com/next-generation
Session Status online
Account XXXXXXX (Plan: Pro)
Version 3.0.6
Region United States (us)
Latency 302ms
Web Interface http://127.0.0.1:4040
Forwarding https://XXXXXXXXXX.ngrok.io -> https://blabla.xxxxx.com:443
Connections ttl opn rt1 rt5 p50 p90
91 0 0.01 0.01 5.03 9.41
HTTP Requests
-------------
GET /frontend/web/debug/default/toolbar 200 OK
GET /frontend/web/payment/checkout/ 200 OK
GET /frontend/web/debug/default/toolbar 200 OK
GET /frontend/web/payment/checkout/ 200 OK
GET /frontend/web/debug/default/toolbar 200 OK
GET /frontend/web/payment/checkout/ 200 OK
GET /frontend/web/debug/default/toolbar 200 OK
GET /frontend/web/payment/checkout/ 200 OK
GET /frontend/web/debug/default/toolbar 200 OK
GET /frontend/web/payment/checkout/ 200 OK
When i view my site through the ngrok domain on Safari, i get this error on the safari console
Either you do not have a card saved to your Wallet or the current domain (XXXXXXXX.ngrok.io) is not registered for Apple Pay. Visit https://dashboard.stripe.com/account/apple_pay to register this domain.
I'm using stripe php and stripe.js for my payment. Here is my JS
var publishableKey = document.getElementById('payment-form').getAttribute('data-stripe-publishable-key');
var paymentIntent = document.getElementById('payment-form').getAttribute('data-stripe-paymentIntent');
document.addEventListener('DOMContentLoaded', async () => {
if (!publishableKey) {
document.getElementById('applepay-error').textContent = 'No publishable key returned from the server';
}
// 1. Initialize Stripe
const stripe = Stripe(publishableKey, {
apiVersion: '2020-08-27',
});
// 2. Create a payment request object
var paymentRequest = stripe.paymentRequest({
country: 'US',
currency: 'usd',
total: {
label: 'Demo total',
amount: 1999,
},
requestPayerName: true,
requestPayerEmail: true,
});
// 3. Create a PaymentRequestButton element
const elements = stripe.elements();
const prButton = elements.create('paymentRequestButton', {
paymentRequest: paymentRequest,
});
// Check the availability of the Payment Request API,
// then mount the PaymentRequestButton
paymentRequest.canMakePayment().then(function (result) {
if (result) {
prButton.mount('#applepay-element');
} else {
document.getElementById('applepay-element').style.display = 'none';
document.getElementById('applepay-error').textContent = 'Apple Pay support not found. Check the pre-requisites above and ensure you are testing in a supported browser.';
}
});
paymentRequest.on('paymentmethod', async (e) => {
// Confirm the PaymentIntent without handling potential next actions (yet).
let {error, paymentIntent} = await stripe.confirmCardPayment(
clientSecret,
{
payment_method: e.paymentMethod.id,
},
{
handleActions: false,
}
);
if (error) {
document.getElementById('applepay-error').textContent = error.message;
// Report to the browser that the payment failed, prompting it to
// re-show the payment interface, or show an error message and close
// the payment interface.
e.complete('fail');
return;
}
// Report to the browser that the confirmation was successful, prompting
// it to close the browser payment method collection interface.
e.complete('success');
// Check if the PaymentIntent requires any actions and if so let Stripe.js
// handle the flow. If using an API version older than "2019-02-11" instead
// instead check for: `paymentIntent.status === "requires_source_action"`.
if (paymentIntent.status === 'requires_action') {
// Let Stripe.js handle the rest of the payment flow.
let {error, paymentIntent} = await stripe.confirmCardPayment(
clientSecret
);
if (error) {
// The payment failed -- ask your customer for a new payment method.
document.getElementById('applepay-error').textContent = error.message;
return;
}
document.getElementById('applepay-error').textContent = 'Payment ${paymentIntent.status}: ${paymentIntent.id}';
}
document.getElementById('applepay-error').textContent = 'Payment ${paymentIntent.status}: ${paymentIntent.id}';
});
});
Any idea how get this to work? Thank you.
There could be multiple reasons you want to double check:
Domain was set up in a different Stripe Account than the Publishable Key's owner account.
Issue with a specific Apple account.
If this involves Stripe Connect and Standard/Direct Charge it would be more complicated.
You can double check 1), ask your friend or colleague for help on checking 2). If that doesn't help, write to Stripe Support and they would be able to help checking further on 3).

Search for PHP example new stripe "checkout" integration stripe-php

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.

Stripe Checkout charging a card

I have this code that works great.
<input class="form-control"
type="number"
id="custom-donation-amount"
placeholder="50.00"
min="0"
value="50"
step="10.00"/>
<script src="https://checkout.stripe.com/checkout.js"></script>
<button id="customButton" class="pay-button">
<h4 class="donate-text button">Donate by
<img src="http://#/testing/credit-card.png" ></h4>
</button>
<script>
var handler = StripeCheckout.configure({
key: 'pk_test_mytestingkey',
image: '',
locale: 'auto',
token: function(token) {
// Use the token to create the charge with a server-side script.
// You can access the token ID with `token.id`
}
});
$('#customButton').on('click', function(e) {
// Open Checkout with further options
var amount = $("#custom-donation-amount").val() * 100;
handler.open({
name: 'Testing',
description: 'Testing',
amount: amount
});
e.preventDefault();
});
// Close Checkout on page navigation
$(window).on('popstate', function() {
handler.close();
});
</script>
It states on the documentation:
"On your server, grab the Stripe token in the POST parameters submitted by your form. From there, it's one simple API call to charge the card:"
I am trying to CHARGE the card information. Stripe provides the following API call to do that: I am assuming this is a charge.php file?
// Set your secret key: remember to change this to your live secret key in production
// See your keys here https://dashboard.stripe.com/account/apikeys
\Stripe\Stripe::setApiKey("sk_test_mykey");
// Get the credit card details submitted by the form
$token = $_POST['stripeToken'];
// Create the charge on Stripe's servers - this will charge the user's card
try {
$charge = \Stripe\Charge::create(array(
"amount" => 1000, // amount in cents, again
"currency" => "usd",
"source" => $token,
"description" => "Example charge"
));
} catch(\Stripe\Error\Card $e) {
// The card has been declined
}
My question: how do I charge the card using the following code without there being a <form> method post, or <form> action...? It's using javascript to capture the token. But I don't know how to send that token to a charge.php file... Basically how do I grab that stripe token and initiate the API call? How do I initiate the API call....?
You should have a charge.php file on your server and use $.post to send to the token to the php.
// make sure you have the right path to charge.php
// pass the token to the php file with POST, your php is expecting $_POST['stripeToken']
token: function(token) {
// Use the token to create the charge with a server-side script.
// You can access the token ID with `token.id
$.post( "charge.php", { stripeToken: token.id})
// check if it worked
.done(function( data ) {
console.log( "Card charged: " + data );
});
}
Your charge.php file, make sure you installed the Stripe PHP library
<?
// composer require stripe/stripe-php
require 'vendor/autoload.php';
// Set your secret key: remember to change this to your live secret key in production
// See your keys here https://dashboard.stripe.com/account/apikeys
\Stripe\Stripe::setApiKey("sk_test_mykey");
// Get the credit card details submitted by the form
$token = $_POST['stripeToken'];
// Create the charge on Stripe's servers - this will charge the user's card
try {
$charge = \Stripe\Charge::create(array(
"amount" => 1000, // amount in cents, again
"currency" => "usd",
"source" => $token,
"description" => "Example charge"
));
} catch(\Stripe\Error\Card $e) {
// The card has been declined
}
?>
Like you say, you need to generate a Stripe token and do a form post. Without a valid token you can not charge the card.
Here's a guide on how to create custom forms with Stripe, including how to generate a token:
https://stripe.com/docs/custom-form
An easier way is to simply embed their ready-to-use checkout:
https://stripe.com/docs/checkout/tutorial
If your are using mamp. UPDATE TO MAMP 4
stripes API no longer supports older versions of MAMP.

How to pass stripe token to the server, create a user account, charge the credit card and have it all show up on the dashboard

So I'm trying to get stripe setup on my server but I'm having a problem.
I'm using checkout v2 on my page and the form works perfectly, however the token never passes through to my php file. the card is charged but the information does not show up on the dashboard, it is in the log though.
here's what I have:
<form action="assets/php/slingshot.php" method="POST">
<button id="customButton">Purchase</button>
<script>
$('#customButton').click(function(){
var token = function(res){
var $input = $('<input type=hidden name=stripeToken />').val(res.id);
$('form').append($input).submit();
};
StripeCheckout.open({
key: 'pk_live_*************************',
address: true,
amount: 2500,
currency: 'usd',
name: 'test',
description: 'A bag of test',
panelLabel: 'Checkout',
token: token
});
return false;
});
</script>
</form>
and then for slingshot.php:
<?php
require_once(dirname(__FILE__) . '/config.php');
$token = $POST['stripeToken']; //get the creditcard details from the form
try {
$charge = Stripe_Charge::create(array(
'card' => $token,
'amount' => 2500, //amount in cents
'currency' => 'usd',
'description' => 'Get Bacon Direct, LLC'
));
} catch(Stripe_CardError $e) {
// The card has been declined
}
echo '<h1>Successfully charged $25.00 </h1>';
}
?>
and my config.php file:
<?php
require_once('stripe-php/lib/Stripe.php');
// Set your secret key: remember to change this to your live secret key in production
// See your keys here https://manage.stripe.com/account
$stripe = array(
"secret_key" => "sk_live_************************************",
"publishable_key" => "pk_live_************************************"
);
Stripe::setApiKey($stripe['secret_key'] );
?>
could you please help me out?
I'm not entirely sure how the charge is being made, but I'm fairly confident that the reason you aren't getting the token, is because of this line
$token = $POST['stripeToken']; //get the creditcard details from the form
When accessing POST data in PHP, the global variable is prefixed with an underscore, so you'd need to do
$token = $_POST['stripeToken']; //get the creditcard details from the form
That should fix it.
-- UPDATE ---
Just for readability, in your javascript, I would specify the input field as follows
var $input = $('<input type="hidden" name="stripeToken" />').val(res.id);
I've also checked out the stripe documentation again, and it looks like the card attribute is optional, as is customer, but it does state that one must be provided. Chances are, it's not throwing an error because of an issue with their code that doesn't catch the eventuality of neither being provided.

No Ajax response even though PHP file set up correctly

I have a simple sign up mailing list form. It sends the user's email address to a store-address.php file. I use jQuery's ajax object to send a request to the php file and then receive a response.
The problem is I am not getting a response from the php file. I tried setting the cache to false in the request. I also tried send the information through the URL like so:
http://www.fifthtribe.com/inc/store-address.php?ajax=true&cache=false&email=test4%40gmail.com
When I do it that way it works and gives me a reponse. But when I do it through ajax it doesn't give me a response. This is from Firebug:
And here's snippets from my code:
HTML:
<div id="mlist">
<form id="mlist_form" method="POST" action="">
<input type="text" id="email" name="email" placeholder="Email" />
<input type="submit" id="submit_btn" value="Join" />
</form>
<div id="response"></div>
</div>
JQuery:
/* Add to mailing list */
$("#mlist_form").submit( function(e){
//$('#response').append('<div id="thanks-mce"><div id="mce-arrow"></div>Thanks for signing up!</div>');
var email = escape( $('#email').val() );
e.preventDefault();
data = {
"ajax" : "true",
"email" : email,
"cache" : "false"
}
$.ajax({
type: "POST",
url: 'inc/store-address.php',
data: data,
success: function( msg ){
// successfully signed up
$('#response').html( msg );
$('#email').val('');
},
error: function( err ){
// error while signing up
$('#response').html('Error: Is your email correct?');
}
});
return false;
});
PHP:
function storeAddress(){
// Validation
if(!$_GET['email']){ return "No email address provided"; }
if(!preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*$/i", $_GET['email'])) {
return "Email address is invalid";
}
require_once('MCAPI.class.php');
// grab an API Key from http://admin.mailchimp.com/account/api/
$api = new MCAPI('xxxxxxxxxxxxxxxxxxxxxxxxxxxxx-us4');
// grab your List's Unique Id by going to http://admin.mailchimp.com/lists/
// Click the "settings" link for the list - the Unique Id is at the bottom of that page.
$list_id = "xxxxxxxx";
if($api->listSubscribe($list_id, $_GET['email'], '') === true) {
// It worked!
return 'Success! Check your email to confirm sign up.';
}else{
// An error ocurred, return error message
return 'Error: ' . $api->errorMessage;
}
}
// If being called via ajax, autorun the function
if($_GET['ajax']){ echo storeAddress(); }
?>
You realize that your PHP script is using GET method but your jQuery code is using the POST method right?
If the information is being posted to PHP, PHP will need to use $_POST to retrieve it. This explains why the URL method using $_GET works but the jQuery POST doesn't.
Good luck!
It looks like you're using $_GET instead of $_POST. Try echoing out the contents of $_REQUEST to see what that holds.
Debug your script!
Place an alert in the success and error parts of your script and then you will know whether the AJAX is working.
If not, you can then work your way up the document and see where the problem is.
In addition, the error here is quite simple. You are using $_GET in PHP and you are POSTING your data using AJAX, this will not show an error. Although the PHP document will not process your request because it is not being fed any parameters.

Categories