So I wish to bill customers (who are not users) the same amount as what is displayed in the stripe form
<form action="/charge" method="POST">
{!! csrf_field() !!}
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="pk_test_key"
data-amount="{{ $note->price*100 }}"
data-name="Hello World"
data-description="{{$note->title}}"
data-image="/img/documentation/checkout/marketplace.png"
data-locale="auto"
data-currency="aud">
</script>
</form>
In the form the price displayed is the price listed in the relevant note model * 100. I would like the customer to actually be billed this value, it will change depending upon the note.
Here is my server billing
public function charge()
{
// 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_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" => 100, // amount in cents, again
"currency" => "aud",
"source" => $token,
"description" => "Example charge"
));
} catch(\Stripe\Error\Card $e) {
// The card has been declined
}
return 'payment succesful';
}
I need to set the "amount" equal to the note value.
Otherwise, payment is going through on my cashier test account and mostly everything else needs to be working.
The customers are not registered users though.
The amount needs to be something that you calculate server side, otherwise people can just modify the DOM and pass whatever amount they would like.
Instead, store the id in the cache on the server side, and pass the note in as a dependency to the charge function, then compare the 2.
/**
* Assuming name of "view" page
*/
public function checkout(Note $note)
{
/**
* Always forget this on each page load, so we can switch seamlessly between Notes.
*/
Illuminate\Support\Facades\Cache::forget('nid')->put('nid', $note->id);
}
Don't forget to modify the charge route to include the new reference to our Note dependency
route::post('charge/{note}', 'Controller#charge')->name('charge');
Make sure to update your form to pass the note as well
<form action="{{route('charge', $note)}}" method="POST">
sidenote I like named routes, but it's not required.
Then when you're processing the request, compare the $nid and the $note->id
public function charge(Illuminate\Http\Request $request, Note $note)
{
$nid = Illuminate\Support\Facades\Cache::get('nid');
// id's match, no sneaky stuff. safe to use $note->price now
if ($nid === $note->id) {
//now we can process our payment.
// 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_key");
// Get the credit card details submitted by the form
$token = $request->get('stripeToken');
// Create the charge on Stripe's servers - this will charge the user's card
try {
$charge = \Stripe\Charge::create(array(
"amount" => number_format($note->price, 0, '', ''), // amount in cents, again
"currency" => "aud",
"source" => $token,
"description" => "Example charge"
));
} catch(\Stripe\Error\Card $e) {
// The card has been declined
}
}
}
Related
I have a little store I'm setting up, and so far, it's relatively simple. You can either order the product one time, weekly, or monthly.
I have set up the corresponding products in the Stripe Dashboard.
If the client sends that they want a recurring order, it creates a Customer with their information.
But whenever I try and create a recurring order, I receive a This customer has no attached payment source or default payment method. thrown in.
I'm using Stripe Elements, and since the card data never goes to my server, I'm not sure how to go about adding a payment method to this Customer.
Create subscription:
\Stripe\Subscription::create([
'customer' => $customer_id,
'items' => [
[
'price' => 'price_id_2',
'quantity' => $qty_1,
'price' => 'price_id_2',
'quantity' => $qty_2,
],
],
]);
$.post to send data to the PHP file
$.post('./secret.php', data, null, "json")
.done(function(data) {
clientSecret = data.client_secret;
stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: card,
}
}).then(function(result) {
if (result.error) {
console.log(result.error.message);
} else {
if (result.paymentIntent.status === 'succeeded') {
console.log("Payment success.");
document.getElementById("processing").classList.add("hide");
document.getElementById("order-success").classList.remove("hide");
}
}
})
})
.fail(function(xhr, status, error) {
document.getElementById("processing").classList.add("hide");
document.getElementById("order-failure").classList.remove("hide");
});
My one-time order works fine, but I just can't understand how to do this. The Docs show "Saving Card Data" as a deprecated utility, so I'm not sure what to do.
It sounds like you likely want to save a card during the payment process: https://stripe.com/docs/payments/save-during-payment
I am trying to create a destination charge from my customer to one of the connected account.
\Stripe\Stripe::setApiKey(STRIPE_SECRET_KEY); //Origin Stripe Secret Key
try {
$connectd_account_id = 'acct_XXXXXXX';
$customer_id = 'cus_XXXXXXX'
// sharing my customer with connected account and creating a token.
$token = \Stripe\Token::create(
["customer" => $customer_id], //doctor stripe customer id
["stripe_account" => $connectd_account_id]); //Lab Stripe Account
// I am receiving response ** No such token: tok_xxxxxxx **
$charge = \Stripe\Charge::create(array(
"amount" => 10000,
"currency" => 'USD',
"source" => $token->id,
"application_fee_amount" => 2000,
"transfer_data" => [
"destination" => $connectd_account_id,
],
)
);
} catch (Exception $e) {
$error = $e->getMessage();
}
everytime I receive
No such token: tok_xxxxxxx
What's my mistake here I can't locate. Please help.
If you're creating a destination charge, the card token and customer and related objects should all be created on your platform account. Your platform account is the one interacting with the cardholder and processing the payment, there is then just a transfer of funds within Stripe to the destination account.
Your code appears to be attempting to clone saved card details from your platform to the destination account, which is not what you would do for a Destination charge(you'd only do this if you were using Direct charges where the payment is processed on the connected account and thus need to copy payment information there).
In short, you should omit the code for creating a token, and instead when creating the charge, pass something like "source" => $customer_id, to charge the customer details on your platform.
I have Stripe working great. Upon a customer's donation, a new Subscription is created, and it works great - except if Stripe recognizes the email and says, "Enter the verification code."
If the customer does that, for some reason, a new subscription is not created and the customer is not charged.
Here is my charge-monthly.php
<?php
require_once('init.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_**************");
// Get the credit card details submitted by the form
$token = $_POST['stripeToken'];
$email = $_POST['stripeEmail'];
$amount = $_POST['amount'];
$finalamount = $amount * 100;
$dollars = ".00";
$plan = "/month";
$dash = " - ";
$monthlyplan = $amount .$dollars .$plan .$dash .$email;
//Create monthly plan
$plan = \Stripe\Plan::create(array(
"name" => $monthlyplan,
"id" => $monthlyplan,
"interval" => "month",
"currency" => "usd",
"amount" => $finalamount,
));
// Create a Customer
$customer = \Stripe\Customer::create(array(
"source" => $token,
"description" => "MONTHLY DONATION",
"plan" => $monthlyplan,
"email" => $email, )
);
?>
Any ideas why when Stripe recognizes the user and he is "logged in" it does not allow me to create a subscription?
In the Stripe log, I receive this 400 error:
{
"error": {
"type": "invalid_request_error",
"message": "Plan already exists."
}
}
But there definitely isn't a plan created... ah!
The reason your request is failing is because if a user comes back with the same email address and wants to sign up for the same plan, you already have an existing plan with that name,
$monthlyplan = $amount .$dollars .$plan .$dash .$email;
so your call to \Stripe\Plan::create will return an error and cause the rest of your calls to fail here.
You could add something like a unique id or time to your plan id.
http://php.net/manual/en/function.time.php
http://php.net/manual/en/function.uniqid.php
Some other ways that folks typically handle this are:
Create a single plan for $1, and then adjust the quantity when creating your subscription. So a monthly plan for $1 with quantity of 100, would charge $100 month.
Store the amount that a customer will pay within your application. Subscribe your customers to a $0/month plan. Use webhooks to listen for invoice.created events. Have your webhook handler add an Invoice Item every month for the balance.
i was implementing stripe payment in testing mode.Here i got an error like Same token is used again. is there any different way to add multiple cards.
or i need to call retrive function in a separate page so that conflict of same token never come again.And how should i set a card default.
public function createToken($data)
{
$TokenResult=Token::create(array(
"card" => array(
"name" => $data['name'],
"number" => $data['card_number'],
"exp_month" => $data['month'],
"exp_year" => $data['year'],
"cvc" => $data['cvc']
)));
//echo "<pre>";;
//print_r($TokenResult);
$this->token=$TokenResult['id'];//store token id into token variable
$this->chargeCard($this->token); //call chargecard function via passing token id
}
/*
* function to create customer
*/
public function createCustomer($data,$token=null)//pass form data and token id
{
$customer=Customer::create(array(
"email"=>$data['email'],
"description" => $data['name'],
"source" => $token // obtained with Stripe.js
));
$customerId=$customer['id'];
$this->retriveCustomer($customerId,$token);
}
/*
* function to retrive current customers for adding multiple cards to same customers*/
public function retriveCustomer($customerid,$token)
{
echo $this->token;
//die('here');
$retriveResult=Customer::retrieve($customerid);
$retriveResult->sources->create(array("source" =>$this->token));
return $retriveResult;
}
First, please note that unless you are PCI certified and allowed to directly manipulate card data, you should never have access to card numbers in your server-side code.
Card tokens should be created client-side, via Checkout or Elements. Your server should only deal with client-side created card tokens and never with PCI-sensitive information (card numbers and CVCs). This will greatly decrease the burden of PCI compliance and make you eligible for PCI SAQ A.
In PHP, this is how you'd add a card to an existing customer object:
$customer = \Stripe\Customer::retrieve("cus_...");
$card = $customer->sources->create(array(
"source" => $token // token created by Checkout or Elements
));
I think you dont need to create a token in case of adding new card. It helps while you update certain card. So the flow of addition will be same as you created for first card.
I dont know which stripe version you are using, I am using bit old:
$card_array = array(
'card' => array(
'number' => $number,
'exp_month' => $exp_month,
'exp_year' => $exp_year,
'cvc' => $cvc,
'name' => $name
)
);
$card_obj = $this->setData("\Stripe\Customer", "retrieve", $customer_id, TRUE);
$card = $card_obj->sources->create($card_array);
Stripe's docs don't explain a lot of the more nuanced procedures so you have to do a lot of testing.
Assuming you have a customer object $cu, with the token you get from checkout or whatever you use:
$card = $cu->sources->create(['source'=>$token]);
will add a card to the customer. It just adds the card to the list; subsequent calls will add cards to the list. Note that it does not check for duplicates, so the same card can be on the list multiple times. It will also not set the new card to the active card. To make a card the default (or active), use
$cu->default_source = $card
$cu->save();
Using the older card interface:
$cu->card = $token;
$cu->save();
The new card will replace the default card. It will NOT make the previously default card inactive; it will delete the current default and make the new card the active default. The card interface is the easiest if you're just allowing 1 card to be attached to a customer at a time.
For some reason, some parameters such as amount, and description are not being passed on from the Form to the Controller.
The token is generated and the email is sent too, but not the other params.
In order for the Payment to work I have to enter manually the amount at the controller.
<form action="checkout" method="POST">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key= "pk_test_zOi8g9ztDo1HNeC6iFFTWqwk"
data-amount="1500"
data-name="Demo Site"
data-description="2 shoes ($20.00)"
data-image="/128x128.png">
</script>
</form>
=====================================
public function PostPaymentData(){
Stripe::setApiKey('sk_test_CvCavCI3G4onNbKxZEaNzkvZ');
// get the data submitted by the CHECK OUT Form
$token = Input::get('stripeToken'); (it gets it)
$amount = Input::get('amount'); (it does not get it)
$description = Input::get('description');(it does not get it)
echo "the amount is . $amount"; //nothing
echo "the description is $description"; // nothing
print_r(input::all()); // it just prints the token and the email
// create the charge on STRIPE servers. This will charge the credit card
try {
$charge = Stripe_Charge::create(array(
"amount" => 1800, // amount in cents, again (I have to enter it manually because $amount = ' ';
"currency" => "usd",
"card" => $token,
"description" => "holycow#gmail.com")
);
}
catch(Stripe_CardError $e) {
// Since it's a decline, Stripe_CardError will be caught
dd($e);
=================================================
Route::get('payments/getpaymentpage', array(
'as'=>'getpaymentpage',
'uses'=>'StripePay#getPaymentPage'
));
Route::post('payments/checkout', array(
'as'=>'checkout',
'uses'=>'StripePay#PostPaymentData'
));
My config for Stripe:
In the providers:
'Abodeo\LaravelStripe\LaravelStripeServiceProvider'
In the composer json
"stripe/stripe-php": "1.*",
"abodeo/laravel-stripe": "dev-master"
Well, it was the support staff from Stripe (very kind people) who has given me the answer:
It's actually expected that the amount doesn't get sent with the token to your server. If it did, the user could easily tamper with it via developer tools or writing javascript snippets, etc. Usually you'll want the price of something to be in your database somewhere (a product or whatever you're selling) and look it up again once you receive the token to get the authoritative price.
But sometimes you've got a situation where the user specifies the price somehow, and that is intentional. In that case I suggest making a hidden form element:
And then populating that with JavaScript using a callback. If you're using Stripe.js you already have a response handler you can use for this, just populate the field before you POST your data. If you're using Stripe Checkout, then you can use the token callback on the handler using the custom integration.