Payment form events

Payment form events
Subscribe to payment form lifecycle events to track user interactions, validate input, handle errors, and respond to payment completion

The events at key points in the payment lifecycle from initial render through approval or decline.

These events provide valuable touchpoints for monitoring and analyzing customer interactions. They track successful payments form initialization and field level behavior across the payment workflow.

By subscribing to these events you can

  • React to UI state changes by showing spinners hiding preloaders and animating containers
  • Build real time analytics and funnel tracking without server side instrumentation
  • Adapt checkout UX dynamically based on the card the customer is entering
  • Handle payment outcomes and redirect users to the appropriate next step
  • Log errors and send diagnostics to monitoring tools like Sentry or Datadog

Subscribe to any event using the SDK method that matches your framework. All event callbacks receive a typed message object.
1
2
3
4
<Payment
    {...restParams}
    onEventName={callback}
/>
1
2
3
4
5
6
const form = PaymentFormSdk.init(data)

form.on('event_type', (e) => {
  const body = e.data // The body of any available event as it described below.
  // The code will be run when the event is received.
})
1
2
3
<Payment
    @event-name="callback"
/>
1
2
3
<ngx-solid-payment
    (eventName)="callback($event)"
/>

Remove event listeners before destroying the form instance or switching payment intents.

  • form.unsubscribeAll() removes all event subscriptions
  • form.unsubscribe("eventName") removes one event subscription
  • Pass the event name you want to stop listening to

Form lifecycle

These events track the major stages of the payment form from initialization to submission and provide feedback on whether the payment process was successful or failed.

Mounted

When the Payment Form, Guide
Add a Google Pay button to your embedded payment form for one-tap checkout on Android devices and Chrome browsers with token security.
Google Pay,
Guide
Add an Apple Pay button to your embedded payment form for one-tap checkout with biometric authentication on supported Apple devices.
Apple Pay,
or Guide
Add alternative payment method buttons to your payment form with customizable styling, placement, and method-specific display conditions.
APM buttons
are initialized, rendered, and displayed.

Use cases

  • Hide a skeleton or preloader and reveal the checkout container
  • Start a session inactivity timer to expire the session after 10 minutes of no interaction
  • Log a form_shown event to your analytics pipeline for funnel tracking
1
2
3
4
interface MountedMessage {
  type: 'mounted',
  entity: 'applebtn' | 'googlebtn' | 'form' | 'resign' | 'bizum' | 'blik' | 'mbway' | 'paypal' | 'pix' | 'pix-qr' | 'clicktopay' | 'cashapp' | 'klarna' | 'upi' // one of listed values; Solidgate may extend this list for new APM buttons
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleMounted = useCallback((event: SdkMessage[MessageType.Mounted]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onMounted={handleMounted}
  />)
}
1
2
3
form.on('mounted', e => {
  const data = e.data // MountedMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @mounted="mounted"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function mounted(event: SdkMessage[MessageType.Mounted]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (mounted)="onMounted($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onMounted(event: SdkMessage[MessageType.Mounted]): void {
    // here your logic
  }
}

Invoice preview

The invoicePreview event reports the calculated invoice for a Billing Guide
Pass Billing-specific fields in paymentIntent for catalog products, subscriptions, and invoices.
checkout
intent. It carries the total, the amount breakdown, and the per-line-item amounts. All amounts are decimal strings, for example “40.00”.

The event arrives only for a payment intent created in checkout flow, with a checkout block and mode subscription or invoice .

The event can fire at two points:

  • Form initialization. PaymentFormSdk.init requests the payment intent, and the event fires as soon as that intent returns with its invoice. The event precedes the mounted event, so subscribe in the same synchronous code block that calls init
  • Billing address change. When the customer enters the ZIP code, country, state, city, or address, Solidgate recalculates the Guide
    Automate sales tax, VAT, and GST calculations with Solidgate to ensure compliance across regions and simplify global tax management.
    tax
    and sends the updated invoice object

The SDK compares each payload with the last one it sent and skips identical payloads. The event does not fire if the address change leaves the invoice unchanged.

Use cases

  • Render an order summary with per-line-item amounts next to the form
  • Show the tax amount added after the customer enters a billing address
  • Match the total on your page with the amount in the wallet payment sheet
  • Send the calculated total to analytics when the form loads
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
interface InvoicePreviewMessage {
  type: 'invoicePreview';
  invoicePreview: CheckoutInvoicePreview;
}

interface CheckoutInvoicePreview {
  total: string; // Total amount due (for example, "40.00")
  currency: string; // ISO 4217 currency code (for example, "USD")
  currencyIcon: string; // Currency symbol (for example, "$")
  amounts?: CheckoutInvoicePreviewAmounts; // Optional, invoice-level breakdown
  lineItems: CheckoutInvoicePreviewLineItem[]; // Empty array when the invoice carries no lines
}

interface CheckoutInvoicePreviewAmounts {
  subtotal: string; // Before discount and tax
  discount: string; // Total discount applied
  unitPrice?: string; // Optional, unit price
  taxable?: string; // Optional, amount subject to tax
  tax?: string; // Optional, tax amount
}

interface CheckoutInvoicePreviewLineItem {
  amount: string; // Line total
  quantity: number;
  currency: string; // Matches the invoice currency
  currencyIcon: string;
  productPriceId: string;
  productId: string;
  amounts?: CheckoutInvoicePreviewAmounts; // Optional, scoped to this line
  tax?: CheckoutInvoicePreviewTax; // Optional, tax applied to this line
}

interface CheckoutInvoicePreviewTax {
  categoryId: string;
  mode: string;
  rate: number;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import React, { FC, useCallback } from 'react'
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleInvoicePreview = useCallback((event: SdkMessage[MessageType.InvoicePreview]) => {
    // Render the order summary from event.invoicePreview
  }, [])

  return (<Payment
    {...props}
    onInvoicePreview={handleInvoicePreview}
  />)
}
1
2
3
4
5
6
7
const form = PaymentFormSdk.init(data)

// Subscribe before the first await, so the initialization event is not missed
form.on('invoicePreview', e => {
  const data = e.data // InvoicePreviewMessage
  // Render the order summary from data.invoicePreview
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @invoice-preview="invoicePreview"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function invoicePreview(event: SdkMessage[MessageType.InvoicePreview]): void {
  // Render the order summary from event.invoicePreview
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (invoicePreview)="onInvoicePreview($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onInvoicePreview(event: SdkMessage[MessageType.InvoicePreview]): void {
    // Render the order summary from event.invoicePreview
  }
}

Submit

Fired when the customer starts payment processing. This is an initiation signal, not a success outcome. Use success or fail for the final result.

The event is emitted for the Payment Form and resign flow, PayPal on Guide
Add alternative payment method buttons to your payment form with customizable styling, placement, and method-specific display conditions.
APM buttons
, and Guide
Add a Google Pay button to your embedded payment form for one-tap checkout on Android devices and Chrome browsers with token security.
Google Pay
/ Guide
Add an Apple Pay button to your embedded payment form for one-tap checkout with biometric authentication on supported Apple devices.
Apple Pay
when started from the card form (DSRP).

Public submit coverage for standalone Guide
Add alternative payment method buttons to your payment form with customizable styling, placement, and method-specific display conditions.
APM buttons
(for example, Pix, Pix QR, Pix Automático, MB WAY, Bizum, Blik, Blik Recurring, UPI, Click to Pay) and for standalone Google Pay is expanding. Until those methods emit submit , use interaction for click tracking and orderStatus / success / fail for payment progress.

Use cases

  • Disable the Pay button to prevent duplicate submissions
  • Show a loading spinner or overlay on the form
  • Record the timestamp for payment latency metrics
  • Lock the order summary UI so the customer cannot change quantity during processing
1
2
3
4
5
6
interface SubmitMessage {
  type: 'submit',
  // Currently emitted for card form, resign, PayPal, and Apple Pay / Google Pay DSRP.
  // Additional APM entities (bizum, blik, mbway, pix, pix-qr, upi, clicktopay, ...) may appear as coverage expands.
  entity: 'applebtn' | 'googlebtn' | 'form' | 'resign' | 'paypal' | 'bizum' | 'blik' | 'mbway' | 'pix' | 'pix-qr' | 'clicktopay' | 'cashapp' | 'klarna' | 'upi'
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleSubmit = useCallback((event: SdkMessage[MessageType.Submit]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onSubmit={handleSubmit}
  />)
}
1
2
3
form.on('submit', e => {
  const data = e.data // SubmitMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @submit="submit"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function submit(event: SdkMessage[MessageType.Submit]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (submit)="onSubmit($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onSubmit(event: SdkMessage[MessageType.Submit]): void {
    // here your logic
  }
}

Card

The card event fires on every valid card number and returns BIN level metadata including brand bin cardType cardCategory bank and binCountry before submit without exposing the PAN CVV expiry or cardholder name.

Use cases

  • Apply dynamic surcharges by adding a fee for CREDIT or AMEX cards before the customer submits
  • Hint at likely decline before submit when payments from this bank can be unavailable
  • Route to a preferred acquirer based on the card scheme and issuing country
  • Adapt UI and pricing and show the card brand logo in real time next to the card number field
  • Prevent declines on risky binCountry mismatches
  • Segment customers by issuer and tier before authorization
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
interface CardMessage {
  type: 'card'
  card: {
    brand: "AMERICAN EXPRESS", // card scheme in upper case: 'VISA', 'MASTERCARD', 'AMERICAN EXPRESS', 'DISCOVER', 'JCB', 'DINERS CLUB', 'UNIONPAY', 'MAESTRO', etc., or 'unknown'
    bin: "377400", // first 6 digits of the PAN as a string
    cardType: "DEBIT", // funding type in upper case: 'CREDIT', 'CREDIT/DEBIT', 'DEBIT', 'PREPAID', 'CHARGE CARD', 'DEFERRED DEBIT', or 'unknown'
    cardCategory: "BUSINESS", // scheme product tier in upper case: 'STANDARD', 'CLASSIC', 'CONSUMER', 'BUSINESS', 'CORPORATE', 'PLATINUM', 'WORLD', 'INFINITE', 'ELECTRON', etc.
    bank: "BANK OF AMERICA", // issuing bank name in upper case (for example, 'BANK OF AMERICA', 'CITIBANK'); empty when not resolved
    binCountry: "USA" // ISO 3-letter country code of the issuing bank (for example, 'USA', 'GBR', 'DEU')
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleCard = useCallback((event: SdkMessage[MessageType.Card]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onCard={handleCard}
  />)
}
1
2
3
form.on('card', e => {
  const data = e.data // CardMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @card="card"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function card(event: SdkMessage[MessageType.Card]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (card)="onCard($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onCard(event: SdkMessage[MessageType.Card]): void {
    // here your logic
  }
}

Wallet card type

The walletCardType event fires inside an Apple Pay or Google Pay flow before the charge and reports the wallet card the payer selected. It includes the wallet that produced the card and the funding type (credit, debit, prepaid, or unknown). It also includes brand and last4 when the wallet exposes them.

The subscriber gets a second argument pauseUntil. Pass it an async callback to act on the wallet card details, for example, update the intent or the UX. Only one subscriber is allowed per form instance. A second form.on('walletCardType', ...) replaces the first.

The wallet flow waits until that promise settles. A rejected callback cancels the wallet payment sheet. The form itself stays fully payable.

Subscribing and calling pauseUntil is the only supported way to change payment details while a wallet sheet is open. form.update() and form.updateCheckout() calls made outside the pauseUntil callback while a payment sheet is open are deferred and dropped entirely.

Use cases

  • Charge a different price for debit and credit cards the payer selects in the wallet sheet
  • Apply a surcharge for prepaid cards before the payer authorizes
  • Reject unwanted funding types by rejecting the callback
  • Send the wallet funding type to analytics without touching the price
Google Pay requires TOTAL_PRICE_STATUS_ESTIMATED in googlePayButtonParams. Under the default TOTAL_PRICE_STATUS_FINAL the pause never starts: pauseUntil is ignored and the cryptogram is submitted immediately.
The callback must settle within 25 seconds of the event, a hard platform limit. Otherwise, the flow is rejected and the payment sheet is closed.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type WalletCardTypeEventName = 'walletCardType'

type WalletCardTypeWallet = 'applePay' | 'googlePay'

type WalletCardTypeFunding = 'credit' | 'debit' | 'prepaid' | 'unknown'

interface WalletCardTypeCard {
  type: WalletCardTypeFunding // always present
  brand?: string // lowercase card network, for example, 'visa'. Display hint, can be absent
  last4?: string // last four digits, can be absent, especially on Apple Pay
}

interface WalletCardTypeEventData {
  wallet: WalletCardTypeWallet
  card: WalletCardTypeCard
}

interface WalletCardTypeEvent {
  data: WalletCardTypeEventData
}

type WalletCardTypeSideEffect = () => Promise<unknown>

type WalletCardTypeSubscriber = (
  event: WalletCardTypeEvent,
  pauseUntil: (sideEffect: WalletCardTypeSideEffect) => void
) => void
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import React, { FC, useState } from 'react'
import Payment, { ClientSdkInstance, InitConfig, WalletCardTypeCallback } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
}> = (props) => {
  const [form, setForm] = useState<ClientSdkInstance | null>(null)

  // required when you update the intent inside the event
  const googlePayButtonParams: InitConfig['googlePayButtonParams'] = {
    totalPriceStatus: 'TOTAL_PRICE_STATUS_ESTIMATED'
  }

  const handleWalletCardType: WalletCardTypeCallback = (data, pauseUntil) => {
    if (data.card.type === 'unknown') {
      return // no intent update, the wallet continues immediately
    }

    pauseUntil(async () => {
      await form?.update({ partialIntent: intentFor(data.card.type) })
    })
  }

  return (<Payment
    merchantData={props.merchantData}
    googlePayButtonParams={googlePayButtonParams}
    onWalletCardType={handleWalletCardType}
    onReadyPaymentInstance={setForm}
  />)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
form.on('walletCardType', (event, pauseUntil) => {
  const { card } = event.data // WalletCardTypeEventData

  if (card.type === 'unknown') {
    return // no intent update, the wallet continues immediately
  }

  pauseUntil(async () => {
    await form.update({ partialIntent: intentFor(card.type) })
  })
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<template>
  <Payment
      :merchant-data="merchantData"
      :google-pay-button-params="googlePayButtonParams"
      :on-wallet-card-type="onWalletCardType"
      @ready-payment-instance="form = $event"
  />
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import Payment, { ClientSdkInstance, InitConfig, WalletCardTypeCallback } from '@solidgate/vue-sdk'

const form = ref<ClientSdkInstance>()

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

// required when you update the intent inside the event
const googlePayButtonParams: InitConfig['googlePayButtonParams'] = {
  totalPriceStatus: 'TOTAL_PRICE_STATUS_ESTIMATED'
}

const onWalletCardType: WalletCardTypeCallback = (data, pauseUntil) => {
  if (data.card.type === 'unknown') {
    return // no intent update, the wallet continues immediately
  }

  pauseUntil(async () => {
    await form.value?.update({ partialIntent: intentFor(data.card.type) })
  })
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import {Component} from '@angular/core';

import {ClientSdkInstance, InitConfig, WalletCardTypeCallback} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      [googlePayButtonParams]="googlePayButtonParams"
      [walletCardType]="onWalletCardType"
      (readyPaymentInstance)="form = $event"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  form: ClientSdkInstance | null = null

  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  // required when you update the intent inside the event
  googlePayButtonParams: InitConfig['googlePayButtonParams'] = {
    totalPriceStatus: 'TOTAL_PRICE_STATUS_ESTIMATED'
  }

  onWalletCardType: WalletCardTypeCallback = (data, pauseUntil) => {
    if (data.card.type === 'unknown') {
      return // no intent update, the wallet continues immediately
    }

    pauseUntil(async () => {
      await this.form?.update({ partialIntent: intentFor(data.card.type) })
    })
  }
}

Rules to follow when updating the order inside the event:

  1. Call pauseUntil synchronously inside the subscriber. Only the first call is applied, any further call is ignored.
  2. You cannot update the currency, it can never change while a sheet is open.

Interaction

Tracks button and input interactions with types click change focus blur enterKeyDown pageClose and resetRequested. Exposes isValid and isTouched per field and form on regular and resign flows. Wallet and Guide
Add alternative payment method buttons to your payment form with customizable styling, placement, and method-specific display conditions.
APM buttons
interactions also cover button clicks and modal close. Event distinction

  • pageClose fires on modal ✕ before submit
  • resetRequested fires on modal ✕ after submit when the Guide
    Add alternative payment method buttons to your payment form with customizable styling, placement, and method-specific display conditions.
    APM button
    has resetEnabled: true

Use cases

  • Track which field users abandon first when drop on cardCvv may indicate UX confusion
  • Show contextual hints on cardExpiryDate focus
  • Monitor cardForm.isValid in real time to progressively enable the Pay button
  • On pageClose show an exit intent modal or save form state
  • On resetRequested destroy the current SDK instance and reinitialize with a new payment intent
  • Feed interaction data to A/B testing tools to compare form layouts
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
interface InteractionMessage {
  type: 'interaction'
  target: { // Indicates source of interaction
    type: 'button' | 'input' // one of the listed
    name: 'submit' | 'applePay' | 'googlePay' | 'clicktopay' | 'cashapp' | 'klarna' | 'bizum' | 'blik' | 'mbway' | 'paypal' | 'pix' | 'pix-qr' | 'upi' | 'cardNumber' | 'cardCvv' | 'cardExpiryDate' | 'cardHolder' | 'email' | 'zipCode' | 'resignCvv'
    // Additional field and APM button names are also possible, for example:
    // 'brazilCpf', 'brazilCustomerPhone', 'brazilZip', 'billingAddress', 'billingCity', 'billingState',
    // 'pakistanCnic', 'blikCode', 'firstName', 'lastName', 'customerPhone', 'pix-automatico', etc.
    interaction: 'click' | 'change' | 'focus' | 'blur' | 'enterKeyDown' | 'pageClose' | 'resetRequested' // one of the listed
  }
  cardForm: { // Indicates current card form state
    fields: {
      cardNumber: {
        isValid: boolean
        isTouched: boolean
      }
      cardCvv: {
        isValid: boolean
        isTouched: boolean
      }
      cardExpiryDate: {
        isValid: boolean
        isTouched: boolean
      }
      // The rest of the fields are optional, including, but not limited to: the `cardHolder` field
    }
    isValid: boolean
    isTouched: boolean
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
interface InteractionMessage {
  type: 'interaction'
  target: { // Indicates source of interaction
    type: 'button' | 'input' // one of the listed
    name: 'submit' | 'resignCvv' // It could be one of the listed; furthermore, Solidgate might extend the list.
    interaction: 'click' | 'change' | 'focus' | 'blur' | 'enterKeyDown' // one of the listed
  }
  resignForm: { // Indicates current resign form state
    fields: {
      resignCvv: {
        isValid: boolean
        isTouched: boolean
      }
    }
    isValid: boolean
    isTouched: boolean
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleInteraction = useCallback((event: SdkMessage[MessageType.Interaction]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onInteraction={handleInteraction}
  />)
}
1
2
3
form.on('interaction', e => {
  const data = e.data // InteractionMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @interaction="interaction"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function interaction(event: SdkMessage[MessageType.Interaction]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (interaction)="onInteraction($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onInteraction(event: SdkMessage[MessageType.Interaction]): void {
    // here your logic
  }
}

Form redirect

Indicates when the form redirects the customer to another page, status, or 3D verification page.

Use cases

  • Show a redirect overlay during bank verification
  • Stop any countdown timers on your page
  • Save the current cart or order state before navigation
  • Prevent the customer from triggering other UI actions while redirect is in progress
1
2
3
interface FormRedirectMessage {
  type: 'formRedirect'
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleRedirect = useCallback((event: SdkMessage[MessageType.Redirect]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onRedirect={handleRedirect}
  />)
}
1
2
3
form.on('formRedirect', e => {
  const data = e.data // FormRedirectMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @redirect="redirect"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function redirect(event: SdkMessage[MessageType.Redirect]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (redirect)="onRedirect($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onRedirect(event: SdkMessage[MessageType.Redirect]): void {
    // here your logic
  }
}

Custom styles appended

If custom styles are in place, this event indicates that the form has become visible to the customer, making it helpful for hiding preloaders.

Use cases

  • Remove skeleton loaders or shimmer effects once the form is fully styled and visible
  • Record time to first render for performance monitoring dashboards
  • Trigger an entrance animation on the checkout container
  • Use instead of mounted when custom styles are configured to avoid a flash of unstyled form
1
2
3
interface CustomStylesAppendedMessage {
  type: 'customStylesAppended'
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleCustomStylesAppended = useCallback((event: SdkMessage[MessageType.CustomStylesAppended]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onCustomStylesAppended={handleCustomStylesAppended}
  />)
}
1
2
3
form.on('customStylesAppended', e => {
  const data = e.data // CustomStylesAppendedMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @custom-styles-appended="customStylesAppended"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function customStylesAppended(event: SdkMessage[MessageType.CustomStylesAppended]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (customStylesAppended)="onCustomStylesAppended($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onCustomStylesAppended(event: SdkMessage[MessageType.CustomStylesAppended]): void {
    // here your logic
  }
}

Payment processing

These events provide insights into the payment process, including 3DS verification, the order status, and details about the payment, like pricing and taxes.

Success

This event indicates that the payment has been successfully processed.

Use cases

  • Show a success modal with the confirmed amount and currency from the order payload
  • Fire a purchase event to Google Analytics 4 Meta Pixel or TikTok Pixel
  • For subscriptions store subscription_id in the user profile for management UI
  • Trigger a post purchase upsell or cross sell flow
  • Clear the cart state from local storage
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
interface SuccessMessage {
  type: 'success',
  entity: 'applebtn' | 'googlebtn' | 'form' | 'resign' | 'bizum' | 'blik' | 'mbway' | 'paypal' | 'pix' | 'pix-qr' | 'clicktopay' | 'cashapp' | 'klarna' | 'upi' // one of listed values, indicates how payment was processed
  order: { // an optional order object
    status: string // an optional order status field
    currency: string // an optional order currency field
    amount: number // an optional order amount field
    subscription_id: string // an optional subscription id field
    order_id: string // an optional order id field
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleSuccess = useCallback((event: SdkMessage[MessageType.Success]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onSuccess={handleSuccess}
  />)
}
1
2
3
form.on('success', e => {
  const data = e.data // SuccessMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @success="success"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function success(event: SdkMessage[MessageType.Success]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (success)="onSuccess($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onSuccess(event: SdkMessage[MessageType.Success]): void {
    // here your logic
  }
}

Verify

This event informs you that the payment is undergoing processing through the 3D flow.

Use cases

  • Tell the customer the bank verifies the payment
  • Keep the form visible and wait for success or fail
  • Show a progress indicator during the 3DS wait
  • Log 3DS initiation and completion for funnel analytics
1
2
3
interface VerifyMessage {
  type: 'verify'
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleVerify = useCallback((event: SdkMessage[MessageType.Verify]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onVerify={handleVerify}
  />)
}
1
2
3
form.on('verify', e => {
  const data = e.data // VerifyMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @verify="verify"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function verify(event: SdkMessage[MessageType.Verify]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (verify)="onVerify($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onVerify(event: SdkMessage[MessageType.Verify]): void {
    // here your logic
  }
}

Fail

This event indicates that the payment had been declined.

Use cases

  • Map decline codes to friendly retry messages
  • Offer Google Pay or another APM button after a decline
  • Keep the form open and prefilled for quick retry
  • Log the decline code and entity for decline analysis
  • Track decline rates by entity across form , applebtn and googlebtn
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
interface FailMessage {
  type: 'fail'
  entity: 'applebtn' | 'googlebtn' | 'form' | 'resign' | 'bizum' | 'blik' | 'mbway' | 'paypal' | 'pix' | 'pix-qr' | 'clicktopay' | 'cashapp' | 'klarna' | 'upi' // one of listed values, indicates how payment was processed
  code: string // an optional error code from https://docs.solidgate.com/payments/payments-insights/error-codes/
  message: string // an optional error message field
  order: { // an optional order object
    status: string // an optional order status field
    currency: string // an optional order currency field
    amount: number // an optional order amount field
    subscription_id: string // an optional subscription id field
    order_id: string // an optional order id field
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleFail = useCallback((event: SdkMessage[MessageType.Fail]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onFail={handleFail}
  />)
}
1
2
3
form.on('fail', e => {
  const data = e.data // FailMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @fail="fail"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function fail(event: SdkMessage[MessageType.Fail]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (fail)="onFail($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onFail(event: SdkMessage[MessageType.Fail]): void {
    // here your logic
  }
}

Order status

This event indicates that the order status was changed while processing. However, the event may not show all changes before the final order Guide
Follow card payment orders through each processing stage with clear status definitions, available actions, and real-time event tracking.
status
approved or declined .

The response can be either the updated card order Webhook or the updated alternative order Webhook , depending on which payment method was used during payment.

Use cases

  • Show step by step progress for Pix BLIK and iDEAL while waiting for bank confirmation
  • Update a status badge in real time as the order moves through processing states
  • Display a countdown or polling indicator when the customer must complete an APM buttons action
  • Log intermediate states for debugging slow or stuck payments
1
2
3
4
5
interface OrderStatusMessage {
  type: 'orderStatus',
  entity: 'applebtn' | 'googlebtn' | 'form' | 'resign' | 'bizum' | 'blik' | 'mbway' | 'paypal' | 'pix' | 'pix-qr' | 'clicktopay' | 'cashapp' | 'klarna' | 'upi', // one of listed values, indicates how payment was processed
  response: object // Partial order status response.
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleOrderStatus = useCallback((event: SdkMessage[MessageType.OrderStatus]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onOrderStatus={handleOrderStatus}
  />)
}
1
2
3
form.on('orderStatus', e => {
  const data = e.data // OrderStatusMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @order-status="orderStatus"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function orderStatus(event: SdkMessage[MessageType.OrderStatus]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (orderStatus)="onOrderStatus($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onOrderStatus(event: SdkMessage[MessageType.OrderStatus]): void {
    // here your logic
  }
}

Payment details

This event informs of updates or changes to payment details, including price, Guide
Automate sales tax, VAT, and GST calculations with Solidgate to ensure compliance across regions and simplify global tax management.
taxes,
and other relevant information, enabling comprehensive tracking of customer actions through the events generated.

To change order parameters from your application call Guide
Update payment form parameters such as amount, currency, and product_id using the partialIntent object and form.update method.
form.update()
or Guide
Replace checkout line items, discounts, and trial terms on an initialized Billing checkout form using the form.updateCheckout method.
form.updateCheckout()
instead of relying on this event alone.

Use cases

  • Render a dynamic price summary with tax next to the form
  • Update the Pay button label with the final charge amount
  • Show the trial period price for subscription products before the customer commits
  • Display the discount amount and original price when a coupon has been applied
  • Reactively update the price display when the customer switches between plans
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
interface PaymentDetailsMessage {
  type: 'paymentDetails';
  payment: {
    priceBreakdown: PriceBreakdown;
  };
}

interface PriceBreakdown {
  productPrice: {
    amount: string;
    currency: string;
    currencyIcon: string;
  }; // Base price
  discountPrice?: {
    amount: string;
    currency: string;
    currencyIcon: string;
  }; // Optional, after discount
  trialPrice?: {
    amount: string;
    currency: string;
    currencyIcon: string;
  }; // Optional, price without discount (if available)
  price: {
    source: "productPrice" | "discountPrice" | "trialPrice";
    amount: string; // Final price amount based on the selected source (for example, "100.00")
    taxAmount: string; // Tax amount applied (2% of taxableAmount, for example, "2.00")
    taxRate: number; // Fixed tax rate (2.0)
    taxableAmount: string; // Amount subject to tax (for example, "100.00")
    currency: string; // ISO 4217 currency code (for example, "USD")
    currencyIcon: string; // Currency symbol (for example, "$")
  };
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handlePaymentDetails = useCallback((event: SdkMessage[MessageType.PaymentDetails]) => {
    // Validate the event structure and handle the payment details logic
  }, [])

  return (<Payment
    {...props}
    onPaymentDetails={handlePaymentDetails}
  />)
}
1
2
3
4
form.on('paymentDetails', e => {
  const data = e.data // PaymentDetailsMessage
  // Add validation logic for data if needed
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @payment-details="paymentDetails"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function paymentDetails(event: SdkMessage[MessageType.PaymentDetails]): void {
  // Validate event structure and handle payment details here
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (paymentDetails)="onPaymentDetails($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onPaymentDetails(event: SdkMessage[MessageType.PaymentDetails]): void {
    // Validate and handle payment details here
  }
}

Technical

Technical events track form resizing and errors to support proper adaptation and debugging.

Resize

When the Payment Form is resized.

Use cases

  • Smoothly animate the checkout container height to match the new form dimensions
  • Recalculate scroll position if the form is embedded in a scrollable panel
  • Adjust a sticky summary panel that is positioned relative to the form

It may resize after displaying a validation message.


1
2
3
4
5
interface ResizeMessage {
  type: 'resize'
  width: number
  height: number
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleResize = useCallback((event: SdkMessage[MessageType.Resize]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onResize={handleResize}
  />)
}
1
2
3
form.on('resize', e => {
  const data = e.data // ResizeMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @resize="resize"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function resize(event: SdkMessage[MessageType.Resize]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (resize)="onResize($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onResize(event: SdkMessage[MessageType.Resize]): void {
    // here your logic
  }
}

Error

Indicates an error during form initialization or processing. The following Error classes are provided:

  • ConnectionError - happens when the customer experiences problems with their internet connection.
  • InitPaymentError - happens when an error with payment intent occurs during initialization.
    The message contains a strict object with code and an explanation of the particular error. Additionally, it includes a details field, allowing you to create different handlers for different errors. The following error codes are supported (details.code):
  • GatewayError - occurs when Solidgate cannot parse the response from its backend, please contact support.
  • Guide
    Cardholder authentication was not successful to complete the payment.
    1.01
    - Invalid credentials or signature generated.
  • Guide
    “Invalid data” code message is used for validation errors, with the reason for the validation triggering specified in the body (object error) of the response.
    2.01
    - Invalid data in payment intent.
    It could be a non-existing product ID or other properties, which is described in a message. Provides detailed description in details.message by pair key from payment intent with corresponding error message.
  • Guide
    An unrecognized decline code was received during the transaction.
    6.01
    - Something went wrong on the backend side, please contact support.

Use cases

  • On ConnectionError show a connection warning with retry
  • On InitPaymentError code 2.01 log details.message to your backend for field validation errors
  • On InitPaymentError code 1.01 alert your backend team when credentials or signature are wrong
  • Send the full error object to Sentry or Datadog for all errors
  • Show a graceful fallback UI instead of a broken form
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
interface ErrorMessage {
  type: 'error'
  value: {
    name: string; // "ConnectionError" | "InitPaymentError" | "GatewayError"
    message: string;
  }
  details?: {
    code: string; // 1.01, 2.01, 6.01 from https://docs.solidgate.com/payments/payments-insights/error-codes/
    message: {
      [key: string]: string
    } | string; // Object for 2.01, otherwise string
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import React, { FC, useCallback } from 'react'
import ReactDOM from 'react-dom';
import Payment, { InitConfig, SdkMessage, MessageType } from "@solidgate/react-sdk"

export const MyPayment: FC<{
  merchantData: InitConfig['merchantData']
  styles?: InitConfig['styles']
  formParams?: InitConfig['formParams']
  width?: string
}> = (props) => {
  const handleError = useCallback((event: SdkMessage[MessageType.Error]) => {
    // here logic
  }, [])

  return (<Payment
    {...props}
    onError={handleError}
  />)
}
1
2
3
form.on('error', e => {
  const data = e.data // ErrorMessage
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <Payment
      :merchant-data="merchantData"
      @error="error"
  />
</template>

<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { InitConfig, SdkMessage, MessageType } from '@solidgate/vue-sdk'
const Payment = defineAsyncComponent(() => import('@solidgate/vue-sdk'))

const merchantData: InitConfig['merchantData'] = {
  merchant: '<<--YOUR MERCHANT ID-->>',
  signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
  paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
}

function error(event: SdkMessage[MessageType.Error]): void {
  // here your logic
}
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {Component} from '@angular/core';

import {InitConfig, SdkMessage, MessageType} from "@solidgate/angular-sdk";

@Component({
  selector: 'app-root',
  template: `
    <ngx-solid-payment
      [merchantData]="merchantData"
      (error)="onError($event)"
    ></ngx-solid-payment>
  `
})
export class AppComponent {
  merchantData: InitConfig['merchantData'] = {
    merchant: '<<--YOUR MERCHANT ID-->>',
    signature: '<<--YOUR SIGNATURE OF THE REQUEST-->>',
    paymentIntent: '<<--YOUR PAYMENT INTENT-->>'
  }

  onError(event: SdkMessage[MessageType.Error]): void {
    // here your logic
  }
}


Looking for help? Contact us
Stay informed with Changelog