# Poynt Collect

# Overview

How Poynt Collect works:

  1. You need to mount Poynt Collect Javascript on your payment page.
  2. Customer enters sensitive card data via Poynt Collect Javascript's form.
  3. Sensitive data are directly sent to Poynt server.
  4. Poynt will return a nonce back to the browser.
  5. You will pass the nonce back to your server.
  6. Using the nonce your server will call Poynt server and obtain a multi-use token that you can save and perform card transactions.

# Setting up Poynt Collect

This will cover the general flow in setting up and using Poynt Collect:

  1. Refer the below document for developer docs, which will provide guidelines for the necessary code.
  2. Use the businessId and applicationId to mount Poynt Collect to your website.
  3. Using event listeners, handle your success & error cases and test.

Note

This guide uses the URL's for the staging environment. Make sure to change to production URL's when moving to production.

  "https://st.poynt.net/snippet/poynt-collect/bundle-st.js" => "https://poynt.net/snippet/poynt-collect/bundle.js"
  "https://services-st.poynt.net" => "https://services.poynt.net"

# Creating a nonce

Set up Poynt Collect

  1. Include the Poynt Collect script on your page by doing this
<script
  type="text/javascript"
  src= "https://st.poynt.net/snippet/poynt-collect/bundle-st.js"
  async
  defer
></script>

or this

<script>
  const poyntCollect = document.createElement("script");
  poyntCollect.src = "https://st.poynt.net/snippet/poynt-collect/bundle-st.js";
  poyntCollect.async = true;
  poyntCollect.onload = () => {
  // put the upcoming collect initialization steps and create transaction steps here
  };
  document.head && document.head.appendChild(poyntCollect);
</script>
  1. Create an instance of Poynt Collect with the following Javascript (You can find the api-key under Business Profile in Poynt HQ).
var collect = new TokenizeJs("<businessId>", "<applicationId>");
  1. To add the credit card form to your page, create an empty DOM container with an unique ID and pass the ID back to poynt collect. For example:
<html>
<head></head>
<body>
<div id="card-element">
<!-- Credit card form iFrame will be inserted here -->
</div>
<button>Pay</button>
</body>
</html>
  1. Once your page has loaded, use your Poynt Collect instance to mount the iFrame to your container.
collect.mount("card-element", document, options);

# Methods

# collect.mount

collect.mount(domElementId, document, options);
  • domElementId (string): string referencing DOM element where the payment form is added by Poynt
  • document
  • options (object): options for customization of payment form An example of the options object
const options = { 
  iFrame: { 
    width: "500px",
    height: "400px",
    border: "1px",
    borderRadius: "4px",
    boxShadow: "0 7px 14px rgba(50, 50, 93, 0.1), 0 3px 6px rgba(0, 0, 0, 0.08)" 
  },
  style: {
    theme: "default" // theme: "customer", (alternative default theme)
  },
  displayComponents: {
    firstName: false, // toggle these to true if you wish to show the forms
    lastName: false,
    emailAddress: false,
    submitButton: false,
    showEndingPage: true // controls ending page,
    labels: false 
  },
  fields: {
    emailAddress: customerEmail,
    firstName: firstName,
    lastName: lastName 
  }, 
  additionalFieldsToValidate: ["firstName", "lastName", "zip"] // fields to validate
}

# collect.getNonce

Get a nonce from Poynt's api service to use for future api calls. To get the nonce returned from collect.getNonce , refer to event listeners Below is the expected object to pass in to get the nonce. Note any field with a '?' is optional. Input:

interface NoncePayload {
  businessId: string;
}
collect.getNonce(noncePayload);

Output:

{ "nonce" : <token> }

# Event Listeners

# ready

To guarantee that Poynt Collect is ready, listen to this event

collect.on("ready", event => {
// handle ready event, proceed.
});

# getNonce

To add an event listener for getting a nonce

collect.on("get_nonce", function(nonce) {
// do something with the nonce
});

Refer to the below section, on how to get a token using nonce and charge using the token.

# error

To add a listener to get notified for any errors on the form add this.

collect.on("error", event => {
// handle error event
});

# Creating a token

The nonce obtained above will be used in the /tokenize call to get a payment token. The payment token is a JWT. As a part of the response, Poynt will parse you back the AVS, CVV response that processor has provided. It's for you to save the token by interpreting the processor validation response. The tokenize output will also contain the status of the payment token to identify the processor validation status. To obtain the ACCESS_TOKEN, please refer to Requesting access-token documentation.

Request URL: https://services-st.poynt.net/businesses/{businessId}/cards/tokenize
Request method: POST
Request headers: Authorization: bearer <ACCESS_TOKEN>
Request body:

{
  "nonce": "12345678-1234-1234-12345789012"
}

Response body:

{
  "card": {
    "type": "VISA",
    "status": "ACTIVE",
    "expirationMonth": 0,
    "expirationYear": 00,
    "id": 000000,
    "numberFirst6": "000000",
    "numberLast4": "0000",
    "numberMasked": "000000******0000",
    "numberHashed": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "cardId": "11111111-1234-1234-12345789012"
  },
  "applicationId": "urn:aid:12345678-1234-1234-12345789012",
  "token": "<token>",
  "paymentToken": "<Payment JWT>",
  "avsResponse": {
    "addressResult": "MATCH",
    "postalCodeResult": "MATCH"
  },
  "cvvResponse": "MATCH",
  "status" : "ACTIVE"
}

If the processor is unable to verify a card eg: for a invalid Card, Sample tokenize output data will be:

{
  "card": {
    "type": "VISA",
    "status": "ACTIVE",
    "expirationMonth": 00,
    "expirationYear": 00,
    "id": 000000,
    "numberFirst6": "000000",
    "numberLast4": "0000",
    "numberMasked": "000000******0000",
    "numberHashed": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "cardId": "11111111-1234-1234-12345789012"
  },
  "applicationId": "urn:aid:12345678-1234-1234-12345789012",
  "avsResponse": {
    "addressResult": "UNAVAILABLE",
    "postalCodeResult": "UNAVAILABLE"
  },
  "cvvResponse": "NOT_APPLICABLE",
  "status" : "INVALID"
}

# Charging a token

Given a token, one can charge it. This request should originate from your servers and uses the same OAuth2 flow as described here. The payment token JWT obtained from the above will be used to charge the card.
To send a receipt to the customer set the emailReceipt attribute to true and receiptEmailAddress should contain the recipient email id.

Request URL: https://services-st.poynt.net/businesses/{businessId}/cards/tokenize/charge
Request method: POST
Request headers: Authorization: bearer ACCESS_TOKEN
Request body:

{
  "action": "<SALE/AUTHORIZE>",
  "context": {
    "businessId": "12345678-1234-1234-12345789012",
    "storeId": "01234567-1234-1234-12345789012",
    "storeDeviceId": "urn:aid:12345678-1234-1234-12345789012",
  },
  "amounts": {
    "transactionAmount": 300,
    "orderAmount": 300,
    "currency": "USD"
  },
  "fundingSource": {
    "cardToken": "<payment JWT>"
  },
  "emailReceipt" : true,
  "receiptEmailAddress" : "joe@example.com"
}

Response body:

{
    "createdAt": "2020-10-29T18:15:18Z",
    "updatedAt": "2020-10-29T18:26:56Z",
    "context": {
        "businessType": "TEST_MERCHANT",
        "transmissionAtLocal": "2020-03-30T16:55:29Z",
        "storeDeviceId": "urn:aid:12345678-1234-1234-12345789012",
        "mcc": "1234",
        "source": "INSTORE",
        "businessId": "12345678-1234-1234-12345789012",
        "storeId": "12345678-1234-1234-12345789012"
    },
    "fundingSource": {
        "debit": false,
        "card": {
            "cardBrand": {
                "createdAt": "2020-04-15T04:35:31Z",
                "scheme": "VISA",
                "logoUrl": "",
                "displayName": "Visa",
                "id": "11111111-1234-1234-12345789012"
            },
            "type": "VISA",
            "expirationMonth": 00,
            "expirationYear": 0000,
            "id": 000000,
            "numberFirst6": "000000",
            "numberLast4": "0000",
            "numberMasked": "000000******0000",
            "numberHashed": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            "serviceCode": "101",
            "cardId": "11111111-1234-1234-12345789012"
        },
        "entryDetails": {
            "customerPresenceStatus": "MOTO",
            "entryMode": "KEYED"
        },
        "type": "CREDIT_DEBIT",
        "cardToken": "<payment JWT>"
    },
    "customerUserId": 0000,
    "processorResponse": {
       "approvedAmount": 300,
        "emvTags": {
            "0x8A": "3030"
        },
        "processor": "ELAVON",
        "acquirer": "ELAVON",
        "status": "Successful",
        "statusCode": "AA",
        "statusMessage": "APPROVAL",
        "transactionId": "0000000",
        "approvalCode": "00000",
        "batchId": "000"
    },
    "action": "<SALE/AUTHORIZE>",
    "amounts": {
        "transactionAmount": 300,
        "orderAmount": 300,
        "tipAmount": 0,
        "cashbackAmount": 0,
        "currency": "USD"
    },
    "status": "<AUTHORIZED/DECLINED>",
    "id": "c5d3730e-3774-4af6-b513-592249771092"
}

# Passing in custom css (Optional)

Say you would like to pass in custom css values over using default. Below is an example of what you can configure and play around with. Poynt collect uses a library called react-payment-inputs found here: https://github.com/medipass/react-payment-inputs#styles (opens new window)

const options = {
  amount: 2000, 
  customCSS: {
    iFrame: {
      width: "397px",
      height: "150px",
      border: "0"
    },
    fieldWrapper: {
      base: `margin-bottom: 1rem;`
    },
    inputWrapper: {
      base: `border-color: green;`,
      errored: `border-color: maroon;`,
      focused: ` border-color: unset; box-shadow: unset; outline: 1px solid blue; outline-offset: 0px;`
    },
    input: {
      base: `color: green;`,
      errored: `color: maroon;`,
      cardNumber: ` font-family: Roboto, Open Sans, Segoe UI, sans-serif; width: 17rem;`,
      expiryDate: `font-family: Roboto, Open Sans, Segoe UI, sans-serif; text-transform: uppercase; width: 5rem;`,
      cvc: `font-family: Roboto, Open Sans, Segoe UI, sans-serif; width: 3rem;`
    },
    errorText: {
      base: `color: maroon;position: absolute;margin-top: 60px;margin-left: 5px;font-family: Roboto, Open Sans, Segoe UI, sans-serif;`
    }
  }
}
Last Updated: 1/4/2021, 6:09:13 PM