six_001
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
import threading
|
||||
from datetime import datetime, timedelta
|
||||
from functools import wraps
|
||||
from pathlib import Path
|
||||
from urllib.parse import urlencode
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import orjson
|
||||
import pydash
|
||||
import requests
|
||||
from Crypto.PublicKey import RSA
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponseRedirect
|
||||
from jwt import JWT, jwk_from_pem
|
||||
from jwt.utils import get_int_from_datetime
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.viewsets import ViewSet
|
||||
|
||||
from wechat_token.token数据库 import weitoken
|
||||
|
||||
|
||||
def sync_lock_线程锁(lock):
|
||||
def decorator(fn):
|
||||
@wraps(fn)
|
||||
def wrapper(*args, **kwargs):
|
||||
with lock:
|
||||
return fn(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class AllowMyAppRedirect(HttpResponseRedirect):
|
||||
allowed_schemes = ["http", "https", "myapp"]
|
||||
|
||||
|
||||
class 接收微信的code回调ViewSets(ViewSet):
|
||||
lock = threading.Lock()
|
||||
private_key_pem_私钥 = Path(settings.BASE_DIR).joinpath("django_jwt_token/private.pem").read_bytes()
|
||||
|
||||
def jwt_生成token(self, openid, uniond):
|
||||
# 读取私钥的 bytes字符串
|
||||
|
||||
# 创建一个 JWT对象
|
||||
jwt对象实例 = JWT() # 创建对象
|
||||
# 创建 payload
|
||||
message = {
|
||||
"openid": openid,
|
||||
"uniond": uniond,
|
||||
'iat': get_int_from_datetime(datetime.now(tz=ZoneInfo(key="utc"))), # 生成jwt-token的时间
|
||||
'exp': get_int_from_datetime(datetime.now(tz=ZoneInfo(key="utc")) + timedelta(hours=1)), # 多长时间过期
|
||||
}
|
||||
# 获取私钥对象 (并且要私钥的密码)
|
||||
私钥对象 = RSA.import_key(extern_key=self.private_key_pem_私钥, passphrase=settings.SECRET_KEY).export_key()
|
||||
signing_key = jwk_from_pem(pem_content=私钥对象, )
|
||||
token = jwt对象实例.encode(payload=message, key=signing_key, alg="RS256")
|
||||
return token
|
||||
|
||||
def get网站授权access_token(self, code, state):
|
||||
uri = "https://api.weixin.qq.com/sns/oauth2/access_token"
|
||||
postData = requests.post(url=uri, params={
|
||||
"appid": "wx6c9d4541e0285d02",
|
||||
"secret": "bb87178b80e23f2fc96b688577dafca4",
|
||||
"code": code,
|
||||
"grant_type": "authorization_code"
|
||||
}).json()
|
||||
access_token = pydash.get(obj=postData, path="access_token")
|
||||
expires_in = pydash.get(obj=postData, path="expires_in")
|
||||
refresh_token = pydash.get(obj=postData, path="refresh_token")
|
||||
openid = pydash.get(obj=postData, path="openid")
|
||||
scope = pydash.get(obj=postData, path="scope")
|
||||
unionid = pydash.get(obj=postData, path="unionid")
|
||||
return postData
|
||||
|
||||
def get获取用户个人信息(self, code, state):
|
||||
uri = f"https://api.weixin.qq.com/sns/userinfo"
|
||||
token, is创建 = weitoken.objects.update_or_create(token_name="web_token")
|
||||
if is创建:
|
||||
wx_access_token_dict = self.get网站授权access_token(code=code, state=state)
|
||||
token.token_value = pydash.get(obj=wx_access_token_dict, path="access_token")
|
||||
token.save()
|
||||
access_token = pydash.get(obj=wx_access_token_dict, path="access_token")
|
||||
openid = pydash.get(obj=wx_access_token_dict, path="openid")
|
||||
getData = requests.get(url=uri, params={"access_token": access_token, "openid": openid})
|
||||
res = orjson.loads(getData.content.decode(encoding="utf-8"))
|
||||
return res
|
||||
else:
|
||||
time创建时间 = token.updateTime.timestamp() # 更新时间的时间戳
|
||||
current_时间戳 = get_int_from_datetime(value=datetime.now())
|
||||
if current_时间戳 - time创建时间 > 3600:
|
||||
# 时间过期时,需要重新请求 拿到新的 access_token
|
||||
wx_access_token_dict = self.get网站授权access_token(code=code, state=state)
|
||||
# 更新token的值
|
||||
token.token_value = pydash.get(obj=wx_access_token_dict, path="access_token")
|
||||
token.save()
|
||||
access_token = pydash.get(obj=wx_access_token_dict, path="access_token")
|
||||
openid = pydash.get(obj=wx_access_token_dict, path="openid")
|
||||
getData = requests.get(url=uri, params={"access_token": access_token, "openid": openid})
|
||||
res = orjson.loads(getData.content.decode(encoding="utf-8"))
|
||||
return res
|
||||
else:
|
||||
wx_access_token_dict = self.get网站授权access_token(code=code, state=state)
|
||||
# 更新token的值
|
||||
token.token_value = pydash.get(obj=wx_access_token_dict, path="access_token")
|
||||
token.save()
|
||||
access_token = pydash.get(obj=wx_access_token_dict, path="access_token")
|
||||
openid = pydash.get(obj=wx_access_token_dict, path="openid")
|
||||
getData = requests.get(url=uri, params={"access_token": access_token, "openid": openid})
|
||||
res = orjson.loads(getData.content.decode(encoding="utf-8"))
|
||||
return res
|
||||
|
||||
@action(detail=False, methods=["get", ], url_path="get_code", )
|
||||
# @sync_lock_线程锁( lock=lock )
|
||||
def get_code(self, request: Request):
|
||||
"""
|
||||
前端,带着code的get请求,在这里拿到code,获取登陆用户的信息,
|
||||
重点: 通过回调,前端,(处理业务逻辑) 由于我这里使用的是Mac桌面版本.
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
code = request.query_params.get(key="code", default=None)
|
||||
state = request.data.get("state", None)
|
||||
user_info_用户信息 = self.get获取用户个人信息(code=code, state=state)
|
||||
openid = pydash.get(obj=user_info_用户信息, path="openid")
|
||||
unionid = pydash.get(obj=user_info_用户信息, path="unionid")
|
||||
print("为什么没有值了呢", openid, unionid)
|
||||
token = self.jwt_生成token(openid=openid, uniond=unionid)
|
||||
setData = pydash.set_(obj=user_info_用户信息, path="token", value=token)
|
||||
query_string = urlencode(setData, )
|
||||
uri = f"myapp://open/home?{query_string}"
|
||||
return AllowMyAppRedirect(redirect_to=uri)
|
||||
Reference in New Issue
Block a user