作者:flyingpang
寫(xiě)在前面
本周剛在項(xiàng)目中實(shí)現(xiàn)了微信第三方網(wǎng)站掃碼登錄。因?yàn)榈谝淮螌?xiě)相關(guān)項(xiàng)目,所以遇到了很多坑。所以寫(xiě)這篇文章是希望像我之前那樣的小白也能從容的開(kāi)發(fā),不要浪費(fèi)無(wú)謂的時(shí)間,這篇文章盡量寫(xiě)的詳細(xì)簡(jiǎn)單。
準(zhǔn)備與注意事項(xiàng)
- 微信公眾平臺(tái)跟微信開(kāi)放平臺(tái)是兩個(gè)不同的平臺(tái),別搞混了。微信公眾平臺(tái)與微信開(kāi)放平臺(tái)的區(qū)別
- 微信開(kāi)放平臺(tái)里需要?jiǎng)?chuàng)建網(wǎng)站的應(yīng)用,網(wǎng)上沒(méi)找到創(chuàng)建網(wǎng)站應(yīng)用的教程,鏈接是創(chuàng)建移動(dòng)應(yīng)用的教程,大體步驟類(lèi)似,細(xì)節(jié)就不啰嗦。
- 創(chuàng)建之后注意修改回調(diào)授權(quán)域名,否則會(huì)出現(xiàn)scope參數(shù)錯(cuò)誤或
沒(méi)有scope權(quán)限錯(cuò)誤
。注意里面的域名格式,例如www.qq.com
,不要加http
- 準(zhǔn)備好
微信開(kāi)放平臺(tái)
的APPID
和APPSECRET
兩個(gè)參數(shù)。參數(shù)在微信開(kāi)放平臺(tái)中查看。 - 微信官方開(kāi)發(fā)文檔
- 開(kāi)發(fā)時(shí)使用到的python第三方庫(kù)
requests
開(kāi)發(fā)
二維碼授權(quán)鏈接
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
其中的
APPID = '你的APPID'
APPSECRET = '你的APPSECRET'
REDIRECT_URL = '指向微信登錄的處理函數(shù),例如django的view地址,注意URL必須編碼'
SCOPE = 'snsapi_login'
STATE = '不是必須的,作用時(shí)重定向后會(huì)帶上state參數(shù),開(kāi)發(fā)者可以填寫(xiě)a-zA-Z0-9的參數(shù)值,最多128字節(jié),'
我剛寫(xiě)的網(wǎng)站的例子,可以幫忙點(diǎn)一下增加下注冊(cè)量(笑),點(diǎn)開(kāi)鏈接可以看具體的參數(shù)。
https://open.weixin.qq.com/co...
不知道現(xiàn)在工作的網(wǎng)站會(huì)不會(huì)倒閉,防止鏈接失效,就再付一個(gè)一號(hào)店的鏈接吧。同樣可以點(diǎn)進(jìn)去看相關(guān)參數(shù)。
https://open.weixin.qq.com/co...
下面就是處理授權(quán)時(shí)的函數(shù)了
class WeiXinLogin(View):
appid = 'wxe0d95453c412f118' # 你自己的
appsecret = 'd785bt925fbc7ebed62734cfdpe5951c' # 你自己的
code = ''
state = ''
# 為了方便大家看,我都寫(xiě)在一個(gè)函數(shù)里
def get_info(self):
# 第一步獲取code跟state
try:
self.code = self.request.GET.get("code")
self.state = self.request.GET.get("state")
except Exception, e:
add_log.info("獲取code和stat參數(shù)錯(cuò)誤:\n%s" % str(traceback.format_exc()))
# 2.通過(guò)code換取網(wǎng)頁(yè)授權(quán)access_token
try:
url = u'https://api.weixin.qq.com/sns/oauth2/access_token'
params = {
'appid': self.appid,
'secret': self.appsecret,
'code': self.code,
'grant_type': 'authorization_code'
}
res = requests.get(url, params=params).json()
access_token = res["access_token"] # 只是呈現(xiàn)給大家看,可以刪除這行
openid = res["openid"] # 只是呈現(xiàn)給大家看,可以刪除這行
except Exception, e:
add_log.info("獲取access_token參數(shù)錯(cuò)誤:\n%s" % str(traceback.format_exc()))
raise Http404()
# 3.如果access_token超時(shí),那就刷新
# 注意,這里我沒(méi)有寫(xiě)這個(gè)刷新功能,不影響使用,如果想寫(xiě)的話,可以自己去看文檔
# 4.拉取用戶(hù)信息
try:
user_info_url = u'https://api.weixin.qq.com/sns/userinfo'
params = {
'access_token': res["access_token"],
'openid': res["openid"],
}
res = requests.get(user_info_url, params=params).json()
"""
注意,這里有個(gè)坑,res['nickname']表面上是unicode編碼,
但是里面的串卻是str的編碼,舉個(gè)例子,res['nickname']的返回值可能是這種形式
u'\xe9\x97\xab\xe5\xb0\x8f\xe8\x83\x96',直接存到數(shù)據(jù)庫(kù)會(huì)是亂碼.必須要轉(zhuǎn)成
unicode的編碼,需要使用
res['nickname'] = res['nickname'].encode('iso8859-1').decode('utf-8')
這種形式來(lái)轉(zhuǎn)換.
你也可以寫(xiě)個(gè)循環(huán)來(lái)轉(zhuǎn)化.
for value in res.values():
value = value.encode('iso8859-1').decode('utf-8')
"""
except Exception, e:
add_log.info("拉取用戶(hù)信息錯(cuò)誤:\n%s" % str(traceback.format_exc()))
# 保存到數(shù)據(jù)庫(kù)及登錄
# 返回的數(shù)據(jù)全部在res字典中
剩下就要看不同項(xiàng)目的第三方登錄的表是怎么設(shè)計(jì)的了.主要的思路是維護(hù)一張第三方登錄的表,把以后第三方登錄的信息都放在里面,設(shè)計(jì)思路可以借鑒廖雪峰的文章.
設(shè)計(jì)一個(gè)可擴(kuò)展的用戶(hù)登錄系統(tǒng) (1)
設(shè)計(jì)一個(gè)可擴(kuò)展的用戶(hù)登錄系統(tǒng) (2)
設(shè)計(jì)一個(gè)可擴(kuò)展的用戶(hù)登錄系統(tǒng) (3)
注意,判斷登錄的時(shí)候是驗(yàn)證該用戶(hù)的unionid,不是openid,因?yàn)槿绻愕木W(wǎng)站還有微信公眾平臺(tái)的微信授權(quán)的話,同一用戶(hù)
使用你的微信公眾平臺(tái)跟微信開(kāi)放平臺(tái)登錄之后,兩次的openid是不一樣的,但是unionid是唯一的.
關(guān)于UnionID機(jī)制
請(qǐng)注意,網(wǎng)頁(yè)授權(quán)獲取用戶(hù)基本信息也遵循UnionID機(jī)制。即如果開(kāi)發(fā)者有在多個(gè)公眾號(hào),或在公眾號(hào)、移動(dòng)應(yīng)用之間統(tǒng)一用戶(hù)帳號(hào)的需求,需要前往微信開(kāi)放平臺(tái)(open.weixin.qq.com)綁定公眾號(hào)后,才可利用UnionID機(jī)制來(lái)滿(mǎn)足上述需求。
UnionID機(jī)制的作用說(shuō)明:如果開(kāi)發(fā)者擁有多個(gè)移動(dòng)應(yīng)用、網(wǎng)站應(yīng)用和公眾帳號(hào),可通過(guò)獲取用戶(hù)基本信息中的unionid來(lái)區(qū)分用戶(hù)的唯一性,因?yàn)橥挥脩?hù),對(duì)同一個(gè)微信開(kāi)放平臺(tái)下的不同應(yīng)用(移動(dòng)應(yīng)用、網(wǎng)站應(yīng)用和公眾帳號(hào)),unionid是相同的。
PyChina將聯(lián)合JetBrain(出品PyCharm的公司)一起在北京舉辦一次Python沙龍活動(dòng)。
時(shí)間:11月26日晚上19:00-21:00
地點(diǎn):科技寺北新橋 北京市東城區(qū)東四北大街107號(hào)科林大廈B座107室(近北新橋地鐵站)
歡迎大家報(bào)名參加本次活動(dòng),特別需要志愿者來(lái)幫忙組織本次活動(dòng)。
詳情請(qǐng)點(diǎn)擊此處