#charaktarrr_error

1 messages · Page 1 of 1 (latest)

digital plinthBOT
#

👋 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/1449071730617352343

📝 Have more to share? Add more details, code, screenshots, videos, etc. below.

gleaming silo
#

We use the dotnet SDK 48.5 for Basil API

#

setup intent eventid: evt_1Sc6GDLqit5oPG41QhtFy5r6
invoiceID: in_1ScwN0Lqit5oPG41Mh6E3qY6

potent mango
#

Thanks for the info and object IDs, looking in to this

fallen hearth
#

Hello
Jumping into to help out here..
Can you clarify what surface you're working with here? Like are you using Checkout Sessions or Payment Element or something else?

The exact step by step instructions would help too in order to reproduce this behavior myself

gleaming silo
#

we use checkout sessions here in this case. This is the code for generating the checkoutsecret:

Product product = null;
if (singleItemPriceAmount.HasValue) {
product = _dbContext.Products
.FirstOrDefault(p => p.ProductId == productId);
}

var options = new Stripe.Checkout.SessionCreateOptions {
PaymentMethodTypes = paymentMethods,
Metadata = metaData,
UiMode = "embedded",
Mode = mode.ToString(),
Customer = stripeCustomerId,
ReturnUrl = $"{globalCleverlySettings.ApplicationBaseUrl}/checkout/success" + (productId != null ? "/"+productId.ToString() : ""),
BillingAddressCollection = "required",
};

#

if (mode == SessionCreateMode_Enum.setup) {
options.CustomText = new SessionCustomTextOptions() {
Submit = new SessionCustomTextSubmitOptions() { Message = "Bitte hinterlege dein Zahlungsmittel, damit wir die Buchung deines Abopakets abschließen können. Wenn du einen späteren Abostart vereinbart hast, wird dein Zahlungsmittel erst zum Start deines Abos belastet, andernfalls startet dein Abo sofort und wir belasten anschließend dein Zahlungsmittel." },
};

} else {
// Use lineItems if provided, otherwise fall back to priceIds with default quantity
if (lineItems != null && lineItems.Any()) {
options.LineItems = lineItems.Select(item =>
new SessionLineItemOptions {
Price = item.PriceId,
Quantity = item.Quantity
}).ToList();
} else {
options.LineItems = priceIds.Select(priceId =>
new SessionLineItemOptions {
Price = singleItemPriceAmount.HasValue ? null : priceId,
Quantity = quantity ?? 1,
PriceData = singleItemPriceAmount.HasValue ? new SessionLineItemPriceDataOptions {
UnitAmount = singleItemPriceAmount.Value,
Currency = "eur",
Product = product!.StripeProductId,
} : null
}

        ).ToList();
}
#

if (mode == SessionCreateMode_Enum.subscription) {

    var description = "";
    
    description = $"Abostart: {subscriptionStartDate ?? DateTime.UtcNow:dd.MM.yyyy}";
    description += runtimeInMonths != null ? $" - Laufzeit: {runtimeInMonths} Monate" : "";

    var subscriptionMetaData = new Dictionary<string, string>{
        { "initialPeriod",runtimeInMonths?.ToString() ?? "" }
    };

    options.SubscriptionData = new SessionSubscriptionDataOptions() {
        Metadata = subscriptionMetaData,
        Description = description
    };

    if (subscriptionStartDate.HasValue && subscriptionStartDate < DateTime.UtcNow) {
        subscriptionStartDate = DateTime.UtcNow;
    }
    if (subscriptionStartDate.HasValue && subscriptionStartDate.Value.Date > DateTime.UtcNow.Date) {
        options.SubscriptionData.BillingCycleAnchor = subscriptionStartDate;
        options.SubscriptionData.ProrationBehavior = "none";
    }
}

if (options.Mode == "payment") {
    options.InvoiceCreation = new SessionInvoiceCreationOptions() { Enabled = true };
}

if (couponIds?.Count > 0) {
    options.Discounts = couponIds.Select(d => new SessionDiscountOptions() { Coupon = d }).ToList();
} else {
    if (mode == SessionCreateMode_Enum.subscription) {
        options.AllowPromotionCodes = true;
    }
}

}

var service = new Stripe.Checkout.SessionService();
var session = await service.CreateAsync(options);

return session.ClientSecret;

#

when we setup the subscription to start later, the issue appears. When the subscription starts immediately, the address and name are being applied as we expect to the invoice and the stripe customer profile

fallen hearth
#

So generally, any billing information collected via the Elements is stored on the payment method object by default

#

have you checked the payment method object to see if it has the billing info you've collected?

#

Can you share the example customer where the address and name is being set?

gleaming silo
#

yes, In my initial post I wrote that the payment method includes all collected data correctly, but not the invoice generated later and also not the profile.

I did post the eventid for the setup_intent and the invoiceid in my second message. This is a sample customer where that happened cus_TZEinhURqcXkpq

#

setup intent eventid: evt_1Sc6GDLqit5oPG41QhtFy5r6
invoiceID: in_1ScwN0Lqit5oPG41Mh6E3qY6

fallen hearth
#

Sorry i got a bit confused.

cus_TZEinhURqcXkpq is where the address was set or wasn't set?

gleaming silo
#

where it wasnt set

fallen hearth
#

Can you share the customer ID where it was set?

#

I have a few theories about why it could be happening..

  • One is that the customer ID you used had an empty address associated with it when you created the Customer. So we didn't overwrite it with the new one

  • Second theory is that the flow might be different for new customer objects created by the Checkout Session versus existing customer ID passed in to the Checkout Session

gleaming silo
#

I just noticed now that the stripe profiles don't show Billing Addresses for all our customers, like this one cus_TXR85yxkZXa28d

But the name is correctly there, but this could be because we set the name via api. I would have too look into that

#

But why is the billing address from the payment method not being used in the invoices?

fallen hearth
gleaming silo
#

I expected that the collected Address is being applied as Billing Address for the customer

digital plinthBOT
fallen hearth
#

If you look at the Customer creation request, you're passing in empty values for the address - https://dashboard.stripe.com/acct_1ISlKWLqit5oPG41/logs/req_diKnpvkypRtIxm

It is creating an underlying address object that's associated with the customer and in that case, we just don't overwrite the existing address.

Can you try creating a brand new customer first, set nothing under address field and then create a test checkout session with it?

gleaming silo
#

we do that already, this is the code for creating the customer:

    if (String.IsNullOrEmpty(customer.StripeId) && !string.IsNullOrEmpty(email)) {
        var customerService = new Stripe.CustomerService();
        var stripeCustomer = await customerService.CreateAsync(new Stripe.CustomerCreateOptions() {
            Metadata = new Dictionary<string, string>() { { "AccountGroupId", customer.AccountGroupId.ToString() } },
            Email = email
        });
        customer.StripeId = stripeCustomer.Id;
        _dbContext.Customers.Update(customer);
        await _dbContext.SaveChangesAsync();
    }

    return customer;
fallen hearth
#

In the request I shared, address was being set

#

to empty strings

#

okay one thing you could try is rather than creating a Customer in advance, allow the Checkout Session to create a Customer automatically by passing customer_creation: 'always'

#

I believe one of my colleagues tested this and if you pass an existing customer ID, Checkout doesn't set it's address upon collection. The collected address is set on the payment method instead.

If you let Checkout Session create a new customer instead then it will set the collected address to the customer

gleaming silo
#

I found a place where we create the customer with address, i have to look into that

#

I will try this, might take a while. Can I get back to this tomorrow here?

fallen hearth
#

The thread might be closed but you can open up a new one and follow up

gleaming silo
#

okay, thank you very much!