Django-jssdk license for wechat official account development

The previous chapter has introduced the basic operation of web page authorization, in the web development will also encounter the issue of JSSDK authorization

Warning: This JSSDK license may have a lot of problems. If any, please check at the end of this article

Part of the code has been explained in the last article, you can refer to the other tip if there is an unofficial web page, do not debug in the wechat client using the wechat Web developer tools

Get ticket

Here the official documentation explicitly states that the user needs to cache jsapi_ticket because the NUMBER of API calls is very limited. According to the documentation, I put acess_token and ticket together to get basic support

#xgc.wechat.py
app_id=os.environ.get('APP_ID')
app_secret=os.environ.get('APP_SECRET')
# Basic licensing part
base_get_access_token = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s'%(app_id,app_secret)
get_ticket = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token='

#views.py
class base_authorization(a):

    @classmethod
    def get_ticket(self):
        key = 'ticket'
        if cache.has_key(key):
            ticket  = cache.get(key)
        else:
            if cache.has_key('access_token'):
                access_token = cache.get('access_token')
            else:
                access_token = self.get_access_token()
            from xgc.wechat import get_ticket
            ticket = requests.get(get_ticket+access_token).json()['ticket']
            cache.set(key,ticket,110*60)
        return ticket

    @classmethod
    def get_access_token(self):
        from xgc.wechat import base_get_access_token
        key = 'access_token'
        access_token = requests.get(base_get_access_token).json()['access_token']
        cache.set(key,access_token,110*60)
        return access_token
Copy the code

Signature is generated

Noncestr (random string), valid jsapi_ticket, timestamp (timestamp), url (url of the current page, The signature class jsapi_ticket is taken from the ticket above

class signature(View):

    def __init__(self,url):
        self.ret = {
            'nonceStr': self.__create_nonce_str(),
            'jsapi_ticket': base_authorization.get_ticket(),
            'timestamp': self.__create_timestamp(),
            'url': url
        }

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

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

    def sign(self):
        string = '&'.join(['%s=%s' % (key.lower(), self.ret[key]) for key in sorted(self.ret)]).encode('utf-8')
        self.ret['signature'] = hashlib.sha1(string).hexdigest()
        return self.ret
Copy the code

Wx interface verification

# urls.py
url(r'^activity', views.activity.as_view(), name='activity'),

# views.py
class activity(View):

    def get(self, request):
        return render(request, 'activaty.html')

    def post(self,request,*args, **kwargs):
        request_type = request.POST.get('type')
        if not request_type:
            request_body = json.loads(request.body.decode())
            pathname = request_body['url']
            sign = signature(unquote(pathname))
            sign = json.dumps(sign.sign())
            return HttpResponse(sign, content_type="application/json")
        elif request_type == 'image/jpeg':
            pass # This is used when uploading pictures
Copy the code

First we set up the route to interact with the front end, then we use the following JS to do the initial WX configuration


    function csrfSafeMethod(method) {
        // these HTTP methods do not require CSRF protection
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }

    $.ajaxSetup({
        beforeSend: function (xhr, settings) {
            if(! csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken".'{{ csrf_token }}'); }}});// Set django-Ajax-cSRf above

    let wxStatus = 0

    $(document).ready(function () {
        $.ajax({
            type: 'POST'.url: "http://test.flywinky.top/activity".// The link to the class Activity setting
            data: JSON.stringify({ 'url': encodeURIComponent(location.href.split(The '#') [0])}),headers: { 'Content-Type': 'application/json' },
            success: function (res) {
                wx.config({
                    debug: false.appId: 'wx4f35679866a1b3a6'.timestamp: res['timestamp'].nonceStr: res['nonceStr'].signature: res['signature'].jsApiList: ['chooseImage'.'uploadImage']}}})); wx.ready(function () {
            wxStatus = 1
        })
        wx.error(function (res) {
            wxStatus = 2
        })
Copy the code

The normal situation is shown below

Then you can call each official interface, as long as you have the corresponding permissions interface list at the bottom of the page

Django-Ajax-CSRF

Django has CSRF validation enabled by default. You need to be aware of the cSRF_Token setting when making Ajax POST requests, as well as the code above in HTML

{% load static %} {{csrf_token}} // can be directly importedCopy the code

All sorts of problems

Config :invalid signature :invalid signature

Summary of official website documents:

Invalid signature Indicates a signature error. You are advised to check in the following order:

  • Confirm correct signature algorithm, available tools for checking http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign pages.
  • Verify that nonceStr (js hump standard capital S) in config, timestamp is consistent with the corresponding nonceStr, timestamp in the signature.
  • Verify that the URL is the full URL of the page (check the current page alert(location.hre.split (‘#’)[0])), including ‘HTTP (s)://’ part, and’? The ‘GET argument part after’, but not the ‘#’hash part.
  • Ensure that the APPID in config is the same as the appID used to obtain jSAPi_ticket.
  • Ensure that access_token and JSAPi_ticket are cached.
  • Make sure that the URL you get for signing is dynamically retrieved, as shown in the example PHP code. If it is a static HTML page, the front end needs to fetch the current page with JS, except for the ‘#’hash part of the link (available location.hp.split (‘#’)[0], and requires encodeURIComponent). Once the page is shared, the wechat client will add other parameters at the end of your link. If the current link is not dynamically obtained, the page after sharing will fail to be signed in person.

There are:

  • Obtaining WeChat jsapi_ticket has two URL address, one is: {0} https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token= & type = wx_card another is: https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token= {0} & type = jsapi first WeChat card voucher address, should be with the second address.
  • The access_token here is the basic supported access_token, which is different from web page authorization
  • Don’t forget “encodeURIComponent” in your url in JavaScript! Invalid signature is reported during initialization, but the API interface can be called.