<?php

namespace app\index\controller;

use app\common\controller\Frontend;
use app\admin\model\Order;
use app\admin\model\Product;
use think\Log;
use addons\epay\library\Service as EpayService;

class Pay extends Frontend
{
    protected $noNeedLogin = '*';
    protected $noNeedRight = '*';
    protected $layout = '';

    /**
     * 发起支付
     */
    public function submit()
    {
        $id = $this->request->param('id');
        $weight = $this->request->param('weight');
        $type = $this->request->param('type', 'alipay'); // alipay 或 wxpay

        if (!$id || !$weight) {
            $this->error('参数错误');
        }

        $product = Product::get($id);
        if (!$product) {
            $this->error('商品不存在');
        }

        $price = $product['price'];
        $amount = bcmul($price, $weight, 2);
       
        $isWechat = strpos($this->request->server('HTTP_USER_AGENT'), 'MicroMessenger') !== false;
        $payType = $type == 'wxpay' ? 'wechat' : 'alipay';
        $openid = '';

        // 微信内并且选择微信支付时,通过 third 插件获取 openid
        if ($isWechat && $payType == 'wechat') {
            $user = $this->auth->getUserinfo();
            if ($user) {
                // 已经登录,尝试获取 third 表中的 openid
                $third = \addons\third\model\Third::where('user_id', $user['id'])->where('platform', 'wechat')->find();
                if ($third) {
                    $openid = $third['openid'];
                }
            }
           
            if (!$openid) {
                // 如果没有 openid,跳转到 third 插件授权登录,登录后会跳回当前链接继续支付流程
                $url = $this->request->url(true); // 当前发起支付的完整URL
                $this->redirect(addon_url('third/index/connect', [':platform' => 'wechat', 'url' => $url]));
                return;
            }
        }
       
        // 创建订单
        $order = new Order();
        $order->sn = date('YmdHis') . mt_rand(1000, 9999);
        $order->product_id = $id;
        $order->product_name = $product['title'];
        $order->weight = $weight;
        $order->amount = $amount;
        $order->pay_type = $type;
        $order->createtime = time();
        $order->status = 'created';
     
        $order->save();

        // 根据设备类型决定发起支付的 method
        $method = 'web';
        if ($payType == 'alipay' && $this->request->isMobile()) {
            $method = 'wap';
        }

        // 构造回调链接
        $notifyurl = request()->domain() . '/index/pay/notify/paytype/' . $payType;
        $returnurl = request()->domain() . '/index/pay/return_url/paytype/' . $payType . '/out_trade_no/' . $order->sn;

        // 发起支付
        $response = EpayService::submitOrder($amount, $order->sn, $payType, $product['title'], $notifyurl, $returnurl, $method, $openid);
       
        return $response;
    }

    /**
     * 支付异步回调
     */
    public function notify()
    {
        $paytype = $this->request->param('paytype');
        $pay = EpayService::checkNotify($paytype);
        if (!$pay) {
            echo "fail";
            return;
        }

        // 获取回调数据,V3和V2的回调接收不同
        $data = EpayService::isVersionV3() ? $pay->callback() : $pay->verify();

        try {
            // 微信支付V3返回和V2不同
            if (EpayService::isVersionV3() && $paytype === 'wechat') {
                $data = $data['resource']['ciphertext'];
                $data['total_fee'] = $data['amount']['total'];
            }

            // 记录回调日志
            Log::info('Pay Notify: ' . json_encode($data));

            $out_trade_no = $data['out_trade_no'];
            // 支付宝是 trade_no,微信是 transaction_id
            $trade_no = $paytype == 'alipay' ? ($data['trade_no'] ?? '') : ($data['transaction_id'] ?? '');

            $order = Order::where('sn', $out_trade_no)->find();
            if ($order && $order['status'] == 'created') {
                $order->status = 'paid';
                $order->paytime = time();
                $order->trade_id = $trade_no; // 记录流水号
                $order->save();
               
                // 更新商品已筹重量和参与人次
                $product = Product::get($order->product_id);
                if ($product) {
                    $product->current_weight += $order->weight;
                    $product->participant_count += 1;
                    $product->save();
                }
            }
        } catch (\Exception $e) {
            Log::error('Pay Notify Error: ' . $e->getMessage());
        }

        // 下面这句必须要执行,且在此之前不能有任何输出
        if (EpayService::isVersionV3()) {
            return $pay->success()->getBody()->getContents();
        } else {
            return $pay->success()->send();
        }
    }

    /**
     * 支付同步回调
     */
    public function return_url()
    {
        $paytype = $this->request->param('paytype');
        $out_trade_no = $this->request->param('out_trade_no');

        $order = Order::where('sn', $out_trade_no)->find();
        if ($order) {
            if ($order['status'] == 'paid') {
                $this->success('支付成功', 'index/ok');
            } else {
                // 尝试主动查询订单状态进行补单
                try {
                    $config = EpayService::getConfig($paytype);
                    $pay = $paytype == 'wechat' ? \Yansongda\Pay\Pay::wechat($config) : \Yansongda\Pay\Pay::alipay($config);
                    $result = EpayService::isVersionV3() ? $pay->find(['out_trade_no' => $out_trade_no]) : $pay->find($out_trade_no);
                   
                    $isPaid = false;
                    $trade_no = '';
                    if ($paytype == 'alipay') {
                        if (in_array($result['trade_status'] ?? '', ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
                            $isPaid = true;
                            $trade_no = $result['trade_no'] ?? '';
                        }
                    } else {
                        if (isset($result['trade_state']) && $result['trade_state'] == 'SUCCESS') {
                            $isPaid = true;
                            $trade_no = $result['transaction_id'] ?? '';
                        }
                    }
                   
                    if ($isPaid) {
                        $order->status = 'paid';
                        $order->paytime = time();
                        $order->trade_id = $trade_no;
                        $order->save();
                       
                        // 更新商品数据
                        $product = Product::get($order->product_id);
                        if ($product) {
                            $product->current_weight += $order->weight;
                            $product->participant_count += 1;
                            $product->save();
                        }
                        $this->success('支付成功', 'index/ok');
                    } else {
                        // 尚未支付完成
                        $this->error('支付尚未完成', 'index/index');
                    }
                } catch (\Exception $e) {
                    $this->success('支付成功或正在处理中', 'index/ok');
                }
            }
        } else {
            $this->error('订单不存在', 'index/index');
        }
    }
}


点赞(0)

评论列表 共有 0 条评论

暂无评论
立即
投稿
发表
评论
返回
顶部