{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"redocly_category":"Documentation","type":"markdown"},"seo":{"title":"FramePay events","description":"Learn about FramePay events.","siteUrl":"https://www.rebilly.com","image":"/assets/rebillysocial.94fb32fc280c9e84b963c440ec462771d25f4e6fdaaa6c59de41e8135113b46b.db81178d.png","lang":"en-US","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]},"keywords":"Developer docs, FramePay"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"framepay-events","__idx":0},"children":["FramePay events"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["FramePay uses events to notify state changes or errors."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["FramePay emits global events that are used in all configurations, and element events that are used in payment card and bank account configurations."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"global-events","__idx":1},"children":["Global events"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To listen for global events, use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Framepay.on()"]}," method."," ","To unsubscribe from an event, use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Framepay.off()"]}," method."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"error","__idx":2},"children":["error"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["FramePay emits this event when there is a problem during its initialization."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Listen to this event to detect network or configuration errors:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"Framepay.initialize({\n  /* configuration */\n});\n\nFramepay.on('error', (err) => {\n  // err\n  // {\"code\":\"network-error\",\"type\":\"error\",\"message\":\"Initialization Error\",\"details\":[...]}\n});\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"ready","__idx":3},"children":["ready"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After initializing FramePay, use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ready"]}," event to start mounting the element, or elements, of your selected payment methods."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example, if you are setting up ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["payment card"]}," method, call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Framepay.card.mount"]}," when FramePay is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ready"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"Framepay.initialize({ /* configuration */ });\n\nFramepay.on('error', (err) => {\n    ...\n})\n\n// This event will not be emitted if there are configuration errors\nFramepay.on('ready', () => {\n    const card = Framepay.card.mount('#mount-point');\n})\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"token-ready","__idx":4},"children":["token-ready"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When using a digital wallet method such as Google Pay, Apple Pay or PayPal, the token data is captured by listening to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["token-ready"]}," event."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For most payment methods, a token is created by calling ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["createToken"]}," when a user submits the form."," ","Digital wallets are express methods and do not require data from the host form."," ","They automatically create a token after the user has completed the wallet flow, and emit a 'token-ready' event."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"Framepay.on('token-ready', (token) => {\n  // Token is ready to be consumed by other Rebilly APIs\n});\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Google Pay™ and Apple Pay methods provide a second parameter that can be used to hold additional data."," ","For example, details of shipping information."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"Framepay.on('token-ready', (token, extraData) => {\n  // Access to the shipping address in here\n  const { shippingDetails } = extraData;\n  console.log(shippingDetails);\n});\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"shipping-address-changed","__idx":5},"children":["shipping-address-changed"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When using Google Pay™ and Apple Pay digital wallet methods, and the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/dev-docs/shipping-configuration-in-express-methods"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["shipping configuration"]}]}," is enabled, the shipping address data is captured by listening to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["shipping-address-changed"]}," event."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The event receives the selected shipping address as the first parameter, and a function is provided as the second parameter to accept or reject the selected shipping address."," ","Optionally, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["shippingOptions"]}," can be updated with new options."," ","Also optionally, new ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["lineItems"]}," and new ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["amount"]}," can be provided."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"const US_SHIPPING = [\n  {\n    id: 'free-shipping',\n    label: 'Free shipping',\n    description: 'Arrives in 5 to 7 days',\n    amount: 0,\n  },\n];\n\nconst INTERNATIONAL_SHIPPING = [\n  {\n    id: 'international-shipping',\n    label: 'International shipping',\n    description: 'Arrives in 20 to 30 days',\n    amount: 10,\n  },\n];\n\nFramepay.on('shipping-address-changed', (shippingAddress, updateShippingOptions) => {\n  if (shippingAddress.country === 'US') {\n    updateShippingOptions({ status: 'success', shippingOptions: US_SHIPPING });\n  } else {\n    updateShippingOptions({\n      status: 'success',\n      shippingOptions: INTERNATIONAL_SHIPPING,\n      lineItems: [\n        {\n          label: 'Shipping',\n          amount: shippingOption.amount,\n        },\n        {\n          label: 'Tax',\n          amount: '10.99',\n        },\n      ],\n      amount: calculateNewTotalAmount(),\n    });\n  }\n});\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If you do not ship to the given location, provide an unsuccessful response."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"const US_SHIPPING = [\n  {\n    id: 'free-shipping',\n    label: 'Free shipping',\n    description: 'Arrives in 5 to 7 days',\n    amount: 0,\n  },\n];\n\nconst INTERNATIONAL_SHIPPING = [\n  {\n    id: 'international-shipping',\n    label: 'International shipping',\n    description: 'Arrives in 20 to 30 days',\n    amount: 10,\n  },\n];\n\nFramepay.on('shipping-address-changed', (shippingAddress, updateShippingOptions) => {\n  if (shippingAddress.country === 'US') {\n    updateShippingOptions({ status: 'fail' });\n    /**\n     - Optional details\n     - updateShippingOptions({ status: 'fail', details: { reason: 'NO_SHIPPING', message: 'Do not have shipping provider' } });\n     */\n  } else {\n    updateShippingOptions({ status: 'success', shippingOptions: INTERNATIONAL_SHIPPING });\n  }\n});\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more information, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://developer.apple.com/documentation/apple_pay_on_the_web/applepayerrorcode"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Apple Pay reference"]}]},", and ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://developers.google.com/pay/api/web/reference/response-objects#PaymentDataError"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Google Pay reference"]}]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"shipping-option-changed","__idx":6},"children":["shipping-option-changed"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When using Google Pay™ and Apple Pay digital wallet methods, and the shipping configuration is enabled with shipping method options, selected shipping option data is captured by listening to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["shipping-option-changed"]}," event."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The event receives the selected shipping option as the first parameter, and a function is provided as the second parameter to update the transaction amount and optionally the line items."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"Framepay.on('shipping-option-changed', (shippingOption, updateTransaction) => {\n  // Update the total amount based on the new shipping cost\n  updateTransaction({\n    amount: calculateNewTotalAmount(shippingOption),\n    lineItems: [\n      {\n        label: 'Shipping',\n        amount: shippingOption.amount,\n      },\n      {\n        label: 'Tax',\n        amount: '10.99',\n      },\n    ],\n  });\n});\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"billing-address-changed","__idx":7},"children":["billing-address-changed"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When using the Apple Pay digital wallet method, to capture the billing address before authorizing the transaction, listen to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["billing-address-changed"]}," event."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The event receives the captured billing contact as the first parameter, and a function as the second parameter to update the transaction amount and, optionally, the line items."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Google Pay™ does not reveal the billing address information before authorizing the transaction."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more information, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://developer.apple.com/documentation/apple_pay_on_the_web/applepaypaymentcontact"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Apple Pay reference"]}]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"Framepay.on('billing-address-changed', (billingContact, updateTransaction) => {\n  // Update the total amount based on the new shipping cost\n  updateTransaction({\n    amount: calculateNewTotalAmount(billingContact),\n    lineItems: [\n      {\n        label: 'E-book',\n        amount: '29.99',\n      },\n      {\n        label: 'Tax',\n        amount: '7.99',\n      },\n    ],\n  });\n});\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"element-events","__idx":8},"children":["Element events"]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Note"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This applies only to ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["payment card"]}," and ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["bank account"]}," payment methods."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"em","attributes":{},"children":["Payment card"]}," or ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["bank account"]}," setups require mounting one or more elements after initialization."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For every mounted element, store it in a JavaScript variable and use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["on()"]}," method to listen for events that are emitted when the customer interacts with the element."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example, if you are mounting a ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["payment card"]}," element:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"const card = Framepay.card.mount('#card');\n\n// Use card.on(<eventType>, <handlerFunction>) to listen for element specific events\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["on()"]}," method accepts two arguments:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["eventName"]},": String with the name of the event."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["handler"]},": Callback function triggered by event."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"ready-1","__idx":9},"children":["ready"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Emitted by an element when the related field is loaded in the UI."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Example:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"JavaScript","header":{"controls":{"copy":{}}},"source":"card.on('ready', function() {\n    console.log('Card element is ready to use!');\n});\n","lang":"JavaScript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"error-1","__idx":10},"children":["error"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Emitted by an element when there is a mount problem."," ","For more information, see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"#error"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]}," global event"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Example:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"JavaScript","header":{"controls":{"copy":{}}},"source":"card.on('error', function() {\n    console.log('Card mount error!');\n});\n","lang":"JavaScript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"change","__idx":11},"children":["change"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Emitted whenever the element is changed after the customer's input."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Validation"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["change"]}," event to detect validation errors in the element."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["change"]}," event handler function is the only one that receives an argument. This argument can have these properties:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Change argument property"},"children":["Change argument property"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["source"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["string"]}," with the type of the element where the event was emitted from."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["valid"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Optional ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["boolean"]}," that is present if the element contains valid data (or potentially valid data while the field is focused)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["completed"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Optional ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["boolean"]}," that is present if the element has valid and completed data."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Optional ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["object"]}," that is present if the element has invalid data. It contains these properties: {code, message, type}"]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-use-completed-property-from-change-event","__idx":12},"children":["Example: Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["completed"]}," property from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["change"]}," event"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["change"]}," event to enable the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["submit button"]}," of your checkout form only when the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["combined card"]}," element is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["completed"]},"."," ","That is, when ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["pan"]},", ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["expiration"]},", and ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["CVV"]}," are correct."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"const button = document.getElementById('button-submit');\n\nFramepay.on('ready', function () {\n  const card = Framepay.card.mount('#mounting-point');\n\n  card.on('change', function (changeData) {\n    if (changeData.completed) {\n      button.removeAttribute('disabled');\n    } else {\n      button.setAttribute('disabled', 'disabled');\n    }\n  });\n});\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"/examples/framepay/listening-for-change-event.html"},"children":["Interactive example: listening for change event"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-use-error-property-from-change-event","__idx":13},"children":["Example: Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]}," property from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["change"]}," event"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Display the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]}," messages whenever the input becomes ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["invalid"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"JavaScript","header":{"controls":{"copy":{}}},"source":"\nconst card = Framepay.card.mount('#card');\n\ncard.on('change', function(changeData) {\n  ...\n  if (changeData.error) {\n      document.querySelector('#errors').innerText = error.message;\n  }\n  ...\n});\n","lang":"JavaScript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"focus","__idx":14},"children":["focus"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Emitted when the element is focused."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"blur","__idx":15},"children":["blur"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Emitted when the element is blurred."]}]},"headings":[{"value":"FramePay events","id":"framepay-events","depth":1},{"value":"Global events","id":"global-events","depth":2},{"value":"error","id":"error","depth":3},{"value":"ready","id":"ready","depth":3},{"value":"token-ready","id":"token-ready","depth":3},{"value":"shipping-address-changed","id":"shipping-address-changed","depth":3},{"value":"shipping-option-changed","id":"shipping-option-changed","depth":3},{"value":"billing-address-changed","id":"billing-address-changed","depth":3},{"value":"Element events","id":"element-events","depth":2},{"value":"ready","id":"ready-1","depth":3},{"value":"error","id":"error-1","depth":3},{"value":"change","id":"change","depth":3},{"value":"Example: Use completed property from change event","id":"example-use-completed-property-from-change-event","depth":4},{"value":"Example: Use error property from change event","id":"example-use-error-property-from-change-event","depth":4},{"value":"focus","id":"focus","depth":3},{"value":"blur","id":"blur","depth":3}],"frontmatter":{"seo":{"title":"FramePay events","description":"Learn about FramePay events.","keywords":"Developer docs, FramePay","lang":"en-US"},"redirects":{"/docs/content/dev-docs/concept/events/":{},"/docs/developer-docs/framepay/events/":{},"/docs/content/concepts-and-features/concept/events/":{},"/docs/concepts-and-features/concept/events/":{}},"excludeFromSearch":true},"lastModified":"2026-01-12T11:16:51.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/dev-docs/events","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}