From afc23165bd3a2ef07dfde610740adbb633e95f69 Mon Sep 17 00:00:00 2001 From: mahmood Date: Mon, 27 Jul 2026 01:11:01 +0330 Subject: [PATCH] fix some for weebhok url and return url on montify --- .../pay/WalletPaymentController.php | 56 +++++++++++++++++++ .../Gateways/MontifyPartnerGateway.php | 10 +++- docs/WALLET_ONLINE_PAYMENT.md | 21 +++++-- routes/customer.php | 1 + 4 files changed, 83 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/pay/WalletPaymentController.php b/app/Http/Controllers/pay/WalletPaymentController.php index 3340284..dcd7994 100644 --- a/app/Http/Controllers/pay/WalletPaymentController.php +++ b/app/Http/Controllers/pay/WalletPaymentController.php @@ -94,6 +94,62 @@ class WalletPaymentController extends Controller ], 201); } + /** + * وریفای برگشت مرورگر از فرانت — امضا و شارژ سمت سرور؛ بدون افشای secret. + * Body یا query: status, reference_id, session_id, amount, track_number, timestamp, signature + */ + public function verifyReturn(Request $request) + { + $gateway = $this->payments->resolve(); + if (!$gateway) { + throw new UnprocessableEntityHttpException('پرداخت آنلاین فعال نیست'); + } + + $payload = array_filter([ + 'status' => $request->input('status'), + 'reference_id' => $request->input('reference_id'), + 'session_id' => $request->input('session_id'), + 'amount' => $request->input('amount'), + 'track_number' => $request->input('track_number'), + 'timestamp' => $request->input('timestamp'), + 'signature' => $request->input('signature'), + ], static fn ($v) => $v !== null && $v !== ''); + + $synthetic = Request::create('/', 'GET', $payload); + $result = $gateway->handleReturn($synthetic); + + if (!($result['ok'] ?? false)) { + return response()->json([ + 'ok' => false, + 'message' => $result['message'] ?? 'خطا در تأیید پرداخت', + ], (int) ($result['http_status'] ?? 400)); + } + + /** @var Withdraw|null $withdraw */ + $withdraw = $result['withdraw'] ?? null; + if (!$withdraw) { + return response()->json(['ok' => false, 'message' => 'سفارش یافت نشد'], 404); + } + + $customerId = (int) auth('customer')->id(); + if ((int) $withdraw->customer_id !== $customerId) { + return response()->json(['ok' => false, 'message' => 'دسترسی غیرمجاز'], 403); + } + + $sts = (int) $withdraw->sts; + $paid = $sts === 2; + + return response()->json([ + 'ok' => true, + 'paid' => $paid, + 'status' => $paid ? 'success' : ((string) ($payload['status'] ?? '') === 'success' ? 'pending' : 'failed'), + 'amount' => (int) $withdraw->cash, + 'reference_id' => 'WD-' . $withdraw->id, + 'withdraw_id' => $withdraw->id, + 'track_number' => $withdraw->tracked_number, + ]); + } + public function returnFromGateway(Request $request, string $provider) { try { diff --git a/app/Services/Payment/Gateways/MontifyPartnerGateway.php b/app/Services/Payment/Gateways/MontifyPartnerGateway.php index 41c6538..33b85b6 100644 --- a/app/Services/Payment/Gateways/MontifyPartnerGateway.php +++ b/app/Services/Payment/Gateways/MontifyPartnerGateway.php @@ -48,7 +48,15 @@ class MontifyPartnerGateway implements WalletPaymentGatewayInterface return $fromSettings; } - return url('/customer/wallet/payment/return/' . $this->key()); + // پیش‌فرض: صفحه فرانت برای نمایش نتیجه + verify سمت سرور + $site = $this->config->resolvePublicSiteUrl(request()); + if ($site === '') { + $appUrl = rtrim((string) config('app.url'), '/'); + // اگر APP_URL با /server تمام شود، دامنه فرانت همان host بدون /server است + $site = preg_replace('#/server$#', '', $appUrl) ?: $appUrl; + } + + return rtrim($site, '/') . '/wallet/payment-result'; } public function webhookUrl(): string diff --git a/docs/WALLET_ONLINE_PAYMENT.md b/docs/WALLET_ONLINE_PAYMENT.md index df21e65..ea754f9 100644 --- a/docs/WALLET_ONLINE_PAYMENT.md +++ b/docs/WALLET_ONLINE_PAYMENT.md @@ -89,12 +89,25 @@ Montify → payment_url → درگاه بانکی | `external_payment_webhook_url` | text | اختیاری؛ خالی = پیش‌فرض سرور | | `min_deposit` | price | حداقل مبلغ واریز (گروه کارمزد و محدودیت‌ها) | -### مقادیر پیش‌فرض URL وقتی فیلد خالی است +### مقادیر پیشنهادی برای abaiegold -- Return: `{APP}/customer/wallet/payment/return/montify` -- Webhook: `{APP}/customer/wallet/payment/webhook/montify` +| فیلد Settings | مقدار | +|---------------|--------| +| `external_payment_return_url` | `https://abaeigold.ir/wallet/payment-result` | +| `external_payment_webhook_url` | `https://abaeigold.ir/server/customer/wallet/payment/webhook/montify` | + +در whitelist پارتنر Montify حداقل این پیشوندها را ثبت کنید: + +- Return: `https://abaeigold.ir/wallet/payment-result` یا `https://abaeigold.ir/wallet/` +- Webhook: همان URL کامل webhook بالا + +جریان برگشت فرانت: + +1. Montify کاربر را به `return_url` با query امضاشده می‌فرستد +2. صفحه `khaneghi_user` → `/wallet/payment-result` +3. فرانت `POST /customer/wallet/payment/verify-return` می‌زند (امضا فقط سمت سرور verify می‌شود) +4. webhook هم موازی برای شارژ قطعی به بک‌اند می‌آید (idempotent) -این آدرس‌ها باید در whitelist پارتنر Montify ثبت شوند. ### Migrationها diff --git a/routes/customer.php b/routes/customer.php index 5d18aa2..5faf157 100644 --- a/routes/customer.php +++ b/routes/customer.php @@ -84,6 +84,7 @@ Route::middleware(['auth:customer', 'customer.active'])->group(function () use ( Route::post('/charge_account ', [paypingController::class, 'startTransation']); Route::get('/wallet/payment/options', [WalletPaymentController::class, 'options']); Route::post('/wallet/payment/initiate', [WalletPaymentController::class, 'initiate']); + Route::post('/wallet/payment/verify-return', [WalletPaymentController::class, 'verifyReturn']); // سازگاری قدیمی Route::post('/wallet/external-payment/initiate', [WalletPaymentController::class, 'initiate']);