Wire outbound Invoice/Document sync after confirmed ops, store sync status with timeout lock, and keep SQL credentials out of frontend responses. Co-authored-by: Cursor <cursoragent@cursor.com>
138 lines
4.6 KiB
PHP
138 lines
4.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Payment;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Customer;
|
|
use App\Models\User;
|
|
use App\Models\Withdraw;
|
|
use App\Services\ConfigService;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Rooyesh\Wallet\interfaces\TransactionInterface;
|
|
use Rooyesh\Wallet\interfaces\WalletInterface;
|
|
|
|
/**
|
|
* شارژ idempotent کیف بعد از پرداخت موفق درگاه.
|
|
*/
|
|
class WalletDepositCreditor
|
|
{
|
|
public function __construct(private ConfigService $config)
|
|
{
|
|
}
|
|
|
|
public function findByReference(string $referenceId): ?Withdraw
|
|
{
|
|
if ($referenceId === '') {
|
|
return null;
|
|
}
|
|
|
|
if (preg_match('/^WD-(\d+)$/', $referenceId, $matches)) {
|
|
return Withdraw::with('customer')->find((int) $matches[1]);
|
|
}
|
|
|
|
return Withdraw::with('customer')
|
|
->where('tracked_number', $referenceId)
|
|
->orderByDesc('id')
|
|
->first();
|
|
}
|
|
|
|
public function markPaidAndCredit(Withdraw $withdraw, string $trackNumber, string $note = 'واریز درگاه'): void
|
|
{
|
|
DB::transaction(function () use ($withdraw, $trackNumber, $note) {
|
|
$locked = Withdraw::query()->whereKey($withdraw->id)->lockForUpdate()->first();
|
|
if (!$locked || (int) $locked->sts === 2) {
|
|
return;
|
|
}
|
|
|
|
if ($trackNumber !== '') {
|
|
$locked->tracked_number = $trackNumber;
|
|
}
|
|
$locked->sts = 2;
|
|
$locked->save();
|
|
|
|
$user = Customer::find($locked->customer_id);
|
|
if (!$user) {
|
|
return;
|
|
}
|
|
|
|
$wallet = new WalletInterface($user->id, $user->type);
|
|
new TransactionInterface($wallet, [
|
|
'cash' => (int) $locked->cash,
|
|
'expire_at' => now(),
|
|
'withdraw_id' => $locked->id,
|
|
'active' => true,
|
|
], 3, false, true);
|
|
|
|
try {
|
|
app(\App\Services\PargarSyncService::class)->queueWalletDocument(
|
|
$user,
|
|
'cash',
|
|
(float) $locked->cash,
|
|
[
|
|
'withdraw_id' => $locked->id,
|
|
'note' => $note,
|
|
'source' => 'gateway',
|
|
]
|
|
);
|
|
} catch (\Throwable $e) {
|
|
report($e);
|
|
}
|
|
|
|
$this->syncGatewayDepositToAccounting($user, $locked, $note);
|
|
|
|
$locked->loadMissing('customer');
|
|
$message = 'کاربر ' . ($locked->customer->name ?? '') . ' با شماره موبایل ' . ($locked->customer->mobile ?? '')
|
|
. ' حساب خود را به مقدار ' . number_format((int) $locked->cash) . ' ریال شارژ کرد. با تشکر، '
|
|
. $this->config->getString('name_fa', '');
|
|
|
|
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
|
|
if (Controller::isSmsNotifEnabled('sms_notif_gateway_charge_admin')) {
|
|
Controller::Send($admin->mobile, $message);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/** سند بانکی تهحساب/زرین — قبلاً فقط پرگار میرفت و در تهحساب «خرید» دستی ثبت میشد */
|
|
private function syncGatewayDepositToAccounting(Customer $customer, Withdraw $withdraw, string $note): void
|
|
{
|
|
$cash = (int) round(abs((float) $withdraw->cash));
|
|
if ($cash <= 0) {
|
|
return;
|
|
}
|
|
|
|
$accountingNote = trim($note) !== '' ? $note : 'دریافت وجه بابت شارژ';
|
|
$payload = [
|
|
'customer_id' => (int) $customer->id,
|
|
'value' => $cash,
|
|
'direction' => 0,
|
|
'withdraw_id' => (int) $withdraw->id,
|
|
'note' => $accountingNote,
|
|
];
|
|
|
|
if ($this->config->isTahesabAccounting()) {
|
|
try {
|
|
app(\App\Http\Controllers\Admin\TahesabController::class)->wallet($payload);
|
|
} catch (\Throwable $e) {
|
|
report($e);
|
|
}
|
|
}
|
|
|
|
if ($this->config->isZarinAccounting()) {
|
|
try {
|
|
app(\App\Http\Controllers\Admin\ZarinController::class)->wallet($payload);
|
|
} catch (\Throwable $e) {
|
|
report($e);
|
|
}
|
|
}
|
|
|
|
if ($this->config->isShayeganAccounting()) {
|
|
try {
|
|
app(\App\Http\Controllers\Admin\ShayeganController::class)->wallet($payload);
|
|
} catch (\Throwable $e) {
|
|
report($e);
|
|
}
|
|
}
|
|
}
|
|
}
|