Fix some for sign body to montify and not get 401 error|

This commit is contained in:
mahmood
2026-07-27 01:36:02 +03:30
parent 815da9896d
commit 933424ddfc
8 changed files with 381 additions and 36 deletions
@@ -3,6 +3,7 @@
namespace App\Services\Payment\Gateways;
use App\Services\ConfigService;
use App\Services\Payment\Contracts\SupportsStatusQuery;
use App\Services\Payment\Contracts\WalletPaymentGatewayInterface;
use App\Services\Payment\Support\MontifyHmacSigner;
use App\Services\Payment\WalletDepositCreditor;
@@ -15,7 +16,7 @@ use RuntimeException;
* درگاه پارتنر Montify (HMAC) — فقط credentials روی سرور.
* @see docs/EXTERNAL_PAYMENT_PARTNER.md
*/
class MontifyPartnerGateway implements WalletPaymentGatewayInterface
class MontifyPartnerGateway implements WalletPaymentGatewayInterface, SupportsStatusQuery
{
public function __construct(
private ConfigService $config,
@@ -169,10 +170,14 @@ class MontifyPartnerGateway implements WalletPaymentGatewayInterface
$query = $this->normalizeReturnQuery($rawQuery);
$signer = $this->signer();
if (!$signer->verifyReturnSignature($query)) {
if ($signer->matchReturnSignatureVariant($query) === null) {
\Log::warning('montify.return_invalid_signature', [
'keys' => array_keys($query),
'reference_id' => $query['reference_id'] ?? null,
'status' => $query['status'] ?? null,
'amount' => $query['amount'] ?? null,
'timestamp' => $query['timestamp'] ?? null,
'has_track_number' => array_key_exists('track_number', $query),
]);
return ['ok' => false, 'withdraw' => null, 'http_status' => 401, 'message' => 'امضای نامعتبر'];
@@ -262,6 +267,73 @@ class MontifyPartnerGateway implements WalletPaymentGatewayInterface
return $normalized;
}
/**
* منبع حقیقت مستقل از redirect: استعلام مستقیم وضعیت از Montify.
*
* @return array{status: string, paid: bool}
*/
public function syncStatusByReference(string $referenceId): array
{
if ($referenceId === '' || !$this->isConfigured()) {
return ['status' => 'unknown', 'paid' => false];
}
$path = '/external-payment/status';
$headers = $this->signer()->signRequest('GET', $path, null);
try {
$response = Http::withHeaders($headers)
->acceptJson()
->timeout(20)
->get($this->baseUrl() . $path, ['reference_id' => $referenceId]);
} catch (\Throwable $e) {
report($e);
return ['status' => 'unknown', 'paid' => false];
}
$data = $response->json();
if (!$response->successful() || !is_array($data)) {
\Log::warning('montify.status_failed', [
'reference_id' => $referenceId,
'http_status' => $response->status(),
'body' => is_array($data) ? $data : $response->body(),
]);
return ['status' => 'unknown', 'paid' => false];
}
$status = strtolower((string) ($data['status'] ?? ''));
if ($status !== 'paid') {
return ['status' => $status !== '' ? $status : 'unknown', 'paid' => false];
}
$withdraw = $this->creditor->findByReference($referenceId);
if (!$withdraw) {
return ['status' => 'paid', 'paid' => false];
}
$amount = (int) ($data['amount'] ?? 0);
if ($amount > 0 && (int) $withdraw->cash !== $amount) {
\Log::warning('montify.status_amount_mismatch', [
'reference_id' => $referenceId,
'remote_amount' => $amount,
'local_amount' => (int) $withdraw->cash,
]);
return ['status' => 'amount_mismatch', 'paid' => false];
}
$trackNumber = (string) ($data['track_number'] ?? '');
$this->creditor->markPaidAndCredit(
$withdraw,
$trackNumber !== '' ? $trackNumber : (string) ($data['token'] ?? ''),
'واریز درگاه Montify'
);
return ['status' => 'paid', 'paid' => true];
}
public function handleWebhook(Request $request): array
{
$body = $request->all();