Wxpay.php 11.9 KB
<?php

namespace app\api\controller;

use app\common\controller\Api;
use addons\epay\library\Service;
use app\admin\model\Porder;
use think\Db;
use Yansongda\Pay\Pay;
use app\admin\model\Account;
use app\admin\model\User;
use app\admin\model\Message;
use app\admin\model\Car;
use app\admin\model\Product;
use think\Log;
use fast\Http;
use think\Validate;
use Exception;
/**
 * 支付接口**
 */
class Wxpay extends Api
{
    protected  $noNeedLogin = ['notify','notifyCharge','handle'];
    protected $noNeedRight = ['notify','notifyCharge','handle'];
    protected $user_id = '';//token存贮user_id
    protected $order_status = [];//订单状态
    public function _initialize()
    {
        parent::_initialize();
        $this->user_id = $this->auth->getUserId();
        $this->order_status = config('site.order_status');
    }

    /**
     * @ApiTitle    (支付订单)
     * @ApiSummary  (支付订单)
     * @ApiMethod   (POST)
     * @ApiRoute    (/api/wxpay/pay)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="openid", type="string", required=true, description="小程序openid")
     * @ApiParams   (name="pay_order_sn", type="string", required=true, description="支付订单号")
     * @ApiParams   (name="type", type="integer", required=true, description="支付方式(0:微信支付,1:余额支付)")
     * @ApiReturn ({code: 0, msg: "无效的订单", time: "1554176100", data: null})
     */
    public function pay(){
        if($this->request->isPost()){
            //创建支付对象
            $pay = Pay::wechat(Service::getConfig('wechat'));
            $openid = $this->request->post('openid');//小程序传递openid
            $pay_order_sn = $this->request->post('pay_order_sn');//支付订单号
            $type = $this->request->post('type');//支付方式(wx:微信支付,balance:余额支付)
            $rule = config('site.pay');
            $validate = new Validate($rule['rule'],$rule['msg']);
            if (!$validate->check(['openid'=>$openid,'pay_order_sn'=>$pay_order_sn,'type'=>$type])) {
                $this->error($validate->getError());
            }
            //查询订单是否已支付
            $is_pay = Db::table('gc_porder')
                ->where(['pay_order_sn' => $pay_order_sn, 'uid' => $this->user_id])
                ->where('status','>',0)
                ->select();
            if ($is_pay) {
                $this->error('该订单已支付过了');
            }
            //是否有此订单
            $exist = Db::table('gc_porder')
                ->where(['pay_order_sn' => $pay_order_sn, 'uid' => $this->user_id, 'status' => $this->order_status[0]])
                ->select();
            if (!$exist) {
                $this->error('无效的订单');
            }
            //计算总价格
            $total_price = 0;
            foreach ($exist as $value) {
                $total_price += $value['total_price'];
            }
            if($type == 'wx'){
                //构建订单信息
                $order = [
                    'out_trade_no' => $pay_order_sn,//支付订单号
                    'body' => '广西小纸皮再生资源回收有限公司',
//                    'total_fee' => 1,
                    'total_fee' => floatval($total_price)*100,//单位:分
                    'openid' => $openid,
                    'notify_url' => url('api/Wxpay/notify','','',true),
                ];
                //跳转或输出
                $this->success('成功',$pay->miniapp($order));
            }else if($type == 'balance'){
                //从余额扣取
                $userModel = new User();
                $user = $userModel->where(['openid'=>$openid])->find();
                if(!$user){
                    $this->error('未找到该用户');
                }
                if($user['money'] < $total_price){
                    $this->error('余额不足');
                }
                //从账户扣取费用
                $sur_money = $user['money'] - $total_price;
                $res = $userModel->where(['openid'=>$openid])->update(['money'=>$sur_money]);
                //更新订单状态
                $porderModel = new Porder();
                $res1 = $porderModel->where(['pay_order_sn'=>$pay_order_sn])->update(['status'=>$this->order_status[1]]);
                //减库存,删相应购物车记录
                $this->handle($pay_order_sn,$openid);
                if($res && $res1){
                    $this->success('成功');
                }else{
                    $this->error('失败');
                }
            }else{
                $this->error('支付方式有误');
            }

        }else{
            $this->error('请求方式错误');
        }
    }

    /**
     * @ApiTitle    (商品订单去付款)
     * @ApiSummary  (商品订单去付款)
     * @ApiMethod   (GET)
     * @ApiRoute    (/api/wxpay/toPay)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="o_id", type="integer", required=true, description="订单id")
     * @ApiReturn ({
            "code": 1,
            "msg": "成功",
            "time": "1554184134",
            "data": {
                "pay_order_sn": "155418413436253500503"
            }
            })
     */
    public function toPay(){
        if($this->request->isGet()){
            $o_id = $this->request->get('o_id');//订单id
            $pay = $this->auth->genPayOrderSn();//支付订单号
            $rule = config('site.orders');
            $validate = new Validate($rule['rule'],$rule['msg']);
            if (!$validate->check(['o_id'=>$o_id])) {
                $this->error($validate->getError());
            }
            $p_order = new Porder();
            $res = $p_order->where(['id'=>$o_id,'uid'=>$this->user_id])->update(['pay_order_sn'=>$pay]);
            if($res){
                $this->success('成功',['pay_order_sn'=>$pay]);
            }else{
                $this->error('失败');
            }
        }else{
            $this->error('请求方式错误');
        }
    }

    /**
     * 微信异步通知(不需调用)
     */
    public function notify(){
        $pay = Pay::wechat(Service::getConfig('wechat'));
        try {
            $data = $pay->verify();
            if($data['result_code'] == 'SUCCESS' && $data['return_code'] == 'SUCCESS'){
                //更新订单状态
                $porderModel = new Porder();
                $porderModel->where(['pay_order_sn'=>$data['out_trade_no']])->update(['status'=>$this->order_status[1]]);
                //减库存,删相应购物车记录
                $this->handle($data['out_trade_no'],$data['openid']);
            }
        } catch (Exception $e) {
            echo "验签失败";
            return;
        }
        return $pay->success()->send();
    }

    /**
     * @ApiTitle    (充值)
     * @ApiSummary  (充值)
     * @ApiMethod   (POST)
     * @ApiRoute    (/api/wxpay/payCharge)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="amount", type="integer", required=true, description="充值金额")
     * @ApiParams   (name="openid", type="integer", required=true, description="openid")
     * @ApiReturn ({
        "code": 1,
        "msg": "成功",
        "time": "1554184134",
        "data": null
    })
     */
    public function payCharge(){
        if($this->request->isPost()){
            $amount = $this->request->post('amount');
            $openid = $this->request->post('openid');//小程序传递openid
            if(empty($openid)){
                $this->error("openid必填");
            }
            $pay = Pay::wechat(Service::getConfig('wechat'));
            if (!$amount || $amount < 0) {
                $this->error("充值金额必须大于0");
            }
            $pay_order_sn = $this->auth->genPayOrderSn();//支付订单号
            //构建订单信息
            $order = [
                'out_trade_no' => $pay_order_sn,//支付订单号
                'body' => '广西小纸皮再生资源回收有限公司',
                'total_fee' => floatval($amount)*100,//单位:分
                'openid' => $openid,
                'notify_url'   => url('api/Wxpay/notifyCharge','','',true),
            ];
            //跳转或输出
            $this->success('成功',$pay->miniapp($order));
        }else{
            $this->error('请求方式错误');
        }
    }

    /**
     * 微信异步通知(不需调用)
     */
    public function notifyCharge(){
        $pay = Pay::wechat(Service::getConfig('wechat'));
        try {
            $data = $pay->verify();
            //你可以在这里你的业务处理逻辑,比如处理你的订单状态、给会员加余额等等功能
            if($data['result_code'] == 'SUCCESS' && $data['return_code'] == 'SUCCESS'){
                $money = $data['total_fee'] / 100;
                $userModel = new User();
                $user = $userModel->where(['openid' => $data['openid']])->find();
                //给用户增加充值金额
                $userModel->where(['openid' => $data['openid']])->setInc('money',$money);

                //充值记录
                $accountModel = new Account();
                $account = $accountModel::create(['uid' => $user['id'], 'money' => $money,'partner_trade_no'=>$data['out_trade_no']]);

                //系统充值消息
                $messageModel = new Message();
                $messageModel::create(['account_id' => $account->id, 'title' => config('site.message')]);
                Log::info('执行一次');
            }
        } catch (Exception $e) {
            echo "验签失败";
            return;
        }
        //下面这句必须要执行,且在此之前不能有任何输出
        return $pay->success()->send();
    }

    /**
     * @ApiTitle    (分享购买成功调用,增加积分并获得相应的积分)
     * @ApiSummary  (分享购买成功调用,增加积分并获得相应的积分)
     * @ApiMethod   (GET)
     * @ApiRoute    (/api/wxpay/addScore)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="share_uid", type="integer", required=true, description="分享uid")
     * @ApiReturn ({
        "code": 1,
        "msg": "成功",
        "time": "1554184134",
        "data": null
        })
     */
    public function addScore(){
        if($this->request->isGet()){
            $share_uid = $this->request->get('share_uid');
            //如果携带分享uid,则按照积分增加
            $person = new Person();
            $person->getScore($share_uid,'share_purchase');
            $this->error('成功');
        }else{
            $this->error('请求方式错误');
        }
    }

    /**
     * 支付完成处理库存,购物车(不需调用)
     * @param $pay_order_sn
     * @param $openid
     */
    private function handle($pay_order_sn,$openid){
        //查询订单信息的商品id,数量num
        $data = Db::table('gc_porder')
            ->where(['pay_order_sn'=>$pay_order_sn])
            ->field('p_id,num')
            ->select();
        $pIds = array_column($data,'p_id');
        //减库存
        $product = Db::table('gc_product')
                ->whereIn('id',$pIds)
                ->field('id,stock')
                ->select();
        foreach($product as &$p_value){
            foreach($data as $value){
                if($value['p_id'] == $p_value['id']){
                    $p_value['stock'] = $p_value['stock'] - $value['num'];
                }
            }
        }
        //更新库存
        $productModel = new Product();
        $productModel->saveAll($product);

        $userModel = new User();
        $user = $userModel->where(['openid' => $openid])->find();

        //清理购物车
        $carModel = new Car();
        $carModel->whereIn('p_id',$pIds)->where('uid',$user['id'])->delete();
    }
}