微信公眾號開發Django 網頁授權

bay1發表於2018-06-22

title: 微信公眾號開發Django-網頁授權 date: 2018-06-21 17:02:36 tags: [微信公眾號,Django]

對於基礎的微信公眾號開發,網頁授權,JSSDK,圖片處理應該是最重要的三部分了 根本上也是按照文件開發,技術含量並不高。

(選Django=很多許可權控制模組已經做好了,比較省力)

在開始之前極力推薦內網穿透的各種工具,可以實時除錯公眾號 推薦自己搭建,可以自定義域名,傳輸也放心 github.com/inconshreve… github.com/fatedier/fr…

不想手動實現全部的可以參考 WeRoBot 一開始就打算用這個,省力一下,不過它也有部分介面沒有實現 改著改著,導致到最後。。。。不經意地自己實現了'小封裝' 不過只用一些基礎介面還是直接用框架比較方便

微信公眾號開發Django 網頁授權

網頁授權,直接摘抄官方文件:

  • 第一步:使用者同意授權,獲取code

  • 第二步:通過code換取網頁授權access_token

  • 第三步:重新整理access_token(如果需要)

  • 第四步:拉取使用者資訊(需scope為 snsapi_userinfo)

  • 附:檢驗授權憑證(access_token)是否有效

# xgc.wechat.py部分

token=os.environ.get('TOKEN') # 文末會提到
app_id=os.environ.get('APP_ID')
app_secret=os.environ.get('APP_SECRET')
redirect_url = os.environ.get('REDIRECT_URL')
state = os.environ.get('STATE')
#網頁授權部分
web_get_code = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&state=%s&scope='%(app_id,redirect_url,state)
web_get_fan_info = 'https://api.weixin.qq.com/sns/userinfo?access_token='
web_check_access_token = 'https://api.weixin.qq.com/sns/auth?access_token='
web_get_access_token = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&grant_type=authorization_code&code='%(app_id,app_secret)

# views.py部分

class web_authorization(View):

    def get(self, request):
        from xgc.wechat import web_get_code, web_get_fan_info,web_get_access_token,web_check_access_token
        code = request.GET.get("code", "")
        if not code:
            return HttpResponse("非法訪問")
        requests_web_get_access_token_result = requests.get(web_get_access_token+code).json()
        if 'errmsg' in requests_web_get_access_token_result.keys():
            return HttpResponseRedirect(web_get_code+'snsapi_base#wechat_redirect')
        if cache.has_key('web_access_token'):
            web_access_token = cache.get('web_access_token')
        else:
            web_access_token = requests_web_get_access_token_result['access_token']
            cache.set('web_access_token',web_access_token,110*60) #下面會有說明
        fan_openid = requests_web_get_access_token_result['openid']
        # 這部分檢驗對於快取來說是多餘的,但是你如果擔心快取出問題,可以再次檢驗一波
        # check_access_token = requests.get(web_check_access_token+'%s&openid=%s'%(web_access_token,fan_openid)).json()
        # if check_access_token['errcode']!=0:
        #     return HttpResponseRedirect(web_get_code+'snsapi_base#wechat_redirect')
        scope = requests_web_get_access_token_result["scope"]
        if scope == "snsapi_userinfo":
            fan_info = requests.get(web_get_fan_info+'%s&openid=%s&lang=zh_CN' % (web_access_token, fan_openid))
            fan_info.encoding = 'utf-8'
            fan_info = fan_info.json()
            FansProfile.create_fan(fan_info)
        check_openid = FansProfile.objects.filter(openid=fan_openid).first()
        if not check_openid:
            return render(request, 'register.html', {'url': web_get_code+'snsapi_userinfo#wechat_redirect','header':'認證提示','text':'你還未進行資訊認證,請進行第一次認證'})
        response = HttpResponseRedirect('index')
        response.set_cookie('fanid',check_openid.id,3600)
        return response
複製程式碼

code

這裡我直接在公眾號選單部分設定了引導url 這裡設定成base授權,是因為在程式碼裡新增了認證部分 使用者第一次認證後我們就能儲存使用者基本資訊了,下一次就沒必要在進行userinfo授權了 而且靜默授權使用者體驗也更好點

{
    "type": "view",
    "name": "申請活動",
    "url": wechat_get_code+'snsapi_base#wechat_redirect',
    "key": "test_4"
}
複製程式碼

access_token

如文件所說,在獲取code之後直接請求換取我們需要的access_token

if cache.has_key('web_access_token'):
    web_access_token = cache.get('web_access_token')
else:
    web_access_token = requests_web_get_access_token_result['access_token']
    cache.set('web_access_token',web_access_token,110*60)
複製程式碼

程式碼中採用了快取策略,微信中很多token是有請求次數限制的 而且都有一段失效期,快取token是一個明智的選擇 具體的快取下面會提到

refresh_token

換取access_token的同時微信會返回一個refresh_token 用於對access_token的重新整理,不過我的程式碼中沒有采用 而是直接採取了重新授權

snsapi_userinfo

在第一次授權的時候我們檢測資料庫中是否有此使用者的認證記錄 如果沒有則跳轉引導使用者進行userinfo授權

其中我們需要注意的是這裡微信伺服器返回的資料沒有指明資料編碼型別導致直接讀取會出現亂碼 我們可以指定response編碼進行轉碼 具體解釋推薦這個帖子www.v2ex.com/t/172276

if scope == "snsapi_userinfo":
    fan_info = requests.get(web_get_fan_info+'%s&openid=%s&lang=zh_CN' % (web_access_token, fan_openid))
    fan_info.encoding = 'utf-8'
    fan_info = fan_info.json()
    FansProfile.create_fan(fan_info)
複製程式碼

PS:set_cookie是因為我沒有把粉絲的模型繼承Django的user模型 不能使用自身的auth模組,後期提交表單,上傳圖片又需要知道是誰上傳的 就採用記錄使用者id到cookie的方式

關於快取

此處採用Redis的方式 首先Django的settings.py引入快取配置

CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache', #本地檔案快取
        'LOCATION': '127.0.0.1:6379',
        'TIMEOUT': 600,
        'OPTIONS': {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "IGNORE_EXCEPTIONS": True,
        }
    }
}
複製程式碼

然後我們就可以通過引入from django.core.cache import cache模組 進行一些基本的操作,比如下面

# 設定web_access_token鍵值
# 有效期110*60s,即110min
cache.set('web_access_token',web_access_token,110*60)
複製程式碼

官方文件

os.environ.get('')

這裡獲取根目錄.env檔案的各種配置 可以針對部分祕密token,app_id進行單獨配置

由此建立虛擬環境推薦工具Pipenv 而不是常用的virtualenv等~ 預設支援.env的匯入

相關文章