• 微信客服消息


    <?php
    
    /**
     * 回复用户消息 - 客服消息
     * 2015-3-31 
     */
    class WeixinReply {
    
        /**
         * 回复消息调用接口
         * @var type 
         */
        private $apiReplyUrl;
    
        /**
         * 获取access token 接口
         * @var type 
         */
        private $apiGetAccessTokenUrl;
    
        /**
         * access token 获取到的凭证 
         * @var string
         */
        private $accessToken;
    
        /**
         * accessToken memcache 缓存名称
         * @var type 
         */
        private $accessTokenCacheName;
    
        const APPID = 'xxxx'; //AppID(应用ID)
        const APPSECRET = 'xxxxxx'; //AppSecret(应用密钥)
    
        public function __construct() {
            $this->accessTokenCacheName = 'weixin_AccessToken';
            $this->apiGetAccessTokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' .
                    self::APPID . '&secret=' . self::APPSECRET;
    
            if (!$this->getAccessToken()) {
                echo "获取AccessToken失败!";
                exit;
            }
    
            $this->apiReplyUrl = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=' . $this->accessToken;
        }
    
        /**
         * 获取access token
         * @param type $force 是否强制获取access token
         */
        private function getAccessToken($force = 0) {
            $objMemcached = new KIFCacheMemcached();
            $accessToken = $objMemcached->get($this->accessTokenCacheName);
            if ($force)
                $accessToken = '';
            if (!$accessToken) {
                $return = $this->curlGetData($this->apiGetAccessTokenUrl);
                $return = json_decode($return, true);
                $accessToken = $return['access_token'];
                if (!$accessToken) {
                    return false;
                }
                $objMemcached->set($this->accessTokenCacheName, $accessToken, $return['expires_in'] - 600);
            }
            $this->accessToken = $accessToken;
            return true;
        }
    
        /**
         * 回复消息
         * @param type $params
         */
        public function reply($params) {
            $return = null;
            if ($params['type'] == WeixinAutoReply::TYPE_TEXT) {
                $return = $this->textMessage($params);
            }
            if (!$return) {
                return '';
            }
            $return = json_decode($return, true);
            // access_token invalid
            if ($return['errmsg'] == 'invalid credential') {
                $this->getAccessToken(1);
                return '';
            }
    
            if ($return['errcode']) {
                return $return['errmsg'];
            }
            /**
             * success {
              "errcode": 0,
              "errmsg": "ok"
              }
             */
            return 'ok';
        }
    
        /**
         * 回复文本消息
         */
        private function textMessage($params) {
    
            if (!isset($params['openid']) || !$params['openid'] || !isset($params['content']) || !$params['content']) {
                return 'openid 或 content为空';
            }
            $params['content'] = htmlentities($params['content'], ENT_COMPAT, 'utf-8');
            $jsonData = <<<EOF
            {
        "touser":"{$params['openid']}",
        "msgtype":"text",
        "text":
        {
             "content":"{$params['content']}"
        }
    }        
    EOF;
            $return = $this->curlPostData($jsonData);
    
            return $return;
        }
    
        /**
         * 发送数据
         */
        private function curlPostData($jsonData) {
            $ch = curl_init($this->apiReplyUrl);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
            curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json',
                'Content-Length: ' . strlen($jsonData))
            );
            $result = curl_exec($ch);
            return $result;
        }
    
        /**
         * 获取数据 - get
         */
        private function curlGetData($url) {
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array());
            $result = curl_exec($ch);
            return $result;
        }
    
        /**
         * 对字符串进行加密和解密
         * @param <string> $string
         * @param <string> $operation  DECODE 解密 | ENCODE  加密
         * @param <int> $expiry 有效期,单位秒
         * @return <string>
         */
        static public function authcode($string, $operation = 'DECODE', $expiry = 2592000) {
            $ckey_length = 4;
            $key = '08127b44d5a005a12b6e880';
            $keya = md5(substr($key, 0, 16));
            $keyb = md5(substr($key, 16, 16));
            $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
    
            $cryptkey = $keya . md5($keya . $keyc);
            $key_length = strlen($cryptkey);
    
            $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
            $string_length = strlen($string);
    
            $result = '';
            $box = range(0, 255);
    
            $rndkey = array();
            for ($i = 0; $i <= 255; $i++) {
                $rndkey[$i] = ord($cryptkey[$i % $key_length]);
            }
    
            for ($j = $i = 0; $i < 256; $i++) {
                $j = ($j + $box[$i] + $rndkey[$i]) % 256;
                $tmp = $box[$i];
                $box[$i] = $box[$j];
                $box[$j] = $tmp;
            }
    
            for ($a = $j = $i = 0; $i < $string_length; $i++) {
                $a = ($a + 1) % 256;
                $j = ($j + $box[$a]) % 256;
                $tmp = $box[$a];
                $box[$a] = $box[$j];
                $box[$j] = $tmp;
                $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
            }
    
            if ($operation == 'DECODE') {
                if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
                    return substr($result, 26);
                } else {
                    return '';
                }
            } else {
                return $keyc . str_replace('=', '', base64_encode($result));
            }
        }
    
    }

    Template

    .main{800px; margin:0 auto; position: relative;} .replybox{ display:none; 200px; height:120px; position: absolute; top:200px; right:-240px; background-color: #fff; padding:10px 20px 40px; border:1px solid #ccc; text-align:center; } .replybox textarea{ 200px; height:60px;} .replybox .tips{ display:block; text-align:left; margin-bottom:5px; color:#3c3c3c;} .btnon{ color:#f00;}

    <div class="replybox">
        <form action="http://xxxx/message.php" method="post">
            <textarea name="content"></textarea>
            <span class="tips">获得奖品说明 《回车换行》微信试用活动链接</span>
            <input type="button" name="replysubmitbtn" value="提交" />
            <input type="hidden" name="msgid" value="" />
        </form>
    </div>
    <script type="text/javascript">
        $(function(){
            //root_domain
            $(".replybtn").click(function() {
                $("input[name=msgid]").val($(this).attr('rel'));
                $(".replybox").show();
                $(".replybtn").removeClass('btnon')
                $(this).addClass('btnon');
            });
            // reply submit
            $("input[name=replysubmitbtn]").click(function() {
                var id = $("input[name=msgid]").val();
                if(!id) {
                    alert('请选择回复项');
                    return false;
                }
                var content =  $("textarea[name=content]").val();
                $.ajax({
                   url: root_domain + '/admin/weixin/message.php?action=replymsg',
                   data:{id:id, content:content},
                   dataType:'json',
                   type:'GET',
                   success:function(data) {
                       if(data.ok) {
                           $("textarea[name=content]").val(data.msg);
                           alert('回复成功');
                       } else {
                           alert(data.msg);
                       }
                   }
                });
            });
            
        });
    </script>

    Recive

    $openid = WeixinReply::authcode(Request::g("e_user"), 'DECODE');

    message.php

    // ACTION 扩展
    if(Request::g('action') == 'replymsg') {
        $id = Request::g('id');
        $content = Request::g('content');
        if(!$content) {
            ajax_fail_exit('回复内容为空');
        }
        
        $message = $objWeixinChatsData->get($id);
        if(!$message) {
            ajax_fail_exit('没有获取到此消息内容');
        }
        // 时间判断, 发布时间两小时内
        if(time() - $message['create_time'] > 86400 * 2) {
            ajax_fail_exit('仅允许在消息发布后48小时内回复');
        }
        
        $objWeixinReply = new WeixinReply();
        $message['openid'] = 'xxxxxx';
        
        if (preg_match('#http://xxx.xxxx.com/weixin/article/w+#i', $content, $match)) {
            $authOpenid = $objWeixinReply->authcode($message['openid'], 'ENCODE');
            $suffix = '?page_type=true' . '&e_user=' . urlencode($authOpenid);
            $content = str_replace($match[0], $match[0]. $suffix, $content);
        }
        
        // 回复
        $params = array(
            'openid' => $message['openid'],
            'content' => $content,
            'type' => 'text',
        );
        
        $return = $objWeixinReply->reply($params);
        if($return == 'ok') {
            // 回复记录... @todo
            
            ajax_success_exit($content);
        } else {
            ajax_fail_exit('回复失败 ' . $return);
        }
        
    }
  • 相关阅读:
    批量转外部样式为行内样式
    AngularJS 笔记2
    windows特殊文件或文件夹
    zepto 入门
    js闭包
    AngularJS 笔记1
    sublime配置 sublimecondeintel 分号后不要提示
    sublime插件开发手记
    用flvplayer.swf在网页中播放视频(网页中flash视频播放的实现)
    无插件启动谷歌浏览器
  • 原文地址:https://www.cnblogs.com/bandbandme/p/4390087.html
Copyright © 2020-2023  润新知