✏️ 正在编辑: Transactions.php
路径:
/srv/systems_dir/koruspay/application/models/Transactions.php
提示:
您可以编辑任何文件(包括二进制文件),但请注意不当修改可能导致文件损坏。
<?php use Carbon\Carbon; use Modules\Api\ApiFactory; use Modules\Api\TransfeeraService; class Model_Transactions extends Core_Model { private $_serviceApi = null; private $_countRequest = 0; const CHAVEHMAC = 'k0rusp4y'; public function __construct() { $this->_serviceApi = ApiFactory::load(); parent::__construct(); } public function display(int $id) { $dbTable = new Model_DbTable_Transactions(); $receipt = $dbTable->fetchRow(["id = ?" => $id]); if ($receipt) { return $receipt; } return false; } public function createTransaction($data, $company, $typeTransaction) { $tax = 'tax_' . strtolower($typeTransaction); $amountTax = $company->$tax; $type = 'type_tax_' . strtolower($typeTransaction); $typeTax = $company->$type; if (empty($typeTax) && $amountTax > 0) { $amountTax = $data['amount'] * ($amountTax / 100); } $dbTable = new Model_DbTable_Transactions(); $where = [ 'company_id = ?' => $company->id, 'payer_id = ?' => $data['payer_id'], 'id_integration = ?' => $data['id_integration'], 'origin = ?' => $data['origin'], 'due_date = ?' => $data['due_date'], 'amount = ?' => $data['amount'], 'type = ?' => $data['type'] ]; $receipt = $dbTable->fetchRow($where); if ($receipt) { return $receipt->id; } else { $data = [ 'company_id' => $company->id, 'payer_id' => $data['payer_id'], 'id_integration' => $data['id_integration'], 'description' => $data['description'], "due_date" => $data['due_date'], 'amount' => $data['amount'], 'discount' => $data['discount'], 'expiration_date' => $data['expiration_date'] ?: null, 'penalty' => $data['penalty'], 'origin' => $data['origin'], 'amount_tax' => $amountTax, 'type' => $data['type'], 'situation' => 'PENDENTE', ]; $id = $dbTable->insert($data); if (empty($id)) { throw new Exception('Ocorreu um erro ao salvar o recebimento'); } return $id; } } public static function updateTransaction(int $id, array $data) { $dbTable = new Model_DbTable_Transactions(); return $dbTable->update($data, ['id = ?' => $id]); } public function createChargeSplit(string $splitId, Model_Company $company) { $splitData = Model_Container::getSplit()->findByIdCrypt($splitId); $splitValues = $splitData->calculateTax(); $amountTotal = round($splitValues['total_split'] + $splitValues['amount_tax'], 2); $dbTable = new Model_DbTable_Transactions(); $where = [ 'company_id = ?' => (int) $company->id, 'split_id = ?' => $splitData->id, 'origin = ?' => $splitData->origin, 'type = ?' => 'CREDITO' ]; $receipt = $dbTable->fetchRow($where); if ($receipt) { $id = $receipt->id; if ($receipt->amount != $amountTotal) { $data = [ 'amount' => $amountTotal, 'amount_tax' => $splitValues['amount_tax'] ]; $dbTable->update($data, "id = " . $receipt->id) ? $receipt->id : null; } } else { $data = [ 'company_id' => $company->id, 'split_id' => $splitData->id, 'origin' => $splitData->origin, 'amount' => $amountTotal, 'amount_tax' => $splitValues['amount_tax'], 'description' => 'Crédito para pagamentos', 'type' => 'CREDITO', 'situation' => 'PENDENTE', "due_date" => Carbon::now()->format('Y-m-d') ]; $id = $dbTable->insert($data); } if (empty($id)) { throw new Exception('Ocorreu um erro ao salvar o recebimento'); } if ($receipt->invoice_id_pix) { $pix = $this->getCharge($id)['pix_qr_code']; } else { $pix = $this->createPixCredit($id); } //salva o valor para validação do valor máximo permitido para execução do split $splitData->amount = $splitValues['total_split']; $splitData->save(); return [ 'amount' => $amountTotal, 'qrcode' => $pix ? (new Core_Qrcode())->gerar($pix, 200) : null, 'copy_paste' => $pix ]; } public function createPixCredit(int $idTransaction) { $update = false; $dbTable = new Model_DbTable_Transactions(); $transaction = $dbTable->findTransactionCredit($idTransaction); try { $data = $this->_serviceApi->createInvoice($transaction, 'SPLIT'); $update = self::updateTransaction($idTransaction, $data); if ($update) { return $data['pix_qr_code']; } } catch (Throwable $tr) { $dataErro = [ "situation" => "ERRO", "status_description" => "Não foi possível criar PIX de Crédito: " . $tr->getMessage(), "date_error" => Carbon::now()->format('Y-m-d H:i:s') ]; self::updateTransaction($idTransaction, $dataErro); throw new Exception($tr->getMessage()); } } public static function updateReceipt(string $id, array $data) { $dbTable = new Model_DbTable_Transactions(); $dbTable->update($data, ["(invoice_id_pix = '{$id}' OR invoice_id_boleto = '{$id}')"]); $where = "(invoice_id_pix = '{$id}' OR invoice_id_boleto = '{$id}')"; return $dbTable->fetchRow($where); } public function insertBatchTransfers(array $itens, $splitData) { if (count($itens) == 0) { throw new Exception('Nenhuma transferência à enviar.'); } $success = 0; $totalAmount = $splitData->amount ?: array_sum((array_column($itens, 'amount'))); $dbTable = new Model_DbTable_Transactions(); foreach ($itens as $item) { Yuppie_Log::write("insertBatchTransfers => " . json_encode($item)); Yuppie_Log::write("insertBatchTransfers => TIPO DE AMOUNT: " . print_r($totalAmount, true) . " - AMOUNT * 100: " . (int)($totalAmount*100) . " - ITEM AMOUNT * 100: " . print_r((int)($item['amount']*100), true)); $balance = String_Refatorar::parseStringToFloat($totalAmount); if ($balance == 0 || (int)($balance*100) < (int)($item['amount']*100)) { Yuppie_Log::write("insertBatchTransfers entrou no IF de verificação do saldo restante com totalAmount = {$balance}" . " GET TYPE: " . gettype($balance)); break; } $payment = $dbTable->findPaymentBySplitItem((int) $item['id']); if ($payment) { Yuppie_Log::write("insertBatchTransfers => Pagamento já existente para o item {$item['id']}: ID Transaction {$payment->id}"); if ($payment->situation !== 'ERRO') { $success++; $totalAmount -= ($item['amount']*1); } continue; } $id = $dbTable->insert([ 'split_id' => $item['split_id'], 'split_item_id' => $item['id'], 'company_id' => $item['company_id'], 'description' => $item['description'], 'amount' => $item['amount'] * -1, 'situation' => $item['situation'], 'origin' => $item['origin'], 'type' => 'PAGAMENTO' ]); Yuppie_Log::write("insertBatchTransfers retorno do insert na tb_transactions => {$id}"); if (!empty($id)) { if ($this->createTransfer($id, 'PAGAMENTO')) { $success++; $totalAmount -= ($item['amount']*1); } } } //se for Transfeera, chama o closeLote para processar as transferências if ($this->_serviceApi instanceof TransfeeraService) { $service = new Core_Service_Transfeera($splitData->company_id); $loteId = $service->findLote((new Model_DbTable_Split())->findById($splitData->id)->number); $service->closeLote($loteId); } return $success; } public function createTransfer(int $idTransaction, string $type) { $update = false; $dbTable = new Model_DbTable_Transactions(); switch ($type) { case 'TARIFA'; $transaction = $dbTable->findTransactionTax($idTransaction); break; case 'PAGAMENTO'; $transaction = $dbTable->findTransactionPayment($idTransaction); break; case 'SAQUE'; $transaction = $dbTable->findTransactionWithdraw($idTransaction); // if (!self::validHashKey($transaction)) { // throw new Exception("Ação não permitida. Chave não validada!"); // }; break; } if (empty($transaction['company_id'])) { throw new Exception('Transaction sem Empresa vinculada'); } try { $this->_countRequest++; $data = $this->_serviceApi->createTransfer($transaction, $type); $update = $dbTable->update($data, "id = " . $idTransaction) ? true : false; $data['split_item_id'] = $transaction['split_item_id']; (new Model_SplitItens())->payOut($data); return $update; } catch (Core_Exception $e) { if ($e->getMessage() == "insufficient funds" && $this->_countRequest < 5) { sleep(20); return $this->createTransfer($idTransaction, $type); } $errorMessage = $e->getMessage(); } catch (Exception $error) { $errorMessage = $error->getMessage(); } $dataErro = [ "status_description" => "Não foi possível criar {$type}: " . $errorMessage, "situation" => "ERRO", "date_error" => Carbon::now()->format('Y-m-d H:i:s') ]; self::updateTransaction($idTransaction, $dataErro); if ($type === 'PAGAMENTO') { (new Model_DbTable_SplitItens)->updateItem($transaction['split_item_id'], $dataErro); } return false; } public static function updateTransfer(string $id, array $data) { $dbTable = new Model_DbTable_Transactions(); $update = $dbTable->update($data, ['transfer_id = ?' => $id]); if (empty($update)) { return false; } return $dbTable->fetchRow(["transfer_id = ?" => $id]); } public static function validHashKey($data) { if (empty($data['chave_pix']) || empty($data['company_id']) || empty($data['created_at']) || empty($data['security_hash'])) { return false; } $concat = $data['chave_pix'] . $data['company_id'] . $data['created_at']; $key = Core_Crypt::Decrypt($concat); if ($key === $data['security_hash']) { return true; } return false; // $hmac = hash_hmac('sha256', $concat, self::CHAVEHMAC); // if ($hmac === $data['security_hash']) { // return true; // } // return false; } public function createBatchPix(array $idsTransaction) { if (count($idsTransaction) == 0) { return false; } foreach ($idsTransaction as $id) { $this->createChargePix($id); } } public function createChargePix(int $idTransaction) { $update = false; $dbTable = new Model_DbTable_Transactions(); $transaction = $dbTable->findTransaction($idTransaction); try { if (!empty($transaction['invoice_id_pix'])) { return true; } $data = $this->_serviceApi->createInvoice($transaction, 'PIX'); $update = self::updateTransaction($idTransaction, $data); return $update; } catch (Exception $error) { $dataErro = [ "situation" => "ERRO", "status_description" => "Não foi possível criar cobrança de PIX: " . $error->getMessage(), "date_error" => Carbon::now()->format('Y-m-d H:i:s') ]; self::updateTransaction($idTransaction, $dataErro); return false; } } public function getCharge(int $idTransaction) { $dbTable = new Model_DbTable_Transactions(); $transaction = $dbTable->findTransaction($idTransaction); try { $data = $this->_serviceApi->getInvoiceDetail($transaction); self::updateTransaction($idTransaction, $data); return $data; } catch (Exception $error) { return false; } } public function createBatchBankSlip(array $idsTransaction) { if (count($idsTransaction) == 0) { return false; } foreach ($idsTransaction as $id) { $this->createChargeBankSlip($id); } } protected function _dataReturnCharge(array $data) { return [ 'koruspay_charge_id' => md5($data['id']), 'id_integration' => $data['id_integration'], "situation" => $data['situation'], "invoice_id_pix" => $data['invoice_id_pix'] ?: null, "invoice_id_boleto" => $data['invoice_id_boleto'] ?: null, "barcode" => $data['barcode'] ?: null, "digitable_line" => $data['digitable_line'] ?: null, "pix_qr_code" => $data['pix_qr_code'] ?: null, "pix_copy_paste" => $data['pix_copy_paste'] ?: null, "invoice_date" => $data['invoice_date'] ]; } public function createChargeBankSlip(int $idTransaction) { $dbTable = new Model_DbTable_Transactions(); $transaction = $dbTable->findTransaction($idTransaction); try { if (!empty($transaction['invoice_id_boleto'])) { return $this->_dataReturnCharge($transaction); } $data = $this->_serviceApi->createInvoice($transaction, 'BANKSLIP'); self::updateTransaction($idTransaction, $data); $data['id'] = $transaction['id']; return $this->_dataReturnCharge($data); } catch (Exception $error) { $dataErro = [ "situation" => "ERRO", "status_description" => "Não foi possível criar cobrança de Boleto: " . $error->getMessage(), "date_error" => Carbon::now()->format('Y-m-d H:i:s') ]; self::updateTransaction($idTransaction, $dataErro); } return false; } public function createTax($receipt) { if (empty($receipt)) { throw new Exception('Nenhuma tarifa à enviar.'); } if ($receipt['type'] == 'CREDITO' && !empty($receipt['split_id'])) { $receipt['amount_tax'] = $this->realTax($receipt); } $dbTable = new Model_DbTable_Transactions(); $where = [ 'company_id = ?' => $receipt['company_id'], 'description = ?' => 'Tarifa referente a ' . $receipt['type'], 'amount = ?' => $receipt['amount_tax'] * -1, 'origin = ?' => $receipt['origin'], 'type = ?' => 'TARIFA', 'parent_id = ?' => $receipt['id'], 'deleted = 0' ]; if (!empty($receipt['split_id'])) { $where['split_id = ?'] = $receipt['split_id']; } else { $where['split_id IS NULL'] = null; } $existingTax = $dbTable->fetchRow($where); if ($existingTax) { return; } $dbTable->insert([ 'company_id' => $receipt['company_id'], 'split_id' => $receipt['split_id'] ?? null, 'description' => 'Tarifa referente a ' . $receipt['type'], 'amount' => $receipt['amount_tax'] * -1, 'amount_paid' => $receipt['amount_tax'] * -1, 'situation' => 'CONCLUIDO', 'origin' => $receipt['origin'], 'type' => 'TARIFA', 'payment_date' => Carbon::now()->format('Y-m-d'), 'low_date' => Carbon::now()->format('Y-m-d H:i:s'), 'parent_id' => $receipt['id'] ]); } public function realTax($receipt) { $splitData = Model_Container::getSplit()->findByIdCrypt(md5($receipt['split_id'])); $splitValues = $splitData->calculateTax(); $realTax = $splitValues['amount_tax']; return round($realTax, 2); } public function balance($companyId) { $company = (Model_Container::getCompany())->findById($companyId); if (!empty($company->access_key)) { $balanceApi = $this->_serviceApi->getBalance($companyId); $balance['balance'] = $balanceApi ?: null; $balance['type_tax_pix'] = $company->type_tax_pix; $balance['tax_pix'] = $company->tax_pix; return $balance; } $dbTable = new Model_DbTable_Transactions(); $balance = $dbTable->getBalance($companyId); $balance['type_tax_pix'] = $company->type_tax_pix; $balance['tax_pix'] = $company->tax_pix; return $balance; } public function withdraw($companyId, $subtotal, $tax) { // $dbTable = new Model_DbTable_Transactions(); // $unpaidTax = $dbTable->unpaidTax($companyId); // if (count($unpaidTax) > 0) { // foreach ($unpaidTax as $tax) { // $data = $this->_serviceApi->getTaxDetail($tax); // self::updateTransfer($tax['transfer_id'], $data); // } // throw new Exception('Algumas tarifas foram baixadas, recarregue para atualizar o saldo!'); // } $balance = [ 'company_id' => $companyId, 'sub_total' => $subtotal, 'tarifa' => $tax ]; $withdraw = $this->createWithdraw($balance); if ($withdraw) { $this->createTax($withdraw); $this->createTransfer($withdraw->id, 'SAQUE'); return true; } return false; } public function createWithdraw(array $balance) { if ($balance['sub_total'] <= 0) { throw new Exception('Não há saldo suficiente para saque.'); } $dbTable = new Model_DbTable_Transactions(); $id = $dbTable->insert([ 'company_id' => $balance['company_id'], 'description' => "Saque solicitado em " . Carbon::now()->format("d-m-Y"), 'amount' => $balance['sub_total'] * -1, 'amount_tax' => $balance['tarifa'], 'situation' => "CONCLUIDO", 'type' => 'SAQUE' ]); if (empty($id)) { throw new Exception('Saque não inserido.'); } return $dbTable->fetchRow(['id = ?' => $id]); } public function withdrawHistory(int $companyId, ?string $fromDate = null, ?string $toDate = null) { $dbTable = new Model_DbTable_Transactions(); $where['company_id'] = $companyId; if (!empty($fromDate)) { $where['created_at >= ?'] = $fromDate . ' 00:00:00'; } if (!empty($toDate)) { $where['created_at <= ?'] = $toDate . ' 23:59:59'; } $history = $dbTable->withdrawHistory($where); return $history; } public function getExtract($fields, $company) { $extract = $this->_serviceApi->getExtract($fields, $company); return $extract; } public static function updateOrCreateTransactionByExtract(string $id, array $data) { $dbTable = new Model_DbTable_Transactions(); $where = "(invoice_id_pix = '{$id}' OR invoice_id_boleto = '{$id}' OR transfer_id = '{$id}')"; $transaction = $dbTable->fetchRow($where); if (!empty($transaction)) { if (!in_array($transaction->situation, ['CONCLUIDO', 'RECEBIDO'])) { unset($data['created_at']); unset($data['company_id']); unset($data['description']); unset($data['amount']); unset($data['type']); } self::updateTransaction($transaction->id, $data); return false; } $transaction = $dbTable->insert($data); if (!empty($transaction)) { return true; } return false; } public static function balanceKorus() { $dbTable = new Model_DbTable_Transactions(); $lastWithdraw = $dbTable->lastWithdrawKorus(); $currentBalance = $dbTable->currentBalanceKorus($lastWithdraw['last_withdraw_at']); $balance = [ 'last_balance' => $lastWithdraw['last_balance'] ? $lastWithdraw['last_balance'] * -1: 0, 'last_withdraw_at' => $lastWithdraw['last_withdraw_at'] ?: null, 'last_withdraw' => $lastWithdraw['last_withdraw'] ? $lastWithdraw['last_withdraw'] * -1 : 0, 'remaining_balance' => $lastWithdraw['remaining_balance'] ? $lastWithdraw['remaining_balance'] * -1 : 0, 'current_balance' => String_Refatorar::parseStringToFloat($currentBalance['current_balance']), 'subtotal' => ($currentBalance['current_balance'] + ($lastWithdraw['remaining_balance'] * -1)) ?: 0 ]; return $balance; } public static function createWithdrawKorus($subtotal, $value) { $dbTable = new Model_DbTable_Transactions(); $id = $dbTable->insert([ 'company_id' => 0, 'description' => "Saque Korus solicitado em " . Carbon::now()->format("d-m-Y"), 'amount' => $subtotal * -1, 'amount_paid' => $value * -1, 'amount_tax' => 0, 'situation' => "PENDENTE", 'type' => 'SAQUE KORUS', ]); if (empty($id)) { throw new Exception('Saque não inserido.'); } return $dbTable->fetchRow(['id = ?' => $id]); } }
💾 保存文件
← 返回文件管理器