RechargeOrderService.php 8.3 KB
<?php
/**
+-----------------------------------------------------------------------------------------------------------------------
 * 逻辑层:RechargeOrder 服务类,处理业务逻辑
+-----------------------------------------------------------------------------------------------------------------------
 *
 * PHP version 7
 *
 * @category  App\Services
 * @package   App\Services
 * @author    Richer <yangzi1028@163.com>
 * @date      2023年4月23日11:21:31
 * @copyright 2021-2022 Richer (http://www.Richer.com/)
 * @license   http://www.Richer.com/ License
 * @link      http://www.Richer.com/
 */
namespace App\Services;

use App\Jobs\User\TimesRecordCreatedJob;
use App\Jobs\UserTimesRecordJob;
use App\Models\RechargeOrder;
use App\Models\System\SystemSetting;
use App\Models\Traits\ChatTrait;
use App\Models\User\TimesRecord;
use App\Models\User\User;
use App\Models\User\UserRemote;
use App\Models\User\WalletRecord;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Yansongda\LaravelPay\Facades\Pay;

/**
 * Class RechargeOrderService
 * @package App\Services
 */
class RechargeOrderService extends BaseService
{
    use ChatTrait;
    /**
     * RechargeOrderService constructor.
     *
     * @param RechargeOrder $model
     */
    public function __construct(RechargeOrder $model)
    {
        // 执行父类构造方法
        parent::__construct($model);
    }

//    /**
//     * Display a listing of the resource.
//     *
//     * @return array|\Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Support\Collection
//     */
//    public function list()
//    {
//        return $this->model
//        ->when($q = request('name'), function ($query) use ($q) {
//            $query->where("name", 'like', "%$q%");
//        })->latest()->get();
//    }

    /**
     * 支付订单后台通知:客户端在支付成功后返回相关信息,如果成功更改数据库状态
     *
     * @param $request
     * @param string $type 支付类型
     *
     * @return bool
     */
    public function notifyPay($request, $type)
    {
        switch ($type) {
            case 'alipay':
//                return $this->notifyAlipay($request);
            case 'wechat':
                return $this->notifyWechat($request);
        }
    }

    /**
     * 微信支付异步通知支付结果
     *
     * {"appid":"wxef22db12a3e9af90","bank_type":"CMB_CREDIT","cash_fee":"1","fee_type":"CNY","is_subscribe":"N",
     * "mch_id":"1515000691","nonce_str":"cbT8iCPuIp3JkodY","openid":"othGt1eA5x4HeRhppnzxGnhC-bIo",
     * "out_trade_no":"1578450561","result_code":"SUCCESS","return_code":"SUCCESS",
     * "sign":"9D86849E44A36D362950381EC5213E84",
     * "time_end":"20200108102928",
     * "total_fee":"1","trade_type":"APP",
     * "transaction_id":"4200000504202001086820896950"
     * }
     *
     * @param Request $request request
     *
     * @return bool
     */
    public function notifyWechat($request)
    {
        $channel = 'wechat-pay';
        $description = '微信 支付异步回调 Wechat notify';
        record_log($channel, $description, 'begin');

        DB::beginTransaction();
        $pay = Pay::wechat();
        try {
            if ($request->test == 1) {
                $model = RechargeOrder::find(request('id', 2));
                // 更新数据库状态
                $this->paid($model, $channel, now()->toDateTimeString());

                DB::commit();
                record_log($channel, $description, 'end');
                return true;
            } else {
                $data = $pay->verify(); // 是的,验签就这么简单!
                record_log($channel, json_encode($data->all()));
                record_log($channel, '交易状态 return_code:' . $data->return_code);
                switch ($data->return_code) {
                    case 'SUCCESS':
                        // 获取商户订单号
                        $out_trade_no = $data->out_trade_no;
                        record_log($channel, '$out_trade_no:' .$out_trade_no);

                        // 根据商户订单号获取系统中的订单
                        $model = RechargeOrder::where('out_trade_no', $out_trade_no)->first();
                        record_log($channel, '订单信息:' . json_encode($model));
                        if (!$model) {
                            record_log($channel, $description, 'end');
                            $this->message = '未查询到本地订单!';
                            return false;
                        }

                        record_log($channel, '订单状态:' . $model->status);
                        // 更新数据库状态
                        $this->paid($model, $channel, Carbon::parse($data->time_end), $data);

                        DB::commit();
                        record_log($channel, $description, 'end');
                        return true;
                }
            }

        } catch (\Exception $e) {
            $this->message = $e->getMessage();
            record_log($channel, '', '错误:' .$this->message);
            record_log($channel, $description, 'end');

            DB::rollBack();
            return false;
        }
    }

    /**
     *  支付
     *
     * @param $order
     * @param $channel
     * @param $paid_at
     * @param null $data
     */
    protected function paid($order, $channel, $paid_at, $data = null)
    {
        // 更新数据库状态
        if ($order->status == RechargeOrder::UNPAID) {
            $order->status      = RechargeOrder::PAID;
            $order->paid_type   = RechargeOrder::H5_PAY;
            $order->paid_at     = $paid_at;
            $order->paid_info   = $data;
            $result = $order->save();
            record_log($channel, '订单执行:' . json_encode($result));

            // 订单支付回调成功后
            $this->handleAfterPaySuccessed($order);
        }
    }

    /**
     * 支付回调成功后
     *
     * @param $order
     * @return bool
     */
    public function handleAfterPaySuccessed($order)
    {
        // 支付成功后,设置会员数量和直推间推像相关用户进行分账
        $user = $order->user;
        // 总次数
        $total_times = $order->package_times * $order->quantity;
        if ($total_times > 0) {
            // 同时用户次数记录
            User::where('id', $user->id)->increment("times", $total_times);// 自增

//            UserRemote::where('id', $user->id)->increment("times", $total_times);// 自增

            // 记录中增加
            $record = $user->timesRecords()->create([
                'recordable_id' => $order->id,
                'recordable_type' => RechargeOrder::OBJ_NAME,
                'times' => $total_times,
                'type'  => TimesRecord::INCREMENT,
                'event' => TimesRecord::RECHARGE,
            ]);

            // 同步记录
//            TimesRecordCreatedJob::dispatch($record);

            // 同步增加记录
//            UserTimesRecordJob::dispatch($record);
//            $this->syncUserTimesRecord($record);
        }

        // add by Richer 于 2023年5月9日10:17:18 支付成功进行分销
        $amount = $order->amount;
        if ($amount > 0) {
            // 获取用户的上级和上上级
            $parent = $user->parent;
            if ($parent) {
                // 进行一级分销
                $this->distribute($parent, $order);
                $grandpa = $parent->parent;
                if ($grandpa && $grandpa->partner == 1) {
                    // 进行二级分销
                    $this->distribute($grandpa, $order, 2);
                }
            }
        }
    }

    /**
     * 用户进行分销
     *
     * @param $user
     * @param $order
     * @param int $level
     */
    public function distribute($user, $order, $level = 1)
    {
        // 获取分销比例
        $rate = 0;
        $event = WalletRecord::DIRECT;
        if ($level == 2) {
            $rate = optional(SystemSetting::getSetting())->secondary_distribution_rate;
        } else {
            $rate = optional(SystemSetting::getSetting())->primary_distribution_rate;
            $event = WalletRecord::INDIRECT;
        }

        $amount = ($rate * $order->amount) / 100;

        // 用户钱包增加金额并记录资金日志
        $user->walletEntry($order, $amount, $event, $rate);
    }
}