PHP实现的微信公众号扫码模拟登录功能示例


Posted in PHP onMay 30, 2019

本文实例讲述了PHP实现的微信公众号扫码模拟登录功能。分享给大家供大家参考,具体如下:

PHP微信公众号扫码模拟登录功能

功能只是将:https://github.com/huanz/wechat-mp-hack 改成PHP实现罢了.
之前有个休闲豆每日晨报订阅号每天定时群发消息,去年微信突然要求一定要扫码授权才能登录,FK,然后就放弃了,前几天看到早有人使用程序扫码登录,获取token,cookie自动群发了,闲着也是闲着,就将js改成php实现了登录功能.

主要流程如下

1,先访问https://mp.weixin.qq.com/ ,模拟登录,进入二维码页面
2,带着返回的cookie下载二维码.程序后台一直while循环,等待扫描消息.
3,打开下载的二维码,微信扫码,登录成功,获取token和cookie,然后后面就可以自由发挥了.

供上代码.

class WeiSendAuto
{
  //--------------------------------------------------------LOGIN START
  private $_apis = [
    "host"     => "https://mp.weixin.qq.com",
    "login"     => "https://mp.weixin.qq.com/cgi-bin/bizlogin?action=startlogin",
    "qrcode"    => "https://mp.weixin.qq.com/cgi-bin/loginqrcode?action=getqrcode¶m=4300",
    "loginqrcode"  => "https://mp.weixin.qq.com/cgi-bin/loginqrcode?action=ask&token=&lang=zh_CN&f=json&ajax=1",
    "loginask"   => "https://mp.weixin.qq.com/cgi-bin/loginqrcode?action=ask&token=&lang=zh_CN&f=json&ajax=1&random=",
    "loginauth"   => "https://mp.weixin.qq.com/cgi-bin/loginauth?action=ask&token=&lang=zh_CN&f=json&ajax=1",
    "bizlogin"   => "https://mp.weixin.qq.com/cgi-bin/bizlogin?action=login&lang=zh_CN"
  ];
  private $_redirect_url = "";
  private $_key      = "";
  private function _getCookieFile(){
    return WEI_UPLOAD_PATH."cookie_{$this->_key}.text";
  }
  private function _getSavePath(){
    return WEI_UPLOAD_PATH.$this->_qrcodeName();
  }
  private function _qrcodeName(){
    return "qrcode_{$this->_key}.png";
  }
  private function _log($msg){
    Log::record("[微信调度:".date("Y-m-d H:i:s")."] ======: {$msg}");
  }
  public function getToken(){
    return Utils::getCache("token_{$this->_key}");
  }
  public function setToken($token){
     Utils::setCache("token_{$this->_key}",$token);
  }
  public function init($options){
    if(!isset($options["key"])){
      die("Key is Null!");
    }
    $this->_key   =  $options["key"];
    if($this->getToken()){
      echo("HAS Token !");
      return;
    }else{
      //尼玛,先要获取首页!!!
      $this->fetch("https://mp.weixin.qq.com/","","text");
      $this->_log("start login!!");
      $this->start_login($options);
    }
  }
  private function start_login($options){
    $_res    = $this->_login($options["account"],$options["password"]);
    if(!$_res["status"]){
      $this->_log($_res["info"]);
      return;
    }
    //保存二维码
    $this->_saveQRcode();
    $_ask_api    =  $this->_apis["loginask"];
    $_input["refer"] =  $this->_redirect_url;
    $_index     =  1;
    while(true){
/*      if($_index>60){
        break;
      }*/
      $_res    =  $this->fetch($_ask_api.$this->getWxRandomNum(),$_input);
      $_status   =  $_res["status"];
      if($_status==1){
        if($_res["user_category"]==1){
          $_ask_api = $this->_apis["loginauth"];
        }else{
          $this->_log("Login success");
          break;
        }
      }else if($_status==4){
        $this->_log("已经扫码");
      }else if($_status==2){
        $this->_log("管理员拒绝");
        break;
      }else if($_status==3){
        $this->_log("登录超时");
        break;
      }else{
        if($_ask_api==$this->_apis["loginask"]){
          $this->_log("请打开test.jpg,用微信扫码");
        }else{
          $this->_log("等待确认");
        }
      }
      sleep(2);
      $_index++;
    }
    /*if($_index>=60){
      $this->_log("U亲,超时了");
      return;
    }*/
    $this->_log("开始验证");
    $_input["post"]   = ["lang"=>"zh_CN","f"=>"json","ajax"=>1,"random"=>$this->getWxRandomNum(),"token"=>""];
    $_input["refer"]   = $this->_redirect_url;
    $_res        = $this->fetch($this->_apis["bizlogin"],$_input);
    $this->_log(print_r($_res,true));
    if($_res["base_resp"]["ret"]!=0){
      $this->_log("error = ".$_res["base_resp"]["err_msg"]);
      return ;
    }
    $redirect_url    =  $_res["redirect_url"];//跳转路径
    if(preg_match('/token=([\d]+)/i', $redirect_url,$match)){//获取cookie
      $this->setToken($match[1]);
    }
    $this->_log("验证成功,token: ".$this->getToken());
  }
  //下载二维码
  private function _saveQRcode(){
    $_input["refer"] = $this->_redirect_url;
    $_res    = $this->fetch($this->_apis["qrcode"],$_input,"text");
    $fp     = fopen($this->_getSavePath(), "wb+") or die("open fails");
    fwrite($fp,$_res) or die("fwrite fails");
    fclose($fp);
  }
  private function _login($_username,$_password){
    $_input["post"] = array(
      'username'  => $_username,
      'pwd'    => md5($_password),
      'f'     => 'json',
      'imgcode'  => ""
    );
    $_input["refer"] = "https://mp.weixin.qq.com";
    $_res      = $this->fetch($this->_apis["login"],$_input);
    if($_res["base_resp"]["ret"]!==0){
      return Utils::error($_res["base_resp"]["err_msg"]);
    }
    $this->_redirect_url  =  "https://mp.weixin.qq.com".$_res["redirect_url"];//跳转路径
    return Utils::success("ok");
  }
  function getWxRandomNum(){
    return "0.".mt_rand(1000000000000000,9999999999999999);
  }
  /**
   * @param $url
   * @param null $_input
   * @param string $data_type
   * @return mixed
   * $_input= ["post"=>[],"refer"=>"",cookiefile='']
   */
  function fetch( $url, $_input=null, $data_type='json') {
    $ch = curl_init();
    $useragent = isset($_input['useragent']) ? $_input['useragent'] : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2';
    //curl_setopt( $ch, CURLOPT_HTTPHEADER, $this->_headers); //设置HTTP头字段的数组
    curl_setopt( $ch, CURLOPT_URL, $url );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $ch, CURLOPT_AUTOREFERER, true );
    curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
    curl_setopt( $ch, CURLOPT_POST, isset($_input['post']) );
    if( isset($_input['post']) )     curl_setopt( $ch, CURLOPT_POSTFIELDS, $_input['post'] );
    if( isset($_input['refer']) )    curl_setopt( $ch, CURLOPT_REFERER, $_input['refer'] );
    curl_setopt( $ch, CURLOPT_USERAGENT, $useragent );
    curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, ( isset($_input['timeout']) ? $_input['timeout'] : 5 ) );
    curl_setopt( $ch, CURLOPT_COOKIEJAR, ( isset($_input['cookiefile']) ? $_input['cookiefile'] : $this->_getCookieFile() ));
    curl_setopt( $ch, CURLOPT_COOKIEFILE, ( isset($_input['cookiefile']) ? $_input['cookiefile'] : $this->_getCookieFile() ));
    $result = curl_exec( $ch );
    curl_close( $ch );
    if ($data_type == 'json') {
      $result = json_decode($result,true);
    }
    return $result;
  }
  //--------------------------------------------------------LOGIN END
}

怎么调用?上码

$arr = array(
  'account'  => '***',
  'password' => '****',
  'key'    => "tmall",
);
$w       =  new WeiSendAuto();
$w->init($arr);
if(!$w->getToken()){
  die("NOT TOKEN!");
}

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
二十行语句实现从Excel到mysql的转化
Oct 09 PHP
PHP mb_convert_encoding 获取字符串编码类型实现代码
Apr 26 PHP
判断PHP数组是否为空的代码
Sep 08 PHP
PHP实现提取一个图像文件并在浏览器上显示的代码
Oct 06 PHP
探讨:如何使用PhpDocumentor生成文档
Jun 25 PHP
领悟php接口中interface存在的意义
Jun 27 PHP
php可生成缩略图的文件上传类实例
Dec 17 PHP
CI框架中site_url()和base_url()的区别
Jan 07 PHP
thinkPHP数据库增删改查操作方法实例详解
Dec 06 PHP
在Laravel5.6中使用Swoole的协程数据库查询
Jun 15 PHP
thinkPHP框架中layer.js的封装与使用方法示例
Jan 18 PHP
Laravel框架路由管理简单示例
May 07 PHP
PHP使用PDO创建MySQL数据库、表及插入多条数据操作示例
May 30 #PHP
TP5(thinkPHP5框架)基于bootstrap实现的单图上传插件用法示例
May 29 #PHP
TP5(thinkPHP框架)实现后台清除缓存功能示例
May 29 #PHP
PHP微信网页授权的配置文件操作分析
May 29 #PHP
thinkPHP5框架实现多数据库连接,跨数据连接查询操作示例
May 29 #PHP
tp5(thinkPHP5框架)时间查询操作实例分析
May 29 #PHP
php fread函数使用方法总结
May 28 #PHP
You might like
教你IIS6的PHP最佳配置方法
2006/09/05 PHP
一个程序下载的管理程序(一)
2006/10/09 PHP
第八节--访问方式
2006/11/16 PHP
安装APACHE
2007/01/15 PHP
PHP中定义数组常量(array常量)的方法
2014/11/17 PHP
全面解析PHP验证码的实现原理 附php验证码小案例
2016/08/17 PHP
详解php与ethereum客户端交互
2018/04/28 PHP
Smarty模板配置实例简析
2019/07/20 PHP
PHP 范围解析操作符(::)用法分析【访问静态成员和类常量】
2020/04/14 PHP
Apache+PHP+MySQL搭建PHP开发环境图文教程
2020/08/06 PHP
使用JavaScript获取电池状态的方法
2014/05/03 Javascript
jquery简单实现图片切换效果的方法
2015/05/12 Javascript
如何用js判断dom是否有存在某class的值
2017/02/13 Javascript
微信小程序动态增加按钮组件
2018/09/14 Javascript
js核心基础之闭包的应用实例分析
2019/05/11 Javascript
Vue中的transition封装组件的实现方法
2019/08/13 Javascript
vue 通过base64实现图片下载功能
2020/12/19 Vue.js
js动态生成表格(节点操作)
2021/01/12 Javascript
[05:53]完美世界携手游戏风云打造 卡尔工作室观战系统篇
2013/04/22 DOTA
[01:10]DOTA2次级职业联赛 - Fly战队宣传片
2014/12/01 DOTA
Python中不同进制互相转换(二进制、八进制、十进制和十六进制)
2015/04/05 Python
Python中str.format()详解
2017/03/12 Python
Python闭包执行时值的传递方式实例分析
2018/06/04 Python
python+selenium实现自动化百度搜索关键词
2019/06/03 Python
详细整理python 字符串(str)与列表(list)以及数组(array)之间的转换方法
2019/08/30 Python
Django单元测试中Fixtures的使用方法
2020/02/26 Python
浅谈pandas dataframe对除数是零的处理
2020/07/20 Python
python matplotlib绘制三维图的示例
2020/09/24 Python
美国领先的精品家居照明和装饰产品在线零售商:LightsOnline.com
2018/01/23 全球购物
Windows和Linux动态库应用异同
2016/07/28 面试题
数学专业毕业生自荐信
2013/11/10 职场文书
制冷与电控专业应届生求职信
2013/11/11 职场文书
财务会计应届生求职信
2013/11/24 职场文书
年终晚会主持词
2014/03/25 职场文书
地质工程专业毕业生求职信
2014/08/08 职场文书
护士岗位竞聘书
2015/09/15 职场文书