PaymentFrame is a TranSafe feature that allows you to embed a secure iframe containing a payment form on an HTTPS-enabled web page. This prevents credit card data from ever touching your systems, while allowing your customers to complete seamless ecommerce transactions on your site.
The PaymentFrame can not be embedded into a non-secured HTTP site, even for testing and development purposes, due to content security policies and mixed active content, the browser will silently fail to load the page.
PCI Notice: This approach to Ecommerce integration follows the PCI Council's best practices as outlined in https://www.pcisecuritystandards.org/pdfs/best_practices_securing_ecommerce.pdf, and qualifies for SAQ-A.
In order to use the PaymentFrame, you will need to create a non-expiring merchant profile API Key on TranSafe. This API Key needs to at a minimum contain the admin permission
TICKETREQUEST
. If you are using the same API Key for the follow-up actions, it must contain any necessary permissions for those actions.
Examples for PaymentFrame implementation and styling are available at bitbucket.org/i3verticals/transafe-iframe-examples with a live demo at iframe.test.transafe.com.
Prepare your credentials: Before rendering your payment page (the page that will host the iframe), you will need to generate a 256-bit keyed-hash message authentication code (HMAC-SHA256) See the HMAC Parameters section.
Add iframe element and components: Your html payment page must include an empty iframe element (with no src attribute specified) with a unique id which will be referenced by the JavaScript where you would like the payment form to appear. The HMAC message components (along with the HMAC itself from step 1) must be included as data- attributes on the iframe element. Note: The order in which the data attributes are concatenated for the HMAC message must match the order of the parameters in the list in the HMAC Parameters section. The ordering is crucial for TranSafe to be able to properly verify the HMAC.
Load script: Your payment page will need to load the PaymentFrame Javascript Library, which provides the client-side logic for generating the iframe.
Load Payment Form: From here you'll just need to write a few lines of your own
Javascript to instantiate a PaymentFrame object and request the iframe. You will
need to define a callback function to be executed after the user's payment information
has been submitted. The basic sequence would be to instantiate PaymentFrame
with the iFrame id and URL for the payment server, define a callback using the
setPaymentSubmittedCallback()
method, and call the request()
method to
load the iFrame.
Submit Cardholder Data: Once the iframe has loaded, it will render a payment form into which the user can enter their payment information. When the user submits the form, their information will be sent directly to the TranSafe server, which will return a CardShield ticket.
Process response: At this point, the callback function that you defined in your Javascript will be executed, receiving a JSON object representing the TranSafe server's response (including the CardShield ticket) as a parameter.
Process the ticket: Once you have a valid ticket then you can communicate directly with
the TranSafe system to run a standard transaction such as as SALE
or a PREAUTH
as defined in the TranSafe API Documentation.
Please ensure these iframe attributes are prefixed with
data-
when using our standard PaymentFrame javascript to display the iFrame as the javascript library uses this prefix to determine the attributes used by the PaymentFrame and sent in the request to the Payment Server.
hmac-hmacsha256
RequiredGenerated HMAC-SHA256 using the API Key Secret as the key. The message must be a concatenation (with no delimiters) of all of the other hmac- values you are providing, in the same order in which they appear in this list (with the exception of this attribute)
hmac-timestamp
RequiredStandard Unix timestamp. Must be within 15 minutes of server's time.
hmac-domain
RequiredThe domain of the page embedding the iframe. This must match exactly what would show in the browser URL bar, including 'https://' (and port, if it is explicitly set). Please note that using 'http://' will NOT work due to Content Security Policies and Mixed Active Content.
hmac-sequence
RequiredMerchant-specified sequence number. May be alphanumeric.
hmac-auth_apikey_id
RequiredThe API key ID that is being used to authenticate with the payment server
hmac-css-url
URL of CSS file the iframe should load. It must be served from the same domain as hmac-domain
. If no CSS URL is provided, the payment form will be rendered with default styling (see Styling the Payment Form for more information).
hmac-include-cardholdername
Indicates whether the cardholder name field should be present on the payment form. Value can be "yes" or "no". Defaults to "yes" if not provided. Only provide "no" here if cardholder name is collected elsewhere during your checkout process, and sent along with the ticket in the TranSafe sale request.
hmac-include-street
Indicates whether the street address field should be present on the payment form. Value can be "yes" or "no". Defaults to "yes" if not provided. Only provide "no" here if street address is collected elsewhere during your checkout process, and sent along with the ticket in the TranSafe sale request.
hmac-include-zip
Indicates whether the zip code field should be present on the payment form. Value can be "yes" or "no". Defaults to "yes" if not provided. Only provide "no" here if zip code is collected elsewhere during your checkout process, and sent along with the ticket in the TranSafe sale request.
hmac-expdate-format
Format of expiration date the iframe should use. Options: single-text
: Free-form text entry. Default if not specified. separate-selects
: Separate dropdown select
elements for month and year. coupled-selects
: Dropdown select
elements for month and year in a containing div
.
hmac-cardholdername-format
Single or split cardholder name. Choices: separate-firstlast
: Split the cardholder name field into separate first and last name inputs. combined-firstlast
: Use a single cardholder name input.
hmac-auto-reload
Indicates whether checkout page containing payment form should auto-reload every 15 minutes in order to avoid the HMAC becoming invalid due to the time it was generated. Value can be 'yes' or 'no'. Defaults to 'no' if not provided. If 'yes', users will see a message on the checkout form (starting approximately 5 minutes before the reload) indicating that the page will be reloaded soon for security purposes. The message will include a timer that counts down the time remaining until the reload occurs.
hmac-autocomplete
Indicates whether browser autocomplete should be enabled on the payment form. Value can be 'yes' or 'no'. Defaults to 'yes' if not provided. If 'yes', payment form fields will allow autocomplete (as long as the user's browser settings are configured to allow it, which is generally the default). If 'no', autocomplete will be disabled on the payment form fields.
hmac-include-submit-button
Indicates whether the payment form should include a submit button within the iframe. Defaults to 'yes' if not provided. If you would like to use a submit button on your own page outside of the iframe, set this value to 'no'. You would then use Javascript to send a message to the iframe to trigger a form submit. See The PaymentFrame Javascript Library
hmac-ach-enabled
Whether to display an ACH payment form in the iframe. Value can be 'yes' or 'no'. Defaults to 'no' if not provided (meaning a credit card payment form will be displayed).
hmac-ach-accounttype
Which ACH account type options should be allowed, and the order in which they will appear. Should be provided as a comma-separated list of values. Options are "business", "personal", "checking", and "savings". Options will be displayed to user in two separate select
elements, one for selecting "business" or "personal" and another for selecting "checking" or "savings". The order of these options (and therefore which options are the default choices) will match the order in which they are provided in this list. If ACH is enabled and this value is not provided, the allowed options will default to "personal"/"business" and "checking/savings". If ACH is not enabled, this value has no effect and should not be provided.
hmac-altpaymentinit-enabled
BetaMust be set to 'yes' in order to enable external payment methods such as PayPal. If enabled, will generate a separate HMAC value that is used to initialize external payment methods.
If you account has 3DS enabled, and some or all of the 3DS field values are already known
prior to rendering the payment form, you specify these values by setting data-
attributes
on the iframe
that will contain the payment form. Once the payment form is requested,
these fields will be passed along with the request and included in the payment form as hidden
input
tags.
3D Secure data fields are not part of the HMAC process.
For example, if the customer's shipping address is collected in an earlier checkout step, it can
be passed into the iframe like so (note the data-3ds
attributes following the required data-hmac
attributes):
<iframe id="my-iframe-id"
data-hmac-hmacsha256="2f46a6407581b4153b97f589fbb321cc13c2fc84c122226991ea95e2aac08c3e"
data-hmac-domain="https://merchantsite.com"
data-hmac-timestamp="1685470601"
data-hmac-sequence="64763d89e3aa2"
data-hmac-auth_apikey_id="P0052319E456B379E"
data-3ds-ship_addr_line_1="123 Main St"
data-3ds-ship_addr_line_2="Apt 1B"
data-3ds-ship_addr_city="Miami"
data-3ds-ship_addr_state="FL"
data-3ds-ship_addr_post_code="33132"
data-3ds-ship_addr_country="USA">
</iframe>
Alternatively, if 3DSecure fields are collected on the same page, you can pass them into the iframe using the add3dsData
Javascript method (see The PaymentFrame Javascript Library)
Below are the 3DSecure-specific fields. They should be prefixed with data-3ds-
when passed into the iframe as attributes.
Name | Description |
---|---|
cardholdername |
Cardholder name (if not included in iframe payment form) |
bill_addr_city |
Billing address city |
bill_addr_country |
ISO 3166-1 numeric three-digit country code of the billing address |
bill_addr_line_1 |
Line 1 of billing street address (if not included in iframe payment form) |
bill_addr_line_2 |
Line 2 of billing street address (if not included in iframe payment form) |
bill_addr_line_3 |
Line 3 of billing street address (if not included in iframe payment form) |
bill_addr_post_code |
Billing address zip/postal code (if not included in iframe payment form) |
bill_addr_state |
Billing address state |
email |
Email address |
home_phone_countrycode |
Home phone country code |
home_phone_number |
Home phone number |
mobile_phone_countrycode |
Mobile phone country code |
mobile_phone_number |
Mobile phone number |
ship_addr_city |
Shipping address city |
ship_addr_country |
ISO 3166-1 numeric three-digit country code of the shipping address |
ship_addr_line_1 |
Line 1 of shipping street address |
ship_addr_line_2 |
Line 2 of shipping street address |
ship_addr_line_3 |
Line 3 of shipping street address |
ship_addr_post_code |
Shipping address zip/postal code |
ship_addr_state |
Shipping address state |
work_phone_countrycode |
Work phone country code |
work_phone_number |
Work phone number |
purchase_amount |
Total amount of the purchase |
purchase_currency |
3-digit ISO 4217 currency code in which purchase amount is expressed |
The iframe
content can be styled using custom CSS. You can use the classes and IDs
documented below in your CSS to style the payment form and the elements it contains.
You can also provide custom text for the form's labels by specifying appropriate CSS rules.
Each label contains an empty span element, so that you can use the ::before
selector in
conjunction with the content
property to insert your desired text into the label. For example,
in order to provide custom text for the ZIP code label, you would use a CSS rule similar to the
following:
#payment-zip-label span::before {
content: "Custom text here";
}
If you do not provide custom text for any label, it will default to the value referenced in the "IDs" table below.
Class | Description |
---|---|
payment-form-label |
Applied to all label elements in the payment form. Each of these elements contains an input or select element into which payment data will be entered. |
payment-expdate-label |
If hmac-expdate-format is set to separate-selects or coupled-selects , this will be applied to the two label elements that contain the select drop-downs for expiration date month and year. |
payment-cardholdername-label |
If hmac-cardholdername-format is set to separate-firstlast , this will be applied to the two label elements that contain the first and last name text entry fields. |
payment-ach-accounttype-container |
If ACH is enabled, this will be applied to div elements that each contain a label and select for selecting ACH account type |
ID | Description |
---|---|
monetra-payment-form |
The payment form element |
payment-account-label |
The label containing the account (credit card number) input element. Label text defaults to 'Card Number'. |
payment-expdate-container |
If hmac-expdate-format is set to coupled-selects , this is the div that contains the two select elements. |
payment-expmonth-label |
If hmac-expdate-format is set to separate-selects or coupled-selects , this is the label that contains the expiration month select element. Label text defaults to 'Expiration Month'. |
payment-expyear-label |
If hmac-expdate-format is set to separate-selects or coupled-selects , this is the label that contains the expiration year select element. Label text defaults to 'Expiration Year'. |
payment-expdate-label |
If hmac-expdate-format is set to single-text , this is the label that contains the 'expdate' (expiration date) input element. Label text defaults to 'Expiration Date'. |
paymentcardholdername-label |
The label containing the 'cardholdername' input element. Label text defaults to 'Cardholder Name'. |
paymentcardholdernamefirstlabel |
If hmac-cardholdername-format is set to separate-firstlast , this is the label that contains the first name field. Label text defaults to Cardholder First Name. |
paymentcardholdernamelastlabel |
If hmac-cardholdername-format is set to separate-firstlast , this is the label that contains the last name field. Label text defaults to Cardholder Last Name. |
payment-street-label |
The label containing the 'street' (street address) input element. Label text defaults to 'Street Address'. |
payment-zip-label |
The label containing the 'zip' (ZIP code) input element. Label text defaults to 'ZIP Code'. |
payment-cv-label |
The label containing the 'cv' (card verification value) input element. Label text defaults to 'CV'. |
payment-submit-button |
The button element used to submit the form. |
payment-ach-accountlabel |
label element containing ACH account number input |
payment-ach-account |
ACH account number input |
payment-ach-accountconfirm-label |
label element containing ACH account number confirmation input |
payment-ach-accountconfirm |
ACH account number confirmation input |
payment-ach-routinglabel |
label element containing ACH routing number input |
payment-ach-routing |
ACH routing number input |
payment-achcardholdername-label |
label element containing ACH account holder name input |
payment-achcardholdername |
ACH account holder name input |
payment-achaccounttype-ownerlabel |
label element containing select element for selecting Business or Personal ACH account type |
payment-achaccounttype-ownerselect |
select element for selecting Business or Personal ACH account type |
payment-achaccounttype-purposelabel |
label element containing select element for selecting Checking or Savings ACH account type |
payment-achaccounttype-purposeselect |
select element for selecting Checking or Savings ACH account type |
The PaymentFrame Javascript library provides a PaymentFrame object that can be used to set up and configure your PaymentFrame instance.
The object can be instantiated as follows:
paymentFrame = new PaymentFrame(
"my-iframe-id",
https://test.transafe.com"
);
The first argument is the ID of the <iframe>
element on your checkout page that will contain
the PaymentFrame payment form.
The second argument is the domain of the payment server you are using to generate the PaymentFrame.
In the above example, the <iframe>
element has an ID of "my-iframe-id", and the
payment server is https://test.transafe.com.
Once you have instantiated the PaymentFrame object, you can utilize the following methods to set callback functions, request the payment form from the payment server, and trigger events within the iframe when necessary.
setPaymentFormLoadedCallback(Function callback)
Set a function that will be triggered once the payment form has loaded within the iframe. Useful if any action should be taken on the host checkout page after the iframe has finished loading.
paymentFrame.setPaymentFormLoadedCallback(function() {
console.log("Payment form has loaded");
});
setFormSubmissionInvalidCallback(Function callback)
Set a function that will be triggered if the user submits the payment form, and the form's data is determined to be invalid. This could be due to required fields that are missing, or fields that are formatted incorrectly. The iframe will highlight any erroneous fields within the payment form, but this function allows the host checkout page to take additional action as needed.
paymentFrame.setFormSubmissionInvalidCallback(function() {
console.log("Form submission was invalid");
});
setPaymentSubmittedCallback(Function callback)
Set a function that has been triggered after the payment form has been submitted and a response has been received from the payment server. The callback will receive an object containing the response data returned by the payment server. This response will indicate whether a ticket was successfully generated, and if so, the response will also contain the ticket.
paymentFrame.setPaymentSubmittedCallback(function(response) {
if (response.code === "AUTH") {
console.log("Ticket received:", response.ticket);
} else {
console.log("Error:", response.verbiage);
}
});
request()
This method is used to request the iframe payment form from the payment server. Once you have instantiated the PaymentFrame object and set any desired callback functions, you must call this method to render the payment form.
paymentFrame.request();
submitPaymentData()
Depending on the layout of your payment page, you might wish to use your own submit button for the payment form rather than use the one shown in the iframe by default. If you have configured the iframe to hide its default submit button, use this method to trigger a submit of the iframe payment form.
var submitButton = document.getElementId("my-submit-button");
submitButton.addEventListener("click", function() {
paymentFrame.submitPaymentData();
});
enableSubmitButton()
By default, once the iframe-generated payment form is submitted, its submit button is disabled. This is to prevent users from clicking the submit button multiple times and potentially generating multiple payment requests. Some integrations may require the submit button to be re-enabled in certain circumstances, such as a user's card declining, in which case the user would need to enter a different card and try again.
Use this method to re-enable the iframe's submit button after submission.
paymentFrame.enableSubmitButton();
If you have 3DSecure (3DS) enabled on your account, there are additional methods you can use that are specific to 3DS-enabled integrations.
add3dsData(Object data)
This method can be used to pass 3DS field data to the iframe. From there it will be added to the payment form and used for 3DS authorization. The method accepts a plain object consisting of 3DS field names and values.
var customerEmailField = document.getElementById("customer-email-field");
customerEmailField.addEventListener("change", function() {
paymentFrame.add3dsData({ email: customerEmailField.value });
});
set3dsDataResultsCallback(Function callback)
When the iframe receives 3DS data from the host page, it will send a response indicating whether it was able to successfully add the 3DS data to the payment form. This method sets a callback function that will be triggered whenever one of these responses is received. The callback will receive results data as an object with the following keys:
valid
: Boolean, whether or not the message was structured correctly.fieldResults
: Array of objects with results for each field included in the message. Object keys:
fieldName
: The provided field nameadded
: Boolean, whether the field was added to the formmessage
: "Field added" if the field was added; otherwise, the reason why it wasn't addedpaymentFrame.set3dsDataResultsCallback(function(response) {
if (response.valid) {
for (let result of response.fieldResults) {
if (result.added) {
console.log("Field", result.fieldName, "was added.");
}
}
} else {
console.log("3DS data was structured incorrectly");
}
});
The PaymentFrame supports PayPal Checkout, and may support additional external payment options in the future. The following methods are specific to integrations that have at least one external payment option enabled.
setExternalPaymentInitiatedCallback(Function callback)
Set a function that will be triggered if the user initiates an external payment flow, such as PayPal.
paymentFrame.setExternalPaymentInitiatedCallback(function() {
console.log("External payment flow started");
});
setExternalPaymentCanceledCallback(Function callback)
Set a function that will be triggered if the user cancels an external payment flow that was previously initiated, such as PayPal.
paymentFrame.setExternalPaymentCanceledCallback(function() {
console.log("External payment flow canceled");
});
setExternalPaymentCompletedCallback(Function callback)
Set a function that will be triggered if the user completes an external payment flow, such as PayPal.
paymentFrame.setExternalPaymentCompletedCallback(function() {
console.log("External payment flow completed");
});
addOrderDetails(Object data)
This method can be used to pass order data into the iframe. If applicable, this data will be applied to the order. The method accepts a plain object consisting of field names and values. Currently, the only valid order data field that can be used here is amount
(used to provide a required dollar amount to external payment flows such as PayPal).
paymentFrame.addOrderDetails({ amount: "99.99" });
enableExternalPaymentButtons()
Once an external payment flow is completed, any external payment buttons (such as a PayPal button) in the payment form are disabled, to prevent the user from restarting the flow before the response is processed by the payment server. After the response has been processed, depending on the contents of the response and on the checkout flow of the host site, integrators may want to re-enable the external payment buttons.
Use this method to re-enable external payment buttons in the payment form.
paymentFrame.enableExternalPaymentButtons();