Browse Source

二维码海报

牟新芬 3 years ago
parent
commit
1ebc3973b0

+ 2 - 4
app/api/controller/v1/Index.php

@@ -4,13 +4,11 @@ namespace app\api\controller\v1;
 
 use app\BaseController;
 use app\model\api\Product;
-use app\model\api\SiteProduct;
 use app\model\system\Category as CategoryModel;
-use app\model\system\News;
 use app\model\system\ProductAttr;
 use app\Request;
 use library\services\UtilService;
-use library\utils\AdvertUtils;
+use library\services\QrcodeService;
 
 class Index extends BaseController
 {
@@ -63,7 +61,7 @@ class Index extends BaseController
     {
         if (!$id || !($storeInfo = Product::getValidProduct($id))) return app('json')->fail('商品不存在或已下架');
         $storeInfo['slider_image'] = json_decode($storeInfo['slider_image'], true);
-        //$storeInfo['code_base'] = QrcodeService::getWechatQrcodePath($id . '_product_detail_wap.jpg', '/pages/goods_details/index?id=' . $id);
+        $storeInfo['code_base'] = QrcodeService::getWechatQrcodePath($id . '_product_detail_wap.jpg', '/pages/product/detail?id=' . $id);
         //替换windows服务器下正反斜杠问题导致图片无法显示
         $storeInfo['description'] = preg_replace_callback('#<img.*?src="([^"]*)"[^>]*>#i', function ($imagsSrc) {
             return isset($imagsSrc[1]) && isset($imagsSrc[0]) ? str_replace($imagsSrc[1], str_replace('\\', '/', $imagsSrc[1]), $imagsSrc[0]) : '';

+ 48 - 0
app/model/routine/RoutineCode.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace app\model\routine;
+
+use crmeb\services\MiniProgramService;
+
+/**
+ * TODO 小程序二维码Model
+ * Class RoutineCode
+ * @package app\models\routine
+ */
+class RoutineCode
+{
+
+    /**
+     * TODO 获取小程序二维码
+     * @param $thirdId
+     * @param $thirdType
+     * @param $page
+     * @param $imgUrl
+     * @return array|bool
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public static function getShareCode($thirdId, $thirdType, $page, $imgUrl)
+    {
+        $res = RoutineQrcode::routineQrCodeForever($thirdId, $thirdType, $page, $imgUrl);
+        $resCode = MiniProgramService::qrcodeService()->appCodeUnlimit($res->id, $page, 280);
+        if ($resCode) {
+            if ($res) return ['res' => $resCode, 'id' => $res->id];
+            else return false;
+        } else return false;
+    }
+
+    /**
+     * TODO 获取小程序页面带参数二维码不保存数据库
+     * @param string $page
+     * @param string $pramam
+     * @param int $width
+     * @return mixed
+     */
+    public static function getPageCode($page = '', $pramam = "", $width = 280)
+    {
+        return MiniProgramService::qrcodeService()->appCodeUnlimit($pramam, $page, $width);
+    }
+}

+ 122 - 0
app/model/wechat/WechatQrcode.php

@@ -0,0 +1,122 @@
+<?php
+
+namespace app\model\wechat;
+
+use crmeb\traits\ModelTrait;
+use crmeb\basic\BaseModel;
+use crmeb\services\WechatService;
+
+/**
+ * 获取二维码
+ * Class WechatQrcode
+ * @package app\models\wechat
+ */
+class WechatQrcode extends BaseModel
+{
+    /**
+     * 数据表主键
+     * @var string
+     */
+    protected $pk = 'id';
+
+    /**
+     * 模型名称
+     * @var string
+     */
+    protected $name = 'wechat_qrcode';
+
+    use ModelTrait;
+
+    /**
+     * 创建临时二维码    有效期 30天
+     *
+     * 修改时    要使用的主键id $qtcode_id
+     * @param $id
+     * @param $type
+     * @param string $qtcode_id
+     */
+    public static function createTemporaryQrcode($id, $type, $qtcode_id = '')
+    {
+        $qrcode = WechatService::qrcodeService();
+        $data = $qrcode->temporary($id, 30 * 24 * 3600)->toArray();
+        $data['qrcode_url'] = $data['url'];
+        $data['expire_seconds'] = $data['expire_seconds'] + time();
+        $data['url'] = $qrcode->url($data['ticket']);
+        $data['status'] = 1;
+        $data['third_id'] = $id;
+        $data['third_type'] = $type;
+        if ($qtcode_id) {
+            self::edit($data, $qtcode_id);
+        } else {
+            $data['add_time'] = time();
+            self::create($data);
+        }
+    }
+
+    /**
+     * 创建永久二维码
+     * @param $id
+     * @param $type
+     */
+    public static function createForeverQrcode($id, $type)
+    {
+        $qrcode = WechatService::qrcodeService();
+        $data = $qrcode->forever($id)->toArray();
+        $data['qrcode_url'] = $data['url'];
+        $data['url'] = $qrcode->url($data['ticket']);
+        $data['expire_seconds'] = 0;
+        $data['status'] = 1;
+        $data['third_id'] = $id;
+        $data['third_type'] = $type;
+        $data['add_time'] = time();
+        self::create($data);
+    }
+
+    /**
+     * 获取临时二维码
+     * @param $type
+     * @param $id
+     * @return array|false|\PDOStatement|string|\think\Model
+     */
+    public static function getTemporaryQrcode($type, $id)
+    {
+        $res = self::where('third_id', $id)->where('third_type', $type)->find();
+        if (empty($res)) {
+            self::createTemporaryQrcode($id, $type);
+            $res = self::getTemporaryQrcode($type, $id);
+        } else if (empty($res['expire_seconds']) || $res['expire_seconds'] < time()) {
+            self::createTemporaryQrcode($id, $type, $res['id']);
+            $res = self::getTemporaryQrcode($type, $id);
+        }
+        if (!$res['ticket']) exception('临时二维码获取错误');
+        return $res;
+    }
+
+    /**
+     * 获取永久二维码
+     * @param $type
+     * @param $id
+     * @return array|false|\PDOStatement|string|\think\Model
+     */
+    public static function getForeverQrcode($type, $id)
+    {
+        $res = self::where('third_id', $id)->where('third_type', $type)->find();
+        if (empty($res)) {
+            self::createForeverQrcode($id, $type);
+            $res = self::getForeverQrcode($type, $id);
+        }
+        if (!$res['ticket']) exception('永久二维码获取错误');
+        return $res;
+    }
+
+    public static function getQrcode($id, $type = 'id')
+    {
+        return self::where($type, $id)->find();
+    }
+
+    public static function scanQrcode($id, $type = 'id')
+    {
+        return self::where($type, $id)->inc('scan')->update();
+    }
+
+}

+ 2 - 2
config/app.php

@@ -34,6 +34,6 @@ return [
     // 显示错误信息
     'show_error_msg'   => true,
     //基域名
-    'SITE_URL'         => 'lipinwawa.com',
-    'API_URL'          => 'https://api.lipinwawa.com'
+    'SITE_URL'         => 'www.boofly.cn',
+    'API_URL'          => 'https://www.boofly.cn'
 ];

+ 5 - 0
config/qrcode.php

@@ -0,0 +1,5 @@
+<?php
+return [
+    'cache_dir' => 'uploads/qrcode', //本地缓存地址
+    'background'=> 'statics/qrcode/background.png' //背景图
+];

+ 128 - 0
library/services/QrcodeService.php

@@ -0,0 +1,128 @@
+<?php
+
+namespace library\services;
+
+use app\model\routine\RoutineCode;
+use app\model\system\Attachment;
+use app\model\wechat\WechatQrcode as QrcodeModel;
+
+class QrcodeService
+{
+    /**
+     * 获取临时二维码  单个
+     * */
+    public static function getTemporaryQrcode($type, $id)
+    {
+        return QrcodeModel::getTemporaryQrcode($type, $id)->toArray();
+    }
+
+    /**
+     * 获取永久二维码  单个
+     * */
+    public static function getForeverQrcode($type, $id)
+    {
+        return QrcodeModel::getForeverQrcode($type, $id)->toArray();
+    }
+
+    public static function getQrcode($id, $type = 'id')
+    {
+        return QrcodeModel::getQrcode($id, $type);
+    }
+
+    public static function scanQrcode($id, $type = 'id')
+    {
+        return QrcodeModel::scanQrcode($id, $type);
+    }
+
+    /**
+     * 获取二维码完整路径,不存在则自动生成
+     * @param string $name 路径名
+     * @param string $link 需要生成二维码的跳转路径
+     * @param int $type https 1 = http , 0 = https
+     * @param bool $force 是否返回false
+     * @return bool|mixed|string
+     */
+    public static function getWechatQrcodePath(string $name, string $link, bool $force = false)
+    {
+        try {
+            $imageInfo = Attachment::getInfo($name, 'name');
+            $siteUrl = config('app')['API_URL'];
+            if (!$imageInfo) {
+                $codeUrl = UtilService::setHttpType($siteUrl . $link, request()->isSsl() ? 0 : 1);//二维码链接
+                $imageInfo = UtilService::getQRCodePath($codeUrl, $name);
+                if (is_string($imageInfo) && $force)
+                    return false;
+                if (is_array($imageInfo)) {
+                    Attachment::attachmentAdd($imageInfo['name'], $imageInfo['size'], $imageInfo['type'], $imageInfo['dir'], $imageInfo['thumb_path'], 1, $imageInfo['image_type'], $imageInfo['time'], 2);
+                    $url = $imageInfo['dir'];
+                } else {
+                    $url = '';
+                    $imageInfo = ['image_type' => 0];
+                }
+            } else $url = $imageInfo['att_dir'];
+            if ($imageInfo['image_type'] == 1 && $url) $url = $siteUrl . $url;
+            return $url;
+        } catch (\Throwable $e) {
+            if ($force)
+                return false;
+            else
+                return '';
+        }
+    }
+
+    /**
+     * 获取小程序分享二维码
+     * @param int $id
+     * @param int $uid
+     * @param int $type 1 = 拼团,2 = 秒杀
+     * @return bool|string
+     */
+    public static function getRoutineQrcodePath(int $id, int $uid, int $type, array $parame = [])
+    {
+        $page = '';
+        $namePath = '';
+        $data = 'id=' . $id . '&pid=' . $uid;
+        switch ($type) {
+            case 1:
+                $page = 'pages/activity/goods_combination_details/index';
+                $namePath = 'combination_' . $id . '_' . $uid . '.jpg';
+                break;
+            case 2:
+                $page = 'pages/activity/goods_seckill_details/index';
+                $namePath = 'seckill_' . $id . '_' . $uid . '.jpg';
+                if (isset($parame['stop_time']) && $parame['stop_time']) {
+                    $data .= '&time=' . $parame['stop_time'];
+                    $namePath = $parame['stop_time'] . $namePath;
+                }
+                break;
+        }
+        if (!$page || !$namePath) {
+            return false;
+        }
+        try {
+            $imageInfo = Attachment::getInfo($namePath, 'name');
+            $siteUrl = config('app')['API_URL'];
+            if (!$imageInfo) {
+                $res = RoutineCode::getPageCode($page, $data, 280);
+                if (!$res) return false;
+                $uploadType = (int)sys_config('upload_type', 1);
+                $upload = UploadService::init();
+                $res = $upload->to('routine/product')->validate()->stream($res, $namePath);
+                if ($res === false) {
+                    return false;
+                }
+                $imageInfo = $upload->getUploadInfo();
+                $imageInfo['image_type'] = $uploadType;
+                if ($imageInfo['image_type'] == 1) $remoteImage = UtilService::remoteImage($siteUrl . $imageInfo['dir']);
+                else $remoteImage = UtilService::remoteImage($imageInfo['dir']);
+                if (!$remoteImage['status']) return false;
+                Attachment::attachmentAdd($imageInfo['name'], $imageInfo['size'], $imageInfo['type'], $imageInfo['dir'], $imageInfo['thumb_path'], 1, $imageInfo['image_type'], $imageInfo['time'], 2);
+                $url = $imageInfo['dir'];
+            } else $url = $imageInfo['att_dir'];
+            if ($imageInfo['image_type'] == 1) $url = $siteUrl . $url;
+            return $url;
+        } catch (\Throwable $e) {
+            return false;
+        }
+    }
+}

+ 172 - 0
library/services/UtilService.php

@@ -11,6 +11,9 @@
 namespace library\services;
 
 use library\exceptions\UtilException;
+use library\services\upload\Upload as Upload;
+use think\facade\Config;
+use dh2y\qrcode\QRcode;
 
 class  UtilService {
 
@@ -174,4 +177,173 @@ class  UtilService {
         return $p;
     }
 
+    /**
+     * TODO 生成分享二维码图片
+     * @param array $config
+     * @param $path
+     * @return array|bool|string
+     * @throws \Exception
+     */
+    public static function setSharePoster($config = array(), $path)
+    {
+        $imageDefault = array(
+            'left' => 0,
+            'top' => 0,
+            'right' => 0,
+            'bottom' => 0,
+            'width' => 100,
+            'height' => 100,
+            'opacity' => 100
+        );
+        $textDefault = array(
+            'text' => '',
+            'left' => 0,
+            'top' => 0,
+            'fontSize' => 32,       //字号
+            'fontColor' => '255,255,255', //字体颜色
+            'angle' => 0,
+        );
+        $background = $config['background'];//海报最底层得背景
+        if (substr($background, 0, 1) === '/') {
+            $background = substr($background, 1);
+        }
+        $backgroundInfo = getimagesize($background);
+        $background = imagecreatefromstring(file_get_contents($background));
+        $backgroundWidth = $backgroundInfo[0];  //背景宽度
+        $backgroundHeight = $backgroundInfo[1];  //背景高度
+        $imageRes = imageCreatetruecolor($backgroundWidth, $backgroundHeight);
+        $color = imagecolorallocate($imageRes, 0, 0, 0);
+        imagefill($imageRes, 0, 0, $color);
+        imagecopyresampled($imageRes, $background, 0, 0, 0, 0, imagesx($background), imagesy($background), imagesx($background), imagesy($background));
+        if (!empty($config['image'])) {
+            foreach ($config['image'] as $key => $val) {
+                $val = array_merge($imageDefault, $val);
+                $info = getimagesize($val['url']);
+                $function = 'imagecreatefrom' . image_type_to_extension($info[2], false);
+                if ($val['stream']) {
+                    $info = getimagesizefromstring($val['url']);
+                    $function = 'imagecreatefromstring';
+                }
+                $res = $function($val['url']);
+                $resWidth = $info[0];
+                $resHeight = $info[1];
+                $canvas = imagecreatetruecolor($val['width'], $val['height']);
+                imagefill($canvas, 0, 0, $color);
+                imagecopyresampled($canvas, $res, 0, 0, 0, 0, $val['width'], $val['height'], $resWidth, $resHeight);
+                $val['left'] = $val['left'] < 0 ? $backgroundWidth - abs($val['left']) - $val['width'] : $val['left'];
+                $val['top'] = $val['top'] < 0 ? $backgroundHeight - abs($val['top']) - $val['height'] : $val['top'];
+                imagecopymerge($imageRes, $canvas, $val['left'], $val['top'], $val['right'], $val['bottom'], $val['width'], $val['height'], $val['opacity']);//左,上,右,下,宽度,高度,透明度
+            }
+        }
+        if (isset($config['text']) && !empty($config['text'])) {
+            foreach ($config['text'] as $key => $val) {
+                $val = array_merge($textDefault, $val);
+                list($R, $G, $B) = explode(',', $val['fontColor']);
+                $fontColor = imagecolorallocate($imageRes, $R, $G, $B);
+                $val['left'] = $val['left'] < 0 ? $backgroundWidth - abs($val['left']) : $val['left'];
+                $val['top'] = $val['top'] < 0 ? $backgroundHeight - abs($val['top']) : $val['top'];
+                imagettftext($imageRes, $val['fontSize'], $val['angle'], $val['left'], $val['top'], $fontColor, $val['fontPath'], $val['text']);
+            }
+        }
+        ob_start();
+        imagejpeg($imageRes);
+        imagedestroy($imageRes);
+        $res = ob_get_contents();
+        ob_end_clean();
+        $key = substr(md5(rand(0, 9999)), 0, 5) . date('YmdHis') . rand(0, 999999) . '.jpg';
+        $uploadType = (int)sys_config('upload_type', 1);
+        $upload = UploadService::init();
+        $res = $upload->to($path)->validate()->stream($res, $key);
+        if ($res === false) {
+            return $upload->getError();
+        } else {
+            $info = $upload->getUploadInfo();
+            $info['image_type'] = $uploadType;
+            return $info;
+        }
+    }
+
+
+    /**
+     * TODO 获取小程序二维码是否生成
+     * @param $url
+     * @return array
+     */
+    public static function remoteImage($url)
+    {
+        $curl = curl_init();
+        curl_setopt($curl, CURLOPT_URL, $url);
+        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+        $result = curl_exec($curl);
+        $result = json_decode($result, true);
+        if (is_array($result)) return ['status' => false, 'msg' => $result['errcode'] . '---' . $result['errmsg']];
+        return ['status' => true];
+    }
+
+    /**
+     * TODO 修改 https 和 http 移动到common
+     * @param $url $url 域名
+     * @param int $type 0 返回https 1 返回 http
+     * @return string
+     */
+    public static function setHttpType($url, $type = 0)
+    {
+        $domainTop = substr($url, 0, 5);
+        if ($type) {
+            if ($domainTop == 'https') $url = 'http' . substr($url, 5, strlen($url));
+        } else {
+            if ($domainTop != 'https') $url = 'https:' . substr($url, 5, strlen($url));
+        }
+        return $url;
+    }
+
+
+    /**
+     * 获取二维码
+     * @param $url
+     * @param $name
+     * @return array|bool|string
+     */
+    public static function getQRCodePath($url, $name)
+    {
+        if (!strlen(trim($url)) || !strlen(trim($name))) return false;
+        try {
+            $uploadType = 2;
+            $info = [];
+            $outfile = Config::get('qrcode.cache_dir');
+            $code = new QRcode();
+            $wapCodePath = $code->png($url, $outfile . '/' . $name)->getPath(); //获取二维码生成的地址
+            $content = file_get_contents('.' . $wapCodePath);
+            if ($uploadType === 1) {
+                $info["code"] = 200;
+                $info["name"] = $name;
+                $info["dir"] = $wapCodePath;
+                $info["time"] = time();
+                $info['size'] = 0;
+                $info['type'] = 'image/png';
+                $info["image_type"] = 1;
+                $info['thumb_path'] = $wapCodePath;
+                return $info;
+            } else {
+                $config = [
+                    'accessKey' => config('qiniu')['accessKeyId'],
+                    'secretKey' => config('qiniu')['accessKeySecret'],
+                    'uploadUrl' => 'imgs.boofly.cn',
+                    'storageName' => config('qiniu')['bucket'],
+                    'storageRegion' => 's3-cn-south-1.qiniucs.com',
+                ];
+                $upload = new Upload(2,$config);
+                $res = $upload->to($outfile)->validate()->stream($content, $name);
+                if ($res === false) {
+                    return $upload->getError();
+                }
+                $info = $upload->getUploadInfo();
+                $info['image_type'] = $uploadType;
+                return $info;
+            }
+        } catch (\Exception $e) {
+            return $e->getMessage();
+        }
+    }
+
 }