merge goldali with abshode_khanegi branch

This commit is contained in:
2026-06-04 12:18:53 +03:30
parent aea3cbbc6e
commit a9815fa717
28 changed files with 1359 additions and 379 deletions
@@ -7,8 +7,11 @@ use App\Models\Cnt;
use App\Models\Customer;
use App\Models\Order;
use App\Models\Price;
use App\Models\Product;
use App\Models\TransactionsAdmin;
use App\Models\Withdraw;
use App\Services\ConfigService;
use App\Services\EtehadiePriceService;
use Carbon\Carbon;
use Hekmatinasser\Verta\Verta;
use Illuminate\Http\Request;
@@ -17,7 +20,8 @@ use Rooyesh\Wallet\models\Wallet;
class DashboardController extends Controller
{
public function dashboardMaster(){
public function dashboardMaster(Request $request)
{
$tallaPrice = Price::latest()->first();
// $talla->update_date = Verta::instance(Carbon::parse($talla->updated_at))->format('Y/n/j-H:i');
$new_customer_major = Customer::where('type',1)->whereDate('created_at','<=',now())->whereDate('created_at','>=',now()->subMonths(3))
@@ -56,6 +60,49 @@ class DashboardController extends Controller
$transactions_admins = TransactionsAdmin::with(['withdraw','order',"user",'customerTo','customer'])->get();
$startDate = $request->startDateProduct
? Carbon::parse($request->startDateProduct)->startOfDay()
: now()->subMonth()->startOfDay();
$endDate = $request->endDateProduct
? Carbon::parse($request->endDateProduct)->endOfDay()
: now()->endOfDay();
$products_report = Product::with(['limitedTransactions' => function ($query) use ($startDate, $endDate) {
$query->whereBetween('created_at', [$startDate, $endDate]);
}])
->whereHas('limitedTransactions', function ($query) use ($startDate, $endDate) {
$query->whereBetween('created_at', [$startDate, $endDate]);
})
->get();
$products_report->each(function ($product) {
$product->transaction_sum_gold_buy = $product->limitedTransactions
->where('gold', '>', 0)
->sum('gold');
$product->total_negative_gold_sell = $product->limitedTransactions
->where('gold', '<', 0)
->sum('gold');
$product->total_gold = $product->limitedTransactions->sum('gold');
});
$gramPrice = (int) ($tallaPrice->price ?? 0);
$FPrices = [];
if (app(ConfigService::class)->usesEtehadiePricing()) {
$etehadie = app(EtehadiePriceService::class)->fetchMainGramPrice();
if (($etehadie['price'] ?? 0) > 0) {
$gramPrice = (int) round($etehadie['price'] / 10);
$FPrices[] = [
'id' => 'etehadie',
'name' => 'اتحادیه',
'price' => $gramPrice,
'profit' => 0,
];
}
}
$FPrices[] = ['id' => '1', 'name' => 'افجو', 'price' => $gramPrice, 'profit' => 0];
$gatewayRow = Cnt::where('key', 'is_gateway_open')->first();
return response()->json([
'GT_all_customers'=>$GT_all_customers,
'GT_no_login_customers'=>$GT_no_login_customers,
@@ -65,7 +112,12 @@ class DashboardController extends Controller
'GT_active_customers_data'=>$GT_active_customers_data,
'GT_deActive_customers'=>$GT_all_customers-$GT_active_customers,
'GT_transactions_admins'=>$transactions_admins,
'price'=>$tallaPrice->price,
'GT_products_report' => $products_report,
'update_date' => now()->timezone('Asia/Tehran')->format('Y-m-d H:i:s'),
'pricem' => round($gramPrice * 4.331802 / 10000) * 10000,
'prices' => $FPrices,
'is_gateway_open' => $gatewayRow && (string) $gatewayRow->value === '1',
'price'=>$tallaPrice?->price ?? $gramPrice,
'new_customer_major'=>$new_customer_major,
'new_customer_single'=>$new_customer_single,
'all_customer_major'=>$all_customer_major,
@@ -80,6 +132,23 @@ class DashboardController extends Controller
]);
}
public function gateway()
{
$cnt = Cnt::where('key', 'is_gateway_open')->first();
if (!$cnt) {
$cnt = Cnt::create([
'key' => 'is_gateway_open',
'value' => '1',
]);
} else {
$cnt->value = ((string) $cnt->value === '0') ? '1' : '0';
$cnt->save();
}
return $cnt;
}
public function getBalance(Request $request)
{
$startDate = Carbon::parse($request->startDate)->startOfDay();
@@ -88,9 +157,15 @@ class DashboardController extends Controller
$response["liman"]=[];
$response["kalhor"]=[];
$excludeCustomerId = (int) app(ConfigService::class)->getInt('balance_report_exclude_customer_id', 4);
$response["pay_at_update"] = Order::whereNull('pay_at')->update(['pay_at' => DB::raw('created_at')]);
//liman
$response["liman"]["orders"] = Order::with(['transactions.product'])->where('customer_id', '!=', 4)->where('sts', 2)->whereBetween('pay_at', [$startDate, $endDate])->get();
$response["liman"]["orders"] = Order::with(['transactions.product', 'customer'])
->where('customer_id', '!=', $excludeCustomerId)
->where('sts', 2)
->whereBetween('pay_at', [$startDate, $endDate])
->get();
$response["liman"]["balance"]["gold"] = 0;
$response["liman"]["balance"]["cash"] = 0;
$response["liman"]["balance_abs"]["gold"] = 0;
@@ -151,8 +151,6 @@ class ProductController extends SuperController
public function getPrice()
{
// $RPrices = Http::get('https://pricing.liman.gold/pricingApi', [])->json();
// $RPrices = Http::get('https://pricing.liman.gold/pricingApi', [])->json();
// $RPrices =Http::timeout(40)->get('http://212.23.201.173:8381/price_list', [])->json();
$RPrices = Http::timeout(40)->get('http://109.122.246.48:4949/api/free', [])->json();
+57 -22
View File
@@ -2,13 +2,12 @@
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Admin\TahesabController;
use App\Http\Controllers\Controller;
use App\Models\Cnt;
use App\Models\Customer;
use App\Models\Setting;
use App\Models\TahesabCustomer;
use App\Models\User;
use App\Services\ConfigService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
@@ -85,7 +84,6 @@ class AuthController extends Controller
$user->token_sms = $rand;
$user->save();
// $this->SendMessage($mobile, 'رمز عبور یکبار مصرف شما جهت ورود به اپلیکشن ' . $this->ConfigService('name_fa') . ' ' . $rand . ' می باشد' . PHP_EOL . "@$subDomain" . " #" . $r and,true ,"sms");
$this->SendMessage($mobile, 'رمز عبور یکبار مصرف شما جهت ورود به اپلیکشن ' . $this->Config('name_fa') . ' ' . $rand . ' می باشد' . PHP_EOL . "@$subDomain" . " #" . $rand,true ,"sms");
return $user->id;
@@ -120,17 +118,20 @@ class AuthController extends Controller
public function register(Request $request)
{
$cfg = app(ConfigService::class);
$register = Setting::where('key', 'open_register')->first();
if($register->is_active == 0){
if ($register && (int) $register->is_active === 0) {
throw new UnprocessableEntityHttpException('امکان ثبت نام وجود ندارد.');
}
$data = $request->all();
$data['type'] = 2;
if (isset($data['referral_id'])) {
$data['referral_to_id'] = $data['referral_id'];
}
$data['name'] = $data['fname'] . ' ' . $data['lname'];
$data['active'] = Setting::where('key', 'auto_active_customer')->first()->value === 'true';
$data['active'] = $cfg->getBool('auto_active_customer', false);
if (isset($data['type']) && $data['type'] == 2) {
$data['active'] = true;
}
@@ -138,40 +139,74 @@ class AuthController extends Controller
if (!is_null($cnt)) {
$data['gram'] = $cnt->value;
}
// Generate unique referral ID
do {
$uniqueId = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyz'), 0, 4);
} while (Customer::where('referral_id', $uniqueId)->exists());
$data['referral_id'] = $uniqueId;
// Handle referrer
if (isset($data['n_code']) && $cfg->getBool('register_jibit_verify', false)) {
$existing = Customer::where('n_code', $data['n_code'])->first();
if (!empty($existing)) {
return response()->json(['message' => 'کد ملی تکراری است'], 422);
}
$response = $this->jibitNcode($data['n_code'], $data['mobile']);
if (isset($response['matched']) && $response['matched'] == true) {
$data['is_legal'] = 1;
}
}
$referrer = null;
if (isset($data['referral_to_id'])) {
$referrer = Customer::where('referral_id', $data['referral_to_id'])->first();
if ($referrer) {
// $messageRef = "{$data['name']} با کد معرف شما ثبت نام کرد.\nدر صورت احراز او پاداش می‌گیرید.\n" . $this->ConfigService('name_fa');
// $this->Send($referrer->mobile, $messageRef);
$AdminMessage = "با معرفی {$referrer->name}، کاربر {$data['name']} در اپ {$this->Config('name_fa')} ثبت نام کرده و منتظر تایید شماست.";
User::where('send_sms', 1)->get()->each(function ($admin) use ($AdminMessage, $data,) {
$this->send($admin->mobile, $AdminMessage);
});
if ($cfg->getBool('register_referral_sms_to_referrer', false)) {
$messageRef = "{$data['name']} با کد معرف شما ثبت نام کرد.\nبا اولین خرید او پاداش دریافت میکنید.\n" . $this->Config('name_fa');
$this->Send($referrer->mobile, $messageRef);
} else {
$adminMessage = "با معرفی {$referrer->name}، کاربر {$data['name']} در اپ {$this->Config('name_fa')} ثبت نام کرده و منتظر تایید شماست.";
User::where('send_sms', 1)->get()->each(function ($admin) use ($adminMessage) {
$this->send($admin->mobile, $adminMessage);
});
}
} else {
return response()->json(["message" => "کد نامعتبره"], 422);
return response()->json(['message' => 'کد نامعتبره'], 422);
}
} else {
if ($this->Config('referral_id') == "required") {
return response()->json(["message" => "کد معرف اجباریست"], 422);
if (
$this->Config('referral_id') == 'required'
|| $cfg->getBool('is_requaire_referral', false)
) {
return response()->json(['message' => 'کد معرف اجباریست'], 422);
}
}
$data['active'] = true;
// Create customer
$customer = Customer::create($data);
// $tah = new TahesabController();
// return $tah->store([
// 'customer_id' => $customer->id,
// ]);
if ($referrer) {
$referrer->increment('total_referrals');
}
$message = "{$data['name']} عزیز، اکانت شما در پلتفرم {$this->Config('name_fa')} ایجاد شد.\nنام کاربری: {$data['mobile']}\n\nورود به نرم افزار:\n{$this->Config('app_url')}";
if ($cfg->getBool('register_jibit_verify', false) && isset($customer->is_legal)) {
$message = $customer->is_legal === 1
? 'احرازهویت برای ' . $customer->name . ' با کد ' . $customer->id . ' انجام شد.'
: 'احرازهویت برای ' . $customer->name . ' با کد ' . $customer->id . ' تأیید نشد لطفا از پنل ادمین اقدام فرمایید.';
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->SendMessage($admin->mobile, $message);
});
}
$message = "{$data['name']} عزیز، اکانت شما در پلتفرم {$this->Config('name_fa')} ایجاد شد.";
if ($cfg->getBool('register_referral_bonus_message', false)) {
$bonus = Setting::where('is_active', 1)->where('key', 'referral_bonus_amount')->first();
if ($bonus) {
$bonusValues = json_decode($bonus->value, true);
$message .= "\nپس از اولین خرید مقدار، " . number_format((int) ($bonusValues[0]['customer'] ?? 0)) . ' ریال پاداش دریافت خواهید کرد.';
}
}
$message .= "\nنام کاربری: {$data['mobile']}\nورود به نرم افزار: {$this->Config('app_url')}";
$this->Send($data['mobile'], $message);
return response()->json($customer);
+40
View File
@@ -303,6 +303,46 @@ class Controller extends BaseController
return $amount > 0 && $amount !== 1.0;
}
public function jibitNcode($nationalCode, $mobile)
{
$counter = Cnt::where('key', 'jibit_counter')->first();
if (empty($counter)) {
$counter = new Cnt();
$counter->key = 'jibit_counter';
$counter->value = 0;
$counter->save();
}
$apiData['refresh'] = Http::withoutVerifying()->withToken(Storage::get('refreshTokenGibit'))
->post('https://napi.jibit.ir/ide/v1/tokens/generate', [
'apiKey' => 'J5WxrPxPOg',
'secretKey' => '7dgeE70xQXsQL7r36j3wif6X9',
])->json();
Storage::put('accessTokenGibit', $apiData['refresh']['accessToken']);
$response = Http::withoutVerifying()->withToken(Storage::get('accessTokenGibit'))
->get("https://napi.jibit.ir/ide/v1/services/matching?mobileNumber=$mobile&nationalCode=$nationalCode")
->json();
if ((isset($response['code'])) && $response['code'] == 'forbidden') {
$refreshToken = Http::withoutVerifying()->withToken(Storage::get('refreshTokenGibit'))
->post('https://napi.jibit.ir/ide/v1/tokens/generate', [
'apiKey' => 'J5WxrPxPOg',
'secretKey' => '7dgeE70xQXsQL7r36j3wif6X9',
])->json();
Storage::put('accessTokenGibit', $refreshToken['accessToken']);
Storage::put('refreshTokenGibit', $refreshToken['refreshToken']);
$response = Http::withoutVerifying()->withToken(Storage::get('accessTokenGibit'))
->get("https://napi.jibit.ir/ide/v1/services/matching?mobileNumber=$mobile&nationalCode=$nationalCode")
->json();
}
$counter->value = (int) $counter->value + 1;
$counter->save();
return $response;
}
public static function jibit($method, $p1 = null, $p2 = null, $p3 = null)
{
$counter = Cnt::where('key', 'jibit_counter')->first();
@@ -5,8 +5,10 @@ namespace App\Http\Controllers\Customer;
use App\DB\Te\TableEngine;
use App\Http\Controllers\Controller;
use App\Jobs\CheckOrder;
use App\Models\Customer;
use App\Models\Order;
use App\Models\Price;
use App\Models\Setting;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
@@ -111,6 +113,38 @@ class OrderController extends Controller
$this->Send(auth('customer')->user()->mobile,$message);
return response()->json($order);
}
public function profit_gold()
{
$customer = Customer::with(['wallet', 'orders'])
->findOrFail(auth('customer')->id());
$lastPrice = Price::latest('created_at')->value('price') ?? 0;
$goldAmount = $customer->wallet->first()->gold ?? 0;
$orders = $customer->orders;
$averagePrice = $orders->avg('price') ?? 0;
$averageFee = $orders->avg('fee') ?? 0;
$totalProfit = $orders->sum(fn ($order) => $order->direction === 1
? $order->profit_per_moment
: -$order->profit_per_moment);
$feeSingle = (float) (Setting::where('key', 'fee_single')->value('value') ?? config('fee.single', 0));
$currentPriceWithFee = $lastPrice + $feeSingle;
$averagePriceWithFee = $averagePrice + $averageFee;
return response()->json([
'current_portfolio_value' => $currentPriceWithFee * $goldAmount,
'average_portfolio_value' => $averagePriceWithFee * $goldAmount,
'unrealized_profit' => ($currentPriceWithFee - $averagePriceWithFee) * $goldAmount,
'average_price' => $averagePrice,
'average_fee' => $averageFee,
'total_profit' => $totalProfit,
'gold_holdings' => $goldAmount,
'customer' => $customer->makeHidden(['password', 'token_sms']),
]);
}
public function table(Request $request){
$records = Order::where('customer_id',auth('customer')->id())
->where('type',1);
@@ -226,27 +226,6 @@ class WalletController extends Controller
if (Customer::where("id", $customer->id)->first()->token_sms != $request->otp) {
return response()->json(['message' => 'رمز دوم اشتباه میباشد'], 422);
}
/* try {
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . $this->ConfigService('liman_token')
])->post('https://limangold.ir/kernel/customer/fin', [
'receive_bank_shaba' => $bCart->shaba_number,
'receive_bank_card' => $bCart->cart_number,
'receive_name' => $customer->name,
'receive_account_number' => $bCart->account_number,
'description' => $this->ConfigService('name_fa') . ' | ' . $customer->mobile . ' | ' . $customer->name . ' | ' . $Withdraw->id,
'amount' => '1000'
])->json();
if (isset($response['id'])) {
$Withdraw->note = $response['id'];
$Withdraw->save();
$message = "کاربر $userName با شماره موبایل $userMobile درخواست برداشت مبلغ " . number_format($withdrawAmount) . " ثبت کرد و به لیمان منتقل شد. با تشکر، $companyName";
} else {
$message = "کاربر $userName با شماره موبایل $userMobile درخواست برداشت مبلغ " . number_format($withdrawAmount) . " ریال را دارد. با تشکر، $companyName";
}
} catch (Exception $e) {
$message = "کاربر $userName با شماره موبایل $userMobile درخواست برداشت مبلغ " . number_format($withdrawAmount) . " ریال را دارد. با تشکر، $companyName";
}*/
}
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->Send($admin->mobile, $message . ' ' . now()->format('H:i:s'));
@@ -42,7 +42,7 @@ class SingleOrderController extends Controller
return filter_var($value, FILTER_VALIDATE_BOOLEAN);
};
if ($toBool($config->Config('montzar_price'))) {
if ($config->usesMontzarPricing()) {
$montzar_closed = $toBool($config->Config('montzar_closed'));
$montzar_buy = !$toBool($config->Config('montzar_open_buy')) && (int) $data['direction'] === 1;
$montzar_sell = !$toBool($config->Config('montzar_open_sell')) && (int) $data['direction'] === 2;
@@ -507,7 +507,7 @@ class SingleOrderController extends Controller
private function sendProviderOrder(array &$data, $wallet_interface, int $direction)
{
if ($this->Config('montzar_price') == "true") {
if (app(\App\Services\ConfigService::class)->usesMontzarPricing()) {
try {
return app(MontzarService::class)->sendOrder($data);
} catch (UnprocessableEntityHttpException $e) {
+26 -9
View File
@@ -10,6 +10,7 @@ use App\Models\Setting;
use App\Models\ConfigStatic;
use App\Models\Customer;
use App\Services\MontzarService;
use App\Services\EtehadiePriceService;
use App\Models\Price;
use App\Models\PriceCandle;
use App\Models\PriceTrigger;
@@ -140,6 +141,7 @@ class ReportController extends Controller
$closed = false;
$montzar_price = 0;
$etehadie_teh = 0;
$tgn = 0;
$pr_price = 0;
@@ -165,11 +167,14 @@ class ReportController extends Controller
'main_product' => 0,
'taban_gohar' => 0,
'montzar' => 0,
'etehadie_teh' => 0,
'closed' => true,
'time' => now(),
]);
};
$priceProvider = $config->priceProvider();
/*
|--------------------------------------------------------------------------
| بستن قیمت طبق منطق قبلی
@@ -222,14 +227,22 @@ class ReportController extends Controller
$diff_buy = (float) $settingsMap->get('buy_fee', $difference);
$diff_sell = (float) $settingsMap->get('sell_fee', $difference);
$montzar_price_enabled = $toBool($config->Config('montzar_price'));
/*
|--------------------------------------------------------------------------
| اتحادیه (گلد علی / refPricer) — فقط وقتی price_provider=etehadie
|--------------------------------------------------------------------------
*/
if ($priceProvider === 'etehadie' && !$closed) {
$etehadie = app(EtehadiePriceService::class)->fetchMainGramPrice();
$etehadie_teh = (int) ($etehadie['price'] ?? 0);
}
/*
|--------------------------------------------------------------------------
| Montzar - اولویت اول
| Montzar — فقط وقتی price_provider=montzar
|--------------------------------------------------------------------------
*/
if ($montzar_price_enabled && !$closed) {
if ($priceProvider === 'montzar' && !$closed) {
try {
$montzarBaseUrl = rtrim($config->Config('montzar_base_url') ?: 'https://montpar.ir', '/');
$montzarProductId = (int) ($config->Config('montzar_product_id') ?: 25);
@@ -347,18 +360,19 @@ class ReportController extends Controller
/*
|--------------------------------------------------------------------------
| انتخاب قیمت اصلی
| اولویت:
| Montzar -> Taban Gohar -> Main Product
| انتخاب قیمت اصلی (همان price_provider)
|--------------------------------------------------------------------------
*/
if ($montzar_price_enabled && ($montzar_price ?? 0) !== 0 && !$closed) {
if ($priceProvider === 'etehadie' && $etehadie_teh > 0 && !$closed) {
$priceValue = (int) $etehadie_teh;
$priceSource = 'etehadie';
} elseif ($priceProvider === 'montzar' && ($montzar_price ?? 0) !== 0 && !$closed) {
$priceValue = (int) $montzar_price;
$priceSource = 'montzar';
} elseif ($toBool($taban_gohar_price) && ($tgn ?? 0) !== 0 && !$closed) {
} elseif ($priceProvider === 'taban_gohar' && $toBool($taban_gohar_price) && ($tgn ?? 0) !== 0 && !$closed) {
$priceValue = $tgn;
$priceSource = 'taban_gohar';
} elseif ($toBool($main_product_price) && ($pr_price ?? 0) !== 0 && !$closed) {
} elseif ($priceProvider === 'main_product' && $toBool($main_product_price) && ($pr_price ?? 0) !== 0 && !$closed) {
$priceValue = $pr_price;
$priceSource = 'main_product';
} else {
@@ -376,6 +390,7 @@ class ReportController extends Controller
'main_product' => $pr_price ?? 0,
'taban_gohar' => $tgn ?? 0,
'montzar' => $montzar_price ?? 0,
'etehadie_teh' => $etehadie_teh ?? 0,
'closed' => true,
'time' => now(),
]);
@@ -392,6 +407,7 @@ class ReportController extends Controller
'main_product' => $pr_price ?? 0,
'taban_gohar' => $tgn ?? 0,
'montzar' => $montzar_price ?? 0,
'etehadie_teh' => $etehadie_teh ?? 0,
'closed' => true,
'time' => now(),
]);
@@ -488,6 +504,7 @@ class ReportController extends Controller
'main_product' => $pr_price ?? 0,
'taban_gohar' => $tgn ?? 0,
'montzar' => $montzar_price ?? 0,
'etehadie_teh' => $etehadie_teh ?? 0,
'closed' => false,
'time' => now(),
]);
@@ -0,0 +1,210 @@
<?php
namespace App\Http\Controllers\Site;
use App\Http\Controllers\Controller;
use App\Models\Cnt;
use App\Models\Customer;
use App\Models\Order;
use App\Models\Price;
use App\Models\TransactionsAdmin;
use App\Models\User;
use App\Models\Withdraw;
use Illuminate\Http\Request;
use Rooyesh\Wallet\interfaces\TransactionInterface;
use Rooyesh\Wallet\interfaces\WalletInterface;
use Rooyesh\Wallet\models\Transaction;
use Rooyesh\Wallet\models\Wallet;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
class RequestsController extends Controller
{
public function order(Request $request)
{
$data = $request->all();
$transactionType = $data['method'] == 'cash' ? 'ریالی' : 'طلایی';
$customer_id = Customer::where('mobile', $request->mobile)->first()?->id;
if (!$customer_id) {
throw new UnprocessableEntityHttpException('کاربری با این شماره موبایل یافت نشد.');
}
$data['customer_id'] = $customer_id;
$latestPrice = Price::latest()->first();
$data['price'] = $latestPrice->price;
$data['price_id'] = $latestPrice->id;
$data['difference'] = 0;
$data['service_charge_percentage'] = 0;
$data['pay_at'] = now();
$data['sts'] = 2;
$data['type'] = 2;
$data['payment_sts'] = 4;
$data['price_original'] = $data['price'];
$data['total_price_original'] = $data['amount'] * ($data['price_original'] ?? 0);
$data['payment_remind'] = 0;
$data['fee'] = $data['difference'];
$data['total_fee'] = $data['amount'] * $data['difference'];
$myCustomer = Customer::find($customer_id);
$wallet_interface = new WalletInterface($customer_id, 2);
$wallet = Wallet::where('owner', $customer_id)->whereNull('fund_id')->first();
$response = [];
// === اینجا قبلاً return بود و همه چیز قطع می‌شد ===
if ($data['method'] == 'cash') {
$response['cash'] = $this->processCashTransaction($data, $wallet, $wallet_interface, $myCustomer);
} else if ($data['method'] == 'gold') {
$response['gold'] = $this->processGoldTransaction($data, $wallet, $wallet_interface, $myCustomer);
}
$response['Notifications'] = $this->sendTransactionNotifications($data, $transactionType);
return response()->json($response);
}
public function getWallet(Request $request)
{
$customer_id = Customer::where('mobile', $request->mobile)->first()?->id;
if($customer_id && $customer_id !== null){
$wallet = Wallet::select(['owner','gold','cash'])->where('owner',$customer_id)->first();
}else{
throw new UnprocessableEntityHttpException('کاربری با این شماره موبایل یافت نشد.');
}
return $wallet;
}
//for orders
private function processCashTransaction(&$data, $wallet, $wallet_interface,$myCustomer)
{
$response = [];
// $data['price'] += $data['difference'];
$data['total_price'] = $data['amount'] /** $data['price']*/;
$data['payment_amount'] = $data['total_price'];
// $data['service_charge'] = $data['service_charge_percentage'] * $data['amount'];
// $data['service_charge_price'] = $data['service_charge'] * $data['price_original'];
// $data['amount'] -= $data['service_charge'];
if ($wallet->cash < $data['payment_amount']) {
throw new UnprocessableEntityHttpException('موجودی شما کمتر از میزان سفارش است');
}
// $data['order'] = $order = Order::create($data);
new TransactionInterface($wallet_interface, [
"cash" => $data['payment_amount'],
"gold" => 0,
'expire_at' => now(),
'active' => true,
// 'order_id' => $order->id,
'start_at' => now(),
], 4, true, false);
$response['1'] = 2;
return $response;
}
private function processGoldTransaction(&$data, $wallet, $wallet_interface,$myCustomer)
{
// if ($data['amount'] < 0.06){
// throw new UnprocessableEntityHttpException('کمترین مقدار مجاز برای فروش 60 سوت است.');
//
// }
// $data['price'] -= $data['difference'];
$montifyCompanyName = $this->Config('montify_name');
$data['total_price'] = $data['amount'] * $data['price'];
$data['payment_amount'] = $data['total_price'];
$data['service_charge'] = $data['service_charge_percentage'] * $data['amount'];
$data['service_charge_price'] = $data['service_charge'] * $data['price_original'];
$data['total_price'] = $data['amount'] * $data['price'] -$data['service_charge_price'];
$data['payment_amount'] = $data['total_price'];
$data['payment_amount'] -= $data['service_charge_price'];
if ($wallet->gold < $data['amount']) {
throw new UnprocessableEntityHttpException('موجودی شما کمتر از میزان سفارش است');
}
$data['direction'] = 2;
$data['description'] = "فروش {$data['amount']} گرم طلا برای $montifyCompanyName توسط کاربر {$myCustomer->name} با شماره موبایل {$myCustomer->mobile}";
$data['order'] = $order = Order::create($data);
new TransactionInterface($wallet_interface, [
"gold" => $data['amount'],
"cash" => 0,
'expire_at' => now(),
'active' => true,
'order_id' => $order->id
], 10, false, true);
}
private function sendTransactionNotifications(array $data, string $transactionType)
{
$customer = Customer::findOrFail($data['customer_id']);
$companyName = $this->Config('name_fa');
$montifyCompanyName = $this->Config('montify_name');
if($data['method'] == 'cash') {
$message = "کاربر {$customer->name} با شماره موبایل {$customer->mobile} اقدام به برداشت موجودی از طرف $montifyCompanyName به مقدار " .
"{$data['amount']} ریال " . " کرد. با تشکر، $companyName";
}elseif ($data['method'] == 'gold') {
$message = "کاربر {$customer->name} با شماره موبایل {$customer->mobile} اقدام به $transactionType طلا به مقدار " .
"{$data['amount']} گرم به مبلغ " . number_format($data['total_price']) .
" ریال کرد. با تشکر، $companyName";
}
User::where('send_sms', 1)->get()->each(function ($admin) use ($message, $data, $transactionType, $companyName) {
$this->send($admin->mobile, $message);
});
// User::whereNotNull('telegram')->get()->each(function ($admin) use ($message, $data, $transactionType, $companyName) {
// $this->SendTelegram($admin->telegram, $message);
// });
// $messageold = "کاربر {$customer->name} با شماره موبایل {$customer->mobile} اقدام به $transactionType طلا به مقدار " .
// "{$data['amount']} گرم به مبلغ " . number_format($data['total_price']) .
// " ریال کرد. با تشکر، $companyName";
// $azOrTa = $data['direction'] == 1 ? 'از' : 'به';
// $messageExam = "
// {$transactionType} قلک طلا $azOrTa شما
// {$data['amount']} گرم
// در مظنه
// " . number_format($data['price_original']) . " ریال";
//
//
//// User::whereNotNull('telegram')->get()->each(function ($admin) use ($messageExam) {
//// $this->SendTelegram($admin->telegram, $messageExam);
//// });
// User::where('send_sms', 1)->get()->each(function ($admin) use ($messageExam) {
// $this->send($admin->mobile, $messageExam);
// });
$wallet = Wallet::where('owner', $data['customer_id'])->whereNull('fund_id')->first();
if($data['method'] == 'cash') {
$pricePerGram = $data['total_price'];
}elseif ($data['method'] == 'gold') {
$pricePerGram = $data['total_price'] / $data['amount'];
}
if($data['method'] == 'cash') {
$customerMessage = "$companyName\nبرداشت ریالی \nمبلغ: {$data['amount']}\n" .
"\nموجودی طلایی: {$wallet->gold}\n" .
"مانده ریالی: " . number_format($wallet->cash) . "\n" . $this->Config('app_url');
}elseif ($data['method'] == 'gold') {
$customerMessage = "$companyName\nبرداشت طلایی \nگرم: {$data['amount']}\nقیمت گرم: " . number_format($pricePerGram) .
"\nمبلغ کل: " . number_format($data['total_price']) . "\nموجودی طلایی: {$wallet->gold}\n" .
"مانده ریالی: " . number_format($wallet->cash) . "\n" . $this->Config('app_url');
}
// $customerMessage = "$companyName\n$transactionType آبشده\nگرم: {$data['amount']}\nقیمت گرم: " . number_format($pricePerGram) .
// "\nمبلغ کل: " . number_format($data['total_price']) . "\n\nموجودی طلایی: {$wallet->gold}\n" .
// "مانده ریالی: " . number_format($wallet->cash) . "\n" . $this->Config('app_url');
// ارسال SMS به مشتری
$this->send($customer->mobile, $customerMessage);
}
}
+189 -102
View File
@@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
use App\Models\Customer;
use App\Models\User;
use App\Models\Withdraw;
use App\Services\ConfigService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Rooyesh\Wallet\interfaces\TransactionInterface;
@@ -13,167 +14,253 @@ use Rooyesh\Wallet\interfaces\WalletInterface;
class paypingController extends Controller
{
private function cfg(): ConfigService
{
return app(ConfigService::class);
}
private function paypingHeaders(): array
{
return [
'payping' => $this->cfg()->getString(
'payping_header_secret',
(string) config('payment.payping_header_secret', '')
),
];
}
private function paypingStartUrl(): string
{
return $this->cfg()->getString(
'payping_start_url',
(string) config('payment.payping_start_url', 'https://payping.limangold.ir/payment/start')
);
}
private function paypingVerifyUrl(): string
{
return $this->cfg()->getString(
'payping_verify_url',
(string) config('payment.payping_verify_url', 'https://payping.limangold.ir/payment/verify')
);
}
/** اگر payping_gateway_items پر باشد (با کاما)، مثل گلد علی بین itemها می‌چرخد */
private function resolveGatewayItem(): string
{
$list = $this->cfg()->getString('payping_gateway_items', '');
if ($list === '') {
return $this->cfg()->getString('payping_gateway_item', (string) config('payment.payping_gateway_item', 'gp1Q'));
}
$items = array_values(array_filter(array_map('trim', explode(',', $list))));
if ($items === []) {
return 'gp1Q';
}
$index = (int) cache()->get('payping_gateway_item_index', 0);
if ($index >= count($items)) {
$index = 0;
}
$item = $items[$index];
cache()->put('payping_gateway_item_index', $index + 1);
return $item;
}
public function startTransation(Request $request)
{
$user = auth()->user();
$finalPriseP = $request->value;
if ($user->id ==4){
$finalPriseP =10700;
if ($user->id == 4) {
$finalPriseP = 10700;
}
if ($this->cfg()->getBool('payping_round_toman', (bool) config('payment.payping_round_toman', false))) {
$finalPriseP = (int) (ceil($finalPriseP / 10) * 10);
}
$Withdraw = Withdraw::create([
'customer_id' => auth('customer')->id(),
"cash" => $finalPriseP,
"note" => "واریز ریالی",
'cash' => $finalPriseP,
'note' => 'واریز ریالی',
'sts' => 1,
]);
try {
$response = Http::withHeaders([
'payping' => '@XOKcNveJ$wpqYy%rdpb78oBh31Aos*bIdQemiUeeq9e9G!oey23SMXp40Ew2fodjx9J5buKNW0M4@nYMr1PR6d0KtuqhLQlx*K$', // Custom header with 'payping' value
])->post("https://payping.limangold.ir/payment/start", [
"amount" => $finalPriseP/10, // Payment amount
"user_name" => $user->name, // User name
"user_id" => $user->id, // User ID
"user" => $user, // User ID
"title" => $this->Config('name_fa'), // Title of the payment
"return_url" => "https://".$this->Config('app_url')."/transactions", // Callback URL
"server_call_url" => url("/customer/charge_account_verify/".$Withdraw->id), // Callback URL
"item" => "gp1Q", // Item identifier
])->json();
}catch (\Exception $exception){
return response()->json(["message"=>"مشکل در ارتباط با درگاه","R"=>$response??$exception,], 422);
if (isset($request->order_id)) {
$Withdraw->order_id = $request->order_id;
if (isset($request->product_id)) {
$Withdraw->product_id = $request->product_id;
}
$Withdraw->save();
}
$payload = [
'amount' => $finalPriseP / 10,
'user_name' => $user->name,
'user_id' => $user->id,
'user' => $user,
'title' => $this->Config('name_fa'),
'return_url' => 'https://' . $this->Config('app_url') . '/transactions',
'server_call_url' => url('/customer/charge_account_verify/' . $Withdraw->id),
'item' => $this->resolveGatewayItem(),
];
$gatewayName = $this->cfg()->getString('payping_gateway_name', (string) config('payment.payping_gateway_name', ''));
if ($gatewayName !== '') {
$payload['gateway'] = $gatewayName;
}
try {
$response = Http::withHeaders($this->paypingHeaders())
->post($this->paypingStartUrl(), $payload)
->json();
} catch (\Exception $exception) {
return response()->json([
'message' => 'مشکل در ارتباط با درگاه',
'R' => $response ?? $exception,
], 422);
}
if (empty($response['id']) || empty($response['url'])) {
return response()->json([
'message' => 'مشکل در ارتباط با درگاه',
'R' => $response ?? null,
], 422);
}
$Withdraw->tracked_number = $response['id'];
$Withdraw->save();
return $response['url'];
return response()->json(["res"=>$response], 422);
}
public function verifyTransationByID(Request $request ,$id)
public function verifyTransationByID(Request $request, $id)
{
if ($request->header('payping') !== '@XOKcNveJ$wpqYy%rdpb78oBh31Aos*bIdQemiUeeq9e9G!oey23SMXp40Ew2fodjx9J5buKNW0M4@nYMr1PR6d0KtuqhLQlx*K$') {
$expectedSecret = $this->cfg()->getString(
'payping_header_secret',
(string) config('payment.payping_header_secret', '')
);
if ($request->header('payping') !== $expectedSecret) {
return response()->json(['auth needed'], 401);
}
$Withdraw = Withdraw::with('customer')->where('id',$id)->first();
$Withdraw = Withdraw::with('customer')->where('id', $id)->first();
$app_url = $this->Config('app_url');
$User = Customer::where('id', $Withdraw->customer_id)->first();
$GTransaction = Http::withHeaders([
'payping' => '@XOKcNveJ$wpqYy%rdpb78oBh31Aos*bIdQemiUeeq9e9G!oey23SMXp40Ew2fodjx9J5buKNW0M4@nYMr1PR6d0KtuqhLQlx*K$', // Custom header with 'payping' value
])->post("https://payping.limangold.ir/payment/verify", [
"id" => "$Withdraw->tracked_number",
])->json();
if (isset( $GTransaction['active']) and $GTransaction['active'] == 5) {
$GTransaction = Http::withHeaders($this->paypingHeaders())
->post($this->paypingVerifyUrl(), [
'id' => (string) ($Withdraw->tracked_number ?? $Withdraw->zify_code),
])
->json();
if (isset($GTransaction['active']) && $GTransaction['active'] == 5) {
if ($Withdraw->cash == $GTransaction['amount'] * 10) {
$Withdraw->zify_code = $Withdraw->tracked_number;
$Withdraw->tracked_number = $GTransaction['invoiceNo'];//ok
$Withdraw->sts = 2;//ok
$Withdraw->tracked_number = $GTransaction['invoiceNo'];
$Withdraw->sts = 2;
$Withdraw->save();
$wallet_interface_fund = new WalletInterface($User->id, $User->type);
$transaction = new TransactionInterface($wallet_interface_fund, $_inp = [
"cash" => $GTransaction['amount'] * 10,
new TransactionInterface($wallet_interface_fund, [
'cash' => $GTransaction['amount'] * 10,
'expire_at' => now(),
'withdraw_id' => $Withdraw->id,
'active' => true
'active' => true,
], 3, false, true);
//----------sms
$userMobile = $Withdraw->customer->mobile; // User's mobile number
$userName = $Withdraw->customer->name; // User's name
$chargedAmount = $Withdraw->cash; // Charged amount
$companyName = $this->Config('name_fa'); // Company name from configuration
$message = "کاربر $userName با شماره موبایل $userMobile حساب خود را به مقدار " . number_format($chargedAmount) . " ریال شارژ کرد. با تشکر، $companyName";
User::where('send_sms', 1)->get()->each(function($admin) use ($message) {
$message = 'کاربر ' . $Withdraw->customer->name . ' با شماره موبایل ' . $Withdraw->customer->mobile
. ' حساب خود را به مقدار ' . number_format($Withdraw->cash) . ' ریال شارژ کرد. با تشکر، ' . $this->Config('name_fa');
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->Send($admin->mobile, $message);
});
return view('showTransactionReport', compact('Withdraw','app_url'));
return redirect('https://app.gholaktala.ir/transactions');
return view('showTransactionReport', compact('Withdraw', 'app_url'));
}
return "مبلغ پرداختی دستکاری شده !";
} else {
$Withdraw->tracked_number;
$Withdraw->sts = 3;//no
$Withdraw->save();
return view('showTransactionReport', compact('Withdraw','app_url'));
return 'مبلغ پرداختی دستکاری شده !';
}
if ($this->cfg()->getBool('payping_strict_failed_withdraw', (bool) config('payment.payping_strict_failed_withdraw', false))) {
if (!$Withdraw->zify_code) {
$Withdraw->priority = 51;
}
$Withdraw->priority = 111;
}
$Withdraw->sts = 3;
$Withdraw->save();
return view('showTransactionReport', compact('Withdraw', 'app_url'));
}
public function verifyTransation()
{
$Withdraw = Withdraw::with('customer')->where('id', $_GET['clientrefid'])->first();
$app_url = $this->Config('app_url');
$User = Customer::where('id', $Withdraw->customer_id)->first();
$url = 'https://zify.ir/api/order/v2/verify';
$payload = [
"order" => "$Withdraw->tracked_number",
];
$verifyResponse = Http::withToken("cf09ee0187335f173c786e7660d778d2dd71ab582d282999f751427f5923d525")
->post($url, $payload);
$verifyResponse = Http::withToken('cf09ee0187335f173c786e7660d778d2dd71ab582d282999f751427f5923d525')
->post('https://zify.ir/api/order/v2/verify', [
'order' => (string) $Withdraw->tracked_number,
]);
$decodedResponse = json_decode($verifyResponse, true);
$verifyMessage = $decodedResponse['message'];
// return $decodedResponse['data'];
$verifyMessage = $decodedResponse['message'] ?? null;
if (isset($decodedResponse['data']['refid']) || $verifyMessage == []) {
if ($Withdraw->cash == $decodedResponse['data']['amount'] * 10) {
$Withdraw->zify_code = $Withdraw->tracked_number;//ok
$Withdraw->tracked_number = $decodedResponse['data']['refid'];//ok
$Withdraw->sts = 2;//ok
$Withdraw->zify_code = $Withdraw->tracked_number;
$Withdraw->tracked_number = $decodedResponse['data']['refid'];
$Withdraw->sts = 2;
$Withdraw->save();
$wallet_interface_fund = new WalletInterface($User->id, $User->type);
$transaction = new TransactionInterface($wallet_interface_fund, $_inp = [
"cash" => $decodedResponse['data']['amount'] * 10,
new TransactionInterface($wallet_interface_fund, [
'cash' => $decodedResponse['data']['amount'] * 10,
'expire_at' => now(),
'withdraw_id' => $_GET['clientrefid'],
'active' => true
'active' => true,
], 3, false, true);
$User = Customer::where('id', $Withdraw->customer_id)->first();
$url = 'https://limangold.ir/kernel/admin/fin';
$payload = [
"amount" => $decodedResponse['data']['amount'] * 10,
"customer_id" => "23",
"date_at" => \Carbon\Carbon::today()->format('Y/m/d'),
"receive_account_number" => "000",
"receive_bank" => "پیپینگ",
"receive_name" => "لیمان گلد",
"send_account_number" => "000",
"send_bank" => " زیفای کد $Withdraw->zify_code",
"send_name" => $User->name,
"track_number" => $decodedResponse['data']['refid'],
"type" => 1,
];
$verifyResponse = Http::withToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvbGltYW5nb2xkLmlyXC9rZXJuZWxcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNzI3NTMwNjA0LCJleHAiOjE3MzAxMjI2MDQsIm5iZiI6MTcyNzUzMDYwNCwianRpIjoiYXBINmlPZXlGTE9oTUhRdyIsInN1YiI6MiwicHJ2IjoiMjNiZDVjODk0OWY2MDBhZGIzOWU3MDFjNDAwODcyZGI3YTU5NzZmNyJ9.IrO6icD-EXjgZ3mYyeEAP4aqG7q35yJTCU_hQhEDGwk")
->post($url, $payload);
//----------sms
// User information
$userMobile = $Withdraw->customer->mobile; // User's mobile number
$userName = $Withdraw->customer->name; // User's name
$chargedAmount = $Withdraw->cash; // Charged amount
// Company name
$companyName = $this->Config('name_fa'); // Company name from configuration
if ($this->cfg()->getBool('payping_fin_sync_enabled', (bool) config('payment.payping_fin_sync_enabled', false))) {
$finUrl = $this->cfg()->getString('payping_fin_url', 'https://limangold.ir/kernel/admin/fin');
$finToken = $this->cfg()->getString('payping_fin_token', '');
if ($finUrl !== '' && $finToken !== '') {
Http::withToken($finToken)->post($finUrl, [
'amount' => $decodedResponse['data']['amount'] * 10,
'customer_id' => $this->cfg()->getString('payping_fin_customer_id', '23'),
'date_at' => \Carbon\Carbon::today()->format('Y/m/d'),
'receive_account_number' => '000',
'receive_bank' => 'پیپینگ',
'receive_name' => $this->Config('name_fa'),
'send_account_number' => '000',
'send_bank' => ' زیفای کد ' . $Withdraw->zify_code,
'send_name' => $User->name,
'track_number' => $decodedResponse['data']['refid'],
'type' => 1,
]);
}
}
// Constructing the SMS message
$message = "کاربر $userName با شماره موبایل $userMobile حساب خود را به مقدار " . number_format($chargedAmount) . " ریال شارژ کرد. با تشکر، $companyName";
$message = 'کاربر ' . $Withdraw->customer->name . ' با شماره موبایل ' . $Withdraw->customer->mobile
. ' حساب خود را به مقدار ' . number_format($Withdraw->cash) . ' ریال شارژ کرد. با تشکر، ' . $this->Config('name_fa');
// Getting admin mobile numbers and sending the SMS
User::where('send_sms', 1)->get()->each(function($admin) use ($message) {
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->Send($admin->mobile, $message);
});
return view('showTransactionReport', compact('Withdraw','app_url'));
return redirect('https://app.gholaktala.ir/transactions');
return view('showTransactionReport', compact('Withdraw', 'app_url'));
}
return "مبلغ پرداختی دستکاری شده !";
} else {
$Withdraw->tracked_number;
$Withdraw->sts = 3;//no
$Withdraw->save();
return view('showTransactionReport', compact('Withdraw','app_url'));
return 'مبلغ پرداختی دستکاری شده !';
}
$Withdraw->sts = 3;
$Withdraw->save();
return view('showTransactionReport', compact('Withdraw', 'app_url'));
}
}
+1
View File
@@ -65,5 +65,6 @@ class Kernel extends HttpKernel
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'validation'=>ValidationMiddleware::class,
'request.validation' => \App\Http\Middleware\ValidateRequests::class,
];
}
+86
View File
@@ -0,0 +1,86 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
class ValidateRequests
{
public function handle(Request $request, Closure $next)
{
//HMAC
$clientId = $request->header('X-Client-Id');
$timestamp = $request->header('X-Timestamp');
$nonce = $request->header('X-Nonce');
$signature = $request->header('X-Signature');
if (!$clientId || !$timestamp || !$nonce || !$signature) {
abort(401, 'Missing HMAC headers');
}
if ($clientId !== config('services.node.client_id')) {
abort(401, 'Invalid client id');
}
/** ✅ اینجا SECRET واقعاً استفاده می‌شود */
$secret = config('services.node.secret');
if (!$secret) {
abort(500, 'Node shared secret not configured');
}
$data = json_decode($request->getContent(), true);
ksort($data);
$normalized = json_encode(
$data,
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
);
$bodyHash = hash('sha256', $normalized);
// $bodyHash = hash('sha256', $request->getContent() ?? '');
$canonical = implode("\n", [
strtoupper($request->method()),
'/' . ltrim($request->path(), '/'),
$bodyHash,
$timestamp,
$nonce,
]);
$expectedSignature = hash_hmac(
'sha256',
$canonical,
$secret
);
if (!hash_equals($expectedSignature, $signature)) {
abort(401, 'Invalid HMAC signature');
}
// return $next($request);
//ANTI REPLAY
$timestamp = (int)$request->header('X-Timestamp');
$nonce = $request->header('X-Nonce');
if (abs(time() - $timestamp) > 99999999999999999) {
abort(401, 'Expired request');
}
$key = "node_nonce:{$nonce}";
if (Cache::has($key)) {
abort(401, 'Replay attack detected');
}
Cache::put($key, true, 60);
return $next($request);
}
}
-26
View File
@@ -20,30 +20,4 @@ class Cnt extends Model
protected $casts = [
'value_json'=>'array'
];
/* public function goldir_login(){
$mobile = self::where('key', 'goldir_mobile')->value('value');
$password = self::where('key', 'goldir_password')->value('value');
$goldir_base_url=Controller::Config('goldir_base_url')??'https://gold.ir';
$goldir = Http::withOptions([
'curl' => [
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
CURLOPT_TCP_FASTOPEN => 1,
]
])
->withoutVerifying()
->post($goldir_base_url.'/server/auth/login', [
'mobile' => $mobile,
'password' => $password,
'provider' => 'customer',
'type_app' => 'client',
])->json();
Cnt::where('key', 'goldir')->update([
'value' => $goldir['access_token'],
'updated_at' => now()
]);
return $goldir['access_token'];
}*/
}
+6
View File
@@ -156,6 +156,12 @@ class Product extends Model
public function transaction(){
return $this->hasMany(Transaction::class);
}
public function limitedTransactions()
{
return $this->hasMany(Transaction::class)->select('id', 'gold', 'title', 'created_at', 'product_id');
}
public function transactionAgentPanel(){
return $this->hasMany(Transaction::class)->where('note','برداشت بابت فروش')->orwhere('note','واریز بابت خرید')->orwhere('note','سند ورود طلا');
}
+94 -2
View File
@@ -6,9 +6,101 @@ use App\Models\Setting;
class ConfigService
{
public const PRICE_PROVIDERS = ['montzar', 'etehadie', 'taban_gohar', 'main_product'];
public function Config($name)
{
return Setting::where('key', $name)->value('value') ?? false;
return $this->get($name, false);
}
/**
* مقدار setting؛ اگر نبود از config/price_providers.php یا default پارامتر.
*/
public function get(string $key, $default = null)
{
$row = Setting::where('key', $key)->first();
if ($row !== null && $row->value !== null && $row->value !== '') {
return $row->value;
}
$fromFile = config("price_providers.{$key}");
return $fromFile !== null ? $fromFile : $default;
}
public function getString(string $key, string $default = ''): string
{
$value = $this->get($key, $default);
return trim((string) ($value === false ? $default : $value));
}
public function getBool(string $key, bool $default = false): bool
{
$value = $this->get($key, $default);
if ($value === false || $value === null || $value === '') {
return $default;
}
return filter_var($value, FILTER_VALIDATE_BOOLEAN);
}
public function getInt(string $key, int $default = 0): int
{
$value = $this->get($key, $default);
return (int) ($value === false || $value === null || $value === '' ? $default : $value);
}
/**
* تنها منبع فعال قیمت — فقط یکی از: montzar | etehadie | taban_gohar | main_product
*
* اولویت:
* 1) price_provider (یا price_primary_source قدیمی)
* 2) montzar_price=true → montzar (ابشده خانگی و پروژه‌های فعلی)
* 3) price_method پر و montzar خاموش → etehadie (گلد علی)
* 4) پیش‌فرض فایل: montzar
*/
public function priceProvider(): string
{
foreach (['price_provider', 'price_primary_source'] as $key) {
$explicit = strtolower($this->getString($key, ''));
if (in_array($explicit, self::PRICE_PROVIDERS, true)) {
return $explicit;
}
}
if ($this->getBool('montzar_price', false)) {
return 'montzar';
}
if ($this->getString('price_method') !== '') {
return 'etehadie';
}
$default = strtolower((string) config('price_providers.price_provider', 'montzar'));
return in_array($default, self::PRICE_PROVIDERS, true) ? $default : 'montzar';
}
/** @deprecated از priceProvider() استفاده کن */
public function pricePrimarySource(): string
{
$provider = $this->priceProvider();
return in_array($provider, ['montzar', 'etehadie'], true) ? $provider : 'montzar';
}
public function usesMontzarPricing(): bool
{
return $this->priceProvider() === 'montzar';
}
public function usesEtehadiePricing(): bool
{
return $this->priceProvider() === 'etehadie';
}
public function UpdateConfig($name, $value)
@@ -53,4 +145,4 @@ class ConfigService
$this->UpdateConfig('down_price', $priceInt);
}
}
}
}
+143
View File
@@ -0,0 +1,143 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class EtehadiePriceService
{
public function __construct(private ConfigService $config)
{
}
public function isEnabled(): bool
{
return $this->config->usesEtehadiePricing();
}
public function apiUrl(): string
{
$url = trim((string) $this->config->getString(
'etehadie_api_url',
(string) config('price_providers.etehadie_api_url', 'http://109.122.246.48:4949/api/free')
));
return $url !== '' ? $url : 'http://109.122.246.48:4949/api/free';
}
/** کلید محصول در پاسخ API اتحادیه (همان price_method گلد علی) */
public function priceKey(): string
{
$key = trim((string) $this->config->getString(
'price_method',
(string) config('price_providers.price_method', '')
));
return $key;
}
/**
* @return array{price: int, raw: array<string, mixed>|null}
*/
public function fetchMainGramPrice(): array
{
if (!$this->isEnabled() && $this->priceKey() === '') {
return ['price' => 0, 'raw' => null];
}
try {
$prices = Http::withoutVerifying()
->timeout(20)
->get($this->apiUrl())
->json();
if (!is_array($prices)) {
return ['price' => 0, 'raw' => null];
}
$key = $this->priceKey();
$collection = collect($prices);
$row = $key !== ''
? $collection->firstWhere('key', $key)
: $collection->first();
if (empty($row)) {
return ['price' => 0, 'raw' => null];
}
$base = (float) ($row['price'] ?? 0);
$profit = (float) ($row['profit'] ?? 0);
$gramPrice = (int) round($base / 10 + $profit);
return ['price' => $gramPrice, 'raw' => $row];
} catch (\Throwable $e) {
Log::warning('Etehadie price fetch failed', ['message' => $e->getMessage()]);
return ['price' => 0, 'raw' => null];
}
}
/** @return array<int, array<string, mixed>>|null */
public function fetchPriceList(): ?array
{
try {
$prices = Http::withoutVerifying()
->timeout(20)
->get($this->apiUrl())
->json();
return is_array($prices) ? $prices : null;
} catch (\Throwable $e) {
Log::warning('Etehadie price list fetch failed', ['message' => $e->getMessage()]);
return null;
}
}
public function syncProductsFromApi(): bool
{
$prices = $this->fetchPriceList();
if ($prices === null) {
return false;
}
$products = \App\Models\Product::with([])->whereNotNull('reading_method')->get();
$collection = collect($prices);
$copper = null;
$dollar = null;
foreach ($products as $product) {
$RPrice = $collection->firstWhere('key', $product->reading_method);
if (empty($RPrice)) {
continue;
}
if (($RPrice['name'] ?? '') === 'TGJU فلز مس') {
$copper = ($RPrice['price'] ?? 0) + ($RPrice['profit'] ?? 0);
}
if (($RPrice['name'] ?? '') === 'TGJU دلار') {
$dollar = ($RPrice['price'] ?? 0) + ($RPrice['profit'] ?? 0);
}
if (($RPrice['name'] ?? '') === 'گلد دات ای از آبشده - رسمی - نقد فردا') {
$RPrice['price'] = ($RPrice['price'] ?? 0) / 4.3318;
}
ProductPriceService::syncFromReference(
$product,
(int) $RPrice['price'],
(int) ($RPrice['profit'] ?? 0)
);
}
if ($copper !== null && $dollar !== null) {
$cp = ($copper / 1000000) * $dollar;
$copperProduct = \App\Models\Product::find(33);
if ($copperProduct) {
ProductPriceService::syncFromReference($copperProduct, (int) round($cp), 0);
}
}
return true;
}
}