Keyed, Swiped and Recharged (Instant) Transactions
These types of transactions work in a traditional, synchronous manner: an HTTP request is sent to the PayJunction API and a success or fail response 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. Therefore, it is 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¶m2=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 to PayJunction Server):
POST https://api.payjunctionlabs.com/transactions cardNumber=4444333322221111&cardExpMonth=12&cardExpYear=2020&baseAmount=1.00&terminalId=654321
RESPONSE (PayJunction Server to API Client):
201 Created { "transactionId": "124", "uri": "https://api.payjunctionlabs.com/transaction/124", ... , "response": { "approved": false, "code": "05", "message": "Do Not Honor", ... }, ... }
In both 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 to PayJunction Server):
GET https://api.payjunctionlabs.com/transactions/123
RESPONSE (PayJunction Server to API Client):
200 OK { "transactionId": "123", "uri": "https://api.payjunctionlabs.com/transactions/123", ... , "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. For other transaction processing requests, the card information is sent directly to the PayJunction API for processing. With the Smart Terminal, the hardware unit handles transaction processing.
For security and EMV compliance, all Smart Terminal communication needs to occur within 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 to PayJunction Server):
POST https://api.payjunctionlabs.com/smartterminals/88888888-4444-4444-4444-cccccccccccc/request-payment amountBase=1.00&terminalId=654321&invoiceNumber=10000201256
RESPONSE (PayJunction Server to API Client):
200 OK { "requestPaymentId" : "422900dc-25bb-4b56-94f4-d7f5c9646e54" }
Payment requests will return the id as the requestPaymentId. All other requests to a Smart Terminal, such as a signature capture request, will return the id as the requestId.
At this point, PayJunction handles the communication with the Smart Terminal, which then prompts the cardholder for payment.
We have two paths for getting transaction results from 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 can be found here: Do I need to use Webhooks or Polling with Smart Terminals?
Webhook Workflow
For full SaaS and backend cloud support products, we encourage you to use the webhook workflow to ensure transaction data is received and recorded.
WEBHOOK SUBSCRIPTIONS ARE LIMITED TO 5 PER PJMID
For more information on PayJunction account structures, see the PayJunction Account Structures guide.
TIP: Is this your first time working with webhooks in a local development environment? We've got you covered.
Once the request to the Smart Terminal is received, status notifications will be sent to the URL subscribed to the SMARTTERMINAL_REQUEST webhook:
REQUEST (PayJunction Server to Webhook Listener):
POST https://your.server.address.com/webhooks/smartterminal-transaction {
"created": "2018-02-20T20:30:01.756Z",
"data": {
"requestId": "422900dc-25bb-4b56-94f4-d7f5c9646e54",
"status": "CONNECTING"
},
"id": "835a3fe6-a7e2-4872-9206-1ed28c4476e6",
"type": "SMARTTERMINAL_REQUEST"
}
RESPONSE (Webhook Listener to PayJunction Server):
201 Created
A few things to note:
- The requestId is the same value in the webhook payload’s data object as the requestPaymentId in our original payment request. This is how we know which Smart Terminal payment request the webhook is referring to.
- 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.
The status progression as the request is processed on the Smart Terminal is CONNECTING, IN_PROGRESS, and COMPLETE. BUSY will be the status if the Smart Terminal receiving the request is not yet ready to accept a new request. Please remember, PayJunction cannot guarantee that the status progression will arrive in exactly that order which should be taken into consideration when designing your solution.
If the request is a payment request, the transactionId parameter will be returned once an approval or decline has been issued. If the request is a signature capture request, the signatureId parameter will be returned instead:
Payment Request
{ id: 'd3519001-1793-427e-b83d-c5d7ed63d560', created: '2018-09-06T18:00:34.860Z', type: 'SMARTTERMINAL_REQUEST', data: { requestId: '1a3b780c-b4d1-4f7f-8a78-b5a329316233', transactionId: 6705, status: 'COMPLETE' } }
Signature Capture Request
{ id: '366692ca-2db0-452f-8582-967a83149486', created: '2018-09-06T17:36:31.982Z', type: 'SMARTTERMINAL_REQUEST', data: { requestId: 'a3a2a721-5811-42fe-baf8-e9e87375c474', signatureId: 'f573a6d12e7d400abb41ad578f301438', status: 'COMPLETE' } }
For more details on the SMARTTERMINAL_REQUEST webhook subscription, please see the full article here.
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 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. 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.
Important:
- BETA: The following API is still in beta. PayJunction is actively seeking integration partners using native applications. If you would like to participate, please open a developer support ticket.
- To prevent busy polling, these requests are rate limited to one request every 1/2 second.
- 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 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 at least a 1/2 second between each poll to avoid getting rate limited. We can represent this with a bit of pseudo-code:
... requestId = "88888888-4444-4444-4444-cccccccccccc" sleep(10000) counter = 0 limit = 45 transactionId = null while counter <= limit: response = get( "https://api.payjunction.com/smartterminals/requests/" + requestId ) if response["status"] === "COMPLETE": transactionId = response["transactionId"] break else:
counter++ sleep(500) if transactionId == null: handleRequestTimeout( requestId ) ...
Notice that we are using the limit variable and sleep command to timeout after 90 seconds and add a 1/2 second between requests to stop rate limiting. If we get a status of COMPLETE, we save the transactionId and use it to get final transaction details, such as whether it was approved or declined.
REQUEST (API Client to PayJunction Server):
GET https://api.payjunctionlabs.com/transactions/126
RESPONSE (PayJunction Server to API Client):
200 OK { "transactionId": "126", "uri": "https://api.payjunctionlabs.com/transactions/126", ... , "response": { "approved": true, "code": "00", "message": "Approved", ... }, ... }
Where to go from here?
We recommend reading all the articles in the Getting Started Guide, but if you only have time for a few articles, 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 multiple login credentials.
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 more to that list. No one wants to get declines, but they're going to come up from time to time, so why not handle them intelligently?
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 maintain services in the event of an attack. To make sure your requests get through consistently, keep your error logs free of 429 responses and give this article a read. If you are using Microsoft's .Net platform or cURL to handle the HTTP requests, this is required reading.