POST Transaction Notification
After a payment flow is finished by customer a notification will be sent from Credify servers to your store. The below guide explains the API specification for accepting transaction notification.
This is only required for custom e-commerce stores, if you are using WooCommerce or Shopify follow the instructions in merchant dashboard.
API Specifications
Endpoint:
POST <Notification Base API URL>
x-hmac-signature: <HMAC Hash>
For this integration method, you will need to provide an endpoint to hook the transaction notifications to, with the following specs.
- HTTPS enabled.
- POST enabled
- Max of 2048 characters url.
- Should expect a json payload:
{
"orderId": "<Order ID>",
"type": "<Operation Type>",
"refundAmount": "<nullable refund amount>",
"timeStamp": 1732742969
}
Parameter | Description |
---|---|
Notification Base API URL | You can pick any base URL on your website and inform Credify with the URL during the setup process |
HMAC Hash | HMAC Hash of the request body, this hash can be used to validate the authenticity of the request. |
orderID | A unique order identifier that was initially sent by iframe/your website |
type | Represents the type of the transaction |
refundAmount | A decimal representing the partially refunded amount, will be null in all operations that are not PartialRefund. |
timestamp | A timestamp that was taken upon sending the notification. Can be used by your side for better security controls. |
Notification types
- "Cancel" : payment flow cancelled by user.
- "Purchase" : payment flow finished and user made a transaction.
- "Refund" : Merchant user fully refunded the payment.
- "PartialRefund" : Merchant user partially refunded the payment and "refundAmount" will contain the refunded amount.
Expected Response
Successful HTTP status (200 Response)
Validating the HMAC
To ensure the integrity and authenticity of the URL with HMAC, you can validate the HMAC provided in the header by calculating HMAC hash of the request body. Here is a step-by-step guide on how to validate the HMAC:
- Take JSON request Body as text
- Generate HMAC: Use the same HMAC secret to generate a hash from the request body.
- Compare HMACs: Compare the generated HMAC with the provided HMACHash in the header. If they match, the URL is valid.
- Node JS
- C# DotNetCore
- Java
- PHP
const express = require('express')
const crypto = require('crypto')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.json())
const HMAC_SECRET = 'your_hmac_secret'
function validateHMAC(secret, message, providedHMAC) {
const hmac = crypto.createHmac('sha256', secret)
const hash = hmac.update(message).digest('hex')
return hash === providedHMAC
}
app.post('/notification', (req, res) => {
const providedHMAC = req.headers['x-hmac-signature']
const jsonData = JSON.stringify(req.body)
if (validateHMAC(HMAC_SECRET, jsonData, providedHMAC)) {
// Process the notification
res.status(200).send('Notification received')
} else {
res.status(401).send('Invalid HMAC')
}
})
app.listen(3000, () => {
console.log('Server is running on port 3000')
})
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Security.Cryptography;
using System.Text;
[ApiController]
[Route("[controller]")]
public class NotificationController : ControllerBase
{
private readonly ILogger<NotificationController> _logger;
private const string HMAC_SECRET = "your_hmac_secret";
public NotificationController(ILogger<NotificationController> logger)
{
_logger = logger;
}
[HttpPost]
public IActionResult Post([FromBody] NotificationData notificationData, [FromHeader(Name = "x-hmac-signature")] string providedHMAC)
{
var jsonData = System.Text.Json.JsonSerializer.Serialize(notificationData);
if (ValidateHMAC(HMAC_SECRET, jsonData, providedHMAC))
{
// Process the notification
return Ok("Notification received");
}
else
{
return Unauthorized("Invalid HMAC");
}
}
private bool ValidateHMAC(string secret, string message, string providedHMAC)
{
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret)))
{
var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
var hashString = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
return hashString == providedHMAC;
}
}
}
public class NotificationData
{
public string OrderId { get; set; }
public string Type { get; set; }
public decimal? RefundAmount { get; set; }
public long TimeStamp { get; set; }
}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.stream.Collectors;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/notification")
public class NotificationController {
private static final String HMAC_SECRET = "your_hmac_secret";
@PostMapping
public String postNotification(HttpServletRequest request) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
String providedHMAC = request.getHeader("x-hmac-signature");
String jsonData = new BufferedReader(request.getReader()).lines().collect(Collectors.joining());
if (validateHMAC(HMAC_SECRET, jsonData, providedHMAC)) {
// Process the notification
return "Notification received";
} else {
return "Invalid HMAC";
}
}
private boolean validateHMAC(String secret, String message, String providedHMAC) throws NoSuchAlgorithmException, InvalidKeyException {
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
hmac.init(secretKeySpec);
byte[] hashBytes = hmac.doFinal(message.getBytes(StandardCharsets.UTF_8));
String hashString = bytesToHex(hashBytes);
return hashString.equals(providedHMAC);
}
private String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}
<?php
function validateHMAC($secret, $message, $providedHMAC) {
$hash = hash_hmac('sha256', $message, $secret);
return hash_equals($hash, $providedHMAC);
}
$HMAC_SECRET = 'your_hmac_secret';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$providedHMAC = $_SERVER['HTTP_X_HMAC_SIGNATURE'];
$jsonData = file_get_contents('php://input');
if (validateHMAC($HMAC_SECRET, $jsonData, $providedHMAC)) {
// Process the notification
http_response_code(200);
echo 'Notification received';
} else {
http_response_code(401);
echo 'Invalid HMAC';
}
}
?>
Error Handling
In case the notify API returns non-success status code, Credify services will keep retrying for approximatly 10 times. Please make sure to log notification requests for monitoring and to be able to ensure successful integration.