• 基于PHP实现微信客服欢迎语发送


    背景:用户通过某客服链接进入客服会话页面,客服进行欢迎语的发送

    技术栈:larvel+redis

    本文章仅提供思路参考,详情查看官方文档

    实现思路如下:

    验证url:

    实现微信客服正常使用首先需要在企微后台进行配置,如果要实现Api进行欢迎语发送时,就需要回调接口,该接口仅用一次配置成功后 该代码可注释 先将使用的方法进行封装一遍调用

    该类为回调信息加解密 方便使用时调用 不理解的话可以参照官方文档一一对应即可
    1. class WXBizMsgCrypt
    2. {
    3. private $m_sToken;
    4. private $m_sEncodingAesKey;
    5. private $m_sReceiveId;
    6. /**
    7. * 构造函数
    8. * @param $token string 开发者设置的token
    9. * @param $encodingAesKey string 开发者设置的EncodingAESKey
    10. * @param $receiveId string, 不同应用场景传不同的id
    11. */
    12. public function __construct($token, $encodingAesKey, $receiveId)
    13. {
    14. $this->m_sToken = $token;
    15. $this->m_sEncodingAesKey = $encodingAesKey;
    16. $this->m_sReceiveId = $receiveId;
    17. }
    18. /*
    19. *验证URL
    20. *@param sMsgSignature: 签名串,对应URL参数的msg_signature
    21. *@param sTimeStamp: 时间戳,对应URL参数的timestamp
    22. *@param sNonce: 随机串,对应URL参数的nonce
    23. *@param sEchoStr: 随机串,对应URL参数的echostr
    24. *@param sReplyEchoStr: 解密之后的echostr,当return返回0时有效
    25. *@return:成功0,失败返回对应的错误码
    26. */
    27. public function VerifyURL($sMsgSignature, $sTimeStamp, $sNonce, $sEchoStr, &$sReplyEchoStr)
    28. {
    29. if (strlen($this->m_sEncodingAesKey) != 43) {
    30. return errorCode::$IllegalAesKey;
    31. }
    32. $pc = new Prpcrypt($this->m_sEncodingAesKey);
    33. //verify msg_signature
    34. $sha1 = new SHA1;
    35. $array = $sha1->getSHA1($this->m_sToken, $sTimeStamp, $sNonce, $sEchoStr);
    36. $ret = $array[0];
    37. if ($ret != 0) {
    38. return $ret;
    39. }
    40. $signature = $array[1];
    41. if ($signature != $sMsgSignature) {
    42. return errorCode::$ValidateSignatureError;
    43. }
    44. $result = $pc->decrypt($sEchoStr, $this->m_sReceiveId);
    45. if ($result[0] != 0) {
    46. return $result[0];
    47. }
    48. $sReplyEchoStr = $result[1];
    49. return errorCode::$OK;
    50. }
    51. /**
    52. * 检验消息的真实性,并且获取解密后的明文.
    53. *
      1. *
      2. 利用收到的密文生成安全签名,进行签名验证
    54. *
    55. 若验证通过,则提取xml中的加密消息
  • *
  • 对消息进行解密
  • *
  • *
  • * @param $msgSignature string 签名串,对应URL参数的msg_signature
  • * @param $timestamp string 时间戳 对应URL参数的timestamp
  • * @param $nonce string 随机串,对应URL参数的nonce
  • * @param $postData string 密文,对应POST请求的数据
  • * @param &$msg string 解密后的原文,当return返回0时有效
  • *
  • * @return int 成功0,失败返回对应的错误码
  • */
  • public function DecryptMsg($sMsgSignature, $sTimeStamp = null, $sNonce, $sPostData, &$sMsg)
  • {
  • if (strlen($this->m_sEncodingAesKey) != 43) {
  • return ErrorCode::$IllegalAesKey;
  • }
  • $pc = new Prpcrypt($this->m_sEncodingAesKey);
  • //提取密文
  • $xmlparse = new XMLParse;
  • $array = $xmlparse->extract($sPostData);
  • $ret = $array[0];
  • if ($ret != 0) {
  • return $ret;
  • }
  • if ($sTimeStamp == null) {
  • $sTimeStamp = time();
  • }
  • $encrypt = $array[1];
  • //验证安全签名
  • $sha1 = new SHA1;
  • $array = $sha1->getSHA1($this->m_sToken, $sTimeStamp, $sNonce, $encrypt);
  • $ret = $array[0];
  • if ($ret != 0) {
  • return $ret;
  • }
  • $signature = $array[1];
  • if ($signature != $sMsgSignature) {
  • return errorCode::$ValidateSignatureError;
  • }
  • $result = $pc->decrypt($encrypt, $this->m_sReceiveId);
  • if ($result[0] != 0) {
  • return $result[0];
  • }
  • $sMsg = $result[1];
  • return errorCode::$OK;
  • }
  • }
  • 用SHA1算法生成安全签名
    1. /**
    2. * 用SHA1算法生成安全签名
    3. * @param string $token token
    4. * @param string $timestamp 时间戳
    5. * @param string $nonce 随机字符串
    6. * @param string $encrypt 密文消息
    7. */
    8. public function getSHA1($token, $timestamp, $nonce, $encrypt_msg)
    9. {
    10. //排序
    11. try {
    12. $array = array($encrypt_msg, $token, $timestamp, $nonce);
    13. sort($array, SORT_STRING);
    14. $str = implode($array);
    15. return array(errorCode::$OK, sha1($str));
    16. } catch (\Exception $e) {
    17. print $e . "\n";
    18. return array(errorCode::$ComputeSignatureError, null);
    19. }
    20. }
    XML解密
    1. /**
    2. * 解密
    3. *
    4. * @param $encrypted
    5. * @param $receiveId
    6. * @return array
    7. */
    8. public function decrypt($encrypted, $receiveId)
    9. {
    10. try {
    11. //解密
    12. if (function_exists('openssl_decrypt')) {
    13. $decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', $this->key, OPENSSL_ZERO_PADDING, $this->iv);
    14. } else {
    15. $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->key, base64_decode($encrypted), MCRYPT_MODE_CBC, $this->iv);
    16. }
    17. } catch (\Exception $e) {
    18. return array(errorCode::$DecryptAESError, null);
    19. }
    20. try {
    21. //删除PKCS#7填充
    22. $pkc_encoder = new PKCS7Encoder;
    23. $result = $pkc_encoder->decode($decrypted);
    24. if (strlen($result) < 16) {
    25. return array();
    26. }
    27. //拆分
    28. $content = substr($result, 16, strlen($result));
    29. $len_list = unpack('N', substr($content, 0, 4));
    30. $xml_len = $len_list[1];
    31. $xml_content = substr($content, 4, $xml_len);
    32. $from_receiveId = substr($content, $xml_len + 4);
    33. } catch (\Exception $e) {
    34. print $e;
    35. return array(errorCode::$IllegalBuffer, null);
    36. }
    37. if ($from_receiveId != $receiveId) {
    38. return array(errorCode::$ValidateCorpidError, null);
    39. }
    40. return array(0, $xml_content);
    41. }
    42. }
    书写验证接口 参数需要unclode需要使用$_Get 
    1. //获取会话信息参数
    2. $msg_signature = $_GET['msg_signature'];
    3. $timestamp = $_GET['timestamp'];
    4. $nonce = $_GET['nonce'];
    5. $echostr = $_GET['echostr'];
    6. // if(empty($msg_signature) || empty($timestamp) || empty($nonce) ||empty($echostr)){
    7. // return json_encode([
    8. // 'code'=>"0001",
    9. // 'msg'=>'回调参数为空!'
    10. // ]);
    11. // }
    12. //配置文件
    13. $corpid = \App\Extend\Qy\Pay\WechatApplet\Config::corp_id;
    14. $token = \App\Extend\Qy\Pay\WechatApplet\Config::corp_token;
    15. $EncodingAESKey = \App\Extend\Qy\Pay\WechatApplet\Config::EncodingAESKey;
    16. $wxcpt = new WXBizMsgCrypt($token, $EncodingAESKey, $corpid);
    17. // 验证url 有效性
    18. $sEchoStr = ""; // 需要返回的明文
    19. $errCode = $wxcpt->VerifyURL($msg_signature, $timestamp, $nonce, $echostr, $sEchoStr);
    20. Log::info("明文日志==>".$sEchoStr);
    21. if ($errCode != 0) {
    22. return json_encode([
    23. 'code'=>$errCode, // 返回错误码到errorCode 查看错误信息
    24. 'msg'=>'明文返回失败!!'
    25. ]);
    26. }
    当获取到xml回调信息后 解析密文在上边封装过调用即可  xml转数组
    1. //xml 格式转换 数组
    2. $xml = simplexml_load_string($sMsg, 'SimpleXMLElement', LIBXML_NOCDATA);
    仔细阅读文档会发现获取到回调后 需要对接读取接口 接收用户事件 对此事件不理解的可以 去了解下swoole  参数自行理解
    1. /**
    2. * @param $open_kfid
    3. * @param $token
    4. * @return false|string
    5. * 读取信息
    6. */
    7. public function sync_msg($cursor,$open_kfid,$token){
    8. //获取access_token
    9. $access_token = $this->getaccess_token($open_kfid);
    10. $url="https://qyapi.weixin.qq.com/cgi-bin/kf/sync_msg?access_token=".$access_token."&debug=1";
    11. $param = [
    12. "cursor"=>$cursor,
    13. "token" =>$token,
    14. "limit" =>1000,
    15. "voice_format"=>0,
    16. "open_kfid"=>$open_kfid
    17. ];
    18. $headers = [
    19. 'Content-Length: '.strlen(json_encode($param)),
    20. 'Content-Type: application/json;charset=UTF-8',
    21. ];
    22. $res = $this->POST($url,$headers,json_encode($param));
    23. Log::info("读取消息日志==>",[$res]);
    24. return $res;
    25. }
    根据读取到的信息 可以进行发送欢迎语  具体看文档

    这里简述一下思路 :

    首次用户操作读取next_cursor  该值可为空,获取到后可以存入redis 方便下次调用;

    首次用户触发读取接口时可以获取到welcome_code,可以根据该值进行欢迎语发送,但是该值会在微信存放48小时,再次期间还想发送信息的话需要注意 msgtype 事件类型

    用户每次触发都会更改事件类型 48小时内再次触发不会出现code值所以我们需要获取用户userid进行信息发送

    到此微信客服发送欢迎语的思路全部结束,如有问题看官方手册或私聊我进行讨论,该功能需要了解swoole的运行机制方便深入了解该功能
     
    
     
    
    
                    
                        
                    
    
                    
  • 相关阅读:
    prometheus 原理(架构,promql表达式,描点原理)
    linux下centOS系统安装vim以及常用命令
    看我简单教会你如何按关键字搜索淘宝商品
    JAVA:实现PrimeFactorization质因数分解算法(附完整源码)
    RocketMQ、Kafka、RabbitMQ 消费原理,顺序消费问题【图文理解】
    新能源汽车行业资讯-2022-9-19
    【LeetCode第362场周赛】8020.字符串转换 | 推导+矩阵快速幂+KMP | 困难
    azkaban编译部署
    CSS 样式
    利用浏览器将Markdown导出为HTML、PDF
  • 原文地址:https://blog.csdn.net/qq_63530862/article/details/133839378