#michael_paymentelement-savedpm

1 messages ¡ Page 1 of 1 (latest)

cunning riverBOT
#

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

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

Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.

knotty bloom
#

Hello! I'm happy to try and help. Can you please share a clear and detailed summary of your exact question end to end all in one message?

sly mantle
#

cus_Ql8MDN8P3IqHZP

#

following up on my last thread, this is the customer id that is not showing the saved payment methods

knotty bloom
#

Can I ask you to write a clear summary end to end all in one message and not just one id? I wasn't part of your other thread and each thread is self-contained.
If you can take a step back, explain in details what you're doing, share some code, share the exact PaymentMethod id that isn't appearing and why you expect it to appear, I'm happy to have a look after that

sly mantle
#

I'm trying to load the saved-payment element, but i'm not able to display the saved payment information

knotty bloom
#

Sorry to be a pain, I'm trying to push you to take a few minutes to cleanly lay out all the information. I'm sorry, I know it can be annoying to repeat yourself, but just fiving a handful of words each time is not enough though
Please take a few minutes and write a clear question with exact information including PaymentMethod id pm_123 and exact code.

#

Okay I'm looking in parallel. That Customer has a PaymentMethod attached and it has allow_redisplay: "always" so it should appear

sly mantle
#

ok, how would you suggest that i debug this, because I can't get this to show

knotty bloom
#

Sorry it's tricky, I am still needing a lot of information from them that you didn't really share. Exact code, exact object ids, what you see, what's going on
I don't really have a way to nudge you until you take the time to share a lot of details

sly mantle
#

here is my payment page:

knotty bloom
#

okay, I'm going to need more than a picture of your browser. Let's pause and please have you share exact code of both how you create the CustomerSession server-side and how you initialize PaymentElement client-side so I can help you
Please don't post pictures of code, post real code as text

sly mantle
#

[HttpPost("create_intent_and_customer_session")]
public async Task<IActionResult> CreateIntentAndCustomerSession([FromBody] CreateCustomerAndIntent createCustomerInformation)
{
//handleReadOAAuthorizationHeader();
_companyId = 179859;
createCustomerInformation = new CreateCustomerAndIntent
{
Name = "John Doe",
Email = "johndoe@test.com"
};

StripeConfiguration.ApiKey = _paymentProcessor.StripeApiKey;

string stripeAccountId = await _stripeAccountSessionBal.GetAccountId(_companyId);

// Todo: look up if there already is a customer for this company with this email address and name return that customer id if it exists
string customerId = "";//await _stripeAccountSessionBal.GetCustomerId(_companyId, createCustomerInformation.Name, createCustomerInformation.Email);


// if customer already exists, skip creating customer

if (string.IsNullOrEmpty(customerId))
{
    // create customer
    var options = new CustomerCreateOptions
    {
        Email = createCustomerInformation.Email,
        Name = createCustomerInformation.Name,

    };

    var requestOptionsCustomer = new RequestOptions()
    {
        StripeAccount = stripeAccountId
    };

    var service = new CustomerService();
    Customer customer = await service.CreateAsync(options, requestOptionsCustomer);

    customerId = customer.Id;


    // Todo: save customer
    //_stripeAccountSessionBal.SaveCustomer(_companyId, customerId, createCustomerInformation.Name, createCustomerInformation.Email);
}
#

var intentOptions = new PaymentIntentCreateOptions
{
Amount = 1099,
Currency = "usd",
// In the latest version of the API, specifying the automatic_payment_methods parameter
// is optional because Stripe enables its functionality by default.
AutomaticPaymentMethods = new PaymentIntentAutomaticPaymentMethodsOptions
{
Enabled = true
},

Customer = customerId,
//SetupFutureUsage = "on_session"

};

RequestOptions requestOptionsPaymentIntent = new RequestOptions();
requestOptionsPaymentIntent.StripeAccount = stripeAccountId;

var intentService = new PaymentIntentService();
var intent = intentService.Create(intentOptions, requestOptionsPaymentIntent);

var customerSessionOptions = new CustomerSessionCreateOptions
{
Customer = customerId,
Components = new CustomerSessionComponentsOptions(),

};

#

customerSessionOptions.AddExtraParam("components[payment_element][enabled]", true);
customerSessionOptions.AddExtraParam(
"components[payment_element][features][payment_method_redisplay]",
"enabled");
customerSessionOptions.AddExtraParam(
"components[payment_element][features][payment_method_save]",
"enabled");
customerSessionOptions.AddExtraParam(
"components[payment_element][features][payment_method_save_usage]",
"on_session");
customerSessionOptions.AddExtraParam(
"components[payment_element][features][payment_method_remove]",
"enabled");
var customerSessionService = new CustomerSessionService();

        RequestOptions requestOptionsCustomerSession = new RequestOptions();
        requestOptionsCustomerSession.StripeAccount = stripeAccountId;
        var customerSession = customerSessionService.Create(customerSessionOptions, requestOptionsCustomerSession);


        return Ok(new {
            client_secret = intent.ClientSecret,
            customerSessionClientSecret = customerSession.ClientSecret
        });
    
    }
#

here is the server ^

#

const stripe = Stripe('pk_test_51NPtx2JjxPibOeqQ0dah6E26WFsyFzd9PrJtUzQygd71i1L3NjINbFFNq9ww7tLri5Wl4SiTv8gM2FsOiaOWdCHZ00KScJkMZu', { stripeAccount: 'acct_1Nd09wR30hnXx3Kv' });

const response = fetch('https://localhost:7060/v1/StripeAccountSession/create_intent_and_customer_session',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(
{ Email: "john.doe@example.com", Name: 'mike test', Amount: 1000, Description: 'test' }
)
})
.then(response => response.json())
.then(data => {
console.log(data);
const options = {
clientSecret: data.client_secret,
customerSessionClientSecret: data.customerSessionClientSecret,
// Fully customizable with appearance API.
appearance: {/.../ },
};

    // Set up Stripe.js and Elements to use in checkout form, passing the client secret obtained in a previous step
    const elements = stripe.elements(options);

    // Create and mount the Payment Element
    const paymentElement = elements.create('payment');
    paymentElement.mount('#payment-element');
#

const form = document.getElementById('payment-form');

    form.addEventListener('submit', async (event) => {
        event.preventDefault();

        const { error } = await stripe.confirmPayment({
            //`Elements` instance that was used to create the Payment Element
            elements,
            confirmParams: {
                return_url: 'http://127.0.0.1:5500/stripe/status.html',
            },
        });

        if (error) {
            // This point will only be reached if there is an immediate error when
            // confirming the payment. Show error to your customer (for example, payment
            // details incomplete)
            const messageContainer = document.querySelector('#error-message');
            messageContainer.textContent = error.message;
        } else {
            // Your customer will be redirected to your `return_url`. For some payment
            // methods like iDEAL, your customer will be redirected to an intermediate
            // site first to authorize the payment, then redirected to the `return_url`.
        }
    });

});
knotty bloom
#

Can you log all your options after const options = { clientSecret: data.client_secret, customerSessionClientSecret: data.customerSessionClientSecret, // Fully customizable with appearance API. appearance: {/.../ }, }; to confirm they match what you expect?

sly mantle
#

{
"client_secret": "pi_3Ptc7wR30hnXx3Kv04UJjsrY_secret_Ma85D7fbhCVZIuPgTqFSEU2ut",
"customerSessionClientSecret": "cuss_secret_Ql8OMjbFskJvrYdS6WD2uHT8yB5uCLWE1afdhr4ZMnI06nR"
}

knotty bloom
#

In parallel I read your code and saw you are using Direct Charges. I just tested this end to end myself and it does work as expected. After I saved a card and I reload I see the saved card

sly mantle
#

{
"clientSecret": "pi_3Ptct7R30hnXx3Kv19S8WhKi_secret_zCkfqIKpxEPLe2Tk9uod3vi7W",
"customerSessionClientSecret": "cuss_secret_Ql9BtbcVPvifUdoT0oVSR0uBvgMAPwK5vM7n37Vq4OCYmjL",
"appearance": {}
}

#

submitting a payment

#

payment successful

knotty bloom
#

hum

#

is it possible you're mixing things up and maybe creating a new Customer every time?

sly mantle
#

yes, i believe i am

knotty bloom
#

that's your issue in that case!

#

You need to re-use the same Customer id cus_12345 if you want to show its saved PaymentMethods

sly mantle
#

ok i'm hard coding the customer id cus_Ql9HparsFcPQ1G

#

it's working!

knotty bloom
#

michael_paymentelement-savedpm

#

yay!