1.首先頁面點擊微信圖標(biāo)
2.后臺方法調(diào)用微信方灾,用戶授權(quán):
- 前臺向后臺請求方法:
@wechat.route('/open_weixin', methods=['GET'])
def open_weixin():
"""第一步:用戶同意授權(quán)理疙,獲取code
redirect_uri :用戶授權(quán)之后回調(diào)地址
state:回調(diào)會帶著此參數(shù)
"""
return_url = request.args.get("return_url", "")
url = _get_open_weixin_url("snsapi_userinfo", return_url)
return redirect(url)
def _get_open_weixin_url(scope, return_url=None, ordernum=None, ip=None):
"""獲取微信授權(quán)頁面url
scope參數(shù):
snsapi_base 靜默授權(quán)不需要用戶操作洞豁,
snsapi_userinfo 需要用戶授權(quán)然后獲取用戶基本信息
state :重定向后會帶上state參數(shù)逛薇,如果你回調(diào)需要參數(shù)就放到這里萍启,最多128字節(jié)
redirect_uri:為微信回調(diào)地址
appid: "qwb*********56d" 公眾號的唯一標(biāo)識
"""
# 網(wǎng)頁授權(quán)兩種方式 回調(diào)不一樣,1 靜默授權(quán)只獲取openid 2 用戶授權(quán)獲取用戶信息女揭,
redirect_uri = ""
state = ""
if scope and scope == "snsapi_userinfo":
redirect_uri = urllib.quote(
os.path.join("http://", DOMAIN_NAME, "wechat/wechat_user_info")
)
if return_url:
state = return_url
else:
redirect_uri = urllib.quote(
os.path.join("http://", DOMAIN_NAME, "wechat/snsapi_base_open_id"))
state = "%s_%s" % (ordernum, ip)
url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={appid}\
&redirect_uri={redirect_uri}&response_type=code&scope={scope}\
&state={state}#wechat_redirect".format(
appid=appid, redirect_uri=redirect_uri,
state=state, scope=scope)
return url
最后return redirect(url)重定向去請求威信接口。
尤其注意:跳轉(zhuǎn)回調(diào)redirect_uri趴腋,應(yīng)當(dāng)使用https鏈接來確保授權(quán)code的安全性吊说。
3.微信回調(diào):
-
snsapi_base 授權(quán)只獲取用戶openid回調(diào):
openid:用戶唯一標(biāo)識,請注意优炬,在未關(guān)注公眾號時颁井,用戶訪問公眾號的網(wǎng)頁,也會產(chǎn)生一個用戶和公眾號唯一的OpenID
這個是微信給微信每個用戶分配的一個唯一標(biāo)識蠢护,這里微信登錄需要獲取用戶的基本信息蚤蔓,這里回調(diào)沒啥用,如果別的操作需要獲取用戶的openid 可以這樣獲取
@wechat.route('/snsapi_base_open_id', methods=['GET'])
def snsapi_base_open_id():
"""靜默授權(quán)回調(diào)方法
獲取openid回調(diào)地址"""
print '==============>>>>>>>>>snsapi_base_open_id'
print request.args.items().str()
print
code = request.args.get("code")
state = request.args.get("state").split("_")
ordernum = state[0]
ip = state[1]# 通過code換取網(wǎng)頁授權(quán)access_token view = _get_web_access_token(code) openid = view['openid'] webutil.session_set_user_open_id(ordernum, openid) return redirect(url_for("order.pay", ordernum=ordernum, ip=ip)) # return render_template("order/pay.html", view=view, ordernum=ordernum, # ip=ip)
snsapi_userinfo 獲取用戶基本信息回調(diào):
@wechat.route('/wechat_user_info', methods=['GET', 'POST'])
def wechat_user_info():
'''
用戶授權(quán)回調(diào)方法
微信獲取用戶基本信息
1 第一步:用戶同意授權(quán)糊余,獲取code
2 第二步:通過code換取網(wǎng)頁授權(quán)access_token
3 第三步:刷新access_token(如果需要)
4 第四步:拉取用戶信息(需scope為 snsapi_userinfo)
5 附:檢驗授權(quán)憑證(access_token)是否有效
'''
# 第一步:用戶同意授權(quán)秀又,獲取code
code = request.args.get("code")
return_url = request.args.get("state")
# 用戶拒絕授權(quán)不會返回code參數(shù)
if not code:
return redirect(url_for('user.login'))
# 通過code換取網(wǎng)頁授權(quán)access_token
view = _get_web_access_token(code)
# 失敗返回
if not view or not view.get("openid"):
return redirect(url_for('user.login'))
access_token = view['access_token']
openid = view['openid']
# 判斷此openid是否注冊過
user = User.query.filter_by(wx_open_id=openid).first()
if user:
return _wechat_login(user, return_url)
# 檢驗授權(quán)憑證(access_token)是否有效
val = _validation_access_token(access_token, openid)
if val != "ok":
# 刷新access_token
new_view = _refresh_access_token(view['refresh_token'])
access_token = new_view['access_token'] if new_view else ""
openid = new_view['openid'] if new_view else ""
user_view = _get_wechat_user_info(access_token, openid)
# 失敗返回
if not user_view:
return redirect(url_for('user.login'))
# 為用戶注冊賬號
user = _wechat_register_user(user_view)
return _wechat_login(user, return_url)
下面是獲取網(wǎng)頁授權(quán)的access_token:
def _get_web_access_token(code):
"""獲取網(wǎng)頁授權(quán)access_token 這個用來獲取用戶信息用
access_token:網(wǎng)頁授權(quán)接口調(diào)用憑證,注意:此access_token與基礎(chǔ)支持的access_token不同
expires_in:access_token接口調(diào)用憑證超時時間,單位(秒)
refresh_token:用戶刷新access_token
openid:用戶唯一標(biāo)識贬芥,請注意吐辙,在未關(guān)注公眾號時,用戶訪問公眾號的網(wǎng)頁蘸劈,也會產(chǎn)生一個用戶和公眾號唯一的OpenID
scope:用戶授權(quán)的作用域昏苏,使用逗號(,)分隔
"""
params = urllib.urlencode(
{
'appid': appid, 'secret': secret, 'code': code,
'grant_type': 'authorization_code'
}
)
f = urllib.urlopen(
"https://api.weixin.qq.com/sns/oauth2/access_token?%s" % params)
res = json.loads(f.read())
view = {}
if res and res.get("openid"):
view = {"access_token": res.get("access_token"),
"expires_in": res.get("expires_in"),
"refresh_token": res.get("refresh_token"),
"openid": res.get("openid"),
"scope": res.get("scope")}
return view
這里獲取用戶基本信息:
def _get_wechat_user_info(access_token, openid):
'''微信獲取用戶基本信息
access_token 網(wǎng)頁授權(quán)的access_token
openid:普通用戶標(biāo)識,對當(dāng)前公眾號唯一
lang:國家地區(qū)語言版本,可不填 zh_CN 簡體 zh_TW 繁體 en 英文
返回參數(shù):
"openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", #用戶的標(biāo)識,對當(dāng)前公眾號唯一
"nickname": "Band",#用戶的昵稱
"sex": 1,#用戶的性別威沫,值為1時是男性贤惯,值為2時是女性,值為0時是未知
"city": "廣州",
"province": "廣東",
"country": "中國",
"headimgurl":"" ,#用戶頭像棒掠,最后一個數(shù)值代表正方形頭像大蟹豕埂(有0、46烟很、64颈墅、96蜡镶、132數(shù)值可選,0代表640*640正方形頭像)恤筛,用戶沒有頭像時該項為空官还。若用戶更換頭像,原有頭像URL將失效毒坛。
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL", #只有在用戶將公眾號綁定到微信開放平臺帳號后望伦,才會出現(xiàn)該字段。
"privilege":用戶特權(quán)信息煎殷,json 數(shù)組屡谐,如微信沃卡用戶為(chinaunicom)
'''
params = urllib.urlencode(
{'access_token': access_token, 'openid': openid, 'lang': 'zh_CN'})
f = urllib.urlopen("https://api.weixin.qq.com/sns/userinfo?%s" % params)
res = json.loads(f.read())
view = {}
if res and res.get("openid"):
view = {
"openid": res.get("openid"),
"nickname": res.get("nickname"),
"sex": res.get("sex"),
"city": res.get("city"),
"province": res.get("province"),
"country": res.get("country"),
"headimgurl": res.get("headimgurl")
}
return view
然后給微信用戶注冊一個帳號,登錄上就可以了蝌数;
其實就是用戶授權(quán)微信獲取用戶信息,給用戶注冊帳號登錄上涝桅;