123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- # 微信公众号相关接口
- import urllib.parse
- import requests
- import json
- import time
- import pytz
- from backend.settings import WECHAT_ID_SECRET
- from backend.models import WeChatAccessToken, JsapiAccessToken
- from datetime import datetime, timedelta
- from backend.functions import HttpRequest, get_nonce_str, SHA1, service_log
- # wechat access token management
- class AccessTokenManagement:
- def __init__(self, application_name):
- self.application = application_name # application_name用于存在本地数据库,和WX客户端没有关系
- def request_new_token(self):
- url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + WECHAT_ID_SECRET['appID']\
- + '&secret=' + WECHAT_ID_SECRET['AppSecret']
- res = urllib.request.urlopen(url)
- values = eval(res.read())
- wechat_token = WeChatAccessToken.search_by_application(self.application)
- if wechat_token is None:
- wechat_token = WeChatAccessToken()
- wechat_token.application = self.application
- try:
- wechat_token.accessTokenKey = values['access_token']
- wechat_token.save()
- except Exception as e:
- print(e)
- service_log("微信获取access token错误")
- service_log(values['errmsg'])
- def get_token(self):
- wechat_token = WeChatAccessToken.search_by_application(self.application)
- if wechat_token is None:
- self.request_new_token()
- wechat_token = WeChatAccessToken.search_by_application(self.application)
- utc = pytz.UTC
- if datetime.utcnow().replace(tzinfo=utc) > (wechat_token.requestTime + timedelta(seconds=7200 - 300)).replace(tzinfo=utc):
- self.request_new_token()
- wechat_token = WeChatAccessToken.search_by_application(self.application)
- return wechat_token.accessTokenKey
- # wechat jsapi token management
- # 参考文档 https://mp.weixin.qq.com/wiki?action=doc&id=mp1421141115&t=0.9173760134966377#62
- class JsapiTokenManagement:
- def __init__(self, application_name):
- self.application = application_name # application_name用于存在本地数据库,和WX客户端没有关系
- def request_new_token(self):
- atm = AccessTokenManagement()
- access_token = atm.get_token()
- url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + access_token + '&type=jsapi'
- res = urllib.request.urlopen(url)
- values = eval(res.read())
- jsapi_token = JsapiAccessToken.search_by_application(self.application)
- if jsapi_token is None:
- jsapi_token = JsapiAccessToken()
- jsapi_token.application = self.application
- jsapi_token.accessTokenKey = values['ticket']
- jsapi_token.save()
- def get_token(self):
- jsapi_token = JsapiAccessToken.search_by_application(self.application)
- if jsapi_token is None:
- self.request_new_token()
- jsapi_token = JsapiAccessToken.search_by_application(self.application)
- if datetime.now() > jsapi_token.requestTime + timedelta(seconds=7200 - 300):
- self.request_new_token()
- jsapi_token = JsapiAccessToken.search_by_application(self.application)
- return jsapi_token.accessTokenKey
- # 微信微信网页授权
- class WeChatOA2:
- def __init__(self):
- self.base_url = 'https://open.weixin.qq.com/connect/oauth2/authorize?'
- # state只接受a-zA-Z0-9
- def snsapi_base(self, state):
- final_url = self.base_url + 'appid=' + WECHAT_ID_SECRET['appID']
- final_url = final_url + '&redirect_uri=' + urllib.parse.quote(WECHAT_ID_SECRET['redirect_uri'])
- final_url = final_url + '&response_type=code'
- final_url = final_url + '&scope=snsapi_base'
- final_url = final_url + '&state=' + state
- final_url = final_url + '#wechat_redirect'
- print(final_url)
- return final_url
- def snsapi_userinfo(self, state):
- final_url = self.base_url + 'appid=' + WECHAT_ID_SECRET['appID']
- final_url = final_url + '&redirect_uri=' + urllib.parse.quote(WECHAT_ID_SECRET['redirect_uri'])
- final_url = final_url + '&response_type=code'
- final_url = final_url + '&scope=snsapi_userinfo'
- final_url = final_url + '&state=' + state
- final_url = final_url + '#wechat_redirect'
- print(final_url)
- return final_url
- # 微信模板消息发送
- # 开发参考页面 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277
- class WeChatMsg:
- def __init__(self, openid, template_id, application_name, url=None, miniprogram=None, pagepath=None):
- self.POST_content = {
- 'touser': openid,
- 'template_id': template_id,
- 'url': url, # 模板跳转链接
- 'miniprogram': miniprogram,
- 'appid': WECHAT_ID_SECRET['appID'],
- 'pagepath': pagepath,
- }
- self.application_name = application_name
- self.first = {}
- self.remark = {}
- self.keywords = {}
- def set_first(self, value, color='#000000'):
- self.first = {'first': {'value': value, 'color': color}}
- def set_remark(self, value, color='#000000'):
- self.remark = {'remark': {'value': value, 'color': color}}
- def add_keyboard(self, value, color='#000000'):
- l = len(self.keywords)
- new_keyboard = {'keyword{}'.format(l + 1): {'value': value, 'color': color}}
- # 从字典中取值 https://blog.csdn.net/weixin_43069755/article/details/85005682
- self.keywords = {**self.keywords, **new_keyboard}
- return self.keywords
- def submit(self):
- data = {'data': {**self.first, **self.keywords, **self.remark}}
- self.POST_content = {**self.POST_content, **data}
- POST_data = json.dumps(self.POST_content)
- atm = AccessTokenManagement(application_name=self.application_name)
- access_token = atm.get_token()
- url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}'.format(access_token)
- resp = requests.post(url, data=POST_data.encode('utf-8'), headers={'Content-Type': 'text/xml'})
- msg = resp.text.encode('ISO-8859-1').decode('utf-8')
- return msg
- # JSAPI 调用
- # https://mp.weixin.qq.com/wiki?action=doc&id=mp1421141115&t=0.9173760134966377#62
- class JSAPI:
- def __init__(self, url):
- self.data = {'timestamp': str(int(time.time())), 'noncestr': get_nonce_str(), 'url': url}
- def get_sign(self):
- # 计算签名
- jtm = JsapiTokenManagement()
- self.data['jsapi_ticket'] = jtm.get_token()
- keys, paras = sorted(self.data), []
- paras = ['{}={}'.format(key, self.data[key]) for key in keys] # and kwargs[key] != '']
- stringA = '&'.join(paras)
- stringSignTemp = stringA # + '&key=' + WECHAT_ID_SECRET['wx_mch_api_key']
- sign = SHA1(stringSignTemp)
- self.data['signature'] = sign
- def get_parameter(self):
- self.get_sign()
- self.data['appId'] = WECHAT_ID_SECRET['appID']
- return self.data
|