diff --git a/app/Http/Controllers/Admin/ZarinController.php b/app/Http/Controllers/Admin/ZarinController.php index 164a4ba..8db4c9d 100644 --- a/app/Http/Controllers/Admin/ZarinController.php +++ b/app/Http/Controllers/Admin/ZarinController.php @@ -171,6 +171,12 @@ class ZarinController extends Controller return $nameG !== '' ? $nameG : 'مشتری نقدی (خریدار)'; } + /** کد حساب بانک/صندوق زرین برای kind=payment (وجه نقد) */ + private function zarinIdBank(): int + { + return (int) preg_replace('/\D+/', '', (string) $this->Config('zarin_idbank')); + } + /** آیا درخواست لیست زرین را خواسته؟ (query/body/header؛ مقاوم به QUERY_STRING خالی) */ private function requestWantsZarinList(Request $request): bool { @@ -2066,28 +2072,31 @@ class ZarinController extends Controller $isWithdraw = (int) ($data['direction'] ?? 0) === 1; $uidSource = $data['withdraw_id'] ?? $zarin->id; - // kind=pooli فی خالی را با HTTP 400 «ERROR: fi is empty» رد می‌کند و فی باید در ۲۵٪ مظنه روز باشد. - // نتیجه همیشه نوع ۵۳ «پولی(خرید و فروش)» / عنوان «خرید فی» است (تبدیل ریال به گرم). نوع ۵۵ «وجه نقد» در API این پنل در دسترس نیست. - $prices = $this->lastPriceData(); - $mazaneh = $isWithdraw ? (int) ($prices['sell'] ?? 0) : (int) ($prices['buy'] ?? 0); - if ($mazaneh <= 0) { - $this->sync()->markFailed($zarin, null, 'مظنه برای سند ریالی زرین در دسترس نیست'); - return 'مظنه برای سند ریالی زرین در دسترس نیست.'; + // kind=payment = نوع ۵۵ «وجه نقد» (فقط ریال). id دریافت می‌کند، idbank پرداخت می‌کند. + $idBank = $this->zarinIdBank(); + if ($idBank <= 0) { + $this->sync()->markFailed($zarin, null, 'کد حساب بانک زرین (zarin_idbank) تنظیم نشده'); + return 'کد حساب بانک زرین تنظیم نشده است. zarin_idbank را در تنظیمات بگذارید.'; + } + + $customerCode = (int) $customer->moshtari_code; + if ($customerCode <= 0) { + $this->sync()->markFailed($zarin, null, 'کد حساب زرین مشتری نامعتبر است'); + return false; + } + if ($customerCode === $idBank) { + $this->sync()->markFailed($zarin, null, 'zarin_idbank نباید با کد مشتری یکی باشد'); + return 'کد حساب بانک زرین با کد مشتری یکی است.'; } try { $http = $this->zarinRequest([ - 'kind' => 'pooli', - 'radif' => 1, - 'korf' => $isWithdraw ? 'f' : 'k', - 'poolorvazn' => 'pool', - 'meghdar' => $data['value'], - 'fi' => $mazaneh, - 'hesab' => $customer->moshtari_code, + 'kind' => 'payment', + 'id' => $isWithdraw ? $idBank : $customerCode, + 'idbank' => $isWithdraw ? $customerCode : $idBank, + 'mablagh' => (string) (int) abs((float) $data['value']), 'sharh' => $sharh, - 'ayar' => '750', - 'movaghat' => '', - 'idFactor' => '', + 'movaghat' => '0', 'uid' => $this->zarinUid('20', $uidSource), ]); diff --git a/app/Services/ZarinSyncService.php b/app/Services/ZarinSyncService.php index cdf44fc..fbde5aa 100644 --- a/app/Services/ZarinSyncService.php +++ b/app/Services/ZarinSyncService.php @@ -36,7 +36,7 @@ class ZarinSyncService private function hasNumericIdKey(array $row): bool { - foreach (['idFactor', 'idSanad', 'pkRadifSanad', 'idHesab', 'OK'] as $key) { + foreach (['idFactor', 'idSanad', 'pkRadifSanad', 'idHesab', 'OK', 'shomareSanad'] as $key) { if (! array_key_exists($key, $row)) { continue; } @@ -70,6 +70,7 @@ class ZarinSyncService ?? $flat['idFactor'] ?? $flat['idSanad'] ?? $flat['pkRadifSanad'] + ?? $flat['shomareSanad'] ?? $flat['idHesab'] ?? null; diff --git a/database/migrations/2026_09_01_000001_add_zarin_idbank_setting.php b/database/migrations/2026_09_01_000001_add_zarin_idbank_setting.php new file mode 100644 index 0000000..25789b6 --- /dev/null +++ b/database/migrations/2026_09_01_000001_add_zarin_idbank_setting.php @@ -0,0 +1,49 @@ + 'کد حساب بانک زرین', + 'description' => 'کد حساب بانک یا صندوق در زرین (idbank) برای واریز/برداشت ریالی کیف. سند نوع وجه نقد است، نه خرید فی. از لیست حساب‌های زرین همان کد عددی را بگذارید.', + 'type' => 'number', + ]; + + $exists = DB::table('settings')->where('key', $key)->exists(); + if (! $exists) { + DB::table('settings')->insert([ + 'key' => $key, + 'value' => '', + 'title_fa' => $meta['title_fa'], + 'can_edit' => 0, + 'is_active' => 1, + 'description' => $meta['description'], + 'type' => $meta['type'], + ]); + + return; + } + + DB::table('settings')->where('key', $key)->update([ + 'title_fa' => $meta['title_fa'], + 'description' => $meta['description'], + 'type' => $meta['type'], + 'can_edit' => 0, + 'is_active' => 1, + ]); + } + + public function down(): void + { + // کلید را حذف نمی‌کنیم + } +}; diff --git a/database/sql/deploy_settings_const.sql b/database/sql/deploy_settings_const.sql index 7fbda47..05dbf53 100644 --- a/database/sql/deploy_settings_const.sql +++ b/database/sql/deploy_settings_const.sql @@ -709,6 +709,11 @@ WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'referral_limit' LIMIT -- SELECT 'zarin_uid_prefix', '', 'پیشوند عددی uid زرین', 0, 1, 'فقط عدد. وقتی چند پنل یک زرین دارند باید متفاوت باشد تا uid تکراری نشود.', 'text' -- WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'zarin_uid_prefix' LIMIT 1); +-- [super-admin can_edit=0] +-- INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +-- SELECT 'zarin_idbank', '', 'کد حساب بانک زرین', 0, 1, 'کد حساب بانک یا صندوق در زرین (idbank وب‌سرویس payment) برای واریز/برداشت ریالی کیف. سند نوع وجه نقد است نه خرید فی.', 'number' +-- WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'zarin_idbank' LIMIT 1); + -- [super-admin can_edit=0] -- INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -- SELECT 'send_to_pargar', 'false', 'ارسال به پرگار (قدیمی)', 0, 0, NULL @@ -2398,7 +2403,7 @@ WHERE `key` = 'deposit_method_shetab'; -- UPDATE `settings` SET `can_edit` = 0 WHERE `key` IN ( -- 'accounting_provider', -- 'tahesab_host', 'tahesab_port', 'tahesab_token', 'tahesab_db', 'tahesab_bank_account', --- 'zarin_api', 'zarin_token', 'zarin_noe_kar', 'zarin_noe_kar_tedadi', 'zarin_gorohe_kar', 'zarin_name_g', 'zarin_uid_prefix', +-- 'zarin_api', 'zarin_token', 'zarin_noe_kar', 'zarin_noe_kar_tedadi', 'zarin_gorohe_kar', 'zarin_name_g', 'zarin_uid_prefix', 'zarin_idbank', -- 'pargar_username', 'pargar_password', 'pargar_api_token', -- 'pargar_item_id_rial', 'pargar_item_id_gold' -- ); @@ -2407,7 +2412,7 @@ WHERE `key` = 'deposit_method_shetab'; -- [super-admin can_edit=0 sync] -- UPDATE `settings` SET `type` = 'text', `can_edit` = 0 WHERE `key` IN ('zarin_api', 'zarin_token', 'zarin_name_g', 'zarin_uid_prefix'); -- [super-admin can_edit=0 sync] --- UPDATE `settings` SET `type` = 'number', `can_edit` = 0 WHERE `key` IN ('zarin_noe_kar', 'zarin_noe_kar_tedadi', 'zarin_gorohe_kar'); +-- UPDATE `settings` SET `type` = 'number', `can_edit` = 0 WHERE `key` IN ('zarin_noe_kar', 'zarin_noe_kar_tedadi', 'zarin_gorohe_kar', 'zarin_idbank'); -- درگاه شارژ آنلاین (Montify) — متادیتا + can_edit=0 (value دست نخورده) -- [super-admin can_edit=0] @@ -2497,6 +2502,8 @@ WHERE `key` = 'deposit_method_shetab'; -- [super-admin can_edit=0] -- UPDATE `settings` SET `title_fa` = 'پیشوند عددی uid زرین', `type` = 'text', `description` = 'فقط عدد. وقتی چند پنل یک زرین دارند باید متفاوت باشد تا uid تکراری نشود.' WHERE `key` = 'zarin_uid_prefix'; -- [super-admin can_edit=0] +-- UPDATE `settings` SET `title_fa` = 'کد حساب بانک زرین', `type` = 'number', `description` = 'کد حساب بانک یا صندوق در زرین (idbank وب‌سرویس payment) برای واریز/برداشت ریالی کیف. سند نوع وجه نقد است نه خرید فی.' WHERE `key` = 'zarin_idbank'; +-- [super-admin can_edit=0] -- UPDATE `settings` SET `value` = 'pargar' -- WHERE `key` = 'accounting_provider' -- AND TRIM(COALESCE(`value`, '')) IN ('', 'none') diff --git a/database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql b/database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql index 14aa935..4c5e11f 100644 --- a/database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql +++ b/database/sql/deploy_settings_const_preserve_value_sync_can_edit.sql @@ -592,6 +592,11 @@ WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'referral_limit' LIMIT -- SELECT 'zarin_uid_prefix', '', 'پیشوند عددی uid زرین', 0, 1, 'فقط عدد. وقتی چند پنل یک زرین دارند باید متفاوت باشد تا uid تکراری نشود.', 'text' -- WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'zarin_uid_prefix' LIMIT 1); +-- [super-admin can_edit=0] +-- INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +-- SELECT 'zarin_idbank', '', 'کد حساب بانک زرین', 0, 1, 'کد حساب بانک یا صندوق در زرین (idbank وب‌سرویس payment) برای واریز/برداشت ریالی کیف. سند نوع وجه نقد است نه خرید فی.', 'number' +-- WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'zarin_idbank' LIMIT 1); + -- [super-admin can_edit=0] -- INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`) -- SELECT 'send_to_pargar', 'false', 'ارسال به پرگار (قدیمی)', 0, 0, NULL @@ -1723,7 +1728,7 @@ UPDATE `settings` SET `type` = 'number' WHERE `key` IN ( -- UPDATE `settings` SET `can_edit` = 0 WHERE `key` IN ( -- 'accounting_provider', -- 'tahesab_host', 'tahesab_port', 'tahesab_token', 'tahesab_db', 'tahesab_bank_account', --- 'zarin_api', 'zarin_token', 'zarin_noe_kar', 'zarin_gorohe_kar', 'zarin_name_g', 'zarin_uid_prefix', +-- 'zarin_api', 'zarin_token', 'zarin_noe_kar', 'zarin_gorohe_kar', 'zarin_name_g', 'zarin_uid_prefix', 'zarin_idbank', -- 'pargar_username', 'pargar_password', 'pargar_api_token' -- ); -- [super-admin can_edit=0 sync] @@ -1731,7 +1736,7 @@ UPDATE `settings` SET `type` = 'number' WHERE `key` IN ( -- [super-admin can_edit=0 sync] -- UPDATE `settings` SET `type` = 'text', `can_edit` = 0 WHERE `key` IN ('zarin_api', 'zarin_token', 'zarin_name_g', 'zarin_uid_prefix'); -- [super-admin can_edit=0 sync] --- UPDATE `settings` SET `type` = 'number', `can_edit` = 0 WHERE `key` IN ('zarin_noe_kar', 'zarin_gorohe_kar'); +-- UPDATE `settings` SET `type` = 'number', `can_edit` = 0 WHERE `key` IN ('zarin_noe_kar', 'zarin_gorohe_kar', 'zarin_idbank'); -- [super-admin can_edit=0] -- UPDATE `settings` SET `title_fa` = 'سیستم حسابداری', `type` = 'select', `description` = 'none,pargar,tahesab,zarin' -- WHERE `key` = 'accounting_provider'; @@ -1753,6 +1758,8 @@ UPDATE `settings` SET `type` = 'number' WHERE `key` IN ( -- [super-admin can_edit=0] -- UPDATE `settings` SET `title_fa` = 'پیشوند عددی uid زرین', `type` = 'text', `description` = 'فقط عدد. وقتی چند پنل یک زرین دارند باید متفاوت باشد تا uid تکراری نشود.' WHERE `key` = 'zarin_uid_prefix'; -- [super-admin can_edit=0] +-- UPDATE `settings` SET `title_fa` = 'کد حساب بانک زرین', `type` = 'number', `description` = 'کد حساب بانک یا صندوق در زرین (idbank وب‌سرویس payment) برای واریز/برداشت ریالی کیف. سند نوع وجه نقد است نه خرید فی.' WHERE `key` = 'zarin_idbank'; +-- [super-admin can_edit=0] -- UPDATE `settings` SET `value` = 'pargar' -- WHERE `key` = 'accounting_provider' -- AND TRIM(COALESCE(`value`, '')) IN ('', 'none')