Charge

The charge flow is the ability to charge credit cards from the back office, by adding your application's Payment Processing Page inside the inTandem UI as an iFrame.

Embedding your Payment Processing Page

inTandem embeds your Payment Processing Page iFrame inside the Charge window by requesting the iFrame page from GET {REDIRECT_URI}/charge?pivot_id={PIVOT_ID}.

As you can see, we'll also append a "pivot_id" query param to the {redirect_uri}/charge route ,so you can identify the business when the iFrame loads.

Charge events

Interacting with the iFrame is done via JavaScript postMessage.
Once the user places all the required information inside the iFrame (card number, expiration dates, etc.) and clicks the Charge button, inTandem will emit a JavaScript postMessage with the following data message object:

{
  type: 'generic', 
  func: 'getToken', 
  params: {
    amount: number,
    save_card: boolean,
    pivot_id: string, // same as business_uid
    client_id: string,
    currency: string
  } 
}

In return, we are expecting a token. This token will be used throughout the payment process to identify the transaction.

const messageObj = {
  type: 'generic',
  token: {TOKEN}
}
window.parent.postMessage(messageObj, '*');

Charge postMessage

Here's an example of how you can listen to the Charge postMessage event and send back a token

window.addEventListener(
        'message',
        (event) => {
           if (event.data.type === 'generic' && event.data.func === 'getToken') {
            // Do some credit card number validations
            const cardValidationErrors = validateCard(); // Can be a function that returns an array of errors
            // if card validations checks error
            if (cardValidationErrors.length > 0) {
              const messageObj = {
                type: 'generic',
                func: 'validationFailure'
              }
              window.parent.postMessage(messageObj, '*')
              // present the errors in the iFrame
              return;
              // If the card checks correctly with no issues
            } else {
              const token = {TOKEN}
              const messageObj = {
                type: 'generic',
                token: {TOKEN}
              }
              window.parent.postMessage(messageObj, '*');
              // Store token and payment details in your database for later reference
              return;
            }
          }
        }
      )

POST /charge

Once the token is received, inTandem sends a POST request to your application's {redirect_uri}/charge, containing the transaction details:
POST {redirect_uri}/charge

{
    "amount": 10,
    "currency": "USD",
    "token": "addtkthQ16trAsldSar50v6sLfdmuQ",
    "description": "30 minutes phone call",
  	"customer_id": "49v0ud9YhquOoYTczn0PkwdRn9QRb7" // customer_id will only be provided if a card was saved during the session. See below "Card on file" section
}

Note that the "token" in the request payload corresponds to the token you initially passed in the postMessage from the iFrame.

Your app processes the payment with the payment gateway, and upon successful payment, you'll respond with a charge_key value:

{
    "charge_key": "DzlrBcilbnvBd48gca8um3AkNHoj85"
}

The Charge flow ends when we are successfully receiving the charge_key value.

๐Ÿ“˜

charge_key

The charge_key can be later used for the Refund process.

Thank You page

The payment dialog closes and a success page will be displayed.

Failed transactions

Upon transaction failure, you can send an error response (instead of โ€˜charge_keyโ€™) with the error message to be presented to the user.

{
    "error": "ERROR MESSAGE",
    "error_data": {
    "message": "error_message"    
  }
}

๐Ÿ“˜

Payment errors

error: error message to be displayed in the payment dialog.
error_data.message: the error message that will be displayed in the payment page when viewing the payment from the Payments page.