def _fetch_access_token(self, url, data): """ The real fetch access token """ logger.info("Fetching component access token") res = self._http.post(url=url, data=data) try: res.raise_for_status() except requests.RequestException as reqe: raise WeChatClientException( errcode=None, errmsg=None, client=self, request=reqe.request, response=reqe.response, ) result = res.json() if "errcode" in result and result["errcode"] != 0: raise WeChatClientException( result["errcode"], result["errmsg"], client=self, request=res.request, response=res, ) expires_in = 7200 if "expires_in" in result: expires_in = result["expires_in"] self.session.set("component_access_token", result["component_access_token"], expires_in) self.expires_at = int(time.time()) + expires_in return result
def _fetch_access_token(self, url, params): """ 替代 requests 版本 _fetch_access_token """ http_client = AsyncHTTPClient() params = urlencode(dict((k, to_binary(v)) for k, v in params.items())) _url = '{0}?{1}'.format(url, params) req = HTTPRequest(url=_url, method="GET", request_timeout=self.timeout) res = yield http_client.fetch(req) if res.error is not None: raise WeChatClientException(errcode=None, errmsg=None, client=self, request=req, response=res) result = self._decode_result(res) if 'errcode' in result and result['errcode'] != 0: raise WeChatClientException(result['errcode'], result['errmsg'], client=self, request=res.request, response=res) expires_in = 7200 if 'expires_in' in result: expires_in = result['expires_in'] self.session.set(self.access_token_key, result['access_token'], expires_in) self.expires_at = int(time.time()) + expires_in raise Return(result)
def _fetch_access_token(self, url, params): """ The real fetch access token """ res = requests.get(url=url, params=params) try: res.raise_for_status() except requests.RequestException as reqe: raise WeChatClientException(errcode=None, errmsg=None, client=self, request=reqe.request, response=reqe.response) result = res.json() if 'errcode' in result and result['errcode'] != 0: raise WeChatClientException(result['errcode'], result['errmsg'], client=self, request=res.request, response=res) expires_in = 7200 if 'expires_in' in result: expires_in = result['expires_in'] self.session.set('access_token', result['access_token'], expires_in) self.expires_at = int(time.time()) + expires_in return result
def _request(self, method, url_or_endpoint, **kwargs): if not url_or_endpoint.startswith(('http://', 'https://')): api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL) url = '{base}{endpoint}'.format(base=api_base_url, endpoint=url_or_endpoint) else: url = url_or_endpoint if 'params' not in kwargs: kwargs['params'] = {} if isinstance(kwargs['params'], dict) and \ 'component_access_token' not in kwargs['params']: kwargs['params']['component_access_token'] = self.access_token if isinstance(kwargs['data'], dict): kwargs['data'] = json.dumps(kwargs['data']) res = requests.request(method=method, url=url, **kwargs) try: res.raise_for_status() except requests.RequestException as reqe: raise WeChatClientException(errcode=None, errmsg=None, client=self, request=reqe.request, response=reqe.response) return self._handle_result(res, method, url, **kwargs)
def _handle_result(self, res, method=None, url=None, **kwargs): result = json.loads(res.content.decode('utf-8', 'ignore'), strict=False) if 'errcode' in result: result['errcode'] = int(result['errcode']) if 'errcode' in result and result['errcode'] != 0: errcode = result['errcode'] errmsg = result['errmsg'] if errcode == 42001: logger.info( 'Component access token expired, fetch a new one and retry request' ) self.fetch_access_token() kwargs['params']['component_access_token'] = self.session.get( 'component_access_token') return self._request(method=method, url_or_endpoint=url, **kwargs) elif errcode == 45009: # api freq out of limit raise APILimitedException(errcode, errmsg, client=self, request=res.request, response=res) else: raise WeChatClientException(errcode, errmsg, client=self, request=res.request, response=res) return result
def _request(self, method, url_or_endpoint, **kwargs): if not url_or_endpoint.startswith(('http://', 'https://')): api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL) url = '{base}{endpoint}'.format(base=api_base_url, endpoint=url_or_endpoint) else: url = url_or_endpoint if 'params' not in kwargs: kwargs['params'] = {} if isinstance(kwargs['params'], dict) and \ 'access_token' not in kwargs['params']: kwargs['params']['access_token'] = self.access_token if isinstance(kwargs.get('data', ''), dict): body = json.dumps(kwargs['data'], ensure_ascii=False) body = body.encode('utf-8') kwargs['data'] = body kwargs['timeout'] = kwargs.get('timeout', self.timeout) result_processor = kwargs.pop('result_processor', None) res = self._http.request(method=method, url=url, **kwargs) try: res.raise_for_status() except requests.RequestException as reqe: raise WeChatClientException(errcode=None, errmsg=None, client=self, request=reqe.request, response=reqe.response) return self._handle_result(res, method, url, result_processor, **kwargs)
def _handle_result(self, res, method=None, url=None, **kwargs): result = json.loads(res.content.decode("utf-8", "ignore"), strict=False) if "errcode" in result: result["errcode"] = int(result["errcode"]) if "errcode" in result and result["errcode"] != 0: errcode = result["errcode"] errmsg = result.get("errmsg", errcode) if self.auto_retry and errcode in ( WeChatErrorCode.INVALID_CREDENTIAL.value, WeChatErrorCode.INVALID_ACCESS_TOKEN.value, WeChatErrorCode.EXPIRED_ACCESS_TOKEN.value, ): logger.info("Component access token expired, fetch a new one and retry request") self.fetch_access_token() kwargs["params"]["component_access_token"] = self.session.get( "{}_component_access_token".format(self.component_appid) ) return self._request(method=method, url_or_endpoint=url, **kwargs) elif errcode == WeChatErrorCode.OUT_OF_API_FREQ_LIMIT.value: # api freq out of limit raise APILimitedException(errcode, errmsg, client=self, request=res.request, response=res) else: raise WeChatClientException(errcode, errmsg, client=self, request=res.request, response=res) return result
def _request(self, method, url_or_endpoint, **kwargs): if not url_or_endpoint.startswith(('http://', 'https://')): api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL) url = '{base}{endpoint}'.format(base=api_base_url, endpoint=url_or_endpoint) else: url = url_or_endpoint # 群发消息上传视频接口地址 HTTPS 证书错误,暂时忽略证书验证 if url.startswith('https://file.api.weixin.qq.com'): kwargs['verify'] = False if 'params' not in kwargs: kwargs['params'] = {} if isinstance(kwargs['params'], dict) and \ 'access_token' not in kwargs['params']: kwargs['params']['access_token'] = self.access_token if isinstance(kwargs.get('data', ''), dict): body = json.dumps(kwargs['data'], ensure_ascii=False) body = body.encode('utf-8') kwargs['data'] = body res = requests.request(method=method, url=url, **kwargs) try: res.raise_for_status() except requests.RequestException as reqe: raise WeChatClientException(errcode=None, errmsg=None, client=self, request=reqe.request, response=reqe.response) return self._handle_result(res, method, url, **kwargs)
def _request(self, method, url_or_endpoint, **kwargs): if not url_or_endpoint.startswith(("http://", "https://")): api_base_url = kwargs.pop("api_base_url", self.API_BASE_URL) url = f"{api_base_url}{url_or_endpoint}" else: url = url_or_endpoint if "params" not in kwargs: kwargs["params"] = {} if isinstance(kwargs["params"], dict) and "suite_access_token" not in kwargs["params"]: kwargs["params"]["suite_access_token"] = self.access_token if isinstance(kwargs.get("data", ""), dict): body = json.dumps(kwargs["data"], ensure_ascii=False) body = body.encode("utf-8") kwargs["data"] = body kwargs["timeout"] = kwargs.get("timeout", self.timeout) result_processor = kwargs.pop("result_processor", None) res = self._http.request(method=method, url=url, **kwargs) try: res.raise_for_status() except requests.RequestException as reqe: raise WeChatClientException( errcode=None, errmsg=None, client=self, request=reqe.request, response=reqe.response, ) return self._handle_result(res, method, url, result_processor, **kwargs)
def _request(self, method, url_or_endpoint, **kwargs): if not url_or_endpoint.startswith(("http://", "https://")): api_base_url = kwargs.pop("api_base_url", self.API_BASE_URL) url = f"{api_base_url}{url_or_endpoint}" else: url = url_or_endpoint if "params" not in kwargs: kwargs["params"] = {} if isinstance( kwargs["params"], dict) and "component_access_token" not in kwargs["params"]: kwargs["params"]["component_access_token"] = self.access_token if isinstance(kwargs["data"], dict): kwargs["data"] = json.dumps(kwargs["data"]) res = self._http.request(method=method, url=url, **kwargs) try: res.raise_for_status() except requests.RequestException as reqe: raise WeChatClientException( errcode=None, errmsg=None, client=self, request=reqe.request, response=reqe.response, ) return self._handle_result(res, method, url, **kwargs)
def _handle_result(self, res, method=None, url=None, **kwargs): res.encoding = 'utf-8' result = res.json() if 'base_resp' in result: # Different response in device APIs. F**k tencent! result = result['base_resp'] if 'errcode' in result: result['errcode'] = int(result['errcode']) if 'errcode' in result and result['errcode'] != 0: errcode = result['errcode'] errmsg = result['errmsg'] if errcode == 42001: # access_token expired, fetch a new one and retry request self.fetch_access_token() kwargs['params']['access_token'] = self.session.get( 'access_token') return self._request(method=method, url_or_endpoint=url, **kwargs) elif errcode == 45009: # api freq out of limit raise APILimitedException(errcode, errmsg, client=self, request=res.request, response=res) else: raise WeChatClientException(errcode, errmsg, client=self, request=res.request, response=res) return result
def auth(self, code, scope=None): """用code进行微信授权 :rtype: (wechat_django.models.WeChatUser, dict) :raises: wechatpy.exceptions.WeChatClientException :raises: wechatpy.exceptions.WeChatOAuthException """ if not self.abilities.api: raise WeChatClientException(WeChatErrorCode.INVALID_CREDENTIAL) if self.type == WeChatApp.Type.SERVICEAPP: if not self.abilities.oauth: raise WeChatClientException(WeChatErrorCode.UNAUTHORIZED_API) return self._auth_service(code, scope) elif self.type == WeChatApp.Type.MINIPROGRAM: return self._auth_miniprogram(code) else: raise WeChatClientException(WeChatErrorCode.UNAUTHORIZED_API)
def _handle_result(self, res, method=None, url=None, result_processor=None, **kwargs): if not isinstance(res, dict): # Dirty hack around asyncio based AsyncWeChatClient result = self._decode_result(res) else: result = res if not isinstance(result, dict): return result if 'base_resp' in result: # Different response in device APIs. F**k tencent! result.update(result.pop('base_resp')) if 'errcode' in result: result['errcode'] = int(result['errcode']) if 'errcode' in result and result['errcode'] != 0: errcode = result['errcode'] errmsg = result.get('errmsg', errcode) if self.auto_retry and errcode in ( WeChatErrorCode.INVALID_CREDENTIAL.value, WeChatErrorCode.INVALID_ACCESS_TOKEN.value, WeChatErrorCode.EXPIRED_ACCESS_TOKEN.value): logger.info('Access token expired, fetch a new one and retry request') self.fetch_access_token() access_token, expires_at = self.session.get(self.access_token_key) kwargs['params']['access_token'] = access_token return self._request( method=method, url_or_endpoint=url, result_processor=result_processor, **kwargs ) elif errcode == WeChatErrorCode.OUT_OF_API_FREQ_LIMIT.value: # api freq out of limit raise APILimitedException( errcode, errmsg, client=self, request=res.request, response=res ) else: raise WeChatClientException( errcode, errmsg, client=self, request=res.request, response=res ) return result if not result_processor else result_processor(result)
def _request(self, method, url_or_endpoint, **kwargs): http_client = AsyncHTTPClient() if not url_or_endpoint.startswith(('http://', 'https://')): api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL) url = '{base}{endpoint}'.format(base=api_base_url, endpoint=url_or_endpoint) else: url = url_or_endpoint headers = {} params = kwargs.pop('params', {}) if 'access_token' not in params: params['access_token'] = self.access_token params = urlencode(dict((k, to_binary(v)) for k, v in params.items())) url = '{0}?{1}'.format(url, params) data = kwargs.get('data') files = kwargs.get('files') if files: from requests.models import RequestEncodingMixin from requests.utils import super_len body, content_type = RequestEncodingMixin._encode_files( files, data) headers['Content-Type'] = content_type headers['Content-Length'] = super_len(body) else: if isinstance(data, dict): body = json.dumps(data, ensure_ascii=False) body = body.encode('utf-8') else: body = data result_processor = kwargs.pop('result_processor', None) timeout = kwargs.get('timeout', self.timeout) req = HTTPRequest(url=url, method=method.upper(), headers=headers, body=body, request_timeout=timeout) res = yield http_client.fetch(req) if res.error is not None: raise WeChatClientException(errcode=None, errmsg=None, client=self, request=req, response=res) result = self._handle_result(res, method, url, result_processor, **kwargs) raise Return(result)
def _fetch_access_token(self, url, params): """ The real fetch access token """ res = requests.get(url=url, params=params) result = res.json() if 'errcode' in result and result['errcode'] != 0: raise WeChatClientException(result['errcode'], result['errmsg']) self._access_token = result['access_token'] expires_in = 7200 if 'expires_in' in result: expires_in = result['expires_in'] self.expires_at = int(time.time()) + expires_in return result
def _handle_result(self, res, method=None, url=None, result_processor=None, **kwargs): if not isinstance(res, dict): # Dirty hack around asyncio based AsyncWeChatClient result = self._decode_result(res) else: result = res if not isinstance(result, dict): return result if 'base_resp' in result: # Different response in device APIs. F**k tencent! result = result['base_resp'] if 'errcode' in result: result['errcode'] = int(result['errcode']) if 'errcode' in result and result['errcode'] != 0: errcode = result['errcode'] errmsg = result['errmsg'] if errcode in (40001, 40014, 42001): # access_token expired, fetch a new one and retry request self.fetch_access_token() access_token = self.session.get(self.access_token_key) kwargs['params']['access_token'] = access_token return self._request( method=method, url_or_endpoint=url, result_processor=result_processor, **kwargs ) elif errcode == 45009: # api freq out of limit raise APILimitedException( errcode, errmsg, client=self, request=res.request, response=res ) else: raise WeChatClientException( errcode, errmsg, client=self, request=res.request, response=res ) return result if not result_processor else result_processor(result)
def _request(self, method, url_or_endpoint, **kwargs): http_client = AsyncHTTPClient() if not url_or_endpoint.startswith(('http://', 'https://')): api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL) url = '{base}{endpoint}'.format( base=api_base_url, endpoint=url_or_endpoint ) else: url = url_or_endpoint headers = {} params = kwargs.pop('params', {}) params = urlencode(dict((k, to_binary(v)) for k, v in params.items())) url = '{0}?{1}'.format(url, params) data = kwargs.get('data') if isinstance(data, dict): data = optionaldict(data) if 'mchid' not in data: # F**k Tencent data.setdefault('mch_id', self.mch_id) data.setdefault('sub_mch_id', self.sub_mch_id) data.setdefault('nonce_str', random_string(32)) sign = calculate_signature(data, self.api_key) body = dict_to_xml(data, sign) body = body.encode('utf-8') else: body = data req = HTTPRequest( url=url, method=method.upper(), headers=headers, body=body ) res = yield http_client.fetch(req) if res.error is not None: raise WeChatClientException( errcode=None, errmsg=None, client=self, request=req, response=res ) result = self._handle_result(res) raise Return(result)
def _handle_result(self, res, method=None, url=None, **kwargs): result = json.loads(res.content.decode('utf-8', 'ignore'), strict=False) if 'errcode' in result: result['errcode'] = int(result['errcode']) if 'errcode' in result and result['errcode'] != 0: errcode = result['errcode'] errmsg = result.get('errmsg', errcode) if self.auto_retry and errcode in ( WeChatErrorCode.INVALID_CREDENTIAL.value, WeChatErrorCode.INVALID_ACCESS_TOKEN.value, WeChatErrorCode.EXPIRED_ACCESS_TOKEN.value): logger.info('Component access token expired, fetch a new one and retry request') self.fetch_access_token() kwargs['params']['component_access_token'] = self.session.get( 'component_access_token' ) return self._request( method=method, url_or_endpoint=url, **kwargs ) elif errcode == WeChatErrorCode.OUT_OF_API_FREQ_LIMIT.value: # api freq out of limit raise APILimitedException( errcode, errmsg, client=self, request=res.request, response=res ) else: raise WeChatClientException( errcode, errmsg, client=self, request=res.request, response=res ) return result
def _handle_result(self, res, method=None, url=None, **kwargs): res.encoding = 'utf-8' try: result = res.json() except (TypeError, ValueError): # Return origin response object if we can not decode it as JSON return res if 'base_resp' in result: # Different response in device APIs. F**k tencent! result = result['base_resp'] if 'errcode' in result: result['errcode'] = int(result['errcode']) if 'errcode' in result and result['errcode'] != 0: errcode = result['errcode'] errmsg = result['errmsg'] if errcode in (40001, 40014, 42001): # access_token expired, fetch a new one and retry request self.fetch_access_token() access_token = self.session.get(self.access_token_key) kwargs['params']['access_token'] = access_token return self._request(method=method, url_or_endpoint=url, **kwargs) elif errcode == 45009: # api freq out of limit raise APILimitedException(errcode, errmsg, client=self, request=res.request, response=res) else: raise WeChatClientException(errcode, errmsg, client=self, request=res.request, response=res) return result