Get last 4 digits of credit card after successful Stripe subscription - php

For compliance reasons I am generating tokens on the client side and sending those details to stripe. I want to display the last four digits and the type of card on my confirmation page
I am creating a customer
// Create a Customer:
$customer = \Stripe\Customer::create([
'source' => $token,
'email' => $current_user->user_email,
]);
than adding them to a subscription
//create the subscription for the customer
$subscription = \Stripe\Subscription::create(array(
'customer' => $customer->id,
"items" => array(
array(
"plan" => "dpc-standard",
),
)
));
The subscription returns https://stripe.com/docs/api#subscription_object
a ton of data including the invoice_id that is generated for the subscription but doesn't return any CC details

When you create a Customer and pass the source parameter set to a token id, it will save that card on the new customer. The value returned by this call is a Customer object with the sources property which will contain the new card you just saved.
You can access the last 4 digits easily using:
$last4 = $customer->sources->data[0]->last4;

Related

Laravel Stripe MultiPlan Subscription

I want to add Add On to my subscription. Thus i follow this MultiPlan in Laravel doc. For every new subscription, new stripe product are create (means every plan have different product. including the addon). User need to subscribe to any subscription before subscript to the addon. There are no error, but the Subscription DB from stripe for the current subscription will return null quantity and null stripe_plan. Then create error from that database as i cant call the current subscription. Why does the stripe does that? or am I surpose to create new plans under the same product id in Stripe?
My code to create stripe product and plan
$stripe = new StripeClient(env('STRIPE_SECRET'));
$product_stripe = $stripe->products->create([
'name' => $request->service_name,
]);
$plan_stripe = $stripe->plans->create([
// 'id' => $stripe_plan,
'nickname' => $request->service_name,
'product' => $product_stripe['id'],
'amount' => $request->price*100,
'currency' => 'usd',
'interval' => $request->period,
'interval_count' => $request->period_num,
]);
This is my code to subscribe to addon
$user = auth()->user();
$user->subscription('default')->addPlanAndInvoice('plan_stripe_id', 'quantity');
Note that default is the user current subscription.

Stripe - Charge user and send invoice via e-mail

I have a mobile app (Flutter) which uses Lumen as backend. For payments I use Stripe SDK for PHP.
I need to send an invoice to user after successful charge. I understood it works this way:
Create customer in Stripe
Charge customer using customer_id
Create invoice item using customer_id
Stripe will automatically send an invoice via email using customer's email
I have two functions:
public function addCard(Request $request) {
$user = User::find($user->id);
if (is_null($user->stripe_id) || empty($user->stripe_id)) {
$customer = \Stripe\Customer::create([
"name" => $user->name,
"email" => $user->email,
"description" => "Test",
]);
$user->stripe_id = $customer->id;
$user->save();
}
}
public function charge(Request $request) {
$charge = \Stripe\Charge::create([
'amount' => 2000,
'currency' => 'eur',
'customer' => $user->stripe_id,
'description' => 'Some description',
]);
\Stripe\InvoiceItem::create([
'customer' => $user->stripe_id,
'amount' => 2500,
'currency' => 'usd',
'description' => 'One-time setup fee',
'auto_advance' => true,
]);
}
It adds user but without credit card details. Which arguments should I pass so that Stripe can create card token for specified user? Since it's a mobile app I cannot use Stripe.js for this purpose.
At the moment when the charge function is called I get the error message:
Cannot charge a customer that has no active card
This is my first project with payment gateway... So any help is really appreciated.
Just to clarify, an Invoice is something you would send to your customer and ask your customer to pay for the invoice 0 .
If you've already charged your customer, you will NOT send invoice to your customer because this will end up double charging your customer. Instead, you should send a receipt 1 to your customer on the charge you've created.
Saying all that,
To accept a payment from a customer, through Stripe, you could do the following
1. Create one-time charge
Step 1: create a token representing the credit card information. This normally involves your customer goes to your app/website and see a credit card form
You could use Stripe Element which is a preBuild secure UI showing a credit card form
...
...
var token = stripe.createToken(cardElement);
...
Step 2: After you get the token, pass it your PHP server side and call Stripe Charge API
// see https://stripe.com/docs/api/charges/create?lang=php#create_charge-source
$charge = \Stripe\Charge::create([
'amount' => 2000,
'currency' => 'eur',
'source' => $token->id,
'description' => 'Some description',
]);
Follow step by step guide to try the above
2. Save a credit card to a customer and charge the customer later
This is very similar to case 1, except now you are saving a card to the customer and charge the customer. token by default is single use only, if you want to reuse the card e.g. you are charging the customer later for some subscriptions, you will need to save the card to the customer aka Attach Card to customer before you can re-use the token/card.
Step 1: create a token same as above
...
var token = stripe.createToken(cardElement);
...
Step 2: Pass the token your PHP server side and save the card to the customer
// Create a new customer with the token
// https://stripe.com/docs/api/customers/create#create_customer-source
$customer = \Stripe\Customer::create([
"name" => $user->name,
"email" => $user->email,
"description" => "Test",
"source" => $token->id,
]);
// Or you could attach it to an existing customer
\Stripe\Customer::createSource(
'cus_xxxx',
[
'source' => $token->id,
]
);
Step 3: Charge the customer with the saved card.
// When charging this customer, it will use the default card saved at step 2
$charge = \Stripe\Charge::create([
'amount' => 2000,
'currency' => 'eur',
'customer' => $customer->id,
'description' => 'Some description',
]);
Follow step by step guide to try the above
The above shows the simplest way to charge to a customer credit card using Stripe API + Stripe Element
This is just the starting point. After you are familiar with the above concept, you could explore more on
1. PaymentMethod and PaymentIntent
These are the new APIs Stripe recommend but built on top of charges API
https://stripe.com/docs/payments/accept-a-payment
https://stripe.com/docs/payments/save-and-reuse
Invoicing
https://stripe.com/docs/billing/invoices/workflow
https://stripe.com/docs/billing/invoices/create-invoice
This is powerful billing tool which allows you to bill your customer either on their saved card or sending an invoice to your customer to pay.
Check this article (link). You can send the receipt of the transaction (not the invoice)
In your case I think you need pass the email from the server with the following
stripe.paymentIntents.create(
{
amount: 1000,
currency: USD,
payment_method: clonedPaymentMethod.id,
confirmation_method: 'automatic',
confirm: true,
receipt_email: 'abc#cde.com',
}, {
stripeAccount: stripeVendorAccount
},
function(err, paymentIntent) {
// asynchronously called
const paymentIntentReference = paymentIntent;

Stripe - Upgrade/downgrade plan response in webhook

Following code I'm using to upgrade a user's plan:
$subscription = \Stripe\Subscription::all(array('customer'=>$customerId,'limit'=>10));
$subscription_id = $subscription->data[0]->id;
$subscription = \Stripe\Subscription::retrieve($subscription_id);
$updatePlan = [
'cancel_at_period_end' => false,
'items' => [
[
'id' => $subscription->items->data[0]->id,
'plan' => planPrefix.$packageId,
],
],
'tax_percent' => $package_tax,
];
\Stripe\Subscription::update($subscription_id, $updatePlan);
//Create invoice now
$invoice = \Stripe\Invoice::create([
'customer' => $customerId,
]);
$invoiceId = $invoice->id;
//Pay invoice now
$invoice = \Stripe\Invoice::retrieve($invoiceId);
$invoice->pay();
And when stripe get paid to that newly created invoice, The event "invoice.payment_succeeded" is triggered to my webhook where I update my database accordingly.
The problem is that stripe sends me previous plan id with the accurate invoice.
E.g., If User A subscribes to plan id 1 then stripe sends me object for the newly subscribed plan details to my webhook with accurate data, but when User A
upgrades to plan whose id is 2, stripe sends me data with the event of "invoice.payment_succeeded" where I can find all the data related to subscription update but the issue is with the plan id. The plan id stripe sends me is old one i.e., 1 instead of 2, and when User A upgrade to plan id 3 then it sends me plan id 2 in the webhook notification.
Any help in this matter would be much appreciated.

Stripe Subscription with Initial setup fee

I'm building a relatively simple subscription based app using Stripe.
My only real hangup at the moment is that the subscription requires an initial setup fee, and I'm really having a hard time with it.
Example:
A new user signs-up for Subscription-A; Subscription-A has a monthly interval price of $10. Upon signing up the new user gets charged a one-time fee of $1 and $10 for subscription, then the following months gets charged only $10.
Currently my code is:
// Stripe New customer
$customer = \Stripe\Customer::create(array(
"email" => $customer_email,
"source" => $token,
),
array("stripe_account" => $connected_account)
);
// Stripe Subscription
$sub = \Stripe\Subscription::create(array(
"customer" => $customer['id'],
"items" => array(
array(
"plan" => $plan_id,
),
),
),
array("stripe_account" => $connected_account)
);
Any idea? thx
After creating the customer, but before creating the subscription, create an invoice item for the setup fee.
When you create the subscription, a first invoice will be immediately created, and this invoice will include all pending invoice items for the customer.
For more information about invoice items, see https://stripe.com/docs/subscriptions/invoices#adding-invoice-items.

Stripe, verify card and only charge it after an action

I'm working on enabling payments for a website. I'm using Stripe as the provider. I wanted to know how I could charge the card if 2 conditions are true. When the user pays, I want to change a value in the database, and charge the card. But I don't want to charge the card if the database query fails. Similarly, I don't want to query if the card is invalid. I need both, the card to be valid and for the query to be successful. How do I do that?
Here's the code for charging the card
try {
$charge = \Stripe\Charge::create(array(
"amount" => $amount, // amount in cents, again
"currency" => "cad",
"source" => $token,
"description" => $description)
);
} catch(\Stripe\Error\Card $e) {
// The card has been declined
}
Instead of charging the card, you should think about charging a customer.
By this I mean:
1. Create a customer
$customer = \Stripe\Customer::create(array(
"description" => "Customer for test#example.com",
"source" => "tok_15gDQhLIVeeEqCzasrmEKuv8" // obtained with Stripe.js
));
2. Create a card
$card = $customer->sources->create(array("source" => "tok_15gDQhLIVeeEqCzasrmEKuv8"));
From Stripe API Reference:
source | external_account
REQUIRED
When adding a card to a customer, the parameter name is source. The value can either be a token, like the ones returned by our Stripe.js, or a dictionary containing a user’s credit card details. Stripe will automatically validate the card.
By creating a card, Stripe will automatically validate it. So having a valid credit card object you can then perform whatever query you want on your db and if success, charge the customer.
3. Charge
\Stripe\Charge::create(array(
"amount" => 400,
"currency" => "usd",
"source" => "tok_15gDQhLIVeeEqCzasrmEKuv8", // obtained with Stripe.js,
// "customer" => $cusomer->id // the customer created above
"metadata" => array("order_id" => "6735")
));
When charging, you can either pass the source (the token obtained with Stripe.js) or the customer id we just created.
Also don't forget to try...catch everything.
Ok, so after reading through the API, I found that this is acheivable by setting the capture parameter to false
Like this:
$charge = \Stripe\Charge::create(array(
"amount" => $amount, // amount in cents, again
"currency" => "cad",
"source" => $token,
"description" => $description,
"capture" => false)
);
And this will authorize the payment and the card but not create a charge. After you do the querying and make sure it's successful, you can charge the customer (capture the charge) using this
$ch = \Stripe\Charge::retrieve({$charge->id});
$ch->capture();

Categories