PackageOrder.php 12.9 KB
<?php

namespace app\api\controller;

use addons\shopro\exception\Exception;
use addons\shopro\model\Config;
use app\api\model\PackageOrder as PackageOrderModel;
use addons\shopro\model\User;
use think\Db;
use think\Log;

/**
 * 会员套餐订单接口
 */
class PackageOrder extends Base
{

    protected $noNeedLogin = ['prepay', 'notifyx'];
    protected $noNeedRight = ['*'];

    /**
     * @ApiWeigh    (99)
     * @ApiTitle    (创建订单)
     * @ApiSummary  (创建订单)
     * @ApiMethod   (POST)
     *
     * @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams  (name=package_id, type=inter, required=true, description="会员套餐ID")
     *
     * @ApiReturn({
        "code": 1,
        "msg": "订单添加成功",
        "time": "1608639849",
        "data": {
            "id": 3, //订单ID
            "order_sn": "202008241079705643001000", //订单号
            "user_id": 1, //用户ID
            "package_id": 1, //会员套餐ID
            "package_name": "季度会员", //会员套餐名称
            "package_price": "150.00", //会员套餐价格
            "month": 3, //会员持续月数
            "pay_fee": "150.00", //支付金额
            "status": 0,
            "paytime": null,
            "pay_type": null,
            "payment_json": null,
            "transaction_id": null,
            "remark": null,
            "createtime": 1608639850
        }
    })
     */
    public function createOrder()
    {
        $params = $this->request->post();

        $order = PackageOrderModel::createOrder($params);

        $this->success('订单添加成功', $order);
    }

    /**
     * @ApiWeigh    (97)
     * @ApiTitle    (拉起支付)
     * @ApiSummary  (拉起支付)
     * @ApiMethod   (POST)
     *
     * @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams  (name=order_sn, type=string, required=true, description="订单号")
     *
     * @ApiReturn()
     */
    public function prepay()
    {
        $order_sn = $this->request->post('order_sn');
        $payment = $this->request->post('payment','wechat');
        $platform = request()->header('platform','wxMiniProgram');

        $order = PackageOrderModel::where('status',0)->where('order_sn', $order_sn)->find();

        if (!$order) {
            throw new Exception("订单不存在");
        }

        if (!$payment || !in_array($payment, ['wechat', 'alipay', 'wallet'])) {
            throw new Exception("支付类型不能为空");
        }

        $order_data = [
            'out_trade_no' => $order->order_sn,
            'total_fee' => $order->pay_fee,
            'body' => '商城订单支付',
        ];
        // openid
        $oauth = \addons\shopro\model\UserOauth::where([
            'user_id' => $order->user_id,
            'provider' => 'Wechat',
            'platform' => 'wxMiniProgram'
        ])->find();
        $order_data['openid'] = $oauth ? $oauth->openid : '';

        if (empty($order_data['openid'])) {
            // 缺少 openid
            return $this->success('缺少 openid', 'no_openid');
        }

        $notify_url = $this->request->root(true) . '/api/package_order/notifyx/payment/' . $payment . '/platform/' . $platform;
        $pay = new \addons\shopro\library\PayService($payment, $platform, $notify_url);
        // 测试支付金额
        // $order_data['total_fee'] = 0.01;
        $result = $pay->create($order_data);

        return $this->success('获取预付款成功', [
            'pay_data' => $result,
            'pay_action' => $pay->method,
        ]);
    }


    /**
     * @ApiInternal
     * 支付成功回调
     */
    public function notifyx()
    {
        Log::write('notifyx-comein:');

        $payment = $this->request->param('payment');
        $platform = $this->request->param('platform');

        $pay = new \addons\shopro\library\PayService($payment, $platform);

        $result = $pay->notify(function ($data, $pay) use ($payment, $platform) {
            Log::write('notifyx-result:'. json_encode($data));
            // {    // 微信回调参数
            //     "appid":"wx39cd0799d4567dd0",
            //     "bank_type":"OTHERS",
            //     "cash_fee":"1",
            //     "fee_type":"CNY",
            //     "is_subscribe":"N",
            //     "mch_id":"1481069012",
            //     "nonce_str":"dPpcZ6AzCDU8daNC",
            //     "openid":"oD9ko4x7QMDQPZEuN8V5jtZjie3g",
            //     "out_trade_no":"202010240834057843002700",
            //     "result_code":"SUCCESS",
            //     "return_code":"SUCCESS",
            //     "sign":"3103B6D06F13D2B3959C5B3F7F1FD61C",
            //     "time_end":"20200407102424",
            //     "total_fee":"1",
            //     "trade_type":"JSAPI",
            //     "transaction_id":"4200000479202004070804485027"
            // }

            // {    // 支付宝支付成功回调参数
            //     "gmt_create":"2020-04-10 19:15:00",
            //     "charset":"utf-8",
            //     "seller_email":"xptech@qq.com",
            //     "subject":"\u5546\u57ce\u8ba2\u5355\u652f\u4ed8",
            //     "sign":"AOiYZ1a2mEMOuIbHFCi6V6A0LJ97UMiHsCWgNdSU9dlzKFl15Ts8b0mL\/tN+Hhskl+94S3OUiNTBD3dD0Kv923SqaTWxNdj533PCdo2GDKsZIZgKbavnOvaccSKUdmQRE9KtmePPq9V9lFzEQvdUkKq1M8KAWO5K9LTy2iT2y5CUynpiu\/04GVzsTL9PqY+LDwqj6K+w7MgceWm1BWaFWg27AXIRw7wvsFckr3k9GGajgE2fufhoCYGYtGFbhGOp6ExtqS5RXBuPODOyRhBLpD8mwpOX38Oy0X+R4YQIrOi02dhqwPpvw79YjnvgXY3qZEQ66EdUsrT7EBdcPHK0Gw==",
            //     "buyer_id":"2088902485164146",
            //     "invoice_amount":"0.01",
            //     "notify_id":"2020041000222191501064141414240102",
            //     "fund_bill_list":"[{\"amount\":\"0.01\",\"fundChannel\":\"PCREDIT\"}]",
            //     "notify_type":"trade_status_sync",
            //     "trade_status":"TRADE_SUCCESS",
            //     "receipt_amount":"0.01",
            //     "buyer_pay_amount":"0.01",
            //     "app_id":"2021001114666742",
            //     "sign_type":"RSA2",
            //     "seller_id":"2088721922277739",
            //     "gmt_payment":"2020-04-10 19:15:00",
            //     "notify_time":"2020-04-10 19:15:01",
            //     "version":"1.0",
            //     "out_trade_no":"202007144778322770017000",
            //     "total_amount":"0.01",
            //     "trade_no":"2020041022001464141443020240",
            //     "auth_app_id":"2021001114666742",
            //     "buyer_logon_id":"157***@163.com",
            //     "point_amount":"0.00"
            // }

            // {   // 支付宝退款成功(交易关闭)回调参数
            //     "gmt_create": "2020-08-15 14:48:32",
            //     "charset": "utf-8",
            //     "seller_email": "xptech@qq.com",
            //     "gmt_payment": "2020-08-15 14:48:32",
            //     "notify_time": "2020-08-15 16:11:45",
            //     "subject": "商城订单支付",
            //     "gmt_refund": "2020-08-15 16:11:45.140",
            //     "sign": "b6ArkgzLIRteRL9FMGC6i\/jf6VwFYQbaGDGRx002W+pdmN5q9+O4edZ3ALF74fYaijSl9ksNr0dKdvanu3uYxBTcd\/GIS4N1CWzmCOv6pzgx5rO\/YvGoHLM3Yop0GKKuMxmnNsZ6jhYKEY7SYD3Y0L6PU9ZMdHV7yIiVj+zZmbKzUgK9MPDCEXs+nzpNAiSM8GTqYRSUvKobAK68hswG2k1QIcqr5z+ZmVYa\/nHHkoC9qXt5zwyGi4P+2eOsr6V2PjA3x8qqe7TN5aI1DeoZD5KqHPYYaYF17J2q6YPlgl3WUl1RhE7H86bivB1fIuYEv\/3+JR74WN\/o7krGw1RPHg==",
            //     "out_biz_no": "R202004114414846255015300",
            //     "buyer_id": "2088902485164146",
            //     "version": "1.0",
            //     "notify_id": "2020081500222161145064141453349793",
            //     "notify_type": "trade_status_sync",
            //     "out_trade_no": "202002460317545607015300",
            //     "total_amount": "0.01",
            //     "trade_status": "TRADE_CLOSED",
            //     "refund_fee": "0.01",
            //     "trade_no": "2020081522001464141438570535",
            //     "auth_app_id": "2021001114666742",
            //     "buyer_logon_id": "157***@163.com",
            //     "gmt_close": "2020-08-15 16:11:45",
            //     "app_id": "2021001114666742",
            //     "sign_type": "RSA2",
            //     "seller_id": "2088721922277739"
            // }

            try {
                $out_trade_no = $data['out_trade_no'];

                // 判断支付宝微信是否是支付成功状态,如果不是,直接返回响应
                if ($payment == 'alipay' && $data['trade_status'] != 'TRADE_SUCCESS') {
                    // 不是交易成功的通知,直接返回成功
                    return $pay->success()->send();
                }
                if ($payment == 'wechat' && ($data['result_code'] != 'SUCCESS' || $data['return_code'] != 'SUCCESS')) {
                    // 微信交易未成功,返回 false,让微信再次通知
                    return false;
                }

                // 支付成功流程
                $pay_fee = $payment == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;

                //你可以在此编写订单逻辑
                $order = PackageOrderModel::where('order_sn', $out_trade_no)->find();

                if (!$order || $order->status > 0) {
                    // 订单不存在,或者订单已支付
                    return $pay->success()->send();
                }

                Db::transaction(function () use ($order, $data, $payment, $platform, $pay_fee) {
                    // 本次购买会员的初始时间
                    $user = User::get($order['user_id']);
                    $starttime = $user['vip_end_time'] > time() ? $user['vip_end_time'] : time();
                    $endtime = strtotime('+'.$order['month'].'month',$starttime);

                    // 修改订单信息
                    $order->status = 1;
                    $order->paytime = time();
                    $order->transaction_id = $payment == 'alipay' ? $data['trade_no'] : $data['transaction_id'];
                    $order->payment_json = json_encode($data->all());
                    $order->pay_type = $payment;
                    $order->pay_fee = $pay_fee;
                    $order->starttime = $starttime;
                    $order->endtime = $endtime;
                    $order->save();

                    // 增加佣金余额
                    $first_user = User::get($user['pid']);
                    if($first_user){
                        // 一级佣金
                        $share = json_decode(Config::where(['name' => 'share'])->value('value'), true);
                        $first_commission = $share['member_first'];
                        $first_user->commission = Db::raw('commission + ' . $first_commission);
                        $first_user->save();
                        // 记录 UserCommissionLog
                        \app\api\model\UserCommissionLog::doAdd($first_user, $first_commission, 'package_commission', $order['id'], 1);

                        // 二级佣金
                        $second_user = User::get($first_user['pid']);
                        if($second_user){
                            $second_commission = $share['member_second'];
                            $second_user->commission = Db::raw('commission + ' . $second_commission);
                            $second_user->save();
                            // 记录 UserCommissionLog
                            \app\api\model\UserCommissionLog::doAdd($second_user, $second_commission, 'package_commission', $order['id'], 1);
                        }
                    }

                    // 赠送优惠券
                    $package_coupons = Db::name('package_coupons')
                        ->alias('pc')
                        ->join('shopro_coupons sc','pc.coupons_id = sc.id')
                        ->where('pc.package_id',$order['package_id'])
                        ->field('pc.coupons_id,pc.give_num,pc.expire_days')
                        ->select();
                    $user_coupons_data = [];
                    foreach ($package_coupons as $v) {
                        for ($i=0; $i < $v['give_num']; $i++) {
                            $user_coupons_data[] = [
                                'user_id' => $order['user_id'],
                                'coupons_id' => $v['coupons_id'],
                                'package_coupons_time' => strtotime('+'.$v['expire_days'].'days')
                            ];
                        }
                    }
                    (new \addons\shopro\model\UserCoupons)->saveAll($user_coupons_data);

                    // 变更会员到期时间
                    if($user['vip_start_time'] <= 0){
                        $user->vip_start_time = time();
                    }
                    $user->vip_end_time = $endtime;
                    $user->save();
                });

                return $pay->success()->send();
            } catch (\Exception $e) {
                Log::write('notifyx-error:' . json_encode($e->getMessage()));
            }
        });

        return $result;
    }
}