Good day team,
I have recently integrated with paynow and I am now doing the production tests. I am getting hash mismatch error after a payment is done which is the last step to finalize the transaction. I tried to generate the new integration key on the portal but still nothing is changing. Kindly help, @paynow team kindly confirm if there is another key specifically for production that you are using to generate the callback hash for my merchant ID. Below is my code and logs :
`public function paynowResult(Request $request)
{
// Loging raw data from Paynow
Log::info(“Paynow Result callback raw data”, $request->all());
// Gather all parameters
$data = $request->all();
// The 'hash' sent by Paynow, if any
$providedHash = $data['hash'] ?? '';
// Remove 'hash' from $data before we do our own hashing
unset($data['hash']);
// Sort & build the string to hash
ksort($data);
$string = '';
foreach ($data as $key => $value) {
// Exclude empty values
if (strlen($value) > 0) {
// Converting key to uppercase, URL-encode the value, then append "KEY=VALUE&"
$string .= strtoupper($key) . '=' . urlencode($value) . '&';
}
}
// Removing trailing ampersand
$string = rtrim($string, '&');
// Generating our own hash
$ourHash = hash('sha512', $string . env('PAYNOW_INTEGRATION_KEY'));
Log::info("Computed string for hash: " . $string);
Log::info("Computed ourHash: " . strtoupper($ourHash));
Log::info("Paynow-sent hash: " . strtoupper($providedHash));
// Comparing (case-insensitive) your computed hash vs Paynow's
if (strtoupper($ourHash) !== strtoupper($providedHash)) {
Log::error('Paynow callback hash mismatch. Potential tampering.');
abort(403, 'Hash mismatch');
}
// If the hash matched proceed.
$reference = $data['reference'] ?? '';
$paynowRef = $data['paynowreference'] ?? '';
$amount = $data['amount'] ?? 0;
$status = $data['status'] ?? 'Unknown';
$pollUrl = $data['pollurl'] ?? '';
Log::info("Paynow callback verified for reference: $reference, status=$status");
// Payment ref.
$payment = Payment::where('reference', $reference)->first();
if (!$payment) {
Log::error("No Payment found for reference: $reference or pollUrl: $pollUrl");
// Return 200 so Paynow doesn't keep retrying
return response('Payment not found', 200);
}
//Handling statuses
if (strtolower($status) === 'paid') {
$payment->status = 'completed';
$payment->transaction_id = $paynowRef;
$payment->save();
$trip = $payment->trip;
if ($trip) {
$trip->payment_status = 'completed';
$trip->save();
}
Log::info("Payment #{$payment->id} completed on Paynow.");
}
elseif (strtolower($status) === 'cancelled') {
$payment->status = 'cancelled';
$payment->transaction_id = $paynowRef;
$payment->save();
}
else {
$payment->status = strtolower($status);
$payment->transaction_id = $paynowRef;
$payment->save();
}
return response('OK', 200);
}`
[2025-03-19 09:12:48] production.INFO: processPayment() invoked {"_token":“pz0MLlYtNbLjYhIYGfQzGT676by6PATJaZ8iPhwF”,“bid_amount”:“1”,“payment_method”:“paynow”,“trip_id”:“98”} [2025-03-19 09:12:50] production.INFO: Paynow response data: {“status”:“Ok”,“browserurl”:“https://www.paynow.co.zw/Payment/ConfirmPayment/22673706/rodnkamamera@gmail.com//",“pollurl”:“https://www.paynow.co.zw/Interface/CheckPayment/?guid=fe3cafa1-5a28-4702-bed2-ac42eda36222”,“hash”:"0752ADC44E65F8B2327203F8BD33ECF81502DC14E08C0492AAF09F95AF891CB9155A052C7F6E174D66852E82740776E700865ADE5F97B7AE05982291264BC5C4”} [2025-03-19 09:12:50] production.INFO: Paynow redirect URL: https://www.paynow.co.zw/Payment/ConfirmPayment/22673706/gd123****@gmail.com// [2025-03-19 09:13:55] production.INFO: Paynow Result callback raw data {“reference”:“Trip-98-Payment-34”,“paynowreference”:“22673706”,“amount”:“1.00”,“status”:“Paid”,“pollurl”:“https://www.paynow.co.zw/Interface/CheckPayment/?guid=fe3cafa1-5a28-4702-bed2-ac42eda36222",“hash”:"F30EC739767D1E1DDEABDB8F1D457042729B27105092FB1A431BD6EB3ABB9E4B0CFE82FC524E153EC9E1D95221419FEDE65ADEEE3C198F13CB942605F7EC3B2F”} [2025-03-19 09:13:55] production.INFO: Computed string for hash: AMOUNT=1.00&PAYNOWREFERENCE=22673706&POLLURL=https%3A%2F%2Fwww.paynow.co.zw%2FInterface%2FCheckPayment%2F%3Fguid%3Dfe3cafa1-5a28-4702-bed2-ac42eda36222&REFERENCE=Trip-98-Payment-34&STATUS=Paid [2025-03-19 09:13:55] production.INFO: Computed ourHash: 7DB2064C3071EFB36FE97C8BB7DCCDA0B58EDE76ADB24C1E1150B20E40CEEEF343747F68765DE554A768158072647E702387A6F6BA38800B924A2AAD8A121B5A [2025-03-19 09:13:55] production.INFO: Paynow-sent hash: F30EC739767D1E1DDEABDB8F1D457042729B27105092FB1A431BD6EB3ABB9E4B0CFE82FC524E153EC9E1D95221419FEDE65ADEEE3C198F13CB942605F7EC3B2F [2025-03-19 09:13:55] production.ERROR: Paynow callback hash mismatch.