123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- <?php
- namespace App\Modules\Finance\Services;
- use App\Libs\Pay\SandPay;
- use App\Modules\Channel\Models\Channel;
- use App\Modules\Finance\Models\BatchPayments;
- use App\Modules\Finance\Models\FinancialConfig;
- use App\Modules\Finance\Models\FinancialStat;
- use App\Modules\Finance\Models\Payment;
- use App\Modules\Finance\Models\WithdrawCash;
- use App\Modules\Manage\Models\Manage;
- use Exception;
- use Illuminate\Support\Collection;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Log;
- use Redis;
- /**
- * 更优的打款结构
- */
- class AdvancedPaymentService
- {
- const wait_merge = '待合并';
- const wait_pay = '待打款';
- const auto_wait_pay = '自动待打款';
- const artifical_wait_pay = '人工待打款';
- const wait_pay_status = [
- self::wait_pay,
- self::auto_wait_pay,
- self::artifical_wait_pay,
- ];
- const artifical_success = '人工打款成功';
- const auto_success = '自动打款成功';
- const success = "打款成功";
- const success_status = [
- self::success,
- self::auto_success,
- self::artifical_success,
- ];
- const paying = "打款中";
- const auto_paying = "自动打款中";
- const artifical_paying = "人工打款中";
- const paying_status = [
- self::paying,
- self::auto_paying,
- self::artifical_paying,
- ];
- const auto_failure = '自动打款失败';
- public function findConfig(int $channel_id)
- {
- FinancialConfig::where('distribution_channel_id', $channel_id)->first();
- }
- public function findFinancialStat(int $channel_id)
- {
- return FinancialStat::where('distribution_channel_id', $channel_id)->first();
- }
- public function findWithdrawCash(int $withdraw_cash_id)
- {
- return WithdrawCash::where('id', $withdraw_cash_id)->first();
- }
- public function isWithdrawCashSuccess(string $status)
- {
- if (in_array($status, self::success_status)) {
- return true;
- }
- return false;
- }
- /**
- * 添加人工打款记录
- */
- private function addPayment(WithdrawCash $withdraw, string $trade_no, int $uid, string $remark)
- {
- $isCompanyName = $withdraw->is_company == 0 ? "对私" : "对公";
- $remark = "[" . $isCompanyName . "]" . $remark;
- Payment::create(
- [
- 'withdraw_cash_id' => $withdraw->id,
- 'amount' => (float) $withdraw->amount - (float) $withdraw->tallage,
- 'remark' => $remark,
- 'pay_time' => date('Y-m-d H:i:s'),
- 'pay_merchant_source' => "人工",
- 'trade_no' => $trade_no,
- 'status' => self::artifical_success,
- 'pay_merchant_source_msg' => '',
- 'is_company' => $withdraw->is_company,
- 'amount_person' => $uid,
- ]
- );
- }
- /**
- * 查找操作账号
- */
- private function findManageUser(int $id)
- {
- return Manage::find($id);
- }
- /**
- * 更新提现信息状态
- * @param WithdrawCash $withdraw
- * @param string $status
- * @param int $uid
- * @param string $serial_number
- * @param string $remark
- * @return WithdrawCash
- */
- public function updateWithdrawCashStatus(WithdrawCash $withdraw, string $status, int $uid = 0, string $serial_number = '', string $remark = '')
- {
- if (in_array($withdraw->status, self::success_status)) {
- return;
- }
- $withdraw->status = $status;
- if ($uid) {
- $user = $this->findManageUser($uid);
- $withdraw->check_user_id = $uid;
- $withdraw->check_user_name = $user ? $user->nickname : '';
- }
- if ($remark) {
- $withdraw->remark = $remark;
- }
- if ($serial_number) {
- if (!strpos($withdraw->serial_number, $serial_number)) {
- $serial_number = $withdraw->serial_number . "," . $serial_number;
- }
- $withdraw->serial_number = $serial_number;
- }
- $withdraw->save();
- if (in_array($status, self::success_status)) {
- //成功提现
- $financialStat = $this->findFinancialStat($withdraw->distribution_channel_id);
- //修改累计提现金额
- $financialStat->accumulative_withdrawal_amount = (float) $financialStat->accumulative_withdrawal_amount + (float) $withdraw->amount;
- //修改提现中金额
- $financialStat->withdraw_pending_amount = (float) $financialStat->withdraw_pending_amount - (float) $withdraw->amount;
- $financialStat->save();
- }
- return $withdraw;
- }
- /**
- * 创建人工打款
- * @param $userId
- * @param $withdrawCashId
- * @param $amount
- * @param $remark
- * @param $tradeNo
- * @param int $amount_person
- * @return bool
- */
- public function makePersonMadePayment($userId, $withdrawCashId, $remark, $trade_no, $amount_person = 0)
- {
- try {
- DB::beginTransaction();
- $withdraw = $this->findWithdrawCash($withdrawCashId);
- //插入人工打款记录
- $this->addPayment($withdraw, $trade_no, $amount_person, $remark);
- //更新当然提现记录为 人工打款成功状态
- $this->updateWithdrawCashStatus($withdraw, self::artifical_success, $userId, $trade_no, $remark);
- DB::commit();
- } catch (Exception $e) {
- Log::error("人工打款失败日志" . $e->getTraceAsString());
- DB::rollback();
- return false;
- }
- return true;
- }
- /**
- * 对私打款改为对公打款
- */
- public function changePrivateToPublicPayment(int $uid, int $batch_payment_id, string $trade_no, string $account_name, string $card_number, string $account_bank)
- {
- $withdraws = WithdrawCash::where('batch_payment_id', $batch_payment_id)->get();
- DB::beginTransaction();
- foreach ($withdraws as $withdraw) {
- $withdraw->account_name = $account_name;
- $withdraw->bank_account = $card_number;
- $withdraw->account_bank = $account_bank;
- $withdraw->batch_payment_id = 0;
- $withdraw->status = '人工待打款';
- $withdraw->is_company = 1;
- $withdraw->is_batch_operate = 0;
- $withdraw->save();
- if (!$this->makePersonMadePayment($uid, $withdraw->id, "[对私转对公]", $trade_no)) {
- DB::rollback();
- return;
- }
- }
- BatchPayments::where('id', $batch_payment_id)->delete();
- DB::commit();
- }
- /**
- * 更新合并打款对应的提现状态
- */
- private function updateBatchPaymentWithdrawCashStatus(int $batch_payment_id, string $status, int $uid = 0, string $serial_number = '', string $remark = '')
- {
- $withdraws = WithdrawCash::where('batch_payment_id', $batch_payment_id)->get();
- foreach ($withdraws as $withdraw) {
- $this->updateWithdrawCashStatus($withdraw, $status, $uid, $serial_number, $remark);
- if (in_array($status, self::success_status)) {
- Payment::create([
- 'withdraw_cash_id' => $withdraw->id,
- 'amount' => $withdraw->amount,
- 'remark' => '合并打款',
- 'pay_time' => date('Y-m-d H:i:s'),
- 'pay_merchant_source' => 'SANDPAY',
- 'trade_no' => $serial_number,
- 'status' => self::auto_success,
- 'is_company' => $withdraw->is_company
- ]);
- }
- }
- }
- /**
- * 更新合并打款状态
- */
- public function updateBatchPaymentStatus(BatchPayments $payment, string $status, int $uid = 0, array $query_result = [], string $serial_number = '')
- {
- try {
- DB::beginTransaction();
- $payment->serial_number = $serial_number ? $serial_number : ($payment->serial_number ?? '');
- $payment->status = $status;
- $payment->pay_merchant_source_msg = $query_result ? json_encode($query_result) : '';
- $payment->pay_merchant_source_result = in_array($status, self::success_status) ? '处理成功' : '';
- $payment->save();
- $this->updateBatchPaymentWithdrawCashStatus($payment->id, $status, $uid, $payment->serial_number);
- DB::commit();
- } catch (Exception $e) {
- myLog('test')->info($e->getTraceAsString());
- DB::rollback();
- }
- }
- /**
- * 查找自动待打款的批量提现记录
- */
- public function findPayingBatchPayments()
- {
- return BatchPayments::where('status', self::auto_paying)->get();
- }
- public function findBatchPayment(int $batch_payment_id)
- {
- return BatchPayments::find($batch_payment_id);
- }
- /**
- * 设置打款的redis缓存
- */
- private function setRedis(string $redis_key, int $id)
- {
- Redis::sAdd($redis_key, $id);
- Redis::expire($redis_key, 60 * 60 * 24);
- }
- /**
- * 判断是否在合并打款中
- */
- public function judgeIsPayment($id)
- {
- $key = 'batch_payment:' . date('Y-m-d');
- if (Redis::sIsmember($key, $id)) {
- return true;
- } else {
- $result = BatchPayments::where('id', $id)->whereIn('status', self::paying_status)->exists();
- if ($result) {
- $this->setRedis($key, $id);
- }
- return $result;
- }
- }
- /**
- * 合并打款
- * @param $uid
- * @param $batch_payment_id
- * @param $amount
- * @param $remark
- * @return bool
- */
- public function makeThreeSourcePayment(BatchPayments $batch_payment, int $uid, float $amount, string $remark)
- {
- $trade_no = date('YmdHis') . ($batch_payment->channel_user_id);
- $pay_service = new SandPay;
- //对私
- $balance = $pay_service->queryBalance([
- 'order_no' => date('YmdHis'),
- 'pay_time' => $batch_payment->pay_time,
- ]);
- if ($balance > 0 && $balance >= $amount) {
- try {
- DB::beginTransaction();
- $this->setRedis('batch_payment:' . date('Y-m-d'), $batch_payment->id);
- //修改状态打款中
- $batch_payment->trade_no = $trade_no;
- $batch_payment->status = self::auto_paying;
- $batch_payment->pay_time = now();
- $batch_payment->save();
- $this->updateBatchPaymentWithdrawCashStatus($batch_payment->id, self::auto_paying, $uid, '', $remark);
- $result = $pay_service->agentPay([
- 'order_no' => $trade_no,
- 'pay_time' => (string) $batch_payment->pay_time,
- 'account_name' => $batch_payment->account_name,
- 'bank_account' => $batch_payment->bank_account,
- 'account_bank' => $batch_payment->account_bank,
- 'remark' => $remark,
- 'amount' => $amount,
- ]);
- $batch_payment->pay_merchant_source_msg = json_encode($result);
- $batch_payment->save();
- DB::commit();
- return true;
- } catch (Exception $e) {
- Log::error($e->getTraceAsString());
- DB::rollback();
- }
- }
- }
- /**
- * 添加合并打款数据
- */
- private function addBatchPayment(string $status, float $amount, int $is_company, WithdrawCash $model, array $channel_ids, array $ids)
- {
- $payment = [
- 'amount' => $amount,
- 'status' => self::wait_pay,
- 'is_company' => $is_company,
- 'channel_user_id' => $model->channel_user_id,
- 'bank_account' => $model->bank_account,
- 'account_name' => $model->account_name,
- 'account_bank' => $model->account_bank,
- 'remark' => "channel_ids:" . (implode(',', $channel_ids)) . ';withdraw_cash_ids:' . implode(',', $ids)
- ];
- $added = BatchPayments::create($payment);
- WithdrawCash::whereIn('id', $ids)->update([
- 'batch_payment_id' => $added->id,
- 'status' => $status
- ]);
- }
- /**
- * 查找待合并提现记录
- * @return Collection
- */
- private function findWaitMergeWithdrawCash(int $is_company)
- {
- $withdraws = WithdrawCash::where('distribution_channel_id', '>', 0)
- ->where('is_batch_operate', 1)
- ->where('is_company', $is_company)
- ->where('status', self::wait_merge)
- ->where(function ($query) {
- $query->whereNull('batch_payment_id')->orwhere('batch_payment_id', 0);
- })
- ->get();
- $channel_ids = $withdraws->pluck('distribution_channel_id')->all();
- $channels = Channel::whereIn('id', $channel_ids)->select('id', 'channel_user_id')->get();
- $withdraws->transform(function ($item) use ($channels) {
- $channel = $channels->where('id', $item->distribution_channel_id)->first();
- $item->channel_user_id = $channel ? $channel->channel_user_id : 0;
- return $item;
- });
- return $withdraws->sortByDesc('amount')
- ->sortBy('bank_account')
- ->sortBy('channel_user_id')
- ->sortBy('pay_merchant_company_id')
- ->values();
- }
- public function mergePayments(int $is_company)
- {
- //获取排好序的待合并数据
- $withdrawCashes = $this->findWaitMergeWithdrawCash($is_company);
- $amount = 0;
- $temp = $withdrawCashes->first();
- $channel_ids = [];
- $ids = [];
- if (count($withdrawCashes) > 0) {
- try {
- DB::beginTransaction();
- foreach ($withdrawCashes as $withdrawCash) {
- if (
- $temp->channel_user_id == $withdrawCash->channel_user_id
- && $temp->bank_account == $withdrawCash->bank_account
- && $temp->pay_merchant_company_id == $withdrawCash->pay_merchant_company_id
- && $amount + $withdrawCash->amount < 50000
- ) {
- $amount += $withdrawCash->amount;
- $ids[] = $withdrawCash->id;
- if (!in_array($withdrawCash->distribution_channel_id, $channel_ids))
- $channel_ids[] = $withdrawCash->distribution_channel_id;
- } else {
- $this->addBatchPayment(self::auto_wait_pay, $amount, $is_company, $temp, $channel_ids, $ids);
- $amount = $withdrawCash->amount;
- $ids = [];
- $channel_ids = [];
- $ids[] = $withdrawCash->id;
- $channel_ids[] = $withdrawCash->distribution_channel_id;
- $temp = $withdrawCash;
- }
- }
- if ($amount > 0) {
- $this->addBatchPayment(self::auto_wait_pay, $amount, $is_company, $temp, $channel_ids, $ids);
- }
- DB::commit();
- } catch (Exception $e) {
- myLog('add_batch_payment')->error($e->getMessage());
- DB::rollBack();
- }
- }
- }
- }
|