Esempio n. 1
0
 def get_access_token(self) -> str:
     """获取接口调用凭据"""
     key = 'authorizer:{0}:access_token'.format(self.appid)
     value = redis_client.get(key)
     if value:
         return to_str(value)
     access_token, expires_in = component.get_authorizer_access_token(
         self.appid, self.refresh_token)
     redis_client.set(key, access_token,
                      ex=int(expires_in) - 300)  # 提前5分钟更新access_token
     return access_token
Esempio n. 2
0
 def get_card_api_ticket(self) -> str:
     """获取微信卡券api_ticket"""
     key = 'authorizer:{0}:card_api_ticket'.format(self.appid)
     value = redis_client.get(key)
     if value:
         return to_str(value)
     url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket'
     params = {'access_token': self.get_access_token(), 'type': 'wx_card'}
     ret = requests.get(url, params=params).json()
     ticket, expires_in = map(ret.get, ['ticket', 'expires_in'])
     if not (ticket and expires_in):
         raise RuntimeError(repr(ret))
     redis_client.set(key, ticket,
                      ex=int(expires_in) - 300)  # 提前5分钟更新ticket
     return ticket
Esempio n. 3
0
 def msg_decrypt(self, xml: Union[bytes, str], timestamp: str, nonce: str,
                 msg_sign: str) -> dict:
     """消息体验证和解密"""
     encrypted_msg = xmltodict.parse(xml)['xml']['Encrypt']
     if msg_sign != self._gen_msg_sign(encrypted_msg, timestamp, nonce):
         raise RuntimeError('消息体签名验证失败')
     cipher = AES.new(self.aes_key, self.aes_mode, iv=self.aes_iv)
     cipher_data = b64decode(encrypted_msg)
     text = cipher.decrypt(cipher_data)
     pad_len = text[-1]
     _, msg_len, content = text[:16], text[16:20], text[20:-pad_len]
     msg_len = socket.ntohl(struct.unpack('I', msg_len)[0])
     msg, app_id = content[:msg_len], content[msg_len:]
     if to_str(app_id) != self.app_id:
         raise RuntimeError('消息体尾部AppId验证失败')
     return xmltodict.parse(msg)['xml']
Esempio n. 4
0
 def get_access_token(self) -> str:
     """获取接口调用凭据"""
     key = 'component:{0}:access_token'.format(self.app_id)
     value = redis_client.get(key)
     if value:
         return to_str(value)
     url = 'https://api.weixin.qq.com/cgi-bin/component/api_component_token'
     body = {
         'component_appid': self.app_id,
         'component_appsecret': self.app_secret,
         'component_verify_ticket': self.verify_ticket
     }
     ret = requests.post(url, json=body).json()
     access_token, expires_in = map(
         ret.get, ['component_access_token', 'expires_in'])
     if not (access_token and expires_in):
         raise RuntimeError(repr(ret))
     redis_client.set(key, access_token,
                      ex=int(expires_in) - 300)  # 提前5分钟更新access_token
     return access_token
Esempio n. 5
0
 def msg_encrypt(self, msg_data: dict) -> str:
     """消息体加密"""
     cipher = AES.new(self.aes_key, self.aes_mode, iv=self.aes_iv)
     msg = to_bytes(xmltodict.unparse(msg_data, full_document=False))
     text = to_bytes(gen_random_str(16)) + struct.pack(
         'I', socket.htonl(len(msg))) + msg + to_bytes(self.app_id)
     pad_len = self.aes_block_size - len(text) % self.aes_block_size
     text += bytes([pad_len] * pad_len)
     cipher_data = cipher.encrypt(text)
     encrypted_msg = to_str(b64encode(cipher_data))
     timestamp = str(int(time()))
     nonce = gen_random_str(16)
     msg_sign = self._gen_msg_sign(encrypted_msg, timestamp, nonce)
     data = {
         'xml': {
             'Encrypt': encrypted_msg,
             'MsgSignature': msg_sign,
             'TimeStamp': timestamp,
             'Nonce': nonce
         }
     }
     return xmltodict.unparse(data, full_document=False)
Esempio n. 6
0
 def verify_ticket(self) -> Optional[str]:
     return to_str(redis_client.get(self._ticket_key()))