title: 微信公眾號開發Django-JSSDK授權 date: 2018-06-21 17:03:13 tags: [微信公眾號,Django]
上篇已經介紹過網頁授權的基本操作,在進行網頁開發的時候 也會遇到JSSDK授權的問題
警示:此JSSDK授權可能坑比較多~ 如出現各種問題,可以到文末檢查
部分程式碼上一篇文章已經提到解釋,可以參考 另外如果出現非官方網頁的提示,則不要在微信客戶端除錯 使用微信web開發者工具就可以了
獲取ticket部分
此處官方文件明確提到使用者需要快取jsapi_ticket 因為其api呼叫次數非常有限,根據文件說明我把獲取基礎支援的acess_token和ticket寫到了一起 程式碼如下
#xgc.wechat.py
app_id=os.environ.get('APP_ID')
app_secret=os.environ.get('APP_SECRET')
#基礎授權部分
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():
@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
複製程式碼
signature生成
首先我們signature生成需要一下幾個引數noncestr(隨機字串), 有效的jsapi_ticket, timestamp(時間戳), url(當前網頁的URL,不包含#及其後面部分) 其中官方提供了signature生成的python例子,如下的signature類,其中jsapi_ticket取自上方的ticket
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
複製程式碼
wx介面驗證
# 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 #傳圖片的時候會用到
複製程式碼
首先我們先設定和前端進行互動的路由,然後我們利用下面的js進行wx初始配置
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 }}');
}
},
});
//上方為Django-Ajax-CSRF設定
let wxStatus = 0
$(document).ready(function () {
$.ajax({
type: 'POST',
url: "http://test.flywinky.top/activity", // class activity設定的連結
data: JSON.stringify({ 'url': encodeURIComponent(location.href.split('#')[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
})
複製程式碼
正常的情況如下圖
然後就可以呼叫官方的各個介面了,只要你有相應的許可權 介面列表在網頁下方
Django-Ajax-CSRF
Django預設開啟了CSRF驗證 在進行Ajax請求POST的時候需要注意csrf_token的設定 官網文件這樣寫的 也可以按照我上方的程式碼,在html裡
{% load static %}
{{ csrf_token }} //就可以直接這樣引入了
複製程式碼
各種問題
首先推薦一篇帖子微信公眾平臺, config:invalid signature一直爆這個錯誤,求教如何解決?
官網文件總結:
invalid signature簽名錯誤。建議按如下順序檢查:
- 確認簽名演算法正確,可用http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 頁面工具進行校驗。
- 確認config中nonceStr(js中駝峰標準大寫S), timestamp與用以簽名中的對應noncestr, timestamp一致。
- 確認url是頁面完整的url(請在當前頁面alert(location.href.split('#')[0])確認),包括'http(s)://'部分,以及'?'後面的GET引數部分,但不包括'#'hash後面的部分。
- 確認 config 中的 appid 與用來獲取 jsapi_ticket 的 appid 一致。
- 確保一定快取access_token和jsapi_ticket。
- 確保你獲取用來簽名的url是動態獲取的,動態頁面可參見例項程式碼中php的實現方式。如果是html的靜態頁面在前端通過ajax將url傳到後臺簽名,前端需要用js獲取當前頁面除去'#'hash部分的連結(可用location.href.split('#')[0]獲取,而且需要encodeURIComponent),因為頁面一旦分享,微信客戶端會在你的連結末尾加入其它引數,如果不是動態獲取當前連結,將導致分享後的頁面簽名失敗。
還有:
- 獲取微信的jsapi_ticket有兩個URL地址,一個是:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=wx_card 另外一個是:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi 第一個微信卡券的地址,應該是用第二個地址。
- 此處的access_token為基礎支援的access_token,和網頁授權的不同
- url在JavaScript中千萬別忘記“encodeURIComponent”!否則後果很詭異,遇到過初始化的時候報invalid signature,但是API介面又能呼叫的情況。