The Smart Terminal supports refunds by setting the action parameter to REFUND when submitting a payment request. Documentation to submit Smart Terminal requests is available here: POST /smartterminals/smartTerminalId/request-payment.
A very common question is, “What is the difference between a Refund and a Void?”. Let’s start with the definitions:
-
REFUND
– Creates a brand new transaction that returns funds to the account holder -
VOID
– Updates an existing transaction so that funds are not captured from the account holder
Rules for a REFUND
:
- The refund amount must not exceed the total amount that has been charged on the card over the previous 12 months.
- PIN Debit transactions must always be refunded, they cannot be voided.
Rules for a VOID
:
- A transaction can be voided before it is settled (Otherwise known as “batched”). If the transaction has already settled, then it must be refunded.
- PIN Debit transactions cannot be voided, they must be refunded.
You always want to VOID
a transaction when possible because it does not create additional transaction fees, but if the transaction has been settled, or the transaction is PIN Debit, then you must issue a refund.
Voiding a Transaction After It Has Been Charged
Note: The transactionId for the transaction that is being voided must be used.
API URI: PUT /transactions/{transactionId} (Click Here for documentation)
Production Request
curl -X PUT -u "login:password" -H "Accept: application/json" -H "X-PJ-Application-Key: YOUR_PRODUCTION_APP_KEY" \
-d "status=VOID" \
"https://api.payjunction.com/transactions/12345"
Remember that you can only VOID
a transaction before it has been settled. Here is a sample error you will receive if you try to VOID
a settled transaction.
{ "errors" : [ { "message" : "Status can not be updated because the Transaction has been settled.", "parameter" : "status", "type" : "invalid" } ], "help" : "http://developer.payjunction.com/documentation/update-a-transaction" }
Refunding a Previously Charged Transaction
API URI: POST /transactions (Click Here for documentation)
- Get the transactionId for the transaction that will be refunded.
- If the amount to refund is not specified, then the amount for the original transaction will be used.
Warning:
In regards to doing partial refunds, using a transactionId as the payment token, it's important to know that if not explicitly stated, any other amount fields from the original charge will be refunded as well. For example, suppose we send a transaction with the following amounts included:
// Process the original charge ... $txn_request['amountBase'] = "100.00";
$txn_request['amountTax'] = "8.50"; ... $result = process($txn_request); // $result['amountTotal'] === "108.50", $result['transactionId'] === "1234567" // Process partial refund ... $refund_request['transactionId'] = "1234567" $refund_request['amountBase'] = "50.00"; ... $result = process($refund_request) // $result['amountTotal'] === "58.50"
So why is our total refund $58.50 instead of $50.00? Because tax was included on the original transaction and since we didn't specify amountTax in the refund request, the API automatically refunded it. The way to get around this is to explicitly send a value for all amount fields to make sure that you get the exact result you were expecting. If you never refund tax/tips/surcharges/shipping you can just zero it all out:
$refund_request['amountTax'] = "0.00"; $refund_request['amountShipping'] = "0.00"; $refund_request['amountSurcharge'] = "0.00"; $refund_request['amountTip'] = "0.00";
Otherwise you'll have to do some logic to set this:
// PHP Example function setRefundAmounts($amountArray, &$req) { $req['amountBase'] = isset($amountArray['amountBase']) ? $amountArray['amountBase'] : "0.00"; $req['amountShipping'] = isset($amountArray['amountShipping']) ? $amountArray['amountShipping'] : "0.00"; $req['amountSurcharge'] = isset($amountArray['amountSurcharge']) ? $amountArray['amountSurcharge'] : "0.00"; $req['amountTip'] = isset($amountArray['amountTip']) ? $amountArray['amountTip']: "0.00"; $req['amountTax'] = isset($amountArray['amountTax']) ? $amountArray['amountTax'] : "0.00"; } $request = Array("transactionId" => "1234567"); setRefundAmounts(Array("amountBase" => "50.00", "amountTax" => "4.25"), $request); // NodeJS Example function setRefundAmounts(amountArray, req) { req['amountBase'] = amountArray['amountBase'] ? amountArray['amountBase'] : "0.00"; req['amountShipping'] = amountArray['amountShipping'] ? amountArray['amountShipping'] : "0.00"; req['amountSurcharge'] = amountArray['amountSurcharge'] ? amountArray['amountSurcharge'] : "0.00"; req['amountTip'] = amountArray['amountTip'] ? amountArray['amountTip'] : "0.00"; return req; } let request = setRefundAmounts({ "amountBase": "50.00", "amountTax": "4.25" }, { "transactionId": "1234567" });
Production Request
curl -X POST -u "login:password" -H "Accept: application/json" -H "X-PJ-Application-Key: YOUR_PRODUCTION_APP_KEY" \
-d "action=REFUND" \
-d "transactionId=12345" \
"https://api.payjunction.com/transactions"
Sandbox Request
curl -X POST -u "pj-ql-01:pj-ql-01p" -H "Accept: application/json" -H "X-PJ-Application-Key: YOUR_LABS_APP_KEY" \
-d "action=REFUND" \
-d "transactionId=3595" \
"https://api.payjunctionlabs.com/transactions"
Refunding a Card Without a transaction id
API URI: POST /transactions (Click Here for documentation)
This is an example of refunding a credit card without using the previous transactionId. Notice that the full card number must be provided.
Production Request
curl -X POST -u "login:password" -H "Accept: application/json" -H "X-PJ-Application-Key: YOUR_PRODUCTION_APP_KEY" \
-d "action=REFUND" \
-d "cardNumber=4444333322221111" \
-d "cardExpMonth=01" \
-d "cardExpYear=2020" \
-d "amountBase=1.00" \
"https://api.payjunction.com/transactions"
Sandbox Request
curl -X POST -u "pj-ql-01:pj-ql-01p" -H "Accept: application/json" -H "X-PJ-Application-Key: YOUR_LABS_APP_KEY" \
-d "action=REFUND" \
-d "cardNumber=4444333322221111" \
-d "cardExpMonth=01" \
-d "cardExpYear=2020" \
-d "amountBase=1.00" \
"https://api.payjunctionlabs.com/transactions"