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 functionpudm
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");
    }