运用Websocket框架之GatewayWorker开发电商平台买家与卖家及时通信

前段时候公司提了一个新的需求,在商品的详情页要完成站内买家和商品卖家及时通信的功用以轻易沟通促进生意营业,要开辟此功用当时起首斟酌到的就是swoole和workerman了,从网上也许了解了一下关于这两款东西的论述,功用都是相称壮大的,斟酌到项目的进度题目,照样挑选上手轻易比较快的GatewayWorker。

先看一下我们前端设想嵬峨上的模板,分别是用户和卖家背景。 功用照样比较全的,险些模拟的是QQ。

《运用Websocket框架之GatewayWorker开发电商平台买家与卖家及时通信》

《运用Websocket框架之GatewayWorker开发电商平台买家与卖家及时通信》
营业上的也许需求是,用户在进入某个商品详情页下,给用户供应一个和卖家沟通的接口,依据商品的ID找到对应的卖家,类似于淘宝,另有发送图片,发送对应的商品链接;商户背景也差不多。

我们的平台上有假造商品和实体商品两大分类,当时也斟酌到了音讯的读取状况。我的表最初设想以下,没有加任何的索引,斟酌的也许也不够全面,有看法的先辈还望指导一二!

DROP TABLE IF EXISTS `hp_chat_log`;
CREATE TABLE `hp_chat_log` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '聊天记录表主键id',
  `user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用户id',
  `merchant_id` varchar(15) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '商家id',
  `send_message` text COLLATE utf8_unicode_ci NOT NULL,
  `send_message_type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '发送音讯范例(1:一般文本;2:商品链接,3:用户发送图片)',
  `sender` tinyint(1) NOT NULL DEFAULT '1' COMMENT '发送方。1:用户。2:商家',
  `send_time` int(11) NOT NULL DEFAULT '0' COMMENT '发送时候',
  `read_status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是不是已读。0:未读取。1:已读取',
  `acc_isonline` tinyint(1) NOT NULL DEFAULT '0' COMMENT '接收方是不是在线 (0:不在线;1:在线)',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=157 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

模板有了,表设想好了,接下来就是搭建效劳了,当前项目开辟的框架用的是TP5,挑选的Websocket框架是GatewayWorker框架,关于GatewayWorker与TP5的整合要领能够看我的这篇文章,讲到了在Linux和

Windows下的整合装置。

http://www.cnblogs.com/wt645631686/p/7219519.html

整合好了今后须要依据当前效劳器的一些端口设置在修正一些默许的设置,由于须要客户端经由过程指定的端口竖立衔接。

TP5整合好了今后Gateway和workerman的主体目次构造都在TP5的框架目次vendor下的workerman目次下。须要修正内里gateway目次下的一些文件的端口及IP地点设置。

设置完成今后,进入项目目次,根据workerman官方手册供应的使用要领,用敕令php start.php start启动socket效劳,如以下截图,分别是1238和8282端口。固然能够在背景运转,细致的使用要领请参考手册。

《运用Websocket框架之GatewayWorker开发电商平台买家与卖家及时通信》

启动好了今后那末就须要在客户端最先动手了,我们项目里是在前端页面里用竖立的链接。看前端代码

当前的一切代码并非终究的,现在只是阶段性开辟,后期在项目中逐步完善。

var ws;
    // 衔接效劳端
    function connect() {
       // 建立websocket
       ws = new WebSocket("ws://"+document.domain+":8282");  //当时为了轻易今后的保护,这里在php的全局文件里定义了一个常量来定义ip,厥后当地开辟完提交到linux效劳器环境今后发明链接失利!
       console.log(ws);
       ws.onopen = onopen;
       ws.onmessage = onmessage;
       ws.onclose = function(e) {
        console.log(e);
          console.log("衔接封闭,定时重连");
          connect();
       };
       ws.onerror = function(e) {
        console.log(e);
          console.log("涌现毛病");
       };
    }
     // 握手
    function onopen()
    {
        var joint = '{"type":"handshake","role":"user"}';
        ws.send(joint);
    }
    // 效劳端发来音讯时
    function onmessage(e)
    {
        var data = JSON.parse(e.data);
          console.log(data);
        switch(data['type']){
            // 效劳端ping客户端
            case 'ping':
                ws.send('{"type":"pong"}');
                break;
            // 登录 更新用户列表
            case 'handshake':
                bindUid(data.client_id);
                $('#client_id').val(data.client_id);
                break;
            // 提示
            case 'reception':
                //{"type":"say","from_client_id":xxx,"to_client_id":"all/client_id","content":"xxx","time":"xxx"}
                warn(data['content'], data['time'], data['timestamp']);
                break;
        }
    }

    //绑定uid
    function bindUid (client_id) {
        var bindUrl = "{:url('push/push/BindUserClientId')}";
        $.post(bindUrl, {client_id: client_id}, function(data){
            console.log(data);
        }, 'json');
    }

    //发送衔接
    function sendLink () {
       sendTrigger('link');
    }
    // 发送信息
    function sendMessage (){
        sendTrigger('message');
    }
    function sendTrigger(sendType) {
      var toMid     = $('#toMid').val();
      var pid       = $('#pid').val();
      var message   = $("footer .send_content").val();
      var client_id = $('#client_id').val();
      var sendUrl   = "{:url('push/push/SendMessageToMerchant')}";
      $.ajax({
        url:sendUrl,
        type:'POST',
        data:{message:message,toMid:toMid,pid:pid,client_id:client_id,sendType:sendType},
        async:false,
        dataType:'JSON',
        success:function(data){
            data = JSON.parse(data);
            if (data.status < 0) {
                alert('发送失利,请稍后再试!');
            } else {
                $('#send_timestamp').val(data.timeStamp);
                $('#send_timestr').val(data.timeStr);
                if (sendType == 'link') {
                    $('#main').append(data.html);
                }
            }
        }
      })
    }

    // 提示
    function warn(content, time, prevTmestamp){
        var V_image = $('#V_image').val();
        var str = '<div class="chat-receiver">' + timestampWarn(prevTmestamp, time) + '<div class="chat-avatar"><img src="'+ V_image+ '" alt=""></div>
        <div class="chat-content"><div class="chat-triangle"></div><span>' + content + '</span></div>';
        domChange(str);
        $("#main").scrollTop($("#main")[0].scrollHeight);

    }

    //发送
    function sender(content, time, prevTmestamp) {
        var user_image = $('#user_image').val();
        var str = '<div class="chat-sender">' + timestampWarn(prevTmestamp, time) + '<div class="chat-avatar"><img src="' +user_image + '" alt="">
</div><div class="chat-content"><div class="chat-triangle"></div>' +
        '<span>' + content + '</span></div></div>';
        domChange(str);
    }

    //音讯时候掌握
    function timestampWarn (nowTimestamp , nowTime) {
        var prevTimestamp = $('#prev_timestamp').val();
        $('#prev_timestamp').val(nowTimestamp);
        var timeOffset    = 6;
        var accTime = '';
        if ((nowTimestamp - prevTimestamp) > timeOffset) {
           accTime =  '<div style="clear:both;"></div><p class="chat-history-date">' + nowTime + '</p>';
        }
        return accTime;
    }
<body onload="connect();">
</body>

在开辟过程当中,修正的GatewayWorker文件并不多,除了几个主要的端口及IP须要修正以外,仅仅修正一个主要的文件就够了,那就是Push模块(项目的通信模块)同级的Events.php文件。看一下项目需求里

修正后的代码,一个要领;

/**
    * 当客户端发来音讯时触发
    * @param int $client_id 衔接id
    * @param mixed $message 详细音讯
    */
   public static function onMessage($client_id, $message)
   {
        $message_data = json_decode($message,true);
        if (!$message_data) {
            return ;
        }
        switch($message_data['type']) {
            case 'pong':
                return;
            case 'handshake':                
                $new_message    = [
                    'type'      => $message_data['type'],
                    'client_id' => $client_id, 
                    'time'      => date('H:i:s')
                ];
                Gateway::sendToClient($client_id, json_encode($new_message));
                return;
            case 'send':
                if (!isset($message_data['toClientUid'])) {
                  throw new \Exception("toClient not set. client_ip:{$_SERVER['REMOTE_ADDR']}");
                }
                $toUid          = $message_data['toClientUid'];
                $message        = $message_data['content'];
                $new_message    = [
                    'type'      => 'reception',
                    'content'   => $message, 
                    'time'      => date('H:i:s'),
                    'timestamp' => time(),
                    'c_type'    => $message_data['c_type'],
                    'primary'   => $message_data['Db_id']
                ];  
                //发送者角色
                $source_info = explode('_', $message_data['source']);
                if ($source_info[0] == 'U') {
            //为了平安,特地做了加密
                    $new_message['source'] = encrypt_hopeband($source_info[1], 'E', 'XXXXXXX');    
                }

                return Gateway::sendToUid($toUid, json_encode($new_message));
        }
   }

然后看一下Push模块下的掌握器文件,在合营前端在绑定客户端ID及发送信息做的一些处置惩罚。

class Push extends Base{

    protected static $user_headimage = '';
    protected static $uid = null;



    public function __construct () {
        parent::__construct();
        $this->checkUserLogin();
        //用户头像昵称等信息
        self::$uid            = session('userinfo.uid');
        $user_info            = Hmodel\User::getUserChatinfoById(self::$uid);
        self::$user_headimage = json_decode($user_info['headimgurl'],true)[0];

    }


    public function chatAction () {
        $product_id = intval(input('param.pid', 0, 'int'));
        $toMid      = Hmodel\Product::getMidByProductid($product_id);
        if ($toMid === false) notFund();

        $productHtml = $this->returnProductData2Html($product_id, 'default');

        $int_toMid = substr($toMid, 2);
        $V_headInfo = Pmodel\Push::getVmerchantHeadImageByVid($int_toMid);
        $V_headimage = is_not_empty_array($V_headInfo) ? json_decode($V_headInfo['headimgurl'])[0] :'/uploads/logo.png';

        if (substr($toMid, 0, 1) == 'V') {
            $chatLogData = Pmodel\Push::getChatlogByUseridAndVid(self::$uid, $int_toMid); 
            if (is_not_empty_array($chatLogData)) {
                $chatLog = self::chatlogData2Html($chatLogData, $V_headimage);
            }
        } elseif (substr($toMid, 0, 1) == 'E') {

        }


        $view = new View;
        $view->assign('pHtml', $productHtml);
        $view->assign('toMid', $toMid);
        $view->assign('pid', $product_id);
        $view->assign('chatlogHtml', $chatLog);
        $view->assign('role', 'user');
        $view->assign('user_image', self::$user_headimage);
        $view->assign('V_image', $V_headimage);
        return $view->fetch();
    }


      private static function chatlogData2Html ($data = [], $V_headimage = '') {
        $todayTimestamp = strtotime(date('Y-m-d'));
        $html = '';
        foreach ($data as $k => $v) {
            $date = $v['send_time'] < $todayTimestamp ? date('Y/m/d H:i:s', $v['send_time']) : date('H:i:s', $v['send_time']);
            $time_nodes = '';
            if (($data[$k]['send_time'] - $data[$k-1]['send_time']) > 180) {
                $time_nodes = '<div style="clear:both;"></div><p class="chat-history-date">' .$date.'</p>';
            } 
            //sender->发送方   1:用户。2:商家
            if ($v['sender'] == 1) {
                
                //send_message_type->发送音讯范例  (1:一般文本;2:商品链接)
                if ($v['send_message_type'] == 1) {
                    $html.= '<div class="chat-sender">';
                    $html.= $time_nodes;
                    $html.= '<div class="chat-avatar"><img src="' . self::$user_headimage . '" alt=""></div>';
                    $html.= '<div class="chat-content"><div class="chat-triangle"></div><span>' . $v['send_message'].'</span></div>';
                    $html.= '</div>';
                }elseif ($v['send_message_type'] == 2) {
                    $html.= $time_nodes;
                    $product_info = json_decode($v['send_message'],true);
                    $html.= self::productData2SendHtml($product_info);
                }elseif ($v['send_message_type'] == 3) {
                    $images_arr = json_decode($v['send_message'],true);
                  
                    $html.= '<div class="chat-sender">';
                    $html.= $time_nodes;
                    $html.= '<div class="chat-avatar"><img src="' . self::$user_headimage . '" alt=""></div>';
                    $html.= '<div class="chat-content"><div class="chat-triangle"></div>';
                    foreach ($images_arr as $v ) {
                        $html.= '<img src="' .WEB_SITE. '/' . $v . '" style="max-width:85%">';
                    }
                    $html.= '</div>';
                    $html.= '</div>';
                }
            }else {
                if ($v['send_message_type'] == 1) {
                    $html.= '<div class="chat-receiver">';
                    $html.= '<div class="chat-avatar"><img src="' . $V_headimage . '" alt=""></div>';
                    $html.= '<div class="chat-content"><div class="chat-triangle"></div><span>' . $v['send_message'].'</span></div>';
                    $html.= '</div>';
                }elseif ($v['send_message_type'] == 2) {

                }
            }
        }
        return $html;
    }
    public function BindUserClientIdAction () {
        if (!Request::instance()->isPost()) { notFund(); }
        $bindUserid = 'U_' . session('userinfo.uid');
        $client_id = input("param.client_id", 0, "string"); 
        // 设置GatewayWorker效劳的Register效劳ip和端口
        Gateway::$registerAddress = SOCKET_SERVER_PORT;
        // client_id与uid绑定
        // Gateway::closeClient($client_id);
        return Gateway::bindUid($client_id, $bindUserid);
}
//用户发送音讯给商家
    public function SendMessageToMerchantAction () {
        if (!Request::instance()->isPost()) { notFund(); }
        $message   = $_POST['message']; 
        $toMid     = input('post.toMid', '' , 'string');
        $product_id= input('post.pid', 0, 'int');
        $client_id = input('post.client_id', '', 'string');
        $sendType  = input('post.sendType', '', 'string');



        if (!in_array($sendType,['link', 'message'])) {                             //客户端毛病
            return json_encode(['status' => -1]);
        }
        if (strlen($client_id) != 20 ) {                                            //客户端毛病
            return json_encode(['status' => -1]);
        }
        if (!is_not_empty_string($toMid) || !is_positive_integer($product_id)) {    //体系毛病
            return json_encode(['status' => -2]);
        }
        $db_toMid      = Hmodel\Product::getMidByProductid($product_id);            //数据毛病
        if ($db_toMid != $toMid) {
            return json_encode(['status' => -3]);
        }
        require_once dirname(dirname(__FILE__)) . '/Events.php';

        $uid            = session('userinfo.uid');
        $accIsOnline    = Gateway::isUidOnline($toMid) == 1 ? 1 : 0;                //判读商家是不是在线
        $message_type   = 1;
        if ($sendType == 'link') {
            $message_type = 2;
            $productData = $this->referProductData($product_id);
            unset($productData['product_price']);
            unset($productData['score']);
            unset($productData['product_stock']);
            unset($productData['product_param']);
            unset($productData['product_desc']);
            unset($productData['product_main']);
            unset($productData['category_id']);
            unset($productData['merchant_id']);
            $message = json_encode($productData);
        }
        //Log入库
        $insertId       = Pmodel\Push::addChatLog($uid, $toMid, $message, $message_type, 1, $accIsOnline);
        if($message_type == 1){
            if(!is_numeric($message)){
                $message = '"'.$message.'"';
            }
            if ($message == '') {
                $message = '';
            }
        }
        if ($insertId === false) {                                                  //入库失利(效劳器毛病)
            return json_encode(['status' => -3]);
        }
        $Worker = new \Events;
        $message_json   = '{"type":"send","source":"U_' . $uid . '","toClientUid":"' . $toMid . '","content":' . $message .',
                 "c_type": ' . $message_type .', "Db_id":' . $insertId . '}';

        $Worker::onMessage($client_id, $message_json);
        //胜利返回相干数据
        return json_encode([
            'status'    => 1,
            'timeStamp' => time(),
            'timeStr'   => date('H:i:s'),
            'html'      => $message_type == 1 ? '' : self::productData2SendHtml($productData)
        ]);

 }
//商家发送信息给用户
    public function sendMessageToUserAction () {
     if (!Request::instance()->isPost()) { notFund(); }
        $post_message = is_not_empty_string($_POST['message']) ? $_POST['message'] : ''; 
        $toUserCode   = input('post.toUserCode', '' , 'string');
        $toU_uid      = encrypt_hopeband($toUserCode, 'D', 'xxxxx');
        $V_client_id  = input('post.client_id', '', 'string');
        $V_uid_code   = input('post.myCode', '', 'string');
        $V_uid        = encrypt_hopeband($V_uid_code, 'D', 'xxxxx');
        $make_message = [];
        $message = '';
        self::trimImageAndTextinfo2str($post_message, $make_message);

        if (is_not_empty_array($make_message)) {
            foreach ( $make_message as &$v ) {
                $message .= self::checkIflegalAndReturn($v);
            }
           
        }
       
        if (strlen($V_client_id) != 20 || Gateway::isOnline($V_client_id) != 1) {       //客户端毛病
            return json_encode(['status' => -2]);
        }    
        $V_merchantInfo = Pmodel\Push::getVmerchantInfoByVid($V_uid);
        if (!is_not_empty_array($V_merchantInfo)) {                                     //商家信息不存在
            return json_encode(['status' => -1]);
        }
        require_once dirname(dirname(__FILE__)) . '/Events.php';

        $accIsOnline    = Gateway::isUidOnline('U_' . $toU_uid) == 1 ? 1 : 0;         //判读用户是不是在线
        $message_type   = 1;
        //Log入库
        $insertId       = Pmodel\Push::addChatLog($toU_uid, 'V_' . $V_uid, $message, 1, 2, $accIsOnline);
        if ($insertId === false) {                                                  //入库失利(效劳器毛病)
            return json_encode(['status' => -3]);
        }
        $Worker = new \Events;
        $img_encrypt_code = encrypt_hopeband('Hp_(legal)', 'E', 'Hp_HopeBand_Chat_img');
        $message = str_replace($img_encrypt_code .' src="', $img_encrypt_code . " src='", $message);
        $message = str_replace('">', "'>", $message);
        $message_json   = '{"type":"send","toClientUid":"U_' . $toU_uid . '","content":"' . $message .'","Db_id": "' . $insertId . '"}';  
        $Worker::onMessage($client_id, $message_json);
        //胜利返回相干数据
        return json_encode([
            'status'    => 1,
            'timeStamp' => time(),
            'timeStr'   => date('H:i:s'),
        ]);

    }
public function BindUserClientIdAction () {
        if (!Request::instance()->isPost()) { notFund(); }
        $bindUserid = 'U_' . session('userinfo.uid');
        $client_id = input("param.client_id", 0, "string"); 
        // 设置GatewayWorker效劳的Register效劳ip和端口
        Gateway::$registerAddress = SOCKET_SERVER_PORT;
        // client_id与uid绑定
        // Gateway::closeClient($client_id);
        return Gateway::bindUid($client_id, $bindUserid);
}
//用户发送音讯给商家
    public function SendMessageToMerchantAction () {
        if (!Request::instance()->isPost()) { notFund(); }
        $message   = $_POST['message']; 
        $toMid     = input('post.toMid', '' , 'string');
        $product_id= input('post.pid', 0, 'int');
        $client_id = input('post.client_id', '', 'string');
        $sendType  = input('post.sendType', '', 'string');



        if (!in_array($sendType,['link', 'message'])) {                             //客户端毛病
            return json_encode(['status' => -1]);
        }
        if (strlen($client_id) != 20 ) {                                            //客户端毛病
            return json_encode(['status' => -1]);
        }
        if (!is_not_empty_string($toMid) || !is_positive_integer($product_id)) {    //体系毛病
            return json_encode(['status' => -2]);
        }
        $db_toMid      = Hmodel\Product::getMidByProductid($product_id);            //数据毛病
        if ($db_toMid != $toMid) {
            return json_encode(['status' => -3]);
        }
        require_once dirname(dirname(__FILE__)) . '/Events.php';

        $uid            = session('userinfo.uid');
        $accIsOnline    = Gateway::isUidOnline($toMid) == 1 ? 1 : 0;                //判读商家是不是在线
        $message_type   = 1;
        if ($sendType == 'link') {
            $message_type = 2;
            $productData = $this->referProductData($product_id);
            unset($productData['product_price']);
            unset($productData['score']);
            unset($productData['product_stock']);
            unset($productData['product_param']);
            unset($productData['product_desc']);
            unset($productData['product_main']);
            unset($productData['category_id']);
            unset($productData['merchant_id']);
            $message = json_encode($productData);
        }
        //Log入库
        $insertId       = Pmodel\Push::addChatLog($uid, $toMid, $message, $message_type, 1, $accIsOnline);
        if($message_type == 1){
            if(!is_numeric($message)){
                $message = '"'.$message.'"';
            }
            if ($message == '') {
                $message = '';
            }
        }
        if ($insertId === false) {                                                  //入库失利(效劳器毛病)
            return json_encode(['status' => -3]);
        }
        $Worker = new \Events;
        $message_json   = '{"type":"send","source":"U_' . $uid . '","toClientUid":"' . $toMid . '","content":' . $message .',
                 "c_type": ' . $message_type .', "Db_id":' . $insertId . '}';

        $Worker::onMessage($client_id, $message_json);
        //胜利返回相干数据
        return json_encode([
            'status'    => 1,
            'timeStamp' => time(),
            'timeStr'   => date('H:i:s'),
            'html'      => $message_type == 1 ? '' : self::productData2SendHtml($productData)
        ]);

 }
//商家发送信息给用户
    public function sendMessageToUserAction () {
     if (!Request::instance()->isPost()) { notFund(); }
        $post_message = is_not_empty_string($_POST['message']) ? $_POST['message'] : ''; 
        $toUserCode   = input('post.toUserCode', '' , 'string');
        $toU_uid      = encrypt_hopeband($toUserCode, 'D', 'xxxxx');
        $V_client_id  = input('post.client_id', '', 'string');
        $V_uid_code   = input('post.myCode', '', 'string');
        $V_uid        = encrypt_hopeband($V_uid_code, 'D', 'xxxxx');
        $make_message = [];
        $message = '';
        self::trimImageAndTextinfo2str($post_message, $make_message);

        if (is_not_empty_array($make_message)) {
            foreach ( $make_message as &$v ) {
                $message .= self::checkIflegalAndReturn($v);
            }
           
        }
       
        if (strlen($V_client_id) != 20 || Gateway::isOnline($V_client_id) != 1) {       //客户端毛病
            return json_encode(['status' => -2]);
        }    
        $V_merchantInfo = Pmodel\Push::getVmerchantInfoByVid($V_uid);
        if (!is_not_empty_array($V_merchantInfo)) {                                     //商家信息不存在
            return json_encode(['status' => -1]);
        }
        require_once dirname(dirname(__FILE__)) . '/Events.php';

        $accIsOnline    = Gateway::isUidOnline('U_' . $toU_uid) == 1 ? 1 : 0;         //判读用户是不是在线
        $message_type   = 1;
        //Log入库
        $insertId       = Pmodel\Push::addChatLog($toU_uid, 'V_' . $V_uid, $message, 1, 2, $accIsOnline);
        if ($insertId === false) {                                                  //入库失利(效劳器毛病)
            return json_encode(['status' => -3]);
        }
        $Worker = new \Events;
        $img_encrypt_code = encrypt_hopeband('Hp_(legal)', 'E', 'Hp_HopeBand_Chat_img');
        $message = str_replace($img_encrypt_code .' src="', $img_encrypt_code . " src='", $message);
        $message = str_replace('">', "'>", $message);
        $message_json   = '{"type":"send","toClientUid":"U_' . $toU_uid . '","content":"' . $message .'","Db_id": "' . $insertId . '"}';  
        $Worker::onMessage($client_id, $message_json);
        //胜利返回相干数据
        return json_encode([
            'status'    => 1,
            'timeStamp' => time(),
            'timeStr'   => date('H:i:s'),
        ]);

    }

分外另有一些关于音讯处置惩罚方面的;

//考证是不是是不是是图片,如果是而且返回图片地点,不然返回字符串
    private static function checkIflegalAndReturn ( $message = '') {
        header('content-type:text/html; charset=utf-8');
        $img_encrypt_code = encrypt_hopeband('Hp_(legal)', 'E', 'Hp_HopeBand_Chat_img');
        if (substr($message, 0, 21) != '<img src="data:image/' || substr($message, strpos($message, ';', 0) ,8) != ';base64,' || 
            substr($message, -2, 2) != '">') {
            return $message;
        }
        $preg = '/<img.*?src="(.*?)".*?>/is';
        preg_match( $preg, $message,$arr);
        $img_src = self::base64_upload($arr[1]);
        return '<img '.$img_encrypt_code.' src="' . $img_src . '">';
    }

    //把接受到的音讯文本和图片有序提出并剖析
    private static function trimImageAndTextinfo2str ($message = '', &$message_arr = []) {
        if (!is_not_empty_string($message)) return '';
        $img_start_code = '<img src="data:image/';
        $img_end_code = '">';
        $tmp_message = strlen($message);
        $initial     = substr($message,0,strlen($img_start_code));
   
        if ($initial == $img_start_code) {
            $start = strpos($message, $img_start_code, 0); 
            $end   = strpos($message, $img_end_code , 0); 
            $message_arr[] = substr($message, 0, $end + 2);
            $message = substr($message, $end + 2);
        }else{
            $start = strpos($message, $img_start_code);
            if ($start !== false) {
                $message_arr[] = substr($message, 0, $start);
                $message = substr($message, $start);
            }else{
                //防备xss进击
                $message_arr[]= string_remove_xss(htmlspecialchars_decode($message));
            }
        }
        if (($tmp_message) != strlen($message) && is_not_empty_string($message)) {
            self::trimImageAndTextinfo2str($message, $message_arr);
        }
      return $message_arr;

    }

    private static function base64_upload($base64 = '') {
    $base64_image = str_replace(' ', '+', $base64);
    if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image, $result)){
        if($result[2] == 'jpeg'){
            $image_name = getCode(16,4).'.jpg';
        }else{
            $image_name = getCode(16,4).'.'.$result[2];
        }
        $image_file = "./upload/chat".'/'.date('Y').'/'.date('m').'/'.date('d').'/'.$image_name;    //效劳器文件存储途径
        //推断文件途径是不是存在
        $path = "./upload/chat".'/'.date('Y').'/'.date('m').'/'.date('d').'/';
        is_dir($path) or mkdir($path,0777,true);
        if (file_put_contents($image_file, base64_decode(str_replace($result[1], '', $base64_image)))){
            return $image_file;
        }else{
            return false;
        }
    }else{
        return false;
    }
  }

微信的图片上传

JS部份

/* 退款挑选图片 -------- start */
        
$("#chooseImage").click(function()
{
                
                wx.chooseImage(
                {
                    count: 9,                                 // 默许9
                    sizeType: ['original','compressed'],     // 能够指定是原图照样压缩图,默许两者都有
                    sourceType: ['album', 'camera'],         // 能够指定泉源是相册照样相机,默许两者都有
                    success: function (res)
                    {
                           images.localId = res.localIds; // 返回选定照片的当地ID列表,localId能够作为img标签的src属性显现图片                       
                            //for(var j = 0;j<images.localId.length;j++)
                              // {                      
                                    // var str = '<div serverId='+images.serverId[j]+' class="chat-sender"><div class="chat-avatar">
                      //<img src="/home/push/img/1.png" alt="">
                       //</div><div class="chat-content"><div class="chat-triangle"></div>
                      //<img src='+images.localId[j]+' data-originalDrawing-src='+images.localId[j]+' data-preview-src="" data-preview-group="1"/></div></div>'
                                    // $("#main").append(str);
                                   
                              // }
                           var t = 0;
                        var i = 0, length = images.localId.length;
                        images.serverId = [];

                        /* upload 要领 -------- start */
                        function upload()
                        {
                              wx.uploadImage(
                              {
                                localId: images.localId[i],
                                success: function (res)
                                {
                                      i++;

                                      images.serverId.push(res.serverId);

                                      if (i < length) { upload(); }
                                 
                                      var str = '<div serverId='+res.serverId+' class="chat-sender"><div class="chat-avatar">
                               <img src="/home/push/img/1.png" alt="">
                            </div><div class="chat-content"><div class="chat-triangle"></div>
                               <img src='+images.localId[i-1]+' data-originalDrawing-src='+images.localId[i-1]+' data-preview-src="" data-preview-group="1"/>
                            </div></div>'
                                   $("#main").append(str);

                                   if(i >= length )    uploadImageToDb(images.serverId);

                                  
                                },
                                fail: function (res){ }
                              });

                        }
                        /* upload 要领 -------- end */

                        upload();
                        

                    }
                })
            });

            function uploadImageToDb(images){
                var str = "";
                var upUrl = "http://xxxxxx.com/push/push/uploadImgage";
                var toMid     = $('#toMid').val();
                  var client_id = $('#client_id').val();
                $.post(upUrl,{images:images,toMid:toMid,client_id:client_id},function(data){
                    if(data == 1){
                        for(var n = 0 ; n < $(".chat-sender").length ; n++){
                            str = $(".chat-sender").eq(n).attr("serverId")+",";
                            for(var z=0;z<data.length;z++){
                                if(data[z] == str){
                                    $(".chat-sender").eq(n).find(".chat-content").append('<div class="chat-sender">上传失利</div>');
                                }
                            }
                        }
                    
                    }
                    
                    
                })
            }
            /* 退款挑选图片 -------- end */

背景部份

//微信上传图片
    public function uploadImgageAction () {
        if (!Request::instance()->isPost()) { notFund(); }
        $images    = $_POST['images'];
        if (empty($images)) die;
        $toMid     = input('post.toMid', '' , 'string');
        $client_id = input('post.client_id', '', 'string');
        if (strlen($client_id) != 20 ) {                                            //客户端毛病
            return json_encode(['status' => -1]);
        }
        if (!is_not_empty_string($toMid)) {                                         //体系毛病
            return json_encode(['status' => -2]);
        }

        require_once dirname(dirname(__FILE__)) . '/Events.php';
 
        $accIsOnline    = Gateway::isUidOnline($toMid) == 1 ? 1 : 0;                //判读商家是不是在线
        $message_type   = 3;
        //微信上传图片处置惩罚Start
        $res = json_decode(file_get_contents("access_token.json"));
        foreach ($res as $key => $value) {
            if($key == 'access_token'){
                $access_token = $value;
            }
        }
        $data = [];
        foreach ($images as $k => $v) {
            $str = date('YmdHis').rand(1000,9999).'.jpg';
            $targetName = './upload/chat/'.$str;
            if (!file_exists("./upload/chat/")) {
              mkdir("./upload/chat/", 0777, true);
            }
            $ch = curl_init("http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=".$access_token."&media_id=".$v);
            $fp = fopen($targetName, 'wb');
            curl_setopt($ch, CURLOPT_FILE, $fp);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            $msg["status"] = curl_exec($ch);
            $msg["filename"] = $str;
            curl_close($ch);
            fclose($fp);
            $data[] = $targetName;
        }
        //微信上传图片处置惩罚End
        if (!is_not_empty_array($data)) {                                       //微信效劳器端图片上传毛病
            return json_encode(['status' => -2]); 
        }
        $message = json_encode($data);
        //Log入库
        $insertId       = Pmodel\Push::addChatLog(self::$uid, $toMid, $message, $message_type, 1, $accIsOnline);
        if ($insertId === false) {                                                  //入库失利(效劳器毛病)
            return json_encode(['status' => -3]);
        }
        $Worker = new \Events;
        $message_json   = '{"type":"send","source":"U_' . self::$uid . '","toClientUid":"' . $toMid . '","content":' . $message .',
                "c_type": ' . $message_type .', "Db_id":' . $insertId . '}';
        $Worker::onMessage($client_id, $message_json);
        //胜利返回相干数据
        return json_encode([
            'status'    => 1,
            'timeStamp' => time(),
            'timeStr'   => date('H:i:s')
        ]);

    }

其他一些不是很主要的代码就不拿出来了。

当前项目只是一个简朴的需求,并没有把GatewayWorker许多壮大的功用表现出来,人人今后在项目开辟中碰到更加庞杂的需求,参考官方手册供应的一些Demo就能够逐步完成并开辟出更加硬朗的项目!

    原文作者:王腾
    原文地址: https://segmentfault.com/a/1190000012971998
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞