微信应用开发【PHP】---笔记6---自定义公众号/测试号菜单并实现功能

一、创建自定义菜单【测试号】

1.截图

【没有小程序,因为我没做】

在这里插入图片描述
1. 点击第一个一级菜单:“今日歌曲”
在这里插入图片描述
2. 点击第二个一级菜单:“菜单”
扫码带提示:扫描QR.jpg
扫码推事件:扫描QR.jpg
在这里插入图片描述
拍照或系统发图,发送位置:这两个和上的次的功能一样,给公众号发送图片和位置
赞一下
在这里插入图片描述
3. 点击第三个一级菜单:“关于我”
看图:为用户发送一张图片
二维码:为用户发送一张二维码图片,扫描得到
在这里插入图片描述
古诗文网:跳转url
在这里插入图片描述
往日推文:为用户发送往日的图文
在这里插入图片描述

2.代码实现

(1)接口函数文件:【FUN.php】

<?php
/**
 * Created by PhpStorm.
 * 函数文件
 */
//获取测试号的token值
function get_TOKEN(){
    $appid = "测试号公众号/的Appid";
    $appsecret = "测试号公众号/的AppSecret";
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$appsecret";
    $output = https_request($url);
    $result = (array)json_decode($output);
    $access_token=$result['access_token'];
    return $access_token;
}
//定义服务请求函数,get/post
//参考链接为:https://segmentfault.com/a/1190000006220620
//php中curl用法就是:创建curl会话 -> 配置参数 -> 执行 -> 关闭会话
function https_request($url, $data = null)
{
    $curl = curl_init();//创建了一个curl会话资源,成功返回一个句柄
    curl_setopt($curl, CURLOPT_URL, $url);//函数传参过来,设置URL
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);// 信任任何证书
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);// 检查证书中是否设置域名
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//设置是否将响应结果存入变量,1是存入,0是直接echo出
    curl_setopt($curl, CURLOPT_TIMEOUT,60);//设置一个最长的可忍受的连接时间,秒为单位
    if (!empty($data)) {
        curl_setopt($curl, CURLOPT_POST, 1);//表明是POST请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);//设置POST的数据域
    }
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//同上
    $output = curl_exec($curl);//执行,然后将响应结果存入$output变量
    curl_close($curl);//关闭curl会话资源
    return $output;
}

(2)创建菜单:【Create_menu.php】

<?php
/**
 * 创建自定义菜单
 * https://tool.ip138.com/json/
 */
//error_reporting(0);
require "FUN.php";
$access_token = get_TOKEN();
echo "测试号access_token的值为:" . $access_token . "</br>";
//创建自定义菜单接口创建自定义菜单
$urlMenu = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=$access_token";
$MenuData = '{
  "button": [
    {
      "type": "click",
      "name": "今日歌曲",
      "key": "KEY_music"
    },
    {
      "name": "菜单",
      "sub_button": [
        {
          "type": "scancode_waitmsg",
          "name": "扫码带提示",
          "key": "rselfmenu_0_0",
          "sub_button": []
        },
        {
          "type": "scancode_push",
          "name": "扫码推事件",
          "key": "rselfmenu_0_1",
          "sub_button": []
        },
        {
          "type": "pic_photo_or_album",
          "name": "拍照或者相册发图",
          "key": "rselfmenu_1_1",
          "sub_button": []
        },
        {
          "name": "发送位置",
          "type": "location_select",
          "key": "rselfmenu_2_0"
        },
        {
          "type": "click",
          "name": "赞一下",
          "key": "KEY_good"
        }
      ]
    },
    {
      "name": "关于我",
      "sub_button": [
        {
          "type": "click",
          "name": "看图",
          "key": "KEY_pic"
        },
        {
          "type": "click",
          "name": "二维码",
          "key": "KEY_qr"
        },
        {
          "type": "view",
          "name": "古诗文网",
          "url": "https://www.gushiwen.org/"
        },
        {
          "type": "click",
          "name": "往日推文",
          "key": "KEY_article"
        }
      ]
    }
  ]
}';
$output1 = https_request($urlMenu, $MenuData);
echo $output1;
?>

(3)菜单事件实现:【Menu.php】

<?php
error_reporting(0);
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (!isset($_GET['echostr'])) {
    $wechatObj->responseMsg();
} else {
    $wechatObj->valid();
}

class wechatCallbackapiTest
{
    //验证接口的函数,用于申请成为开发者时向微信发送验证信息
    public function valid()
    {
        $echoStr = $_GET["echostr"];
        if ($this->checkSignature()) {
            echo $echoStr;
            exit;
        }
    }

    //校验函数,校验对接身份函数,签名验证程序
    private function checkSignature()
    {
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];
        $token = TOKEN;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);
        if ($tmpStr == $signature) {
            return true;
        } else {
            return false;
        }
    }

    //响应消息函数
    public function responseMsg()
    {
        //$postStr为用户在微信公众平台发的信息
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        if (!empty($postStr)) {
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $RX_TYPE = trim($postObj->MsgType);//判断平台接受的消息类型
            //用户发送的消息类型判断
            switch ($RX_TYPE) {
                case "event":    //事件消息
                    $resultStr = $this->receiveEvent($postObj);
                    break;
                default:
                    $resultStr = "unknow msg type: " . $RX_TYPE;
                    break;
            }
            echo $resultStr;
        } else {
            echo "???";
            exit;
        }
    }

    //7.事件处理
    private function receiveEvent($object)
    {
        $MsgEvent = trim($object->Event);
        if ($MsgEvent == 'subscribe') {  //订阅事件
            $keyword = $object->EventKey;
            if (isset($keyword)) {
                $qrscene_Str = substr(trim($keyword), 0, 7);
                if ($qrscene_Str == qrscene) {
                    $contentStr = "欢迎关注公众号,你是来自扫描二维码关注的,你的场景值为:" . $object->EventKey . "\n";
                } else {
                    $contentStr = "欢迎关注公众号,你不是来自扫描二维码关注的" . "\n";
                }
            } else {
                $contentStr = "欢迎关注公众号";
            }
        } elseif ($MsgEvent == "SCAN") {
            $keyword = $object->EventKey;
            switch ($keyword) {
                case "123":
//                    $contentStr = "你的场景值为:" . $keyword;
                    $contentStr = array();
                    $contentStr[] = array
                    ("Title" => "推文标题",
                        "Description" => "公众号:介绍图文",
                        "PicUrl" => "图片链接",
                        "Url" => "推文链接");
                    $resultStr = $this->transmitNews($object, $contentStr);
                    break;
                case "1234":
                    $contentStr = "点赞❤";
                    $resultStr = $this->transmitText($object, $contentStr);
                default:
                    break;
            }
            return $resultStr;
        } elseif ($MsgEvent == "CLICK") {//点击事件
            $EventKey = $object->EventKey;
            switch ($EventKey) {
                case "KEY_music":
                    $content = array("Title" => "借一束光",
                        "Description" => "歌手:圈九",
                        "MusicUrl" => "随便一个音乐链接",
                        "HQMusicUrl" => "随便一个音乐链接");
                    $resultStr = $this->transmitMusic($object, $content);
                    break;
                case "KEY_good":
                    $contentStr = "点赞❤ヾ(≧▽≦*)o";
                    $resultStr = $this->transmitText($object, $contentStr);
                    break;
                case "KEY_pic":
                    $contentStr = array
                    ("MediaId" => "图片的Mediaid,需要上传素材获得,代码附后,尚未研究看懂");
                    $resultStr = $this->transmitImage($object, $contentStr);
                    break;
                case "KEY_article":
                    $contentStr = array();
                    $contentStr[] = array
                    ("Title" => "推文标题",
                        "Description" => "单图文内容:(往日推文)",
                        "PicUrl" => "图片链接",
                        "Url" => "推文链接");
                    $resultStr = $this->transmitNews($object, $contentStr);
                    break;
                case "KEY_qr":
                    $contentStr = array
                    ("MediaId" => "图片的Mediaid");
                    $resultStr = $this->transmitImage($object, $contentStr);
                    break;
                default:
                    break;
            }
            return $resultStr;
        } elseif ($MsgEvent == "scancode_push") {
            $contentStr = "扫码推事件";
        } elseif ($MsgEvent == "scancode_waitmsg") {//扫码推送图文消息
//            $contentStr = "为您推送公众号介绍图文";
            $contentStr = "扫码带提示:类型为 " . $object->ScanCodeInfo->ScanType . " 结果为:" . $object->ScanCodeInfo->ScanResult;
        }
        $resultStr = $this->transmitText($object, $contentStr);
        return $resultStr;
    }

    //1.回复文本消息
    private function transmitText($object, $content)
    {
        $textTpl = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[text]]></MsgType>
                        <Content><![CDATA[%s]]></Content>
                    </xml>";
        $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);
        return $resultStr;
    }

    //2.回复图文消息
    private function transmitNews($object, $arr_item)
    {
        if (!is_array($arr_item))
            return;
        $itemTpl = "    <item>
                            <Title><![CDATA[%s]]></Title>
                            <Description><![CDATA[%s]]></Description>
                            <PicUrl><![CDATA[%s]]></PicUrl>
                            <Url><![CDATA[%s]]></Url>
                        </item>
                    ";
        $item_str = "";
        foreach ($arr_item as $item)
            $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
        $newsTpl = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[news]]></MsgType>
                        <Content><![CDATA[]]></Content>
                        <ArticleCount>%s</ArticleCount>
                        <Articles>
                        $item_str
                        </Articles>
                    </xml>";
        $resultStr = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(), count($arr_item));
        return $resultStr;
    }

    //3.回复音乐信息
    private function transmitMusic($object, $musicArray)
    {
        $itemTpl = "<Music>
                        <Title><![CDATA[%s]]></Title>
                        <Description><![CDATA[%s]]></Description>
                        <MusicUrl><![CDATA[%s]]></MusicUrl>
                        <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
                    </Music>";
        $item_str = sprintf($itemTpl, $musicArray['Title'], $musicArray['Description'], $musicArray['MusicUrl'], $musicArray['HQMusicUrl']);
        $textTpl = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[music]]></MsgType>
                        $item_str
                   </xml>";
        $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
        return $resultStr;
    }

    //4.回复图片信息
    private function transmitImage($object, $imageArray)
    {
        $itemTpl = "<Image>
    				    <MediaId><![CDATA[%s]]></MediaId>
					</Image>";
        $item_str = sprintf($itemTpl, $imageArray['MediaId']);
        $textTpl = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[image]]></MsgType>
                        $item_str
                    </xml>";
        $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
        return $resultStr;
    }
}

?>

3.解析

菜单:
在这里插入图片描述在这里插入图片描述在这里插入图片描述代码解析:

略,懒得写,可能过几天写。。。

注:https://tool.ip138.com/json/在线格式化json数据
学习链接:https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html
附加:上传永久素材的代码:【修改一下两处的图片名称和最开头的appid和appsercret即可】
代码摘抄于网上

<?php
$APPID = "测试号/公众号的appid";
$APPSECRET = "测试号/公众号的appsercret";
$info = json_decode(file_get_contents("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$APPID&secret=$APPSECRET"));
//获取token
$access_token = $info->access_token;

/* 使用curl函数 */
$url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=$access_token&type=image";;
$post_data = array(
    'media' => '@QR.jpg',
);
$response = curl_http($url, 'POST', $post_data);
$params = array();
$params = json_decode($response, true);
if (isset($params['errcode'])) {
    echo "error:" . $params['errcode'];
    echo "msg :" . $params['errmsg'];
    exit;
}
var_dump($params);
/**
 * http请求方式: 默认GET
 */
function curl_http($url, $method = "GET", $postfields)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_URL, $url);
    switch ($method) {
        case "POST":
            curl_setopt($ch, CURLOPT_POST, true);
            if (!empty($postfields)) {
                $hadFile = false;
                if (is_array($postfields) && isset($postfields['media'])) {
                    /* 支持文件上传 */
                    if (class_exists('\CURLFile')) {
                        curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
                        foreach ($postfields as $key => $value) {
                            if (isPostHasFile($value)) {
                                $postfields[$key] = new \CURLFile(realpath(ltrim($value, '@')));
                                $hadFile = true;
                            }
                        }
                    } elseif (defined('CURLOPT_SAFE_UPLOAD')) {
                        if (isPostHasFile($value)) {
                            curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
                            $hadFile = true;
                        }
                    }
                }
                $tmpdatastr = (!$hadFile && is_array($postfields)) ? http_build_query($postfields) : $postfields;
                curl_setopt($ch, CURLOPT_POSTFIELDS, $tmpdatastr);
            }
            break;
        default:
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); /* //设置请求方式 */
            break;
    }
    $ssl = preg_match('/^https:\/\//i', $url) ? TRUE : FALSE;
    curl_setopt($ch, CURLOPT_URL, $url);
    if ($ssl) {
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // 不从证书中检查SSL加密算法是否存在
    }
    $response = curl_exec($ch);
    curl_close($ch);
    if (empty($response)) {
        exit("错误请求");
    }
    return $response;
}

function isPostHasFile($value)
{
    if (is_string($value) && strpos($value, '@') === 0 && is_file(realpath(ltrim($value, '@')))) {
        return true;
    }
    return false;
}

//命令不会返回错误 如果返回空  2>&1 输出报错信息  如果乱码就是用 header("content-type:text/html;charset=gbk");  curl下载地址  https://curl.haxx.se/download.html

$filepath = './QR.jpg';
/* 使用exec函数 */
$command = 'curl -F media=@' . $filepath . ' "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=' . $access_token . '&type=image"';
$retval = array();
exec($command, $retval, $status);
$params = array();
$params = json_decode($retval[0], true);
if ($status != 0) {
    $params = array(
        'errcode' => '-100',
        'errmsg' => '公众号服务出错,请联系管理员',
    );
}
return $params;

/* 使用system函数 */
$command = 'curl -F media=@' . $filepath . ' "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=' . $access_token . '&type=image" 2>&1';
$retval = 1;

$last_line = system($command, $retval);
$params = array();
$params = json_decode($last_line, true);
if ($retval != 0) {
    if (isset($params['errcode'])) {
        $params = array(
            'errcode' => '-100',
            'errmsg' => '公众号服务出错,请联系管理员',
        );
    }
}
return $command;

2020-06-16
phpWechat 是由一个具有多年行业开发经验的前端 UI 设计师、PHP开发工程师组成的团队设计、研发的一套的微信公众平台管理系统,您可以瞬间完成一个公共或者PC站或者两者皆有的平台搭建。 phpWeChat 微信+网站开发框架功能亮点: 1、100%开源,没有任何加密文件 phpWeChat核心文件100%开源,没有任何加密文件,开发者可以放心使用而无需担心留有后门程序等。 2、程序轻量级,一天读完所有代码 核心框架压缩包只有2.66M,十分利于开发者迅速阅读全部代码。 3、代码严谨,结构清晰 phpWeChat使用MVC开发模式,各个功能模块之间独立并目录结构统一。开发者可迅速掌握phpWeChat的框架结构。 4、二次开发文档十分完善 我们提供了完善的phpWeChat二次开发文档,便于开发者学习与查阅。 5、高度集成微信接口 phpWeChat高度集成了微信公共的自动回复、菜单管理、素材管理、模板消息、粉丝管理、微信支付等常用接口,您只需一个函数或2/3行代码即可实现原本需要很费时费力才能开发功能。 6、phpWeChat也是一个PC(网站)开发框架和CMS 慢慢您会发现,phpWeChat是一个更接近CMS功能的框架。 7、高度封装常用开发功能 只需一两行固定的代码,您便可以写出列表分页、微信支付、文件上传、邮件发送、短信发送等功能。 8、数据结构合理,负载强劲 phpWeChat集成了常见的内存级缓存(MemCache)、文件缓存处理方案,使得系统更符合大数据、大并发的公共或网站使用。 9、集成应用市场,功能拓展一瞬间 phpWeChat集成了应用市场并在线安装应用的功能,您可以在一瞬间安装完成其他开发开发功能模块。 phpWeChat安装方法: 将下载的程序压缩包(zip格式)解压后,将全部文件和文件夹上传至网站根目录。然后输入域名/install.php 即可进入安装程序。 注意:安装phpWeChat前请先创建好phpWeChat所需的数据库。 phpWeChat 目录结构: addons 功能模块目录 admin 公用后台目录 api 插件目录 data 数据缓存目录 install 安装程序目录,安装后请改名或删除 include 公用操作类目录 statics 静态文件目录 template 视图(模板)目录 upload 上传文件存放目录 phpWeChat 更新日志: 新版v1.0.3发布: phpWeChat PC+微信公众号开发核心框架v1.0.3针对v1.0.2版本出现的问题,主要修复了和增加了以下功能: 1、优化自定义模块操作; 2、优化安装过程; 3、修复一处在线支付的PHP版本兼容问题; 4、修复一处自定义模块的问题; 5、修复后台模块管理显示未知版本的bug; 6、修复粉丝行为IP报错的Bug; 7、删除一些冗余代码; 8、修复消息模板不存在时,一直提示[同步中]的bug。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值