Smart views not working

Feature(s) impacted

Smart Actions

Observed behavior

We’re getting CORS related error when using one of our smart actions. The problem rose 3-4 days ago, same time when you had a system down time so it might be related?

Expected behavior

Smart Actions return a valid response

Failure Logs

caught (in promise) TypeError: Cannot read properties of undefined (reading ‘isFilterable’)

Acess to fetch at ‘https://sps-fa.scratchpay.com/forest/stats/payments/last/quarter?timezone=America%2FLos_Angeles’ from origin ‘https://app.forestadmin.com’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.

Context

  • Project name: scratchpay-payment-service
  • Team name: all
  • Environment name: production
  • Agent (forest package) name & version: no idea
  • Recent changes made on your end if any: none

This is related to a smart view.

@Rap_Navalez (and whoever can help answer) I did some more research on this and it seems like it’s related to the errors in the SS, not the CORS error.

The errors in the SS are related to deprecation of automatic property fallback. When using the hbs template to generate the html, Ember is no longer reading the variables as it once did.
https://deprecations.emberjs.com/v3.x/#toc_this-property-fallback

The issue I’m running into now is that I can’t get the hbs FA to actually read the changes to the hbs template. I changed all of the variable references as well as some text (to make sure I was correct) and the changes are not reflected in FA dev env.

Hi @Rap_Navalez,

Could you please let me know on which smart view you are having this issue :thinking: ?
And if you could actually share the code of your smart view it will be actually much easier for me to help you :angel:

Hi @Brett_Belka,

What do you mean by they are not reflected in dev env :thinking: ? You cannot edit your smart view ?
Did you save ?

@vince not sure if it’s useful, but we only have one smart view on our project: smart-views/subscription-token/ with 2 files inside: add-payment-method.js and add-payment-method.hbs

it definitely could but I would need your Project name, team name and environment name ?
And what’s your issue on your side ? Because if you have a lot of error logs about deprecations, it’s just deprecations meaning that your app will break when we will upgrade but your smart view should work atm (as we did not upgrade Ember yet)

@vince
project: scratch-payment-service
env: any

I’ll post code in a moment

@vince

You cannot edit your smart view? Did you save ?

LOL. Yes. And refreshed. And closed/updated/cleared cache on my browser. And saved again. And undid changes, saved, changed plain text. And redid changes. And saved again. And restarted the dev server after each change.

What do you mean by they are not reflected in dev env :thinking:?

I mean that no matter what I change in the hbs template, the change does not load in FA UI on the development environment but change to, say, smart actions (I commented one out) do.

It seems telling/related that nodemon does not automatically restart the dev server when the hbs template is saved. For changes in any of the /forest or /routes (etc) files it restarts (correctly) on save.

Also, this worked fine until a few days ago. There were no changes on our end and now it doesn’t.

<div class="wrapper" id="smv_add_token">
	<div class="wrapper-list">
		<div class="sub-tok-list-table">
			<div class="sub-tok-list-heading">
				<div class="sub-tok-list-heading-row">
					<div class="column sub-tok-ids">Subscription ID/Token ID</div>
					<div class="column loan-number">Loan number</div>
					<div class="column pm-info">Payment method info<br>(Vendor/Type/Last 4)</div>
				</div>
			</div>
			<div class="sub-tok-list-body">
				{{#each records as |record|}}
				<div class="sub-tok-list-row {{if (eq selectedRecord record) 'selected'}}" {{action "onSelectRecord" record}}>
					<div class="column sub-tok-ids">
						<span class="value">
							{{record.forest-subscription.id}}
							<br>
							{{record.forest-token.id}}
							<br>
							{{#if record.forest-isPrimary}}
								<div class="primary-token">primary</div>
							{{/if}}
						</span>
					</div>
					<div class="column loan-number">
						<span class="value">{{record.forest-subscription.forest-loanNumber}}</span>
					</div>
					<div class="column pm-info">
						<span class="value">{{record.forest-subscription.forest-vendor}}</span>
						<span class="value">&nbsp;/&nbsp;{{record.forest-token.forest-paymentMethod}}&nbsp;/&nbsp;</span>
						<span class="value">{{record.forest-token.forest-last4}}</span>
					</div>
				</div>
				{{/each}}
			</div>
		</div>

		{{table/table-footer
			collection=@collection
			viewList=@viewList
			records=@records
			currentPage=@currentPage
			numberOfPages=@numberOfPages
			recordsCount=@recordsCount
			isLoading=@isLoading
			fetchRecords=@fetchRecords
		}}
	</div>

	<div class="wrapper-forms">
		{{#if stripe}}
		<h2 class="forms-title">New payment method for Loan: <b>{{selectedRecord.forest-subscription.forest-loanNumber}}</b></h2>
		{{else}}
		<h2 class="forms-title">Getting ready ... blah blah</h2>
		{{/if}}

		{{#if @resultToken}}
			{{#if (eq @resultToken.paymentMethod 'CARD')}}
				<div class="wrapper-result">
					<div class="result-row">
						<div class="label">Name</div>
						<div class="value">{{@resultToken.name}}</div>
					</div>
					<div class="result-row">
						<div class="label">Card brand</div>
						<div class="value">{{@resultToken.type}}</div>
					</div>
					<div class="result-row">
						<div class="label">Last 4 digits</div>
						<div class="value">{{@resultToken.last4}}</div>
					</div>
					<div class="result-row">
						<div class="label">Expiry date</div>
						<div class="value">{{@resultToken.expiry}}</div>
					</div>
					{{#if @resultToken.billingZip}}
					<div class="result-row">
						<div class="label">Billing zip</div>
						<div class="value">{{@resultToken.billingZip}}</div>
					</div>
					{{/if}}
				</div>
			{{else}}
				<div class="wrapper-result">
					<div class="result-row">
						<div class="label">Bank name</div>
						<div class="value">{{@resultToken.bankName}}</div>
					</div>
					<div class="result-row">
						<div class="label">Account owner's full name</div>
						<div class="value">{{@resultToken.name}}</div>
					</div>
					<div class="result-row">
						<div class="label">Last 4 digits</div>
						<div class="value">{{@resultToken.last4}}</div>
					</div>
					{{#if @resultToken.type}}
					<div class="result-row">
						<div class="label">Account type</div>
						<div class="value">{{@resultToken.type}}</div>
					</div>
					{{/if}}
				</div>
			{{/if}}
			{{#if @isClickedToSync}}
				<h2 class="warning">Please refresh your browser to see new update after finishing the synchronization successfully.</h2>
				{{else}}
				<button class="btn btn-sync" {{action "onSyncToPaymentService"}}>
					Upload new Payment method to Payment service
				</button>
			{{/if}}
		{{else}}
		<div data-loaded="{{@isLoadedStripe}}"
			data-visibility="{{if (eq this.vendor 'stripe') true false}}"
			class="wrapper-stripe-forms">
			{{!-- STRIPE CARD --}}
			<form id="stripe-form" data-visibility="{{if this.resultToken false true}}"
				onsubmit={{action "onSubmitToCreateStripeCard" }}>
				<div class="stripe-form-row">
					<input id="stripe-card-holder-name" class="form-input" placeholder="Name" />
					<div id="stripe-card-holder-name-error" class="stripe-error" role="alert" />
				</div>
				<div class="stripe-form-row">
					<div id="stripe-card-element" />
					<div id="stripe-card-errors" class="stripe-error" role="alert" />
				</div>
				<div class="form-actions">
					{{#if @isCreatingStripeCard}}
					<div class="wrapper-dots">
						<div class="dot"></div>
						<div class="dot"></div>
						<div class="dot"></div>
					</div>
					{{else}}
					<button type="submit" class="btn btn-stripe-add">Add Card</button>
					{{/if}}
				</div>
			</form>

			{{!-- STRIPE ACH --}}
			<form class="stripe-ach-form" onsubmit={{action "onSubmitToCreateStripeACH" }}>
				<div class="stripe-ach-form-cols-wrapper">
					<div class="stripe-ach-form-col col-inputs">
						<div class="ach-form-input">
							<input type="text" id="stripe-ach-holder-name" placeholder="Account owner full name">
							<div id="stripe-ach-holder-name-error" class="stripe-error" role="alert" />
						</div>
						<div class="ach-form-input">
							<input type="text" id="stripe-ach-account-number" placeholder="Account number">
							<div id="stripe-ach-account-number-error" class="stripe-error" role="alert" />
						</div>
						<div class="ach-form-input">
							<input type="text" id="stripe-ach-routing-number" placeholder="Routing number">
							<div id="stripe-ach-routing-number-error" class="stripe-error" role="alert" />
						</div>
				</div>

				<div class="stripe-ach-form-col col-selectors">
					<div class="ach-form-selector">
						<label for="bank_country">Bank country</label>
						<select id="stripe-ach-bank-country" name="bank_country" disabled>
							<option value="US" selected>United States</option>
						</select>
					</div>
					<div class="ach-form-selector">
						<label for="currency">Currency</label>
						<select id="stripe-ach-currency" name="currency" disabled>
							<option value="USD" selected>USD</option>
						</select>
					</div>
					<div class="ach-form-selector">
						<label for="account_type">Account type</label>
						<select id="stripe-ach-account-type" name="account_type">
							<option value="individual">Individual</option>
							<option value="company">Company</option>
						</select>
					</div>
				</div>
				</div>
				<div class="form-actions">
					{{#if @isCreatingStripeACH}}
					<div class="wrapper-dots">
						<div class="dot"></div>
						<div class="dot"></div>
						<div class="dot"></div>
					</div>
					{{else}}
					<button disabled={{@isCreatingStripeACH}} type="submit" class="btn btn-stripe-add">Add ACH</button>
					{{/if}}
				</div>
			</form>

		</div>


		{{#if (eq @vendor 'payix')}}
		<div class="wrapper-payix-iframes">
			<div class="warning-pad">PAD only supports for Canadian</div>
			<div class="wrapper-iframes">
				<iframe src="{{@payixIframeCardAchURL}}" />
				<iframe src="{{@payixIframePadURL}}" />
			</div>
		</div>
		{{/if}}
		{{/if}}
	</div>
</div>

Hmm really weird. Could you also share your component.js please ?

And on which environment are you trying to update your smart views ?

I saw also that you are using @vendor and a lot of other variables prefixed with @.
Just to be clear, it seems you are relying on a bug :sweat_smile:
To explain a bit more:

  • Everything that is passed as an argument to the component should be prefixed with @. So things that Forest Admin pass to your smart view are:
    • records
    • recordsCount
    • collection
    • isLoading
    • error
    • currentPage
    • numberOfPages
    • canEdit
    • viewList
    • fetchRecords
    • addCondition
    • removeCondition
    • That’s it
  • Everything property/function that is define inside your component.js should be prefixed with this. just like in a js file

Another things I’ve noticed is that you are using

{{action "myFunction" myArg}}

This is deprecated as it won’t throw an error if myFunction is not defined until you actually trigger the action. You can use that instead

{{fn (this.myFunction myArg)}}

And finally, I strongly suggest you to use simple components like so:

// What you actually have
{{table/table-footer collection=@collection}}

// What you should do instead
<Table::TableFooter @collection={{@collection}} />

So taking everything I’ve said into account you should have the following template:

<div class="wrapper" id="smv_add_token" {{did-update this.onRecordsChange @records}}>
	<div class="wrapper-list">
		<div class="sub-tok-list-table">
			<div class="sub-tok-list-heading">
				<div class="sub-tok-list-heading-row">
					<div class="column sub-tok-ids">Subscription ID/Token ID</div>
					<div class="column loan-number">Loan number</div>
					<div class="column pm-info">Payment method info<br>(Vendor/Type/Last 4)</div>
				</div>
			</div>
			<div class="sub-tok-list-body">
				{{#each @records as |record|}}
					<div
						class="sub-tok-list-row {{if (eq this.selectedRecord record) 'selected'}}"
						{{on 'click' (fn this.onSelectRecord record)}}
					>
						<div class="column sub-tok-ids">
							<span class="value">
								{{record.forest-subscription.id}}
								<br>
								{{record.forest-token.id}}
								<br>
								{{#if record.forest-isPrimary}}
									<div class="primary-token">primary</div>
								{{/if}}
							</span>
						</div>
						<div class="column loan-number">
							<span class="value">{{record.forest-subscription.forest-loanNumber}}</span>
						</div>
						<div class="column pm-info">
							<span class="value">{{record.forest-subscription.forest-vendor}}</span>
							<span class="value">&nbsp;/&nbsp;{{record.forest-token.forest-paymentMethod}}&nbsp;/&nbsp;</span>
							<span class="value">{{record.forest-token.forest-last4}}</span>
						</div>
					</div>
				{{/each}}
			</div>
		</div>

		<DataDisplay::Table::TableFooter
			@collection={{@collection}}
			@viewList={{@viewList}}
			@records={{@records}}
			@currentPage={{@currentPage}}
			@numberOfPages={{@numberOfPages}}
			@recordsCount={{@recordsCount}}
			@isLoading={{@isLoading}}
			@fetchRecords={{@fetchRecords}}
		/>
	</div>

	<div class="wrapper-forms">
		{{#if this.stripe}}
			<h2 class="forms-title">New payment method for Loan: <b>{{this.selectedRecord.forest-subscription.forest-loanNumber}}</b></h2>
		{{else}}
			<h2 class="forms-title">Getting ready ... blah blah</h2>
		{{/if}}

		{{#if this.resultToken}}
			{{#if (eq this.resultToken.paymentMethod 'CARD')}}
				<div class="wrapper-result">
					<div class="result-row">
						<div class="label">Name</div>
						<div class="value">{{this.resultToken.name}}</div>
					</div>
					<div class="result-row">
						<div class="label">Card brand</div>
						<div class="value">{{this.resultToken.type}}</div>
					</div>
					<div class="result-row">
						<div class="label">Last 4 digits</div>
						<div class="value">{{this.resultToken.last4}}</div>
					</div>
					<div class="result-row">
						<div class="label">Expiry date</div>
						<div class="value">{{this.resultToken.expiry}}</div>
					</div>
					{{#if this.resultToken.billingZip}}
					<div class="result-row">
						<div class="label">Billing zip</div>
						<div class="value">{{this.resultToken.billingZip}}</div>
					</div>
					{{/if}}
				</div>
			{{else}}
				<div class="wrapper-result">
					<div class="result-row">
						<div class="label">Bank name</div>
						<div class="value">{{this.resultToken.bankName}}</div>
					</div>
					<div class="result-row">
						<div class="label">Account owner's full name</div>
						<div class="value">{{this.resultToken.name}}</div>
					</div>
					<div class="result-row">
						<div class="label">Last 4 digits</div>
						<div class="value">{{this.resultToken.last4}}</div>
					</div>
					{{#if this.resultToken.type}}
					<div class="result-row">
						<div class="label">Account type</div>
						<div class="value">{{this.resultToken.type}}</div>
					</div>
					{{/if}}
				</div>
			{{/if}}
			{{#if this.isClickedToSync}}
				<h2 class="warning">Please refresh your browser to see new update after finishing the synchronization successfully.</h2>
			{{else}}
				<button class="btn btn-sync" {{on 'click' (fn this.onSyncToPaymentService)}}>
					Upload new Payment method to Payment service
				</button>
			{{/if}}
		{{else}}
			<div data-loaded="{{this.isLoadedStripe}}"
				data-visibility="{{if (eq this.vendor 'stripe') true false}}"
				class="wrapper-stripe-forms">
				{{!-- STRIPE CARD --}}
				<form id="stripe-form" data-visibility="{{if this.resultToken false true}}"
					onsubmit={{fn this.onSubmitToCreateStripeCard}}>
					<div class="stripe-form-row">
						<input id="stripe-card-holder-name" class="form-input" placeholder="Name" />
						<div id="stripe-card-holder-name-error" class="stripe-error" role="alert" />
					</div>
					<div class="stripe-form-row">
						<div id="stripe-card-element" />
						<div id="stripe-card-errors" class="stripe-error" role="alert" />
					</div>
					<div class="form-actions">
						{{#if this.isCreatingStripeCard}}
						<div class="wrapper-dots">
							<div class="dot"></div>
							<div class="dot"></div>
							<div class="dot"></div>
						</div>
						{{else}}
						<button type="submit" class="btn btn-stripe-add">Add Card</button>
						{{/if}}
					</div>
				</form>

				{{!-- STRIPE ACH --}}
				<form class="stripe-ach-form" onsubmit={{fn this.onSubmitToCreateStripeACH }}>
					<div class="stripe-ach-form-cols-wrapper">
						<div class="stripe-ach-form-col col-inputs">
							<div class="ach-form-input">
								<input type="text" id="stripe-ach-holder-name" placeholder="Account owner full name">
								<div id="stripe-ach-holder-name-error" class="stripe-error" role="alert" />
							</div>
							<div class="ach-form-input">
								<input type="text" id="stripe-ach-account-number" placeholder="Account number">
								<div id="stripe-ach-account-number-error" class="stripe-error" role="alert" />
							</div>
							<div class="ach-form-input">
								<input type="text" id="stripe-ach-routing-number" placeholder="Routing number">
								<div id="stripe-ach-routing-number-error" class="stripe-error" role="alert" />
							</div>
					</div>

					<div class="stripe-ach-form-col col-selectors">
						<div class="ach-form-selector">
							<label for="bank_country">Bank country</label>
							<select id="stripe-ach-bank-country" name="bank_country" disabled>
								<option value="US" selected>United States</option>
							</select>
						</div>
						<div class="ach-form-selector">
							<label for="currency">Currency</label>
							<select id="stripe-ach-currency" name="currency" disabled>
								<option value="USD" selected>USD</option>
							</select>
						</div>
						<div class="ach-form-selector">
							<label for="account_type">Account type</label>
							<select id="stripe-ach-account-type" name="account_type">
								<option value="individual">Individual</option>
								<option value="company">Company</option>
							</select>
						</div>
					</div>
					</div>
					<div class="form-actions">
						{{#if this.isCreatingStripeACH}}
						<div class="wrapper-dots">
							<div class="dot"></div>
							<div class="dot"></div>
							<div class="dot"></div>
						</div>
						{{else}}
						<button disabled={{this.isCreatingStripeACH}} type="submit" class="btn btn-stripe-add">Add ACH</button>
						{{/if}}
					</div>
				</form>

			</div>


			{{#if (eq this.vendor 'payix')}}
				<div class="wrapper-payix-iframes">
					<div class="warning-pad">PAD only supports for Canadian</div>
					<div class="wrapper-iframes">
						<iframe src="{{this.payixIframeCardAchURL}}" />
						<iframe src="{{this.payixIframePadURL}}" />
					</div>
				</div>
			{{/if}}
		{{/if}}
	</div>
</div>

@vince

// v1.5.0: Set Stripe as Default Vendor

import Component from "@ember/component";
import { observer } from "@ember/object";
import { scheduleOnce } from "@ember/runloop";
import { inject as service } from "@ember/service";
import SmartViewMixin from "client/mixins/smart-view-mixin";
import $ from "jquery";

const CARD_STYLE = {
  base: {
    color: "#54BD7E",
    fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
    fontSmoothing: "antialiased",
    fontSize: "14px",
    "::placeholder": {
      color: "#aab7c4", // --color-beta-on-surface_light
    },
  },
  invalid: {
    color: "#FB6669",
    iconColor: "#FB6669",
  },
};

const ELEMENT_IDS = {
  STRIPE_CARD_ELEMENT: "stripe-card-element",
  STRIPE_CARD_ERROR: "stripe-card-errors",
  STRIPE_CARD_HOLDER_NAME: "stripe-card-holder-name",
  STRIPE_CARD_HOLDER_NAME_ERROR: "stripe-card-holder-name-error",

  STRIPE_ACH_HOLDER_NAME: "stripe-ach-holder-name",
  STRIPE_ACH_ACCOUNT_NUMBER: "stripe-ach-account-number",
  STRIPE_ACH_ROUTING_NUMBER: "stripe-ach-routing-number",
  STRIPE_ACH_ACCOUNT_TYPE: "stripe-ach-account-type",
  STRIPE_ACH_HOLDER_NAME_ERROR: "stripe-ach-holder-name-error",
  STRIPE_ACH_ACCOUNT_NUMBER_ERROR: "stripe-ach-account-number-error",
  STRIPE_ACH_ROUTING_NUMBER_ERROR: "stripe-ach-routing-number-error",
};

const PAYMENT_METHOD = {
  CARD: "CARD",
  ACH: "ACH",
  PAD: "PAD",
};
const PAYMENT_METHOD_VENDOR = {
  STRIPE: "stripe",
  PAYIX: "payix",
};
const STRIPE_ACH_DEFAULT_VALUE = {
  BANK_COUNTRY_CODE: "US",
  CURRENCY: "USD",
};

const obfuscateToken = (token) =>
  token.includes("_")
    ? token.replace(/^(.*)_((.{3}).*(.{3}))$/, "$1_$3***$4")
    : token.replace(/^(.{3})(.*)(.{3})$/, "$1***$3");

export default Component.extend(SmartViewMixin, {
  customAction: service(),
  store: service(),

  selectedRecord: null,
  resultToken: null,

  stripe: null,
  isLoadedStripe: false,
  stripeCard: null,
  isCreatingStripeCard: false,
  isCreatingStripeACH: false,
  isClickedToSync: false,
  stripePublicKey: null,
  payixIframeCardAchURL: null,
  payixIframePadURL: null,
  subscriptionId: null,
  vendor: null,

  init(...args) {
    this._super(...args);
    console.log("===== Smart view: v1.5.0: Set Stripe as Default Vendor =====");
  },

  didInsertElement() {
    this.setDefaultSelectedRecord();

    this.onCreatedPayixToken = this.onCreatedPayixToken.bind(this);
    window.addEventListener("message", this.onCreatedPayixToken);
  },

  willRemoveElement() {
    window.removeEventListener("message", this.onCreatedPayixToken);
  },

  onRecordsChange: observer("records.[]", function() {
    this.setDefaultSelectedRecord();
  }),

  isSupportedStripe() {
    return this.vendor === PAYMENT_METHOD_VENDOR.STRIPE;
  },
  setURLs(data) {
    this.set("payixIframeCardAchURL", data["forest-payix_iframe_card_ach_url"]);
    this.set("payixIframePadURL", data["forest-payix_iframe_pad_url"]);
    this.set("stripePublicKey", data["forest-stripe_public_key"]);
  },
  setSubscriptionIdAndVendor(record) {
    this.set("subscriptionId", record["forest-subscription"]["id"]);
    this.set("vendor", record["forest-subscription"]["forest-vendor"]);
  },
  setDefaultSelectedRecord() {
    if (this.records && this.records.recordData) {
      this.set("subscriptionId", this.records.recordData.id);
      this.set("vendor", PAYMENT_METHOD_VENDOR.STRIPE);
      if (this.records.recordData.__data) {
        this.setURLs(this.records.recordData.__data);
        //Setting the vendor here again as if it's a Canadian User
        //The Vendor should be Payix not Stripe
        if (this.records.recordData.__data["forest-vendor"]) {
          this.set("vendor", this.records.recordData.__data["forest-vendor"]);
        }
      }
    }

    if (!this.selectedRecord && this.records) {
      if (this.records.firstObject) {
        this.set("selectedRecord", this.records.firstObject);
        this.setURLs(this.records.firstObject);
        this.setSubscriptionIdAndVendor(this.records.firstObject);
      }

      if (!this.stripe) this.loadPlugins();
    }
  },

  loadPlugins() {
    scheduleOnce("afterRender", this, () => {
      try {
        const stripePublicKey = this.stripePublicKey;
        $.getScript("//js.stripe.com/v2/", () => {
          $.getScript("//js.stripe.com/v3/", () => {
            Stripe.setPublishableKey(stripePublicKey); // v2
            const stripe = Stripe(stripePublicKey); // v3
            this.set("stripe", stripe);
            this.set("isLoadedStripe", true);

            if (this.isSupportedStripe()) {
              this.renderStripeElements();
            }
          });
        });
      } catch (error) {
        console.error("Internal Error: Failed to load Stripe:\n", error);
      }
    });
  },

  renderStripeCard() {
    const { stripe } = this;
    const elements = stripe.elements();
    const stripeCard = elements.create("card", { style: CARD_STYLE });
    stripeCard.mount(`#${ELEMENT_IDS.STRIPE_CARD_ELEMENT}`);

    stripeCard.on("change", function(event) {
      let errorElement = document.getElementById(ELEMENT_IDS.STRIPE_CARD_ERROR);
      if (event.error) {
        errorElement.textContent = event.error.message;
      } else {
        errorElement.textContent = "";
      }
    });
    this.set("stripeCard", stripeCard);
  },

  renderStripeElements() {
    if (!this.stripe) return;
    this.renderStripeCard();
  },

  onCreatedStripeCardToken(cardData, cardName) {
    try {
      const {
        id,
        billing_details: {
          address: { postal_code },
        },
        card: { brand, last4, exp_month, exp_year },
      } = cardData;
      const expiry = `${exp_year}-${("0" + exp_month).slice(-2)}-01`;
      const resultToken = {
        paymentMethod: PAYMENT_METHOD.CARD,
        name: cardName,
        token: id,
        last4,
        type: brand,
        expiry,
        billingZip: postal_code,
      };
      console.log("===== Created Stripe Card Token =====\n", {
        ...resultToken,
        token: obfuscateToken(resultToken.token),
      });
      this.set("resultToken", resultToken);
    } catch (error) {
      console.error(
        "Internal Error: Failed to add new Card with Stripe:\n",
        error
      );
    }
  },

  onCreatedStripeACHToken(achData, achValues) {
    try {
      const {
        id,
        bank_account: { last4, bank_name },
      } = achData;
      const resultToken = {
        paymentMethod: PAYMENT_METHOD.ACH,
        token: id,
        last4,
        bankName: bank_name,
        name: achValues.achHolderName,
        type: achValues.achAccountType,
      };
      console.log("===== Created Stripe ACH Token =====\n", {
        ...resultToken,
        token: obfuscateToken(resultToken.token),
      });
      this.set("resultToken", resultToken);
    } catch (error) {
      console.error(
        "Internal Error: Failed to add new ACH with Stripe:\n",
        error
      );
    }
  },

  onCreatedPayixToken(event) {
    try {
      const isAddedWithPayixSuccessfully =
        event.data &&
        event.data.token !== "" &&
        event.data.token !== null &&
        event.data.token !== undefined;
      if (isAddedWithPayixSuccessfully) {
        const {
          token,
          nameOnCard,
          nameOnAch,
          nameOnPad,
          cardBrand,
          expiryDate,
          lastFourDigits,
          billingZip,
          bankName,
        } = event.data;
        const isCard = !!nameOnCard;
        const isACH = !isCard && !!nameOnAch;
        const isPAD = !isCard && !isACH && !!nameOnPad;
        let resultToken;

        if (isCard) {
          const expiry = expiryDate.replace(/(\d{2})\/(\d{4})/, "$2-$1-01");
          resultToken = {
            paymentMethod: PAYMENT_METHOD.CARD,
            name: nameOnCard,
            token,
            last4: lastFourDigits,
            type: cardBrand,
            expiry,
            billingZip,
          };
        } else if (isACH) {
          resultToken = {
            paymentMethod: PAYMENT_METHOD.ACH,
            name: nameOnAch,
            token,
            last4: lastFourDigits,
            bankName,
          };
        } else if (isPAD) {
          resultToken = {
            paymentMethod: PAYMENT_METHOD.PAD,
            name: nameOnPad,
            token,
            last4: lastFourDigits,
            bankName,
          };
        }

        if (resultToken) {
          console.log(
            `===== Created Payix ${resultToken.paymentMethod} Token =====\n`,
            {
              ...resultToken,
              token: obfuscateToken(resultToken.token),
            }
          );
          this.set("resultToken", resultToken);
        }
      }
    } catch (error) {
      console.error(
        "Internal Error: Failed to add new payment method with Payix:\n",
        error
      );
    }
  },

  validateStripeACHForm() {
    const { value: achHolderName } = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_HOLDER_NAME
    );
    const { value: achAccountNumber } = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_ACCOUNT_NUMBER
    );
    const { value: achRoutingNumber } = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_ROUTING_NUMBER
    );
    const { value: achAccountType } = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_ACCOUNT_TYPE
    );
    const holderNameErrorElement = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_HOLDER_NAME_ERROR
    );
    const accountNumberErrorElement = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_ACCOUNT_NUMBER_ERROR
    );
    const routingNumberErrorElement = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_ROUTING_NUMBER_ERROR
    );

    let isValidHolderName = false;
    if (!achHolderName) {
      holderNameErrorElement.textContent =
        "Please input Account ownner's fullname";
    } else {
      holderNameErrorElement.textContent = "";
      isValidHolderName = true;
    }

    let isValidAccountNumber = false;
    if (!achAccountNumber) {
      accountNumberErrorElement.textContent = "Please input Account number";
    } else {
      const isValidAccountNumberByStripe = Stripe.bankAccount.validateAccountNumber(
        achAccountNumber,
        STRIPE_ACH_DEFAULT_VALUE.BANK_COUNTRY_CODE
      );
      if (!isValidAccountNumberByStripe) {
        accountNumberErrorElement.textContent =
          "Your Account number is invalid";
      } else {
        accountNumberErrorElement.textContent = "";
        isValidAccountNumber = true;
      }
    }

    let isValidRoutingNumber = false;
    if (!achRoutingNumber) {
      routingNumberErrorElement.textContent = "Please input Routing number";
    } else {
      const isValidRoutingNumberByStripe = Stripe.bankAccount.validateRoutingNumber(
        achRoutingNumber,
        STRIPE_ACH_DEFAULT_VALUE.BANK_COUNTRY_CODE
      );
      if (!isValidRoutingNumberByStripe) {
        routingNumberErrorElement.textContent =
          "Your Routing number is invalid";
      } else {
        routingNumberErrorElement.textContent = "";
        isValidRoutingNumber = true;
      }
    }

    const isValid = [
      isValidHolderName,
      isValidAccountNumber,
      isValidRoutingNumber,
    ].every((isValidValue) => isValidValue);

    if (!isValid) {
      return null;
    }

    return {
      achHolderName,
      achAccountNumber,
      achRoutingNumber,
      achAccountType,
    };
  },

  actions: {
    onSelectRecord(record) {
      this.set("selectedRecord", record);
      this.set("resultToken", null);
      this.setURLs(record);
      this.setSubscriptionIdAndVendor(record);

      if (this.isSupportedStripe()) {
        this.renderStripeElements();
      }
    },
    onSyncToPaymentService() {
      try {
        const subscriptionId = this.subscriptionId;
        if (!this.resultToken || !this.resultToken.token) {
          throw new Error("Missing Token data");
        }
        const tokenData = {
          ...this.resultToken,
          subscriptionId,
          vendor: this.vendor,
        };
        console.log("===== Sync to Payment Service =====\n", {
          ...tokenData,
          token: obfuscateToken(tokenData.token),
          vendor: this.vendor,
        });
        this.set("isClickedToSync", true);

        //Getting Add Token Custom Action
        const customActions = this.store
          .peekAll("custom-action")
          .filter((c) => c.name === "Add Token");

        console.log("===== CustomAction is retreived =====\n");

        //Setting the customerActionValues with the tokenData
        customActions[0].fields.forEach((f) => {
          f.customActionValue = tokenData[f.fieldName];
        });

        console.log("===== CustomAction Fields are set =====\n");

        if (!this.selectedRecord) {
          this.selectedRecord = {};
        }

        //Triggering CustomAction
        this.customAction.triggerCustomAction(
          customActions[0],
          [this.selectedRecord],
          tokenData
        );

        console.log("===== CustomAction is triggered =====\n");
      } catch (error) {
        console.error(
          "Internal Error: Failed to sync to Payment Service:\n",
          error
        );
      }
    },
    async onSubmitToCreateStripeCard(event) {
      event.preventDefault();
      const { value: cardHolderName } = document.getElementById(
        ELEMENT_IDS.STRIPE_CARD_HOLDER_NAME
      );
      let stripeCardNameErrorElement = document.getElementById(
        ELEMENT_IDS.STRIPE_CARD_HOLDER_NAME_ERROR
      );
      if (!cardHolderName) {
        stripeCardNameErrorElement.textContent =
          "Please input card's owner name";
      } else {
        stripeCardNameErrorElement.textContent = "";
        try {
          this.set("isCreatingStripeCard", true);
          const { value: cardName } = document.getElementById(
            ELEMENT_IDS.STRIPE_CARD_HOLDER_NAME
          );
          const { stripe, stripeCard } = this;
          const { paymentMethod: cardData } = await stripe.createPaymentMethod({
            type: "card",
            card: stripeCard,
            billing_details: { name: cardName },
          });
          this.set("isCreatingStripeCard", false);
          this.onCreatedStripeCardToken(cardData, cardName);
        } catch (error) {
          let stripeCardErrorElement = document.getElementById(
            ELEMENT_IDS.STRIPE_CARD_ERROR
          );
          stripeCardErrorElement.textContent = error.message;
        }
      }
    },
    onSubmitToCreateStripeACH(event) {
      event.preventDefault();
      const achValues = this.validateStripeACHForm();
      if (!achValues) {
        return;
      }

      try {
        this.set("isCreatingStripeACH", true);
        Stripe.bankAccount.createToken(
          {
            country: STRIPE_ACH_DEFAULT_VALUE.BANK_COUNTRY_CODE,
            currency: STRIPE_ACH_DEFAULT_VALUE.CURRENCY,
            account_holder_name: achValues.achHolderName,
            account_number: achValues.achAccountNumber,
            routing_number: achValues.achRoutingNumber,
            account_holder_type: achValues.achAccountType,
          },
          (status, response) => {
            if (response.error) {
              throw error;
            }
            this.set("isCreatingStripeACH", false);
            this.onCreatedStripeACHToken(response, achValues);
          }
        );
      } catch (error) {
        let stripeCardErrorElement = document.getElementById(
          ELEMENT_IDS.STRIPE_CARD_ERROR
        );
        stripeCardErrorElement.textContent = error.message;
      }
    },
  },
});

Okey could you try to update your component to

// v1.5.0: Set Stripe as Default Vendor

import Component from "@ember/component";
import { observer } from "@ember/object";
import { scheduleOnce } from "@ember/runloop";
import { inject as service } from "@ember/service";
import $ from "jquery";
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { loadExternalStyle, loadExternalJavascript } from 'client/utils/smart-view-utils';

const CARD_STYLE = {
  base: {
    color: "#54BD7E",
    fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
    fontSmoothing: "antialiased",
    fontSize: "14px",
    "::placeholder": {
      color: "#aab7c4", // --color-beta-on-surface_light
    },
  },
  invalid: {
    color: "#FB6669",
    iconColor: "#FB6669",
  },
};

const ELEMENT_IDS = {
  STRIPE_CARD_ELEMENT: "stripe-card-element",
  STRIPE_CARD_ERROR: "stripe-card-errors",
  STRIPE_CARD_HOLDER_NAME: "stripe-card-holder-name",
  STRIPE_CARD_HOLDER_NAME_ERROR: "stripe-card-holder-name-error",

  STRIPE_ACH_HOLDER_NAME: "stripe-ach-holder-name",
  STRIPE_ACH_ACCOUNT_NUMBER: "stripe-ach-account-number",
  STRIPE_ACH_ROUTING_NUMBER: "stripe-ach-routing-number",
  STRIPE_ACH_ACCOUNT_TYPE: "stripe-ach-account-type",
  STRIPE_ACH_HOLDER_NAME_ERROR: "stripe-ach-holder-name-error",
  STRIPE_ACH_ACCOUNT_NUMBER_ERROR: "stripe-ach-account-number-error",
  STRIPE_ACH_ROUTING_NUMBER_ERROR: "stripe-ach-routing-number-error",
};

const PAYMENT_METHOD = {
  CARD: "CARD",
  ACH: "ACH",
  PAD: "PAD",
};
const PAYMENT_METHOD_VENDOR = {
  STRIPE: "stripe",
  PAYIX: "payix",
};
const STRIPE_ACH_DEFAULT_VALUE = {
  BANK_COUNTRY_CODE: "US",
  CURRENCY: "USD",
};

const obfuscateToken = (token) =>
  token.includes("_")
    ? token.replace(/^(.*)_((.{3}).*(.{3}))$/, "$1_$3***$4")
    : token.replace(/^(.{3})(.*)(.{3})$/, "$1***$3");

export default class extends Component {
  @service() customAction;
  @service() store;

  @tracked selectedRecord = null;
  @tracked resultToken = null;

  @tracked stripe = null;
  @tracked isLoadedStripe = false;
  @tracked stripeCard = null;
  @tracked isCreatingStripeCard = false;
  @tracked isCreatingStripeACH = false;
  @tracked isClickedToSync = false;
  @tracked stripePublicKey = null;
  @tracked payixIframeCardAchURL = null;
  @tracked payixIframePadURL = null;
  @tracked subscriptionId = null;
  @tracked vendor = null;

  constructor(...args) {
    super(...args);

    console.log(`===== Smart view: ${this.viewList?.name} =====`);
  }

  didInsertElement() {
    this.setDefaultSelectedRecord();

    this.onCreatedPayixToken = this.onCreatedPayixToken.bind(this);
    window.addEventListener("message", this.onCreatedPayixToken);
  }

  willRemoveElement() {
    window.removeEventListener("message", this.onCreatedPayixToken);
  }

  @action
  onRecordsChange() {
    this.setDefaultSelectedRecord();
  }

  isSupportedStripe() {
    return this.vendor === PAYMENT_METHOD_VENDOR.STRIPE;
  }

  setURLs(data) {
    this.payixIframeCardAchURL = data["forest-payix_iframe_card_ach_url"];
    this.payixIframePadURL = data["forest-payix_iframe_pad_url"];
    this.stripePublicKey = data["forest-stripe_public_key"];
  }

  setSubscriptionIdAndVendor(record) {
    this.subscriptionId = record["forest-subscription"]["id"];
    this.vendor = record["forest-subscription"]["forest-vendor"];
  }

  setDefaultSelectedRecord() {
    if (this.records && this.records.recordData) {
      this.subscriptionId = this.records.recordData.id;
      this.vendor = PAYMENT_METHOD_VENDOR.STRIPE;
      if (this.records.recordData.__data) {
        this.setURLs(this.records.recordData.__data);
        //Setting the vendor here again as if it's a Canadian User
        //The Vendor should be Payix not Stripe
        if (this.records.recordData.__data["forest-vendor"]) {
          this.vendor = this.records.recordData.__data["forest-vendor"];
        }
      }
    }

    if (!this.selectedRecord && this.records) {
      if (this.records.firstObject) {
        this.selectedRecord = this.records.firstObject;
        this.setURLs(this.records.firstObject);
        this.setSubscriptionIdAndVendor(this.records.firstObject);
      }

      if (!this.stripe) this.loadPlugins();
    }
  }

  loadPlugins() {
    scheduleOnce("afterRender", this, async () => {
      try {
        const stripePublicKey = this.stripePublicKey;
        await loadExternalJavascript('//js.stripe.com/v2/');
        await loadExternalJavascript('//js.stripe.com/v3/');

        Stripe.setPublishableKey(stripePublicKey); // v2
        const stripe = Stripe(stripePublicKey); // v3
        this.stripe = stripe;
        this.isLoadedStripe = true;

        if (this.isSupportedStripe()) {
          this.renderStripeElements();
        }
      } catch (error) {
        console.error("Internal Error: Failed to load Stripe:\n", error);
      }
    });
  }

  renderStripeCard() {
    const { stripe } = this;
    const elements = stripe.elements();
    const stripeCard = elements.create("card", { style: CARD_STYLE });
    stripeCard.mount(`#${ELEMENT_IDS.STRIPE_CARD_ELEMENT}`);

    stripeCard.on("change", function(event) {
      let errorElement = document.getElementById(ELEMENT_IDS.STRIPE_CARD_ERROR);
      if (event.error) {
        errorElement.textContent = event.error.message;
      } else {
        errorElement.textContent = "";
      }
    });
    this.stripeCard = stripeCard;
  }

  renderStripeElements() {
    if (!this.stripe) return;
    this.renderStripeCard();
  }

  onCreatedStripeCardToken(cardData, cardName) {
    try {
      const {
        id,
        billing_details: {
          address: { postal_code },
        },
        card: { brand, last4, exp_month, exp_year },
      } = cardData;
      const expiry = `${exp_year}-${("0" + exp_month).slice(-2)}-01`;
      const resultToken = {
        paymentMethod: PAYMENT_METHOD.CARD,
        name: cardName,
        token: id,
        last4,
        type: brand,
        expiry,
        billingZip: postal_code,
      };
      console.log("===== Created Stripe Card Token =====\n", {
        ...resultToken,
        token: obfuscateToken(resultToken.token),
      });
      this.resultToken = resultToken;
    } catch (error) {
      console.error(
        "Internal Error: Failed to add new Card with Stripe:\n",
        error
      );
    }
  }

  onCreatedStripeACHToken(achData, achValues) {
    try {
      const {
        id,
        bank_account: { last4, bank_name },
      } = achData;
      const resultToken = {
        paymentMethod: PAYMENT_METHOD.ACH,
        token: id,
        last4,
        bankName: bank_name,
        name: achValues.achHolderName,
        type: achValues.achAccountType,
      };
      console.log("===== Created Stripe ACH Token =====\n", {
        ...resultToken,
        token: obfuscateToken(resultToken.token),
      });
      this.resultToken = resultToken;
    } catch (error) {
      console.error(
        "Internal Error: Failed to add new ACH with Stripe:\n",
        error
      );
    }
  }

  onCreatedPayixToken(event) {
    try {
      const isAddedWithPayixSuccessfully =
        event.data &&
        event.data.token !== "" &&
        event.data.token !== null &&
        event.data.token !== undefined;
      if (isAddedWithPayixSuccessfully) {
        const {
          token,
          nameOnCard,
          nameOnAch,
          nameOnPad,
          cardBrand,
          expiryDate,
          lastFourDigits,
          billingZip,
          bankName,
        } = event.data;
        const isCard = !!nameOnCard;
        const isACH = !isCard && !!nameOnAch;
        const isPAD = !isCard && !isACH && !!nameOnPad;
        let resultToken;

        if (isCard) {
          const expiry = expiryDate.replace(/(\d{2})\/(\d{4})/, "$2-$1-01");
          resultToken = {
            paymentMethod: PAYMENT_METHOD.CARD,
            name: nameOnCard,
            token,
            last4: lastFourDigits,
            type: cardBrand,
            expiry,
            billingZip,
          };
        } else if (isACH) {
          resultToken = {
            paymentMethod: PAYMENT_METHOD.ACH,
            name: nameOnAch,
            token,
            last4: lastFourDigits,
            bankName,
          };
        } else if (isPAD) {
          resultToken = {
            paymentMethod: PAYMENT_METHOD.PAD,
            name: nameOnPad,
            token,
            last4: lastFourDigits,
            bankName,
          };
        }

        if (resultToken) {
          console.log(
            `===== Created Payix ${resultToken.paymentMethod} Token =====\n`,
            {
              ...resultToken,
              token: obfuscateToken(resultToken.token),
            }
          );
          this.resultToken = resultToken;
        }
      }
    } catch (error) {
      console.error(
        "Internal Error: Failed to add new payment method with Payix:\n",
        error
      );
    }
  }

  validateStripeACHForm() {
    const { value: achHolderName } = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_HOLDER_NAME
    );
    const { value: achAccountNumber } = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_ACCOUNT_NUMBER
    );
    const { value: achRoutingNumber } = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_ROUTING_NUMBER
    );
    const { value: achAccountType } = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_ACCOUNT_TYPE
    );
    const holderNameErrorElement = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_HOLDER_NAME_ERROR
    );
    const accountNumberErrorElement = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_ACCOUNT_NUMBER_ERROR
    );
    const routingNumberErrorElement = document.getElementById(
      ELEMENT_IDS.STRIPE_ACH_ROUTING_NUMBER_ERROR
    );

    let isValidHolderName = false;
    if (!achHolderName) {
      holderNameErrorElement.textContent =
        "Please input Account ownner's fullname";
    } else {
      holderNameErrorElement.textContent = "";
      isValidHolderName = true;
    }

    let isValidAccountNumber = false;
    if (!achAccountNumber) {
      accountNumberErrorElement.textContent = "Please input Account number";
    } else {
      const isValidAccountNumberByStripe = Stripe.bankAccount.validateAccountNumber(
        achAccountNumber,
        STRIPE_ACH_DEFAULT_VALUE.BANK_COUNTRY_CODE
      );
      if (!isValidAccountNumberByStripe) {
        accountNumberErrorElement.textContent =
          "Your Account number is invalid";
      } else {
        accountNumberErrorElement.textContent = "";
        isValidAccountNumber = true;
      }
    }

    let isValidRoutingNumber = false;
    if (!achRoutingNumber) {
      routingNumberErrorElement.textContent = "Please input Routing number";
    } else {
      const isValidRoutingNumberByStripe = Stripe.bankAccount.validateRoutingNumber(
        achRoutingNumber,
        STRIPE_ACH_DEFAULT_VALUE.BANK_COUNTRY_CODE
      );
      if (!isValidRoutingNumberByStripe) {
        routingNumberErrorElement.textContent =
          "Your Routing number is invalid";
      } else {
        routingNumberErrorElement.textContent = "";
        isValidRoutingNumber = true;
      }
    }

    const isValid = [
      isValidHolderName,
      isValidAccountNumber,
      isValidRoutingNumber,
    ].every((isValidValue) => isValidValue);

    if (!isValid) {
      return null;
    }

    return {
      achHolderName,
      achAccountNumber,
      achRoutingNumber,
      achAccountType,
    };
  }

  @action
  onSelectRecord(record) {
    this.selectedRecord = record;
    this.resultToken = null;
    this.setURLs(record);
    this.setSubscriptionIdAndVendor(record);

    if (this.isSupportedStripe()) {
      this.renderStripeElements();
    }
  }

  @action
  onSyncToPaymentService() {
    try {
      const subscriptionId = this.subscriptionId;
      if (!this.resultToken || !this.resultToken.token) {
        throw new Error("Missing Token data");
      }
      const tokenData = {
        ...this.resultToken,
        subscriptionId,
        vendor: this.vendor,
      };
      console.log("===== Sync to Payment Service =====\n", {
        ...tokenData,
        token: obfuscateToken(tokenData.token),
        vendor: this.vendor,
      });
      this.isClickedToSync = true;

      //Getting Add Token Custom Action
      const customActions = this.store
        .peekAll("custom-action")
        .filter((c) => c.name === "Add Token");

      console.log("===== CustomAction is retreived =====\n");

      //Setting the customerActionValues with the tokenData
      customActions[0].fields.forEach((f) => {
        f.customActionValue = tokenData[f.fieldName];
      });

      console.log("===== CustomAction Fields are set =====\n");

      if (!this.selectedRecord) {
        this.selectedRecord = {};
      }

      //Triggering CustomAction
      this.customAction.triggerCustomAction(
        customActions[0],
        [this.selectedRecord],
        tokenData
      );

      console.log("===== CustomAction is triggered =====\n");
    } catch (error) {
      console.error(
        "Internal Error: Failed to sync to Payment Service:\n",
        error
      );
    }
  }

  @action
  async onSubmitToCreateStripeCard(event) {
    event.preventDefault();
    const { value: cardHolderName } = document.getElementById(
      ELEMENT_IDS.STRIPE_CARD_HOLDER_NAME
    );
    let stripeCardNameErrorElement = document.getElementById(
      ELEMENT_IDS.STRIPE_CARD_HOLDER_NAME_ERROR
    );
    if (!cardHolderName) {
      stripeCardNameErrorElement.textContent =
        "Please input card's owner name";
    } else {
      stripeCardNameErrorElement.textContent = "";
      try {
        this.isCreatingStripeCard = true;
        const { value: cardName } = document.getElementById(
          ELEMENT_IDS.STRIPE_CARD_HOLDER_NAME
        );
        const { stripe, stripeCard } = this;
        const { paymentMethod: cardData } = await stripe.createPaymentMethod({
          type: "card",
          card: stripeCard,
          billing_details: { name: cardName },
        });
        this.isCreatingStripeCard = false;
        this.onCreatedStripeCardToken(cardData, cardName);
      } catch (error) {
        let stripeCardErrorElement = document.getElementById(
          ELEMENT_IDS.STRIPE_CARD_ERROR
        );
        stripeCardErrorElement.textContent = error.message;
      }
    }
  }

  @action
  onSubmitToCreateStripeACH(event) {
    event.preventDefault();
    const achValues = this.validateStripeACHForm();
    if (!achValues) {
      return;
    }

    try {
      this.isCreatingStripeACH = true;
      Stripe.bankAccount.createToken(
        {
          country: STRIPE_ACH_DEFAULT_VALUE.BANK_COUNTRY_CODE,
          currency: STRIPE_ACH_DEFAULT_VALUE.CURRENCY,
          account_holder_name: achValues.achHolderName,
          account_number: achValues.achAccountNumber,
          routing_number: achValues.achRoutingNumber,
          account_holder_type: achValues.achAccountType,
        },
        (status, response) => {
          if (response.error) {
            throw error;
          }
          this.isCreatingStripeACH = false;
          this.onCreatedStripeACHToken(response, achValues);
        }
      );
    } catch (error) {
      let stripeCardErrorElement = document.getElementById(
        ELEMENT_IDS.STRIPE_CARD_ERROR
      );
      stripeCardErrorElement.textContent = error.message;
    }
  }
}
1 Like

@vince just noticed this and we’re having the same issue as well our smart actions in smart views has stopped working

Yeah I’m working on a fix. It should be live in an hour I hope

The fix is being released right now. I’ll let you know as soon as it is live

1 Like

The fix is live, please let me know if it works for you @Zero and @Lucas_Aquino.

If it doesn’t, I would require your component and template to be able to fix it :pray:

Looks all good now thank you!

1 Like