Stripe Cancel Subscription Error - stripe-payments

I am writing the code to cancel subscription so following is the code
var objSubscriptionService = new StripeSubscriptionService(stripekey);
objSubscriptionService.Cancel(ClientID, planId, true);
But I am getting error
Message "Customer does not have a subscription with ID "
But my customer is attached with plan. I can see it on stripe dashboard.
What is wrong with this code?

I think you are using Stripe.NET library based on your code. In that case, to cancel a subscription you need to provide the subscription id sub_XXX not the plan id here as you can see on his documentation
var subscriptionService = new StripeSubscriptionService();
subscriptionService.Cancel(*customerId*, *subscriptionId*); // optional cancelAtPeriodEnd flag
You can retrieve that subscription id on the Customer object or listing all the customer's subscription as explained here:
var subscriptionService = new StripeSubscriptionService();
IEnumerable<StripeSubscription> response = customerService.List(*customerId*); // optional StripeListOptions

Related

Creating Stripe transfers at the same time as creating Payment intent

I'm using Stripe and am trying to implement the scenario described here
The frontend is making a call to the backend that has this code
var service = new PaymentIntentService();
var createOptions = new PaymentIntentCreateOptions
{
PaymentMethodTypes = new List<string>
{
"card",
},
Amount = (long?)(payment.Amount * 100),
Currency = "EUR"
};
var result = await service.CreateAsync(createOptions);
return result.ClientSecret
In the documentation it says that the below code should be run "later" but it doesn't specify when. In my case I would prefer submitting the transfers to Stripe as soon as possible and preferably connecting them to the above payment so the transfers would be automatically handled by Stripe when the payment is done.
As I read the documentation (https://stripe.com/docs/api/transfers/create#create_transfer-source_transaction) SourceTransaction could be used for this.
var transferService = new TransferService();
var transfer1Options = new TransferCreateOptions
{
Amount = 100,
Currency = "eur",
Destination = "{{CONNECTED_STRIPE_ACCOUNT_ID}}",
SourceTransaction = result.Id
};
var transfer1 = transferService.Create(transfer1Options);
The result -variable contains a Charges -list but that is empty and when doing the above, i.e. adding the payment intent's id to SourceTransaction property, I get an error that the charge does not exist.
In the documentation it says that the below code should be run "later" but it doesn't specify when
It's whenever you are ready to make the transfer, after the payment has succeeded, essentially.
As I read the documentation (https://stripe.com/docs/api/transfers/create#create_transfer-source_transaction) SourceTransaction could be used for this.
Yep, you should definitely use source_transaction here! Otherwise the transfers won't succeed since the funds would not be available yet.
The result -variable contains a Charges -list but that is empty and when doing the above, i.e. adding the payment intent's id to SourceTransaction property, I get an error that the charge does not exist.
The value to pass to source_transaction is indeed the intent.charges.data[0].id , of a PaymentIntent that has succeeded and has a Charge.
You don't have a Charge ID because you haven't actually processed a payment yet. Creating a PaymentIntent doesn't process a payment.
You have to do the normal full PaymentIntent integration by building a form that collects payment details and 'confirms' the PaymentIntent, that's the action that processes the payment, and after that succeeds, the charges array will have a Charge in it that can be used for the transfer. For example you might create the transfer as part of handling the payment_intent.payment_succeeded webhook event.
https://stripe.com/docs/payments/accept-a-payment?platform=web&ui=elements

Stripe update subscription and add new payment method with 3d secure

I created a subscription as described on https://stripe.com/docs/billing/subscriptions/elements but now I want to give the user the choice to change the plan on the subscription and use another payment method, ex 3d Secure card. However if I update the subscription to get a client secret for a new payment intent as following:
func (c *Client) UpdateSubscription(s *models.Subscription) (*models.Subscription, error) {
sps := &stripe.SubscriptionParams{
DefaultPaymentMethod: stripe.String(s.PaymentMethodId),
CancelAtPeriodEnd: stripe.Bool(false),
ProrationBehavior: stripe.String(string(stripe.SubscriptionProrationBehaviorAlwaysInvoice)),
}
if s.CreatePaymentIntent {
s.PaymentBehavior = "allow_incomplete"
sps.PaymentBehavior = stripe.String(s.PaymentBehavior)
sps.AddExpand("latest_invoice.payment_intent")
} else if s.ItemID != "" {
sps.Items = []*stripe.SubscriptionItemsParams{
{Price: stripe.String(s.PriceID)},
{ID: stripe.String(s.ItemID), Deleted: stripe.Bool(true)},
}
}
ss, err := sub.Update(s.ID, sps)
if ss.LatestInvoice != nil && ss.LatestInvoice.PaymentIntent != nil {
s.PaymentIntentClientSecret = ss.LatestInvoice.PaymentIntent.ClientSecret
}
return s, err
}
the PaymentIntentClientSecret is the same for the subscription which means it is already processed.
Stripe 'confirm card' API is throwing error payment_intent_unexpected_state https://stripe.com/docs/error-codes/payment-intent-unexpected-state and that's probably because I used that payment intent previously to create the subscription. However I still need a new payment intent to authorise the new card.
What is the status of the PaymentIntent that you are getting these errors on?
It looks like you are properly updating the Subscription’s Price and PaymentMethod as well as creating a new Invoice for this proration. If that is the case, the Invoice may automatically be getting paid on that update. So this error might be happening because you are trying to confirm a PaymentIntent that has already successfully charged your customer.
I think it would be good to check the status of the LatestInvoice’s PaymentIntent when you get the updated Subscription object in your function.
If the status is succeeded you can simply send the customer back that updating their subscription was successful.
If the status is requires_action you should send the PaymentIntent’s client secret back to your client side and call handleCardAction[1] to allow your customer to resolve whatever action may need to be taken (3DS Auth, etc)
If the status is requires_payment_method the new card was declined and you should have your customer input new credit card info to try to update the subscription’s PaymentMethod again.
[1]https://stripe.com/docs/js/payment_intents/handle_card_action

Stripe Promotion Code / Coupon code checking client side checking before subscription

I am using React and Stripe payments for subscriptions. I have the checkout all set using Elements. I want to add the possibility for a user to add a promo code set up in stripe that will be added to the subscription on creation.
What i want to do is check that the promo code is valid (after checking the various subscriptions on the code) and show the affect to the customer before they commit to subscribe. I thought there would have been something built into the API but apparently not. And Stripe support desk (which is generally very good) don't don't seem to know why i want to check a code is valid and show customer it is before they actually click subscribe.
const promotionCodes = await stripe.promotionCodes.list({
active: true,
code: promoCode,
});
if (promotionCodes.data.length > 0) {
const today = Math.floor(Date.now() / 1000);
const expiry =
promotionCodes.data[0].expires_at ||
Math.floor(Date.now() / 1000) + 20;
if (today <= expiry) {
valid = true;
}
}
This is retrieving the code (there can only be 1 active result so it gets it fine). I then check its not expired. All fine, the data I cannot get is if the Coupon the Promotion code is attached to, is restricted to only certain products. For example, if i chose gold plan and try to use a code for silver plan then it would be invalid.

Stripe update customer payment method

I am getting the following error message when I update a Stripe client: Error: Received unknown parameter: payment_method My code:
var customer = await stripe.customers.update(
user.stripe_id,
{payment_method: req.body.paymentMethodId}
);
How do I update a Stripe client's payment method? I tried using source, but source doesn't accept a paymentMethodId.
To update a customer’s payment method you can use invoice_settings.default_payment_method (https://stripe.com/docs/api/customers/update#update_customer-invoice_settings-default_payment_method). This sets the default PaymentMethod for the customer’s future Invoices and Subscriptions only.
If what you are trying to do is attach a new payment method to the customer than you will want to do something like this.
const paymentMethod = await stripe.paymentMethods.attach(
'pm_1IwABt2eZvKYlo2CRqildJzv',
{customer: 'cus_4QEipX9Dj5Om1P'}
);
(https://stripe.com/docs/api/payment_methods/attach)

Azure Topic Subscription Rule created with Service Bus Explorer not triggering

I am using Service Bus Explorer as a quick way of testing a rule that does not work when deployed via ARM.
In JavaScript in the Azure Function I am setting the Topic message to:
context.bindings.outputSbMsg = { Indicator: 'Itinerary'};
In Service Bus Explorer I am setting a Rule on a Subscription with this string:
Indicator = 'Itinerary'
But messages sent to the Topic do not go to this Subscription ( they go to another with the rule 1 = 1)
Question: What am I missing here?
Supplementary info:
I do not seem to have access to the Indicator property. As a test I created an action on the 1=1 rule that appended to the Indicator property and the result was empty.
I am able to access the Indicator property in JavaScript if I have a Function that is triggered by the 1 = 1 rule, so the property is there.
The rule doesn't work because
The rule works against system or user-defined properties rather than message body.
What js function outputs is merely message body, i.e. context.bindings.outputSbMsg = { Indicator: 'Itinerary'}; sends a message { Indicator: 'Itinerary'} and no property is set by us.
And the default rule with 1=1 true filter enables all messages to be selected into the subscription, so you see messages went there all the time. Check doc of topic filters for more details.
For now, it's by design that js function output can't populate message properties. To make the filter work, we have to send messages with property using SDK instead. Install azure-sb package then try sample code below.
const azuresb = require("azure-sb");
const connStr = "ServiceBusConnectionString";
const mytopic = "mytopic";
var serviceBus = azuresb.createServiceBusService(connStr);
const msg =
{
body: "Testing",
customProperties: {
Indicator: 'Itinerary'
}
};
serviceBus.sendTopicMessage(mytopic, msg, function(error) {
if (error) {
context.log(error);
}
else{
context.log("Message Sent");
}
});

Resources