问答

jssdk基础支持,wxconfig的时候提示“63002签名无效”?

作者:admin 2021-09-27 我要评论

场景H5 页面调用扫一扫。 我已经确保appid正确,secret还没有重置过,首次是我生成并且记录的而且成功完成了微信登录,因此安全域名,js域名也没问题,我亲自检...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

场景H5 页面调用扫一扫。
我已经确保appid正确,secret还没有重置过,首次是我生成并且记录的而且成功完成了微信登录,因此安全域名,js域名也没问题,我亲自检查了微信公众平台,url也确保了前后端统一,我做了匹配了
image.png
上图中的rawstring可以看到后端获取到的页面url,
下图可看到在js脚本里获取的当前页面url
image.png

截止目前,耗费7+小时来排查问题了。。我心态崩了。。。。

相关代码
前端:主要摘自官方demo

      // var pageurl = encodeURIComponent(location.href.split('#')[0]);
    var pageurl = location.href.split('#')[0];
    console.log(location.href, pageurl == location.href); //, pageurl
    var appid = $("#appid").val();
    var timestamp = $("#timestamp").val();
    var nonceStr = $("#nonceStr").val();
    var signature = $("#signature").val();
    console.log(appid + "-" + timestamp + "-" + nonceStr + "-" + signature);
    wx.config({
        debug: false,
        appId: appid,
        timestamp: timestamp,
        noncestr: nonceStr,
        signature: signature,
        jsApiList: ['scanQRCode'
            // 所有要调用的 API 都要加到这个列表中
        ]
    });
    wx.ready(function () {
        wx.error(function (res) {
            // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
            console.log("wx.error", res);
        });

    });

不忘推广个人网站: 八个八
后端 :直接用的官方demo

  <?php

namespace wechat;

use app\model\Constant;
use think\Log;

class WechatOauth
{
    //微信授权配置信息

    private $wechat_config = ['appid' => 'XXX', 'appsecret' => '这个怎么能随便放出来哈哈哈',];


    public function __construct()
    {

        $this->wechat_config = $this->wechatConfig();
    }

    /**
     * 获取秘钥配置
     * @return [type] 数组
     */

    public function wechatConfig()
    {

        //        $wechat_config = array_merge($this->wechat_config, config('wechat.oauth'));

        return $this->wechat_config;
    }

    /**
     * 获取openid
     * @return string|mixed
     */

    public function getUserAccessUserInfo($code = "")

    {


        if (empty($code)) {

            $baseUrl = request()->url(true);

            $url = $this->getSingleAuthorizeUrl($baseUrl, "123");

            Header("Location: $url");

            exit();
        } else {

            $access_token = $this->getSingleAccessToken($code);
            return $this->getUserInfo($access_token);
        }
    }

    /**
     * 微信授权链接
     * @param string $redirect_uri 要跳转的地址
     * @return [type]               授权链接
     */

    public function getSingleAuthorizeUrl($redirect_url = "", $state = '1')
    {

        $redirect_url = urlencode($redirect_url);

        return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $this->wechat_config['appid'] . "&redirect_uri=" . $redirect_url . "&response_type=code&scope=snsapi_userinfo&state={$state}#wechat_redirect";
    }

    /**
     * 获取token
     * @return [type] 返回token
     */

    public function getSingleAccessToken($code)
    {

        $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $this->wechat_config['appid'] .
            '&secret=' . $this->wechat_config['appsecret'] . '&code=' . $code . '&grant_type=authorization_code';


        $access_token = $this->https_request($url);
        Log::log($access_token);
        return $access_token;
    }


    /**
     * 发送curl请求
     * @param $url string
     * @param return array|mixed
     */

    public function https_request($url)

    {

        $curl = curl_init();

        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

        curl_setopt($curl, CURLOPT_URL, $url);

        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

        $AjaxReturn = curl_exec($curl);

        //获取access_token和openid,转换为数组

        $data = json_decode($AjaxReturn, true);

        curl_close($curl);

        return $data;
    }

    /**
     * @explain
     * 通过code获取用户openid以及用户的微信号信息
     * @return array|mixed
     * @remark
     * 获取到用户的openid之后可以判断用户是否有数据,可以直接跳过获取access_token,也可以继续获取access_token
     * access_token每日获取次数是有限制的,access_token有时间限制,可以存储到数据库7200s. 7200s后access_token失效
     **/

    public function getUserInfo($access_token = [])

    {

        if (!$access_token) {

            return [

                'code' => 0,

                'msg' => '微信授权失败',

            ];
        }

        $userinfo_url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token['access_token'] . '&openid=' . $access_token['openid'] . '&lang=zh_CN';

        $userinfo_json = $this->https_request($userinfo_url);

        //获取用户的基本信息,并将用户的唯一标识保存在session中

        if (!$userinfo_json) {

            return [

                'code' => 0,

                'msg' => '获取用户信息失败!',

            ];
        }

        return $userinfo_json;
    }
    /**
     *  以下 是芋头丸摘自微信jssd的 demo  2020年2月18日15:56:31 
     */


    public function getSignPackage()
    {
        $jsapiTicket = $this->getJsApiTicket();

        // 注意 URL 一定要动态获取,不能 hardcode.
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
        $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
        // $url = $_GET['pageurl'] ; //pageurl
        // $url = $_POST['pageurl'] ; //pageurl
        // $index = strpos($url, '.html');
        // $url = substr($url, 0, $index);
        // $url = 'http://wl.quanjing-vr.com/index/track/index';
        $timestamp = time();
        // $nonceStr = 'tX0gO4slk7LErn6K';
        $nonceStr = $this->createNonceStr();
        // $url = urldecode($url);
        // 这里参数的顺序要按照 key 值 ASCII 码升序排序  
        // $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&amp;timestamp=$timestamp&url=$url";
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
        Log::log('签名来源字符串=' . $string);
        $signature = sha1($string);

        $signPackage = array(
            "appId"     =>  $this->wechat_config['appid'],
            "nonceStr"  => $nonceStr,
            "timestamp" => $timestamp,
            "url"       => $url,
            "signature" => $signature,
            "rawString" => $string
        );
        return $signPackage;
    }

    private function createNonceStr($length = 16)
    {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    private function getJsApiTicket()
    {
        Log::error('-getJsApiTicket-');
        // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
        $data = json_decode($this->get_php_file("jsapi_ticket.php"));
        if ($data->expire_time < time()) {
            $accessToken = $this->getAccessToken();
            // 如果是企业号用以下 URL 获取 ticket
            // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
            // Log::error('getJsApiTicket-' . $url);
            $aa = $this->httpGet($url);
            Log::error('新获取ticket=' . $aa);
            // die('暂停。。');
            $res = json_decode($aa);

            $ticket = $res->ticket;
            if ($ticket) {
                $data->expire_time = time() + 7000;
                $data->jsapi_ticket = $ticket;
                $this->set_php_file("jsapi_ticket.php", json_encode($data));
            }
        } else {
            $ticket = $data->jsapi_ticket;
            Log::error($data);
        }

        return $ticket;
    }

    private function getAccessToken()
    {
        // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
        $data = json_decode($this->get_php_file("access_token.php"));
        if ($data->expire_time < time()) {
            // 如果是企业号用以下URL获取access_token
            // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" .
                $this->wechat_config['appid'] . "&secret=" . $this->wechat_config['appsecret'];
            Log::log("刷新普通token=" . $url);
            $res = json_decode($this->httpGet($url));

            Log::error($res);
            $access_token = $res->access_token;
            if ($access_token) {
                $data->expire_time = time() + 7000;
                $data->access_token = $access_token;
                $this->set_php_file("access_token.php", json_encode($data));
            }
        } else {
            Log::error($data);
            $access_token = $data->access_token;
        }
        return $access_token;
    }

    private function httpGet($url)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 500);
        // 为保证第三方服务器与微信服务器之间数据传输的安全性,所有微信接口采用https方式调用,必须使用下面2行代码打开ssl安全校验。
        // 如果在部署过程中代码在此处验证失败,请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
        // curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
        curl_setopt($curl, CURLOPT_URL, $url);

        $res = curl_exec($curl);
        curl_close($curl);

        return $res;
    }

    private function get_php_file($filename)
    {
        return trim(substr(file_get_contents($filename), 15));
    }
    private function set_php_file($filename, $content)
    {
        $fp = fopen($filename, "w");
        fwrite($fp, "<?php exit();?>" . $content);
        fclose($fp);
    }
}
 
###

好吧,经过三天加一晚的间歇性处理,最后总算解决了,现记录过程如下:
1-首先是基于百度、官方社区里提到的各种解决办法,都不奏效
2-换了一个同框架的程序将代码放进去,也还是不行
3-换了基于TP6开发的一个cms,将官方demo拷进去还是不行,然后修改了官方demo前端的一个参数,noncestr --> nonceStr ,问题解决,当然还有个地方是多了一行重复代码,这个删掉就好,如图:image.png
4-到这个地步了,就把代码拷到项目里吧,考进来还是签名不对,于是又一顿改,结果还没记住改的哪里,程序就好了,你说搞笑不搞笑。。

      ![image.png](/img/bVbDJcv)

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • jssdk基础支持,wxconfig的时候提示“6

    jssdk基础支持,wxconfig的时候提示“6

  • 关于ES6 module的疑问

    关于ES6 module的疑问

  • 求助 关于mongodb 深入 查找的问题

    求助 关于mongodb 深入 查找的问题

  • 前端如何设计这种通过多种参数画叶片

    前端如何设计这种通过多种参数画叶片

腾讯云代理商
海外云服务器