0
votes

I am trying to add Stripe Subscription to my Blazor WASM Application following these instructions Since they are using JavaScript I am using the JavaScript interop. I added Stripe's script to my index.html and added a custom script with the javascript they have in the instructions. Index.html inside the <head> tag

<script src="https://js.stripe.com/v3/"></script>
<script src="stripescript.js"></script>

stripescript.js:

let stripe = window.Stripe('MY PUBLIC KEY');
let elements = stripe.elements();

let card = elements.create('card', { style: style });
card.mount('#card-element');

card.on('change', function (event) {
    displayError(event);
});
function displayError(event) {
    changeLoadingStatePrices(false);
    let displayError = document.getElementById('card-element-errors');
    if (event.error) {
        displayError.textContent = event.error.message;
    } else {
        displayError.textContent = '';
    }
}


function createPaymentMethod(cardElement, customerId, priceId) {
    return stripe
        .createPaymentMethod({
            type: 'card',
            card: cardElement,
        })
        .then((result) => {
            if (result.error) {
                displayError(error);
            } else {
                //change this to call .net
                createSubscription({
                    customerId: customerId,
                    paymentMethodId: result.paymentMethod.id,
                    priceId: priceId,
                });
            }
        });
}

My assumption is that the variable initializations would happen when the application is loaded. However, when I add the following HTML to my Razor page is not populating the card component.

<form id="payment-form">
    <div id="card-element">
        <!-- Elements will create input elements here -->
    </div>

    <!-- We'll put the error messages in this element -->
    <div id="card-element-errors" role="alert"></div>
    <button type="submit">Subscribe</button>
</form>

I am lost on how to debug this, or if this is even possible in Blazor.

1
You have not shown code for the JsRuntime you are using to call the method to initialize, please update the question with all relevant code. - Umair
that is my question, since this is not in a function let stripe = window.Stripe('MY PUBLIC KEY'); let elements = stripe.elements(); let card = elements.create('card', { style: style }); card.mount('#card-element'); do I have to put it in a function and call it from there? or would it be automatically run since it is not in a function - pudm
Correct you need to put that in a function, and call that function from C# code on the page where you are loading it in. - Umair
if I put it in a function, is there a way to make the stripe variable available to other javascript functions? basically making it a global variable? - pudm
Basically, the code that initializes the stripe card element needs to be put in a method that will be called from c#. Other variables can be outside of the function so they are globally accessible. - Umair

1 Answers

1
votes

Thanks to @Umair's Comments, I realized that I had made a few mistakes and some of them were showing up in the console since I was trying to initialize the card element before the DOM was loaded. I was able to fix my problem by first changing the card mount into its own function. Here is the full stripescript.js for future people that have this problem:

let stripe = window.Stripe('MY KEY');
let elements = stripe.elements();
let style = {
    base: {
        fontSize: '16px',
        color: '#32325d',
        fontFamily:
            '-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif',
        fontSmoothing: 'antialiased',
        '::placeholder': {
            color: '#a0aec0',
        },
    },
};
let card = elements.create('card', { style: style });

function mountCard() {
    card.mount('#card-element');
}

card.on('change', function (event) {
    displayError(event);
});
function displayError(event) {
    changeLoadingStatePrices(false);
    let displayError = document.getElementById('card-element-errors');
    if (event.error) {
        displayError.textContent = event.error.message;
    } else {
        displayError.textContent = '';
    }
}


function createPaymentMethod(cardElement, customerId, priceId) {
    return stripe
        .createPaymentMethod({
            type: 'card',
            card: cardElement,
        })
        .then((result) => {
            if (result.error) {
                displayError(error);
            } else {
                //todo change this to call .net
                createSubscription({
                    customerId: customerId,
                    paymentMethodId: result.paymentMethod.id,
                    priceId: priceId,
                });
            }
        });
}

and added the following C# code to my Blazor component to render the card:

[Inject] IJSRuntime js { get; set; }
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await js.InvokeVoidAsync("mountCard");
    }