Transaction Processing Workflow

Keyed, Swiped & Recharged (Instant) Transactions

These types of transactions work in a traditional, synchronous manner: an HTTP request is sent to the PayJunction API and a response indicating if the transaction was successful or not is immediately returned.

TIP: Some HTTP libraries will throw an exception if the HTTP status code sent back is not a 'successful' status code. For example, if the wrong API credentials are supplied, a response of "401 Unauthorized" is returned by the PayJunction API server. This is also the code if the wrong Application Key is sent. It is therefore important to capture the body of the response when catching the exception to see the specific error message.

Example POST request

NOTE: POST data must be sent in the x-www-form-urlencoded format, i.e. "param1=value1&param2=value2". Depending on the HTTP library used, you might either need to manually create the string or set the Content-Type header to "application/x-www-form-urlencoded" to tell the library how to format the data.

REQUEST (API Client->PayJunction Server):


RESPONSE (PayJunction Server->API Client):

201 Created 
{ "transactionId": "124", "uri": "", ... , "response": { "approved": false, "code": "05", "message": "Do Not Honor", ... }, ... }

In both of our above examples, the client sends an HTTP request to the PayJunction server and the server responds with the requested information or an error response if there was an issue.

Example GET request

REQUEST (API Client->PayJunction Server):


RESPONSE (PayJunction Server->API Client):

200 OK
{ "transactionId": "123", "uri": "", ... , "response": { "approved": true, "code": "00", "message": "Approved", ... }, ... }

Smart Terminal Transactions

NOTE: Documentation for submitting Smart Terminal transaction requests

Transactions processed via the Smart Terminal are handled differently from other transaction requests. In other transaction processing requests, the card information is sent directly to the PayJunction API for processing. However, with the Smart Terminal, we are instead requesting that the hardware unit handle the processing of the transaction. 

For security and EMV compliance, we can't just allow any service to communicate with the Smart Terminal, so all communication needs to be with PayJunction's cloud service. Therefore, we send a request to the Smart Terminal to process a transaction and we get the transaction information afterwards, making this an asynchronous workflow. 

First, we start by making the payment request:

REQUEST (API Client->PayJunction Server):


RESPONSE (PayJunction Server->API Client):

200 OK
{ "requestPaymentId" : "422900dc-25bb-4b56-94f4-d7f5c9646e54" }

At this point, PayJunction handles the communication with the Smart Terminal which then prompts the cardholder to make their payment.

We now have two general paths to getting the results of the transaction on the Smart Terminal: long polling or a webhook. Generally speaking, if you have a native, locally installed application without cloud support you will need to use the long polling technique. More information here: Do I need to use Webhooks or Polling with Smart Terminals? 

Webhook Workflow

Is your product a full SaaS product? This is the workflow you almost assuredly must use. Even if your product only has backend cloud support, we encourage you to consider using this workflow to help ensure transaction data is received and recorded. 

Jump to Long Polling Workflow

TIP: First time working with webhooks in a local development environment? We've got you covered.

Once the payment has been either approved or declined, PayJunction sends a notification to the webhook listener url subscribed to webhooks of type SMARTTERMINAL_TRANSACTION:

REQUEST (PayJunction Server->Webhook Listener):

{ "id":"b3cdd8ab-adc9-43a8-a428-a88e7f50a977", "created":"2016-04-07T18:03:40.158Z", "type":"SMARTTERMINAL_TRANSACTION", "data":{ "requestPaymentId":"422900dc-25bb-4b56-94f4-d7f5c9646e54", "smartTerminalId":"88888888-4444-4444-4444-cccccccccccc", "transactionId":"126" } }

RESPONSE (Webhook Listener->PayJunction Server):

201 Created

A few things to take note of:

  • The requestPaymentId value is the same in the original payment request and in the webhook payload’s data object. This is how we know which Smart Terminal payment request the webhook is in reference to.
  • We received a transactionId parameter and value in the webhook payload's data object.
  • There is no status information supplied for the transaction indicating whether it was approved or declined.
  • We responded to the webhook with a 2xx status code to tell PayJunction the webhook was successfully received and processed. Read the Important Considerations section under Webhooks for more details.

You might be wondering why the transaction details are not included in the webhook payload. While PayJunction encourages you to set up a shared secret for webhooks to verify the data payload is coming from PayJunction, there is no authentication performed. Therefore, to protect our merchants' data, the GET request is required.

We know at this point that the payment request was completed on the Smart Terminal, but we still need to get the actual details of the transaction to see if it was approved or if it was declined and for what reason. In our scenario we are assuming that the webhook listener is able to communicate to the API client that the webhook was received and fetch the transaction details using the transactionId token. Click the link below to move on to fetching the full transaction details with the transactionId token:

Jump to Transaction Details Request

Long Polling Workflow

For non-SaaS (Software as a Service) applications and platforms without cloud support.

Jump to Webhook Workflow


  • BETA: The following API is still in beta. PayJunction is actively seeking integration partners whom need to use this API to support native applications. If you would like to participate please open a developer support ticket and let us know.
  • To prevent busy polling, these requests are rate limited to one request every 2 seconds.
  • If the transaction is cancelled by the cardholder on the Smart Terminal, the response will still list "Pending" as the status. Therefore we recommend an internal timeout of no less than 90 seconds after the initial request is made and the requestPaymentId is returned.

After receiving the response with the requestPaymentId, we can start polling the API to see if the transaction has completed or not. While processing the transaction itself on a Smart Terminal takes only 3.61 seconds (on average), the customer will still need to either sign for the transaction on the screen or enter a PIN number. We should therefore wait at least 10 seconds before beginning the polling. We'll then need to make sure there is at least 2 seconds between each poll to avoid getting rate limited. We can represent this with a bit of pseudo-code:

requestId = "88888888-4444-4444-4444-cccccccccccc"
counter = 0
limit = 45
transactionId = null
while counter <= limit:
    response = get( "" + requestId )
    if response["status"] === "COMPLETE":
        transactionId = response["transactionId"]
counter++ sleep(2000) if transactionId == null: handleRequestTimeout( requestId ) ...

Notice that we are using the limit variable and sleep command to timeout after 90 seconds and make sure we have 2 seconds between requests to stop rate limiting. If we get a status of COMPLETE we grab the transactionId we'll need to get the final transaction details, such as whether it was approved or declined.

REQUEST (API Client->PayJunction Server):


RESPONSE (PayJunction Server->API Client):

200 OK
{ "transactionId": "126", "uri": "", ... , "response": { "approved": true, "code": "00", "message": "Approved", ... }, ... }

Where to go from here?

We of course recommend reading (or at least skimming) all the articles in the Getting Started Guide, but if you're excited to get going and just want the important bits to think about before planning the integration, please consider the following:

PayJunction Account Structures

Unless you're creating a one-off solution for one merchant, who will only ever need one batch, this is a critical read. PayJunction allows the flexible joining of multiple accounts under one login, which is a great feature for accountants and business owners who don't want to keep track of a plethora of login credentials to get access to all the reporting, statements and deposit information available in PayJunction. So why not let them take advantage of that? 

Decline Handling

Still just testing for the basic "approved" or "declined" response? There's a lot of information that can be gleaned by paying attention to specific decline codes returned by the bank, and PayJunction adds a few to that list as well. No one wants to get declines, but they're going to come up from time to time, so why not handle them intelligently? 

Rate Limiting

The dread of SaaS providers everywhere: DDoS attacks. What is a company to do? In our case, PayJunction utilizes multiple data centers and Cloudflare to make sure we can still supply service even in the event of one of these attacks. In order to make sure your requests gets through consistently, keep your error logs free of 429 responses, and smooth transacting for your merchants, make sure to give this a read. If you are using Microsoft's .Net platform or cURL to handle the HTTP requests, this is required reading.