nginx - WeChat JSSDK, an error is reported when config is executed: invalid signature
给我你的怀抱
给我你的怀抱 2017-05-16 17:23:32
0
8
1061

1, the calculated signature is consistent with the sandbox provided by WeChat: http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
2. Tried to use two methods to solve the problem, but still got the same error: 1), pass the URL from the local to the server, get the json data of the server through ajax, and then fill in the content of wx.config; 2), get it from the server Link to this visit
3. Use nginx as reverse domain name proxy, but it has been processed for upstream
Conclusion: It is suspected that WeChat’s JSSDK has a bug

给我你的怀抱
给我你的怀抱

reply all(8)
左手右手慢动作

May need to be checked
1) Do you cache WeChat’s jsticket globally on the server? After a new jsticket is obtained, the original jsticket (including access_token) will be refreshed
2) Whether the url is consistent, including query string, etc.
3) Whether nonceStr and timestamp are consistent with the signature

Ty80

I also suspect there is a bug. The invalid signature is invalid under android, but it is correct under ios. And it is passed on the official debugging page. I wonder if the original poster has solved it now?

过去多啦不再A梦

Perhaps url传入的问题,建议wx.config is generated through the background and then written to the foreground.

Like mine

import time
import random
import string
import hashlib
import urllib2
import json

from sae.kvdb import Client


kvdb = Client()


class WXSDK(object):
    httpHandler = urllib2.HTTPHandler()
    httpsHandler = urllib2.HTTPSHandler()
    opener = urllib2.build_opener(httpHandler, httpsHandler)
    urllib2.install_opener(opener)

    JSAPI_TICKET_URL = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi'
    ACCESS_TOKEN_URL = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}'

    def __init__(self, app_id, app_secret, url=None):
        self.app_id = app_id
        self.app_secret = app_secret
        self.url = url


    def __sendRequest(self, url):
        return json.loads(urllib2.urlopen(url).read())

    def __get_access_token(self):
        data = kvdb.get('access_token_key') or {'expire_time': 0}
        now = self.__get_time()
        if data['expire_time'] < now:
            data['expire_time'] = now + 7000
            res = self.__sendRequest(
                self.ACCESS_TOKEN_URL.format(self.app_id, self.app_secret))
            data['access_token'] = res['access_token']
            kvdb.set('access_token_key', data)
            return res['access_token']
        else:
            return data['access_token']

    def __get_jsapi_ticket(self):
        data = kvdb.get('jsapi_token_key') or {'expire_time': 0}
        now = self.__get_time()
        if data['expire_time'] < now:
            data['expire_time'] = now + 7000
            access_token = self.__get_access_token()
            res = self.__sendRequest(
                self.JSAPI_TICKET_URL.format(access_token))
            data['jsapi_ticket'] = res['ticket']
            kvdb.set('jsapi_token_key', data)
            return res['ticket']
        else:
            return data['jsapi_ticket']

    def __get_time(self):
        return int(time.time())

    def __create_nonce_str(self):
        return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15))

    def get_sign_package(self):
        options = {
            'nonceStr': self.__create_nonce_str(),
            'jsapi_ticket': self.__get_jsapi_ticket(),
            'timestamp': self.__get_time(),
            'url': self.url
        }
        options['signature'] = Sign(options.copy()).sign()
        options['app_id'] = self.app_id
        return options


class Sign(object):
    def __init__(self, options):
        self.ret = options

    def sign(self):
        signature = '&'.join(['%s=%s' % (key.lower(), self.ret[key])
                              for key in sorted(self.ret)])
        return hashlib.sha1(signature).hexdigest()

Then

@card.route("/")
def index():
    url = request.base_url
    if len(request.args) > 0:
        url = url + "?" + urllib.urlencode(request.args)
    wx.url = url
    signature_data = wx.get_sign_package()
    return render_template("card/index.html", wx=signature_data)

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <script> wx.config({ appId: '{{wx.app_id}}', timestamp: {{wx.timestamp}}, nonceStr: '{{wx.nonceStr}}', signature: '{{wx.signature}}', jsApiList: [ 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo' ] }); </script>
仅有的幸福

Has the poster’s problem been solved? I have the same problem. Anyway, I also tested the interface for comparison with WeChat’s testing tool, but it keeps showing invalid signature

给我你的怀抱

The signature is the same as the official one, and the URL is also obtained through location.href.split('#')[0]. . It also keeps prompting config:invalid signature. The JS interface security domain name of the official account is also configured OK, but not working. . Ask God for help,
Test address: http://weixin.zhjckx.com/ApiWeiXin/JsSdk

淡淡烟草味

Check out my answer from another person:

/q/1010000002502269/a-1020000002549180X2X

Ty80

The situation I encountered was that when obtaining the current URL when generating a signature, the URL:full() method of the laravel framework was used. As a result, this method will rearrange the order of the query string in the URL. For example, the url when you visit is

http://test.com?x=1&a=2

, the result obtained by using URL:full() is

http://test.com?a=2&x=1

Changed to the honest and practical WeChat official example:

$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

It’s OK.

阿神

I modified it myself and tested it ok. The reason is because the official httpGet function cannot be used.

Tell me these two sentences in jssdk.php

curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);

改为 

curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);// 这里改为false, 可以请求https的网页
//curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template