一、效果图展示:
二、企业微信配置
1、需要注册企业微信账号,官方地址:https://work.weixin.qq.com/
2、登录企业微信 → 应用管理 → 创建应用(支持小程序),我这里已经注册了一个“美奇客服”
3、创建成功后,进入应用“美奇客服”,拉到最底部 → 开发者接口,这里配置一下域名和IP
4、应用 → 点击进入“微信客服”,点击API图标,然后设置“可调用接口的应用”
5、应用 → 点击进入“审批”,点击API图标,然后设置“可调用接口的应用”
三、接收消息服务器配置
1、应用 → 点击进入我们自创建的应用“美奇客服”,点击“接口消息”功能里的API设置
2、填写接收消息服务器配置,Token和EncodingAESKey随机生成即可;
3、编写控制器的PHP代码,用于验证这个URL(验证成功才能保存)
<?php namespace app\index\controller; use think\Controller; use think\Request; use weixinwork\WXBizMsgCrypt; /** * 微信接口类 */ class Weixin extends Controller { /** * 企业微信客服:接收消息回调接口 */ public function msg() { $token = config("weixin.token"); $encodingAesKey = config("weixin.encodingAesKey"); $corpId = config("weixin.corpid");//企业ID //接收GET参数 $sReqMsgSig = $_GET['msg_signature']; $sReqTimeStamp = $_GET['timestamp']; $sReqNonce = $_GET['nonce']; $sVerifyEchoStr = $_GET['echostr']; $sEchoStr = ""; $wxcpt = new WXBizMsgCrypt($token, $encodingAesKey, $corpId); $errCode = $wxcpt->VerifyURL($sReqMsgSig, $sReqTimeStamp, $sReqNonce, $sVerifyEchoStr, $sEchoStr); if ($errCode == 0) { //原样返回明文消息内容 echo $sEchoStr; } } }
四、相关文件代码:
WeWorkAPI.php
<?php namespace weixinwork; use think\Request; use think\Cache; use think\Db; use think\Exception; class WeWorkAPI { private function getAccessToken(){ $access_token = Cache::get("wxwork-accesstoken"); if(empty($access_token)){ $corpid = config("weixin.corpid"); $corpsecret = config("weixin.corpsecret"); $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$corpid&corpsecret=$corpsecret"; $response = file_get_contents($url); $data = json_decode($response, true); $access_token = $data['access_token']; //设置缓存(expires_in过期时间为7200) Cache::set("wxwork-accesstoken",$access_token,$data['expires_in']); } return $access_token; } //获取客服帐号列表 public function getKFList() { $accessToken = $this->getAccessToken(); if(empty($accessToken)){ outputError("Token获取失败"); } $url = 'https://qyapi.weixin.qq.com/cgi-bin/kf/account/list?access_token='.$accessToken; $post = ['offset'=>0, 'limit'=>100]; $response = get_curl($url, json_encode($post)); $result = json_decode($response, true); if ($result['errcode'] == 0) { $account_list = $result['account_list']; $open_kfid = $account_list[0]["open_kfid"]; return $open_kfid; }else{ return null; } } //获取微信客服链接 public function getKFURL($scene) { $accessToken = $this->getAccessToken(); if(empty($accessToken)){ outputError("Token获取失败"); } $kfid = $this->getKFList(); if(empty($kfid)){ outputError("获取客服ID失败"); } $url = 'https://qyapi.weixin.qq.com/cgi-bin/kf/add_contact_way?access_token='.$accessToken; $post = ['open_kfid'=>$kfid, 'scene'=>$scene]; $response = get_curl($url, json_encode($post)); $result = json_decode($response, true); if ($result['errcode'] == 0 && $result['url']) { //存放数据库 $wxwork = Db::name("wxwork")->field('id')->where('openkfid',$kfid)->find(); if(empty($wxwork)){ Db::name("wxwork")->insert(["openkfid"=>$kfid,"url"=>$result['url'],"addtime"=>time(),]); } return $result['url']; }else{ printLog('获取微信客服链接失败:'.$result['errmsg']); } } //读取消息 public function syncMsg($kfid, $token, $cursor = '') { $accessToken = $this->getAccessToken(); $url = 'https://qyapi.weixin.qq.com/cgi-bin/kf/sync_msg?access_token='.$accessToken; $post = ['cursor'=>$cursor, 'token'=>$token, 'open_kfid'=>$kfid]; $response = get_curl($url, json_encode($post)); $result = json_decode($response, true); if ($result['errcode'] == 0) { return $result; }else{ return null; } } //加锁获取最新消息 public function lockGetMsg($kfid, $token) { $wxwork = Db::name("wxwork")->field('id,cursor')->where('openkfid',$kfid)->find(); $cursor = !empty($wxwork['cursor']) ? $wxwork['cursor'] : ""; $result = $this->syncMsg($kfid, $token, $cursor); if($result){ $cursor = $result['next_cursor']; Db::name("wxwork")->where('id',$wxwork['id'])->setField('cursor',$cursor); return $result['msg_list']; }else{ return []; } } //发送消息 public function sendMsg($touser, $kfid, $msgtype, $msgparam) { $accessToken = $this->getAccessToken(); $url = 'https://qyapi.weixin.qq.com/cgi-bin/kf/send_msg?access_token='.$accessToken; $post = ['touser'=>$touser, 'open_kfid'=>$kfid, 'msgtype'=>$msgtype]; $post[$msgtype] = $msgparam; $response = get_curl($url, json_encode($post)); $result = json_decode($response, true); if ($result['errcode'] == 0) { return $result['msgid']; }else{ printLog('发送消息失败:'.$result['errmsg']); } } //发送文本消息 public function sendTextMsg($touser, $kfid, $content) { $param = ['content'=>$content]; return $this->sendMsg($touser, $kfid, 'text', $param); } //发送菜单消息 public function sendMenuMsg($touser, $kfid, $head_content, $list, $tail_content = '') { $param = ['head_content'=>$head_content, 'list'=>$list]; if($tail_content) $param['tail_content'] = $tail_content; return $this->sendMsg($touser, $kfid, 'msgmenu', $param); } //发送欢迎消息 public function sendWelcomeMsg($code, $msgtype, $msgparam) { $accessToken = $this->getAccessToken(); $url = 'https://qyapi.weixin.qq.com/cgi-bin/kf/send_msg_on_event?access_token='.$accessToken; $post = ['code'=>$code, 'msgtype'=>$msgtype]; $post[$msgtype] = $msgparam; $response = get_curl($url, json_encode($post)); $result = json_decode($response, true); if ($result['errcode'] == 0) { return $result['msgid']; }else{ printLog('发送欢迎消息失败:'.$result['errmsg']); } } //发送欢迎文本消息 public function sendWelcomeTextMsg($code, $content) { $param = ['content'=>$content]; return $this->sendWelcomeMsg($code, 'text', $param); } //发送欢迎菜单消息 public function sendWelcomeMenuMsg($code, $head_content, $list, $tail_content = '') { $param = ['head_content'=>$head_content, 'list'=>$list]; if($tail_content) $param['tail_content'] = $tail_content; return $this->sendWelcomeMsg($code, 'msgmenu', $param); } }
Weixin.php
<?php namespace app\index\controller; use think\Controller; use think\Request; use think\Cache; use think\Db; use weixinwork\WXBizMsgCrypt; /** * 微信接口类 */ class Weixin extends Common{ public function _initialize(){ parent::_initialize(); } /** * 企业微信客服:接收消息和事件 */ public function msg(){ //1.验证URL //$this->verifyURL($_GET);exit; //2.接收微信发过来的消息或者事件 $token = config("weixin.token"); $encodingAesKey = config("weixin.encodingAesKey"); $corpId = config("weixin.corpid"); //接收GET参数 $sReqMsgSig = $_GET['msg_signature']; $sReqTimeStamp = $_GET['timestamp']; $sReqNonce = $_GET['nonce']; $xmldata=file_get_contents("php://input"); try { $sMsg = ''; //解密后的明文内容 $wxcpt = new WXBizMsgCrypt($token, $encodingAesKey, $corpId); //检验消息的真实性,并且获取解密后的明文 $errCode = $wxcpt->DecryptMsg($sReqMsgSig, $sReqTimeStamp, $sReqNonce, $xmldata,$sMsg); if ($errCode == 0 && !empty($sMsg)) { $xml = simplexml_load_string($sMsg, 'SimpleXMLElement', LIBXML_NOCDATA); $array = json_encode($xml); $array = json_decode($array,true); //读取消息 $OpenKfId = $array["OpenKfId"]; if(isset($array["next_cursor"])){ //修改数据库 Db::name("wxwork")->where('openkfid',$OpenKfId)->update(["cursor"=>$array["next_cursor"]]); } $wework = new \weixinwork\WeWorkAPI(); $msg_list = $wework->lockGetMsg($OpenKfId, $array["Token"]); $this->completeMsg($wework,$msg_list); }else{ printLog("接收消息事件失败,错误码: " . $errCode); } } catch (Exception $e) { printLog("接收消息事件异常,Error: " . $e); } } /** * 企业微信客服:验证链接 */ public function verifyURL($data){ $token = config("weixin.token"); $encodingAesKey = config("weixin.encodingAesKey"); $corpId = config("weixin.corpid"); //接收GET参数 $sReqMsgSig = $data['msg_signature']; $sReqTimeStamp = $data['timestamp']; $sReqNonce = $data['nonce']; $sVerifyEchoStr = $data['echostr']; $sEchoStr = ""; $wxcpt = new WXBizMsgCrypt($token, $encodingAesKey, $corpId); $errCode = $wxcpt->VerifyURL($sReqMsgSig, $sReqTimeStamp, $sReqNonce, $sVerifyEchoStr, $sEchoStr); if ($errCode == 0) { //原样返回明文消息内容 echo $sEchoStr; } } /** * 企业微信客服:处理消息和事件 */ public function completeMsg($wework,$msg_list){ foreach($msg_list as $row){ if($row['msgtype'] == 'event' && $row['event']['event_type'] == 'enter_session' && $row['event']['scene'] == 'pay'){ //1.用户进入客服聊天界面,发送确认支付菜单消息 try{ parse_str(urldecode($row['event']['scene_param']), $scene_param); if(isset($scene_param['trade_no']) && isset($scene_param['money'])){ $wxkflog = Db::name("wxwork_record")->field('trade_no,payurl')->where('trade_no',$scene_param['trade_no'])->find(); if($wxkflog){ $head_content = '您的订单金额:'.$scene_param['money'].'元'; $wxkflog["payurl"]= "weixin://wxpay/bizpayurl?pr=G9MfNwqz1"; if(strpos($wxkflog['payurl'], 'wxpay://')!==false){ $menu_list[] = ['type'=>'text', 'text'=>['content'=>$wxkflog['payurl']]]; }else if(strpos($wxkflog['payurl'], 'wxp://')!==false){//微信个人收款码 $apiurl = getSiteUrl()."/Index/Qr/api.html?width=200&text=".$wxkflog["payurl"]; $menu_list[] = ['type'=>'view', 'view'=>['url'=>$apiurl, 'content'=>"点击长按二维码快速识别"]]; }else{ $menu_list[] = ['type'=>'click', 'click'=>['id'=>$scene_param['trade_no'], 'content'=>"点击获取支付链接"]]; } if(!empty($row['event']['welcome_code'])){ $wework->sendWelcomeMenuMsg($row['event']['welcome_code'], $head_content, $menu_list,); }else{ $wework->sendMenuMsg($row['event']['external_userid'], $row['event']['open_kfid'], $head_content, $menu_list); } //修改记录状态 Db::name("wxwork_record")->update(['status'=>1, 'addtime'=>time()])->where('trade_no',$wxkflog['trade_no']); }else{ if(!empty($row['event']['welcome_code'])){ $wework->sendWelcomeTextMsg($row['event']['welcome_code'], '订单不存在'); }else{ $wework->sendTextMsg($row['event']['external_userid'], $row['event']['open_kfid'], '订单不存在'); } } }else{ if(!empty($row['event']['welcome_code'])){ $wework->sendWelcomeTextMsg($row['event']['welcome_code'], '订单参数有误'); }else{ $wework->sendTextMsg($row['event']['external_userid'], $row['event']['open_kfid'], '订单参数有误'); } } }catch(Exception $e){ printLog("微信客服发送信息异常,Error:".$e); } }elseif($row['msgtype'] == 'text' && $row['text']['content'] == "点击获取支付链接"){ //2.用户回复菜单消息,发送支付链接 $orderid = $row['text']['menu_id']; if(!empty($orderid)){ $wxkflog = Db::name("wxwork_record")->field('payurl')->where('trade_no',$orderid)->find(); if($wxkflog["payurl"]){ $wework->sendTextMsg($row['external_userid'], $row['open_kfid'], "您的支付链接:\r\n".$wxkflog["payurl"]."\r\n(请点击链接进行付款)"); }else{ $wework->sendTextMsg($row['external_userid'], $row['open_kfid'], '订单支付链接不存在'); } }else{ $wework->sendTextMsg($row['external_userid'], $row['open_kfid'], '订单参数有误'); } } } echo 'success'; } /** * 企业微信客服:获取客服链接 */ public function getlink(){ $data = input('post.'); !isset($data['number']) && $this->error('缺少订单编号参数'); !isset($data['payurl']) && $this->error('缺少支付链接参数'); !isset($data['money']) && $this->error('缺少订单金额参数'); $number = trim($data['number']); $payurl = trim($data['payurl']); $money = trim($data['money']); empty($number) && $this->error('订单编号不能为空'); empty($payurl) && $this->error('支付链接不能为空'); empty($money) && $this->error('订单金额不能为空'); $link = Cache::get("wxwork-kf-link"); if(empty($link)){ $wework = new \weixinwork\WeWorkAPI(); $link = $wework->getKFURL('pay'); //设置缓存 Cache::set("wxwork-kf-link",$link,86400); } empty($link) && $this->error('获取微信客服链接失败'); $scene_param = 'trade_no='.$number.'&money='.$money; //$kfurl = 'weixin://biz/ww/kefu/' . $link . '&schema=1&scene_param='.urlencode($scene_param); $kfurl = $link . '&schema=1&scene_param='.urlencode($scene_param); //printLog("企业微信客服链接:".$kfurl); //将支付信息存入数据库 $record = Db::name("wxwork_record")->field('id')->where('trade_no',$number)->find(); if(empty($record)){ Db::name("wxwork_record")->insert(["trade_no"=>$number,"payurl"=>$payurl]); } $arr['code'] = 1; $arr['msg'] = 'success'; $arr['url'] = $kfurl; header('Content-Type:application/json; charset=utf-8'); echo json_encode($arr, JSON_UNESCAPED_UNICODE); exit; } }
请登录之后再进行评论