How to extend a subscription after a customer submits payment - stripe-payments

When I direct a user with an existing subscription to the Stripe payment page, Stripe automatically creates a new subscription at the time the customer submits payment.
What is the workflow that will allow me to tell Stripe that I want to extend the existing subscription and not create a new one?
I asked this question to Stripe support and this is the answer I got:
To answer your question, this will depend on your integration if you are using a third party platform to create this option, but with Stripe, this can only be done manually using the reference that we provided, this means that you have to extend the subscription without requiring a customer to make a payment first.
With regard to the third party platform, I don't understand why the API works differently for them and for me. Does this mean Stripe has a secret API and I MUST purchase a third party product to use the service effectively?
this means that you have to extend the subscription without requiring a customer to make a payment first.
This is the part that is giving me grief. This seems like an extraordinarily difficult workflow. At what point do I extend the subscription? What if the customer never pays? What triggers me to un-extend it? How can I reliably report to the customer the date their subscription ends? Extending a subscription seems like a fundamental, mundane task. Can it really be this difficult?
Edit code posted per requests:
SessionCreateOptions options = new SessionCreateOptions
{
PaymentMethodTypes = new List<string> { "card" },
LineItems = new List<SessionLineItemOptions>
{
new SessionLineItemOptions { Price = order.PaymentProviderPlanID, Quantity = 1 }
},
Customer = order.CustomerID,
CustomerEmail = string.IsNullOrEmpty(order.CustomerID)? order.UserEmail : null,
Mode = "subscription",
SuccessUrl = hostURL + "/Subscription/CreateSubscription?session_id={CHECKOUT_SESSION_ID}",
CancelUrl = hostURL + "/SubActivationFailure",
};

Per clarifications to the question in the comments, do nothing and this will happen automatically. This is the default unless you explicitly set a subscription to cancel or for invoice to not be paid automatically.

Related

Stripe update payment on subscription to make it use the default on the customer

So we have some Stripe customers with subscriptions that are setup with payment methods and they work just fine.
The issue is, when the subscription were setup, They were explicitly given the payment method id, instead of letting it default to the one on the customer ( dun... dun.. the same payment method. ).
So what this means is, if a customer updates their payment method, we have to explicitly update each subscription to use it, since the subscription has its own payment method ( the old default ).
The question is, without rebuilding the subscription, how do we tell the subscription to forget about the payment method it has, and start using the default source on the Customer?
The docs on the Subscription talk here about setting the default value, but not how do you clear it?
I attempted to null it out by running this node.js snippet:
const subscription = await stripe.subscriptions.update(
subscriptionId,
{
default_payment_method: undefined
}
);
and it succeeded, but did nothing.
Thanks in advance.
You should be able to send an empty string to clear the value of default_payment_method:
const subscription = await stripe.subscriptions.update(
subscriptionId,
{
default_payment_method: "",
}
);
Then, if default_source isn't set on the subscription, the customer's invoice_settings.default_payment_method or default_source will be used.

How to prevent creating duplicate subscription in stripe when trial period is set on subscription

I am encoutering a problem with stripe. let me explain my working
scenario.my requirement is do not charge user for 14 days with card up front
1)user enter card details
2)sca popup appear
3)regardless of user complete the authentication or not a subscription is created in stripe because i set trial_end_date=>now()+14 days
4)user payment fails in some reason and attempt again, another subscription created
i am worried about the duplicate subscription as the stripe will attempt to pay after the 14 days for both of these subscription as it send a Stripe-hosted link for cardholders for both of these subscription
let me give a snapshot of what i have so far
$data['customer']='customerId';
$data['items']=[];
$data['items'][0]['plan']='stripe_plan_id'
$data['default_payment_method']='pm_xxxx'
$data['trial_end']= strtotime('+14 days');
$data['prorate']=true;
$data['tax_percent']=env('VAT_PERCENTAGE');
$data['expand']= ['latest_invoice.payment_intent', 'pending_setup_intent'];
try {
$subscription=\Stripe\Subscription::create($data);
}
catch(Exception $e) {
return response()->json(['success' => false,'message'=>$e->getMessage()]);
}
what i am missing? how to prevent the duplicate subscription scenario.please expain with the correct example which is i am missing.thanks in advance
I think the problem is in your payment flow, there is not a stripe api that explicitly detects duplicate subscription. You are after all allowed to assign more then 1 subscription per customer id. You can create idempotent keys, but that isn't for the same thing you're talking about, idempotent keys are for accidently hitting the submit button twice within the same timeframe.
The solution would be to attach a payment method to your stripe customer id before your subscription trial is over. For example if you are using stripe elements you would call
Node/JS Example below :
const result = await stripe.createPaymentMethod({
type: 'card',
card: card
})
then pass that result to your backend
const result = await stripe.paymentMethods.attach(paymentMethodId, {customerId})
You do not need to create a new subscription, as one has already been created for that user. Credit cards are assigned to customer Ids, and not to subscriptions. Stripe will do the rest.
You do also need to update the customer with the default payment method as follows :
const customer_update = await stripe.customers.update(stripeCustomerId,{invoice_settings: {default_payment_method:paymentMethodId}});
Now when you visit your dashboard you will see a default card assigned to your customer. Once the subscriptions falls out of the trail period, the default card will be charged.
So in this case there wont be a duplicate subscription created, as you are not calling stripe.subscriptions.create again.

How to implement Paypal subscription in a vue application?

I am working on a project which needs to deducts a fixed amount from a user's account to a business account on monthly basis. I am trying to create a Paypal button client side (vue) for accepting subscriptions on monthly basis. The users deduction information on monthly basis shall be stored in a database. The user shall also provided an option to cancel the subscription. Any help would be greatly appreciated.
Well i found out an answer after a little digging in the documentation provided at https://developer.paypal.com/docs/subscriptions/integrate and went through the steps they provided.
Steps
Create a product through their API by providing access_token in the headers.
After the product has been created, get product-Id from response and then create plan using the product_id in request body.
After the plan has been successfully created copy Plan_id and replace the id in smart subscription button.
paypal.Buttons({
createSubscription: function(data, actions) {
return actions.subscription.create({
'plan_id': 'P-your_plan_id'
});
onApprove: function(data, actions) {
alert('You have successfully created subscription ' + data.subscriptionID);
}
}

New Customer created by Checkout, then create Subscription on Customer results in Error: This customer has no attached payment source

New Customer created by Checkout, then create a new Subscription on the same Customer by Node SDK results in Error: This customer has no attached payment source.
However if I look at the Customer at the dashboard, there is a Card, but not set as Default. Once it is "Set as Default" by clicking the ... it works.
Here is the code I used to create a new Subscription on a Customer:
const customer = 'cus_xxxxxx'
const plan = 'plan_xxxxxx'
stripe.subscriptions.create({
customer,
items: [
{
plan
}
]
})
I'm not sure if this is a limitation of Checkout since https://stripe.com/docs/payments/checkout says
Better support for saving customer details and reusing saved payment methods
Right now my workaround is to use webhook to update Customer's invoice_settings.default_payment_method on payment_method.attached.
This works but it feels strange. Did I miss something? Why does Checkout not set the only Card as invoice_settings.default_payment_method?
This behavior seems intentional on Stripe's part, the card from Checkout is attached to the Customer as a Payment Method, and is not set as default.
The same thing happens if you create a Customer directly with a PM,
let cust = await stripe.customers.create({ payment_method: "pm_card_visa" });
Also, fwiw, one can create their subscription directly from Checkout, passing a plan instead of sku https://stripe.com/docs/stripe-js/reference#stripe-redirect-to-checkout
From Stripe support:
Checkout does not currently support the ability to reuse saved payment
methods. We are aware that this is a feature request for a lot of our
users, and we are working on implementing this in the future.
If you'd like, you can see a roadmap of the updates we'll be making to
Checkout in the document below.
https://stripe.com/docs/payments/checkout#checkout-roadmap
That said, the work around you're doing for the moment is the same
work around that we're suggesting to users for the time being.
After a lot of digging I realized there is one step that is easy to miss in the docs: take the attached payment method and set it up as a default.
Here is my full server node.js code for creating a subscription:
const customerResponse = await stripe.customers.create({ email, name })
const customer = customerResponse.id
await stripe.paymentMethods.attach(paymentMethodId, { customer })
await stripe.customers.update(customer, {
invoice_settings: { default_payment_method: paymentMethodId }
})
await stripe.subscriptions.create({
customer,
items: [{ price: 'price_XXXXXX' }]
})
paymentMethodId name and email come from the client.

In the Authorizenet SDK version 1.1.8 for PHP Is there a way to charge a card using a customer payment profile?

I have been up and down through the SDK code and have the ability to add customer profiles and payment profiles for them but I can't see anywhere, where I can charge a card or create a subscription from a customer profile and customer payment profile. Does anyone have an answer for this for either the create subscription, or charge a card, using the PHP SDK. Please understand, giving me an interactive web example using AuthorizeNet's web API is not helpful here. The requirements are that it has to be done through the PHP SDK as we cannot have card user interaction past the point of the customer profile and customer payment profile creation.
First off need to define the normal credentials used for SDK requests
if (!defined("AUTHORIZENET_API_LOGIN_ID")) define("AUTHORIZENET_API_LOGIN_ID", {authorizenet_api_login_id};
if (!defined("AUTHORIZENET_TRANSACTION_KEY")) define("AUTHORIZENET_TRANSACTION_KEY", {authorizenet_transaction_key};
Then create the transaction and set the fields.
$transaction = new AuthorizeNetTransaction;
$transaction->amount = $amount;
$transaction->customerProfileId = $customerProfileId;
$transaction->customerPaymentProfileId = $customerPaymentProfileId;
// next line may be optional depending on your situation
$transaction->customerShippingAddressId = $customerShippingAddressId;
Then process the transaction
$request = new AuthorizeNetCIM;
$response = $request->createCustomerProfileTransaction("AuthCapture", $transaction);
if ($response->xml->messages->resultCode=="Ok") echo "It Was Approved"
;

Resources