#karls_api
1 messages ยท Page 1 of 1 (latest)
๐ Welcome to your new thread!
โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
๐ This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1332374497742946314
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
Yeah you can't combine them
May I describe what I'm trying to do and perhaps we can come up with a solution?
Yep!
OK
I am selling 5 products along with a subscription. It's a 5 for 1 deal, so the line items show: $24.99 and then $0.00, $0.00, for the next 4 items plus a $4.99 subscription.
So.. I apply an adjusted amount for each line item, basically $24.99 - $24.99 = $0.00 and is added accordingly, I guess as a discount on the line item (I'd have to double check my code)... However, and aside from that, I'd like to offer a PROMO code, to offer 50% off of everything, or 100% off, or whatever.
This is where I am stuck... question: can line items have adjusted discounts, but the complete invoice have a promo code?
How are you adding the line items?
looking..
No. I create the line items before the final invoice. The final invoice picks up the lineitems on checkout. Obviously this all happens in an instant.
But are you using Stripe Checkout for the payment page?
Where is the customer checking out?
foreach(var item in Items)
{
if(item.PriceDiscount != null)
{
var promo = new Service.StripePromotionCode(_key);
var discount = promo.Lookup(item.PriceDiscount);
if (discount != null && discount.DiscountAmount != null)
{
if (item.TotalAmount.HasValue)
{
item.TotalAmount -= discount.DiscountAmount;
}
}
else if (discount != null && discount.DiscountPercent != null)
{
var discountpercent = discount.DiscountPercent / 100.0m;
var discountamt = (long)(item.TotalAmount * discountpercent);
if (item.TotalAmount.HasValue)
{
item.TotalAmount -= discountamt;
}
}
}
}
Basically, I'm setting the item TotalAmount to whatever the calculated amount should be.
And that's for an invoice item?
Is your checkout page elements?
Or is the customer paying on the hosted invoice page?
Not using elements.
Basic webflow is: 1) Create a payment intent 2) post to my backend 3) generate invoice line items 4) create subscription invoice and pay
Right
But my question is how is the customer inputting card details
I'm trying to get a sense for how your integration works
Also why do you need to create a payment intent?
I host a secure order form on my website. I think it is elements that draws the form, I'm using stripe client-side code to draw the form and to handle the initial post to stripe and get back the payment intent.
Ah so the payment intent is the one from the subscription?
Or you need to accept a separate 1-time payment?
Well, sort of. The payment intent doesn't know that I'm trying to create a subscription.
Ok so it's separate. Not the payment from the subscription that has all the line items
Correct. The line items are created, and then the subscriptin invoice is create, with:
PaymentBehavior = "default_incomplete",
I see ok that makes sense
I think what you're doing via just reducing the invoice item amount makes the most sense
That way the customer can still enter a promo code later
Would it help to look at the log item? Maybe it will shed some light on what exactly I sent ..
Let me look for it.
Here: req_jFBSfWuQndIzTQ
My scenario is a little more complicated I am realizing.
So.. Total Amount User should ever pay is $24.99. The susbscription is $4.99 and the 5 for 1 cost $24.99. So the finalize invoice price is: 5 for 1, $24.99 + $4.99 - (1st month subscription fee discount $4.99) = $24.99
I think I see my own solution...
Instead of adding a discount code to the subscription invoice, adjust the total amount. This shouldn't interfere then with the PROMO code.
yeah exactly
Well, thank you for being my sounding board!
Happy to help!
I may need more help. I'm getting the following error now: No such promotion code: 'MSO25FREE'. Please check your card or try another.
Looks like I need to pass the promotion code ID, not the code provided by the user.
Can you share the request id where this happened?
req_jFBSfWuQndIzTQ
Hi ๐
I'm stepping in as m colleague needs to go.
Thx.. I'm struggling with added a promo code, now discount code, to my subscription invoice on checkout..
The error message you are receiving in that request https://dashboard.stripe.com/test/logs/req_jFBSfWuQndIzTQ is pretty explicit. You are passing BOTH a coupo (in the discounts parameter) and a promotion_code. You can't do both
*adding
Yep, we come to this conclussion. I am adding a promo code in place of a discount code when present.
Okay but in that request you shared you included both instead of one or the other. Your code will need to not pass the coupon ID when passing the promo code ID
Dealing with this error now: You must pass one of plan, price, or price_data.. Please check your card or try another.
req_SltPVQqsA8bUpS
For what it's worth, you can use the discounts parameter to pass either the Coupon ID or Promo Code ID
https://docs.stripe.com/api/subscriptions/create#create_subscription-discounts
Again, the error message says what is wrong
You didn't provide a Price the Subscription is for
OK.. let me pass a promo code, instead of coupon id (i like that) and figure out what happened to my subscription price! I must have just broke that.
I recommend slowing down and reviewing what you code is doing to esnure you provide all the required and optional parameters to get the behavior you expect
back to the discounts, I still have to provide the ID in each case, which means I have to look it up myself to determine the ID on the fly.. no biggy, just confirming that there is no way to pass "SOMEFREECODE" to stripe.
Correct. we require the ID, not the code
Yes, slowing down.. everything has been working.. my rewrite for PROMO code has tripped me up a bit.
That's understandable.
ok, dumb UI woopsy fixed! testing again..
Stuck. Have a look at this screeshot please.
This is throwing an exception. I have a promo code: promo_1QkofUDOnh5qjbu1WxpAM3jn
Not sure how to attach it.
I take that back..
To be fair, I think the .NET framework was designed to make developers sad so I might be a bit biased ๐
oh! jab
But I'm starting to get into static typed languages so maybe I'll change my tune
your language of choice?
Python is my general purpose solution language, it's how I got started. Lately I've been doing some Android development so I've gotten into Kotlin.
For supporting Stripe devs, we have to be basically familiar with .NET, Java, Go, Node, PHP, Python, & Ruby but this just means having a basic setup where we can drop code snippets and run them.
OK, I have a new issue. Can you help?
That depends on what the issue is ๐
Grabbing the IdempotencyKey after invoice paid.
I call invoice service Pay method, which I than grab the key. However in this case, my invoice item status is already paid, but I don't have, or I should say, the key is Null
quite honestly, this is new behaviour.
Sorry but I'm kind of confused about what objects you are referring to. The service.Pay method should return the full Invoice object: https://docs.stripe.com/api/invoices/pay?lang=dotnet
Yes, in this case it was alreay paid. I'm still digging.
Can you share an Invoice ID so I can review what you are referring to?
yes, 1 sec.
in_1Qkqg4DOnh5qjbu1OagInSXT
OK, it is a zero total invoice. that changes things
Okay yeah we mark those as paid immediately
hmmm. ok... now I'm in my webhook handler
Okay ....
by the way, Stripe API and Dev tools, are #1
๐ ๐
100 years newer than PayPal!
So.. back to the zero invoice.
Okay,
So that Invoice was created as part of this request; https://dashboard.stripe.com/test/logs/req_0jC6sFa77TwGBR to create a Subscription
I use the ImpodetencyKey (worse name ever, can never remember it) to look up in my log the webhook event.
Let me give you the latest test...
req_YVd8SlnzIanogQ
The zero pay scenario, where/when do I get the key?
I think you are misunderstanding what the idempotency key does
It exists, just not part of my current flow. 94baed9a-0079-4981-a14a-2f7d10849846
I only rely on it for this one specific scenario.
Okay gonna ignore this for a sec while I explain what these keys are doing.
The idempotency key is designed for a situation where you send an API request but, due to whatever reason, you fail to get a response.
k
You can then make a second request to the same API with that request ID to get the saved response
k
Even if the response is an error and your second request would be successful, if you pass the key we will return the error
k
So, your system is attempting to pay and invoice that is already paid, and you want to collect the key for that API request?
yes, but for this reason. The invoice.paid webhook includes the key.
It includes the idempotency key for the /v1/subscriptions request
hold on..
because that is the API request that triggered this event
This key (typically) is available when you call Pay on the invoice. At this moment, I grab the key, and then in my UI, I wait for this key to appear in my logs... then user flow continues.
This key (typically) is available when you call Pay on the invoice
Available how? From where?
So the key is still created, I just don't know how to grab it without calling Pay on the invoice.
Let me show you my code... 1 sec.
Calling the /v1/invoice/*/pay endpoint will generate a new idempotency key that corresponds to the failing request
Correct.. however when automatically paid due to zero total amount invoice, it is unvailable, or at least it is based on my implmentation. There must be a lookup... here's my code.
switch (subinvoice.Status)
{
case "draft":
fininvoice = invservice.FinalizeInvoice(invoice.Id, finalizeOptions);
invpaid = invservice.Pay(invoice.Id, payoptions);
break;
case "open":
invpaid = invservice.Pay(invoice.Id, payoptions);
break;
case "paid":
invpaid = subinvoice;
break;
case "finalized":
break;
}
return new Model.StripeAddSubscriptionResponse()
{
IdempotencyKey = invpaid.StripeResponse.IdempotencyKey,
ID = newsub.Id
};
So, invpaid is the local variable that is the result of calling the Pay method which contains the key value which I pass back to UI.
This is the API request that triggered the Invoice to be paid: https://dashboard.stripe.com/test/logs/req_YVd8SlnzIanogQ
When I look at the Response headers I can see the idempotency key is 76e5ecae-70ef-4a6a-bafc-faa31b22ce11
If you want to have it for whatever reason, you would need to collect it in the response to the above request. In that case the object being returned is the Subscription.
It's really unclear to me what the code above is handling. When does execution reach this code?
Pseudo:
Pay Invoice
Deliver Key to UI
Webhook Event is Logged (my system)
UI looks for Paid.Invoice with this Key
Loops several times
When found, UI flow continues.
Not found, Warning message delivered to customer.
Looking for key now in subscription request.
testing...
LatestInvoice is not set on the subscription response
Can you share the request ID?
I'm looking at the latest invoice in the response here: https://dashboard.stripe.com/test/logs/req_AimNBPR3b85fbN
in_1Qkrb1DOnh5qjbu1Nl1C9HIg
yes
status: "paid",
Yes, exactly.
Here's some code:
invpaid = newsub.LatestInvoice;
invpaid.StripeResponse IS NULL
So this:
IdempotencyKey = invpaid.StripeResponse.IdempotencyKey
fails
The Response is not on the Invoice
It should be on the newsub because that is the object created by the API call
checking
The creation of the Invoice is a side effect of the creation of the Subscription
newsub.LatestInvoice.StripeResponse.IdempotencyKey
'newsub.LatestInvoice.StripeResponse.IdempotencyKey' threw an exception of type 'System.NullReferenceException'
Data: {System.Collections.ListDictionaryInternal}
HResult: -2147467261
HelpLink: null
InnerException: null
Message: "Object reference not set to an instance of an object."
Source: "bb586fa3c3ac491399c8f3fb435bf700"
StackTrace: " at <>x.<>m0(StripeSubscription <>4__this, StripeAddSubscriptionRequest Request)"
TargetSite: {System.String <>m0(msoStripe.Service.StripeSubscription, msoStripe.Model.StripeAddSubscriptionRequest)}
LatestInvoice?
ha! Found it!
newsub.StripeResponse.IdempotencyKey
That is what I have been saying all along
๐ค
Bingo! All set.
Woo hoo ๐ I'm glad we got there! ๐
Much grasias
Happy to help, it's why we're here.