#karls_api

1 messages ยท Page 1 of 1 (latest)

compact dirgeBOT
#

๐Ÿ‘‹ 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.

brittle plover
#

Yeah you can't combine them

gloomy dagger
#

May I describe what I'm trying to do and perhaps we can come up with a solution?

brittle plover
#

Yep!

gloomy dagger
#

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?

brittle plover
#

How are you adding the line items?

gloomy dagger
#

looking..

brittle plover
#

The one-time line items

#

And is this a checkout session?

gloomy dagger
#

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.

brittle plover
#

But are you using Stripe Checkout for the payment page?

#

Where is the customer checking out?

gloomy dagger
#

All custom code, custom for etc. Code incoming.

#

What is the syntax for code?

brittle plover
#

Triple back ticks

#

`

gloomy dagger
#
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.

brittle plover
#

And that's for an invoice item?

#

Is your checkout page elements?

#

Or is the customer paying on the hosted invoice page?

gloomy dagger
#

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

brittle plover
#

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?

gloomy dagger
#

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.

brittle plover
#

Ah so the payment intent is the one from the subscription?

#

Or you need to accept a separate 1-time payment?

gloomy dagger
#

Well, sort of. The payment intent doesn't know that I'm trying to create a subscription.

brittle plover
#

Ok so it's separate. Not the payment from the subscription that has all the line items

gloomy dagger
#

Correct. The line items are created, and then the subscriptin invoice is create, with:

PaymentBehavior = "default_incomplete",

brittle plover
#

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

gloomy dagger
#

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.

gloomy dagger
#

Well, thank you for being my sounding board!

brittle plover
#

Happy to help!

gloomy dagger
#

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.

compact dirgeBOT
brittle plover
#

Can you share the request id where this happened?

gloomy dagger
#

req_jFBSfWuQndIzTQ

deft stump
#

Hi ๐Ÿ‘‹

I'm stepping in as m colleague needs to go.

gloomy dagger
#

Thx.. I'm struggling with added a promo code, now discount code, to my subscription invoice on checkout..

deft stump
gloomy dagger
#

*adding

#

Yep, we come to this conclussion. I am adding a promo code in place of a discount code when present.

deft stump
#

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

gloomy dagger
#

Dealing with this error now: You must pass one of plan, price, or price_data.. Please check your card or try another.

req_SltPVQqsA8bUpS

deft stump
#

Again, the error message says what is wrong

#

You didn't provide a Price the Subscription is for

gloomy dagger
#

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.

deft stump
#

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

gloomy dagger
#

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.

deft stump
#

Correct. we require the ID, not the code

gloomy dagger
#

Yes, slowing down.. everything has been working.. my rewrite for PROMO code has tripped me up a bit.

deft stump
#

That's understandable.

gloomy dagger
#

ok, dumb UI woopsy fixed! testing again..

gloomy dagger
#

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..

deft stump
#

To be fair, I think the .NET framework was designed to make developers sad so I might be a bit biased ๐Ÿ˜…

gloomy dagger
#

oh! jab

deft stump
#

But I'm starting to get into static typed languages so maybe I'll change my tune

gloomy dagger
#

your language of choice?

deft stump
#

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.

gloomy dagger
#

OK, I have a new issue. Can you help?

deft stump
#

That depends on what the issue is ๐Ÿ˜…

gloomy dagger
#

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.

deft stump
gloomy dagger
#

Yes, in this case it was alreay paid. I'm still digging.

deft stump
#

Can you share an Invoice ID so I can review what you are referring to?

gloomy dagger
#

yes, 1 sec.

#

in_1Qkqg4DOnh5qjbu1OagInSXT

#

OK, it is a zero total invoice. that changes things

deft stump
#

Okay yeah we mark those as paid immediately

gloomy dagger
#

hmmm. ok... now I'm in my webhook handler

deft stump
#

Okay ....

gloomy dagger
#

by the way, Stripe API and Dev tools, are #1

deft stump
#

๐Ÿ™Œ ๐ŸŽ‰

gloomy dagger
#

100 years newer than PayPal!

gloomy dagger
#

So.. back to the zero invoice.

deft stump
#

Okay,

gloomy dagger
#

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?

deft stump
#

I think you are misunderstanding what the idempotency key does

gloomy dagger
#

It exists, just not part of my current flow. 94baed9a-0079-4981-a14a-2f7d10849846

#

I only rely on it for this one specific scenario.

deft stump
#

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.

gloomy dagger
#

k

deft stump
#

You can then make a second request to the same API with that request ID to get the saved response

gloomy dagger
#

k

deft stump
#

Even if the response is an error and your second request would be successful, if you pass the key we will return the error

gloomy dagger
#

k

deft stump
#

So, your system is attempting to pay and invoice that is already paid, and you want to collect the key for that API request?

gloomy dagger
#

yes, but for this reason. The invoice.paid webhook includes the key.

deft stump
#

It includes the idempotency key for the /v1/subscriptions request

gloomy dagger
#

hold on..

deft stump
#

because that is the API request that triggered this event

gloomy dagger
#

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.

deft stump
#

This key (typically) is available when you call Pay on the invoice

Available how? From where?

gloomy dagger
#

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.

deft stump
#

Calling the /v1/invoice/*/pay endpoint will generate a new idempotency key that corresponds to the failing request

gloomy dagger
#

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.

deft stump
#

When I look at the Response headers I can see the idempotency key is 76e5ecae-70ef-4a6a-bafc-faa31b22ce11

gloomy dagger
#

ok, so can I grab this request in code to then grab the Iempotency key?

#

*lookup

deft stump
#

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?

gloomy dagger
#

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

deft stump
#

Can you share the request ID?

gloomy dagger
#

1 sec, yes.

#

req_AimNBPR3b85fbN

deft stump
#

in_1Qkrb1DOnh5qjbu1Nl1C9HIg

gloomy dagger
#

yes

deft stump
#

status: "paid",

gloomy dagger
#

Yes, exactly.

#

Here's some code:

#
invpaid = newsub.LatestInvoice;
invpaid.StripeResponse IS NULL
#

So this:
IdempotencyKey = invpaid.StripeResponse.IdempotencyKey
fails

deft stump
#

The Response is not on the Invoice

#

It should be on the newsub because that is the object created by the API call

gloomy dagger
#

checking

deft stump
#

The creation of the Invoice is a side effect of the creation of the Subscription

gloomy dagger
#

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

deft stump
#

That is what I have been saying all along

gloomy dagger
#

my bad..

#

final test and then moving to production! here we go..

deft stump
#

๐Ÿคž

compact dirgeBOT
gloomy dagger
#

Bingo! All set.

deft stump
#

Woo hoo ๐ŸŽ‰ I'm glad we got there! ๐Ÿ™‚

gloomy dagger
#

Much grasias

deft stump
#

Happy to help, it's why we're here.