Server : Apache
System : Linux iZ6xhqomji47p1Z 5.10.134-15.al8.x86_64 #1 SMP Thu Jul 20 00:44:04 CST 2023 x86_64
User : www ( 1000)
PHP Version : 8.1.30
Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv
Directory :  /www/wwwroot/fsjlkj.cn/application/api/model/v1/
Upload File :
Current Directory [ Writeable ] Root Directory [ Writeable ]


Current File : /www/wwwroot/fsjlkj.cn/application/api/model/v1/Poster.php
<?php
/**
 * 易优CMS
 * ============================================================================
 * 版权所有 2016-2028 海南赞赞网络科技有限公司,并保留所有权利。
 * 网站地址: http://www.eyoucms.com
 * ----------------------------------------------------------------------------
 * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
 * ============================================================================
 * Author: 陈风任 <491085389@qq.com>
 * Date: 2022-03-10
 */

namespace app\api\model\v1;

use think\Db;
use think\Cache;
use Grafika\Color;
use Grafika\Grafika;
require_once './vendor/grafika/src/autoloader.php';

/**
 * 微信小程序商品海报模型
 */
load_trait('controller/Jump');

class Poster extends Base
{
    use \traits\controller\Jump;

    //初始化
    protected function initialize()
    {
        // 需要调用`Model`的`initialize`方法
        parent::initialize();

        $this->aid = 0;
        $this->typeid = 0;
        $this->channel = 1;
        $this->product = [];
        $this->postData = [];
        $this->posterPath = '';
        $this->posterImage = '';
        $this->appletsQrcode = [];
    }

    // 商品海报生成处理
    // $appletsType: 1=开源小程序,2=可视化小程序
    public function getCreateGoodsShareQrcodePoster($post = [], $channel = 1, $appletsType = 1)
    {
        // 商品ID
        $this->aid = $post['aid'];
        // 商品栏目ID
        $this->typeid = $post['typeid'];
        // 分销商会员ID
        $this->usersID = $post['users_id'];
        // 分销商ID
        $this->dealerID = $post['dealer_id'];
        // 模型ID
        $this->channel = $channel;
        // 图片、海报保存目录
        $this->posterPath = UPLOAD_PATH . 'tmp/poster_' . $this->typeid . '_' . $this->aid . '/';
        // 存在 分销商会员ID 和 分销商ID 则执行
        if (!empty($this->usersID) && !empty($this->dealerID)) {
            $this->posterPath = UPLOAD_PATH . 'tmp/poster_' . $this->typeid . '_' . $this->aid . '_' . $this->usersID . '_' . $this->dealerID . '/';
        }
        // 背景图片处理
        if (1 == $this->channel) {
            $this->posterImage = './public/static/common/images/article-bg.png';
        } else if (2 == $this->channel) {
            $this->posterImage = './public/static/common/images/product-bg.png';
        }
        // 获取商品信息
        $this->product = $this->getProductData();

        // 生成小程序二维码需携带参数
        if (1 === intval($appletsType)) {
            $page = 'pages/archives/product/view';
        } else if (2 === intval($appletsType)) {
            $page = 'pages/article/view';
        } else {
            $page = 'pages/index/index';
        }
        $scene = 'aid=' . $this->aid . '&typeid=' . $this->typeid;
        // 存在 分销商会员ID 和 分销商ID 则执行
        if (!empty($this->usersID) && !empty($this->dealerID)) {
            $scene .= '&u_id=' . $this->usersID . '&d_id=' . $this->dealerID;
        }
        $width = '430';
        $this->postData = compact('page', 'scene', 'width');

        // 小程序二维码处理
        $this->appletsQrcode = $this->getAppletsQrcode();

        // 组合并返回商品分享海报图片
        return $this->getProductSharePosterImage();
    }

    // 返回已处理的商品信息
    private function getProductData()
    {
        // 查询商品信息
        $where['aid'] = $this->aid;
        $field = 'aid, title, litpic, users_price, seo_description';
        $Product = Db::name("archives")->where($where)->field($field)->find();

        if (!empty($Product)) {
            // 商品图片处理
            $ProductLitpic = $this->get_default_pic($Product['litpic'], true);
            // 保存图片的完整路径
            $LitpicSavePath = $this->posterPath . 'product_' . md5($this->aid . $this->typeid) . '.png';
            // 若文件夹不存在则创建
            !is_dir($this->posterPath) && tp_mkdir($this->posterPath);

            // 图片保存到文件处理
            $ch = curl_init($ProductLitpic);
            curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
            curl_setopt($ch,CURLOPT_BINARYTRANSFER,true);
            // https请求 不验证证书和hosts
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);   //重要,源文件链接带https的话就必须使用
            curl_setopt($ch,CURLOPT_TIMEOUT,60);

            $img = curl_exec($ch);
            curl_close($ch);
            $fp = fopen($LitpicSavePath, 'w');
            fwrite($fp, $img);
            fclose($fp);
            // 返回数据
            $Product['litpic'] = $LitpicSavePath;

            return $Product;
        } else {
            $this->error('商品不存在');
        }
    }

    // 返回已处理的小程序二维码
    private function getAppletsQrcode()
    {
        // 保存图片的完整路径
        $qrcodeSavePath = $this->posterPath . 'qrcode_' . md5($this->aid . $this->typeid) . '.png';

        // 若文件夹不存在则创建
        !is_dir($this->posterPath) && tp_mkdir($this->posterPath);

        // 是否配置小程序信息
        $appletsToken = get_weixin_access_token(true);
        if (empty($appletsToken['code'])) {
            return [
                'status' => false,
                'msg' => $appletsToken['msg'],
            ];
        }

        // 调用微信接口获取小程序二维码
        return $this->getWeChatAppletsQrcode($appletsToken['access_token'], $qrcodeSavePath);
    }

    // 返回微信小程序商品详情页二维码
    private function getWeChatAppletsQrcode($accessToken = null, $qrcodeSavePath = null)
    {
        // 获取微信小程序二维码
        $postUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" . $accessToken;
        $appletsQrcode = httpRequest($postUrl, 'POST', json_encode($this->postData, JSON_UNESCAPED_UNICODE));
        $is_fail = strpos($appletsQrcode,"errcode");
        // 保存图片,保存成功则返回图片路径
        if ($is_fail != false){   //报错
            $error_msg = json_decode($appletsQrcode,true);
            $result = [
                'status' => false,
                'errcode' => $error_msg['errcode'],
                'errmsg' => '获取二维码失败,'.$error_msg['errcode'].":".$error_msg['errmsg'],
            ];
        } else if (@file_put_contents($qrcodeSavePath, $appletsQrcode)) {
            $result = [
                'status' => true,
                'qrcode' => $qrcodeSavePath,
            ];
        } else {
            $result = [
                'status' => false,
                'errcode' => 10000,
                'errmsg' => '获取二维码失败,请重试',
            ];
        }

        return $result;
    }

    // 返回商品分享海报图片
    private function getProductSharePosterImage()
    {
        $Grafika = new Grafika;
        $editor = $Grafika::createEditor(['Gd']);
        // 打开海报背景图
        $editor->open($backdropImage, $this->posterImage);
        // 打开商品图片
        $editor->open($ProductLitpic, $this->product['litpic']);
        // 重设商品图片宽高
        $editor->resizeExact($ProductLitpic, 690, 690);
        // 商品图片添加到背景图
        $editor->blend($backdropImage, $ProductLitpic, 'normal', 1.0, 'top-left', 30, 30);

        // 字体文件路径
        $fontPath = Grafika::fontsDir() . '/' . 'st-heiti-light.ttc';
        // 商品名称处理换行
        $fontSize = 30;
        $productName = $this->wrapText($fontSize, 0, $fontPath, $this->product['title'], 680, 2);
        // 写入商品名称
        $editor->text($backdropImage, $productName, $fontSize, 30, 750, new Color('#333333'), $fontPath);

        //写入商品价格
        if (1 == $this->channel) {
            // 字体文件路径
            $fontPath = Grafika::fontsDir() . '/' . 'st-heiti-light.ttc';
            // 文档描述处理换行
            $fontSize = 20;
            $seoDescription = $this->wrapText($fontSize, 0, $fontPath, $this->product['seo_description'], 500, 4);
            // 写入文档描述
            $editor->text($backdropImage, $seoDescription, $fontSize, 30, 920, new Color('#333333'), $fontPath);
        } else if (2 == $this->channel) {
            $editor->text($backdropImage, $this->product['users_price'], 38, 62, 964, new Color('#ff4444'));
        }

        // 打开小程序码
        if (!empty($this->appletsQrcode['status'])){
            $editor->open($qrcodeImage, $this->appletsQrcode['qrcode']);
            // 重设小程序码宽高
            $editor->resizeExact($qrcodeImage, 140, 140);
            // 小程序码添加到背景图
            $editor->blend($backdropImage, $qrcodeImage, 'normal', 1.0, 'top-left', 570, 914);

            // 保存商品海报
            $posterImageName = 'product_poster_' . md5($this->aid . $this->typeid) . '.png';
            $posterImagePath = $this->posterPath . $posterImageName;
            $editor->save($backdropImage, $posterImagePath);

            // 返回商品海报
            $posterImagePath = request()->domain() . ROOT_DIR . '/' . $posterImagePath;
            return [
                'name' => $posterImageName,
                'path' => $this->posterPath,
                'poster' => $posterImagePath
            ];
        } else {
            return $this->appletsQrcode;
        }
    }

    // 处理文字超出长度自动换行
    private function wrapText($fontsize, $angle, $fontface, $string, $width, $max_line = null)
    {
        // 这几个变量分别是 字体大小, 角度, 字体名称, 字符串, 预设宽度
        $content = "";
        // 将字符串拆分成一个个单字 保存到数组 letter 中
        $letter = [];
        for ($i = 0; $i < mb_strlen($string, 'UTF-8'); $i++) {
            $letter[] = mb_substr($string, $i, 1, 'UTF-8');
        }
        $line_count = 0;
        foreach ($letter as $l) {
            $testbox = imagettfbbox($fontsize, $angle, $fontface, $content . ' ' . $l);
            // 判断拼接后的字符串是否超过预设的宽度
            if (($testbox[2] > $width) && ($content !== "")) {
                $line_count++;
                if ($max_line && $line_count >= $max_line) {
                    $content = mb_substr($content, 0, -1, 'UTF-8') . "...";
                    break;
                }
                $content .= "\n";
            }
            $content .= $l;
        }
        return $content;
    }
}