access_token、同步菜单以及创建自定义菜单

本文介绍微信公众号菜单二次开发的全过程,包括获取access_token、菜单的创建、更新及删除等关键步骤,并提供了详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

现在人们越来越离不开微信,有数据统计平均每个人打开微信的次数为7-8次/天,与微信相关的技术也开始出现,比如微信二次开发,有可能很多人还不太懂知道微信二次开发,只知道别人都做了自己也要做,那么下面云端科技就浅谈一下,不涉及高深的技术只是让你能够清楚的知道这是怎么一件事。


@Controller
@RequestMapping("wechat")
public class WeChatController {

    @RequestMapping(value = "/hello")
    public String index(){
        return "index";
    }

    @RequestMapping(value = "/detail")
    public String detail(){
        return "detailpage";
    }


    @RequestMapping(value = "/home",method= RequestMethod.GET)
    @ResponseBody
    public void valid(HttpServletRequest request, HttpServletResponse response) throws IOException {
        boolean isGet = request.getMethod().toLowerCase().equals("get");
        String code = request.getParameter("code");
        if (isGet) {
            // 微信加密签名
            String signature = request.getParameter("signature");
            // 时间戳
            String timestamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            // 随机字符串
            String echostr = request.getParameter("echostr");

            PrintWriter out = response.getWriter();
            // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
            if (SignUtil.checkSignature(signature, timestamp, nonce)) {
                out.print(echostr);
            }
            out.close();
            out = null;
        }else{
            userpost(request,response);
        }
    }

    @RequestMapping(value = "/home",method= RequestMethod.POST)
    public void userpost(HttpServletRequest request, HttpServletResponse response) throws IOException   {
        request.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        String str = null;
        String code = request.getParameter("code");
        try {
            Map<String, String> message = MessageUtil.xmlToMap(request);
            String fromUser = message.get("FromUserName");
            String toUser = message.get("ToUserName");
            String content = message.get("Content");
            String msgType = message.get("MsgType");
            String msgId = message.get("MsgId");
            Message ms = new Message();
            ms.setContent(content);
            ms.setFromUserName(toUser);
            ms.setToUserName(fromUser);
            ms.setMsgType(msgType);
            str = MessageUtil.textMessageToXml(ms).replace("\n","").replace(" ","");
            out.print(str);
            out.close();
            out = null;
        }catch (Exception e){
            e.printStackTrace();
        }
    }
签名认证
/** 
 * 请求校验工具类 
 *  
 * @author liufeng 
 * @date 2013-05-18 
 */  
public class SignUtil {  
    // 与接口配置信息中的Token要一致  
    private static String token = "chenmianhai";

    /** 
     * 验证签名 
     *  
     * @param signature 
     * @param timestamp 
     * @param nonce 
     * @return 
     */  
    public static boolean checkSignature(String signature, String timestamp, String nonce) {  
        String[] arr = new String[] { token, timestamp, nonce };  
        // 将token、timestamp、nonce三个参数进行字典序排序  
        Arrays.sort(arr);  
        StringBuilder content = new StringBuilder();  
        for (int i = 0; i < arr.length; i++) {  
            content.append(arr[i]);  
        }  
        MessageDigest md = null;  
        String tmpStr = null;  

        try {  
            md = MessageDigest.getInstance("SHA-1");  
            // 将三个参数字符串拼接成一个字符串进行sha1加密  
            byte[] digest = md.digest(content.toString().getBytes());  
            tmpStr = byteToStr(digest);  
        } catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();  
        }  

        content = null;  
        // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信  
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;  
    }  

    /** 
     * 将字节数组转换为十六进制字符串 
     *  
     * @param byteArray 
     * @return 
     */  
    private static String byteToStr(byte[] byteArray) {  
        String strDigest = "";  
        for (int i = 0; i < byteArray.length; i++) {  
            strDigest += byteToHexStr(byteArray[i]);  
        }  
        return strDigest;  
    }  

    /** 
     * 将字节转换为十六进制字符串 
     *  
     * @param mByte 
     * @return 
     */  
    private static String byteToHexStr(byte mByte) {  
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };  
        char[] tempArr = new char[2];  
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];  
        tempArr[1] = Digit[mByte & 0X0F];  

        String s = new String(tempArr);  
        return s;  
    }  
}  

1.首先我们要有appid(wx4ff531ee8a470861)和appsecret(2ec9b2f1a1f67b8743d23f9fc70c1c97)。

2.这里我们用的是rh_mp与rh_mp_menu数据表。

3.首先我们在Common模块的Common文件夹下创建function.php文件,在里面我们写入以下获取access_token的代码和获取当前公众号的代码:

[php]  view plain  copy
  1. function getAccess_token(){  
  2.     $mp=M('mp')->where('is_use=1')->find();  
  3.     if(empty($mp)) return false;  
  4.     $id=$mp['id'];  
  5.       if(empty($mp['access_token']) || $mp['expire_time']<time()){  
  6.         $appid=$mp['appid'];  
  7.         $appsecret=$mp['appsecret'];  
  8.         $url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret;//接口  
  9.         include APP_PATH.'LaneWeChat/lanewechat.php';  
  10.         $arr= \LaneWeChat\Core\Curl::callWebServer($url,'','GET');  
  11.         // print_r($arr);  
  12.         // exit;  
  13.         if(isset($arr['access_token'])){  
  14.             $data['access_token']=$arr['access_token'];  
  15.             $data['expire_time']=$arr['expires_in']+ time()-200;  
  16.             // print_r($data);  
  17.             // exit;  
  18.             // $data=M('mp')->create($data);  
  19.            M("mp")->where("id=$id")->save($data);  
  20.           
  21.             return $arr['access_token'];  
  22.         }else{  
  23.             return false;  
  24.         }  
  25.       }else{  
  26.         return $mp['access_token'];  
  27.       }  
[php]  view plain  copy
  1. function getCurrentMp(){  
  2.     $mp=M('mp')->where('is_use=1')->find();  
  3.     return  $mp;  
  4. }  

在menuController.class.php中增加以下代码:

[php]  view plain  copy
  1. <?php  
  2. namespace Home\Controller;  
  3. use Think\Controller;  
  4. use LaneWeChat\Core\menu;  
  5. // define('WECHAT_APPID','wx4ff531ee8a470861');  
  6. // define('WECHAT_APPSECRET','2ec9b2f1a1f67b8743d23f9fc70c1c97');  
  7. class MenuController extends Controller {  
  8.     public function index(){  
  9.         $mp=getCurrentMp();  
  10.         if(empty($mp)){  
  11.             $this->error('无此公账号',U('mp/index'));  
  12.         }  
  13.         $data=M('mp_menu')->where("mp_id={$mp['id']}")->order('id')->select();  
  14.         $data2=$data;  
  15.         foreach ($data as $k => $v) {  
  16.             foreach ($data2 as $k2 => $v2) {  
  17.                 if($v['index']==$v2['pindex']){  
  18.                     $data[$k]['sub'][]=$v2;  
  19.                     unset($data[$k2]);  
  20.                 }  
  21.             }  
  22.         }  
  23.   
  24.         $this->assign('mpInfo',$mp);  
  25.         $this->assign('list',$data);  
  26.         $this->display();  
  27.     }  
  28.     public function menuedit(){  
  29.         $mp=getCurrentMp();  
  30.         if(empty($mp)){  
  31.             $this->ajaxReturn(array('error'=>true,'msg'=>'无此公账号','url'=>U('mp/index')));  
  32.             exit;  
  33.         }  
  34.         $data=I('post.data');  
  35.   
  36.         foreach ($data as  &$value) {  
  37.             $value['mp_id']=$mp['id'];  
  38.         }  
  39.         // }print_r($value);  
  40.         // exit;  
  41.         // $this->ajaxReturn($data);  
  42.         // $arr=array();  
  43.         // foreach ($data1 as $key => $value) {  
  44.         //  $row=array();  
  45.         //  $row['mp_id']=$mp['id'];  
  46.         //  $row['index']=$value['id'];  
  47.         //  $row['pindex']=$value['pid'];  
  48.         //  $row['name']=$value['name'];  
  49.         //  $row['content']=$value['code'];  
  50.         //  $row['type']=$value['type'];  
  51.         //  $row['sort']=$value['sort'];  
  52.         //  $arr[]=$row;  
  53.         // }  
  54.         $model=M('mp_menu');  
  55.         $model->where("mp_id={$mp['id']}")->delete();  
  56.         $model->addAll($data);  
  57.         // $this->ajaxReturn(array('error'=>false,'data'=>$arr));  
  58.         // exit;  
  59.         // $data2=$data1;  
  60.         // foreach ($data1 as $key1 => $value1) {  
  61.         //  foreach ($data2 as $key2 => $value2) {  
  62.         //      if($value1['id']==$value2['pid']){  
  63.         //          $data1[$key1]['type']='';  
  64.         //          $data1[$key1]['code']='';  
  65.         //          break;  
  66.         //      }  
  67.         //  }  
  68.         //  unset($data1[$key1]['sort']);  
  69.         //  if($value['type']='event'){  
  70.         //      $value['type']=$value['code'];  
  71.         //      $value['code']='k_'.rand(100,999);  
  72.         //  }  
  73.         // }  
  74.           
  75.             include APP_PATH.'LaneWeChat/lanewechat.php';  
  76.             $ret= Menu::setMenu($data);  
  77.           
  78.             if($ret===true){  
  79.                 $this->ajaxReturn(array('msg'=>'创建菜单成功'));  
  80.             }else{  
  81.                 $this->ajaxReturn(array('msg'=>$ret));  
  82.             }  
  83.             // file_put_contents('menu.txt',$ret);  
  84.             // $this->ajaxReturn($ret);  
  85.     }  
  86.     public function downmenu(){  
  87.         $mp = getCurrentMp();  
  88. //      print_r($mp);  
  89. // exit;  
  90.         $mp_id = $mp['id'];  
  91.   
  92.         include APP_PATH . 'LaneWeChat/lanewechat.php';  
  93.         $menu = Menu::getMenu($data);  
  94.   
  95.         // print_r($menu);  
  96.         // exit;  
  97.   
  98.         // print_r($menu['menu']['button']);  
  99.         // exit;  
  100.   
  101.         $menu = $menu['menu']['button'];  
  102.   
  103.         $arr = array();  
  104.         $index = 1;  
  105.         foreach ($menu as $key => &$value) {  
  106.             $value['mp_id']= $mp_id;  
  107.             $value['index'] = $index;  
  108.             $value['pindex'] = 0;  
  109.             $value['sort'] = $index;  
  110.               
  111.             if(!empty($value['sub_button'])){  
  112.                 $value['type'] = '';//设置一级菜单,默认值  
  113.                 $value['content'] = '';//设置一级菜单,默认值  
  114.   
  115.                 $sub_menu = $value['sub_button']; //把二级菜单入到变量$sub_menu  
  116.                 unset($value['sub_button']);  
  117.                 $arr[] = $value;  
  118.   
  119.                 $subindex = 1;  
  120.                 foreach ($sub_menu as $subkey=>&$subvalue) {  
  121.                     $subvalue['mp_id'] = $mp_id;  
  122.                     $subvalue['index'] = $index . $subindex;  
  123.                     $subvalue['pindex'] = $index;  
  124.                     $subvalue['sort'] = $subindex;  
  125.   
  126.                     if($subvalue['type']== 'click'){  
  127.                         $subvalue['content'] = $subvalue['key'];  
  128.                         unset($subvalue['key']);  
  129.                     }else if($subvalue['type']=='view'){  
  130.                         $subvalue['content'] = $subvalue['url'];  
  131.                         unset($subvalue['url']);  
  132.                     }else {  
  133.                            
  134.                          $subvalue['content'] = $subvalue['type'];  
  135.                          $subvalue['type'] = 'event';  
  136.                          unset($subvalue['key']);  
  137.                     }  
  138.   
  139.                     unset($subvalue['sub_button']);  
  140.                     $arr[] = $subvalue;  
  141.   
  142.                     $subindex++;  
  143.                 }  
  144.                   
  145.             }else{  
  146.                 if($value['type']== 'click'){  
  147.                     $value['content'] = $value['key'];  
  148.                     unset($value['key']);  
  149.                 }else if($value['type']=='view'){  
  150.                     $value['content'] = $value['url'];  
  151.                     unset($value['url']);  
  152.                 }else {  
  153.                        
  154.                      $value['content'] = $value['type'];  
  155.                      $value['type'] = 'event';  
  156.                      unset($value['key']);  
  157.                 }  
  158.   
  159.                 unset($value['sub_button']);  
  160.                 $arr[] = $value;  
  161.             }  
  162.             $index++;  
  163.         }  
  164.   
  165. //      print_r($arr);  
  166. // exit;  
  167.   
  168.         $model = M('mp_menu');  
  169.         $model->where("mp_id={$mp['id']}")->delete();  
  170.         foreach ($arr as $key => $value) {  
  171.             $model->add($value);   
  172.         }  
  173.         $this->redirect('index');  
  174.           
  175.     }  
  176.     public function delmenu(){  
  177.         // $mp=getCurrentMp();  
  178.      //    include APP_PATH . 'LaneWeChat/lanewechat.php';  
  179.         // $menu = Menu::delMenu($data);  
  180.         // $this->display('index');  
  181.         $mp = getCurrentMp();  
  182.         $mp_id = $mp['id'];  
  183.         // print_r($mp_id);  
  184.         // exit;          
  185.           
  186.         include APP_PATH . 'LaneWeChat/lanewechat.php';  
  187.         $menu =  \LaneWeChat\Core\Menu::delMenu();  
  188.         // print_r($menu);  
  189.         // exit;  
  190.         $model = M('mp_menu');  
  191.         $ret=$model->where("mp_id={$mp['id']}")->delete();  
  192.         if($ret){  
  193.             $this->success('删除成功');  
  194.         }else{  
  195.             $this->error('删除失败');  
  196.         }  
  197.     }  
  198.   
  199. }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值