1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| class WechatAuthHandler(BaseHandler): def get(self): try: appid = settings.WECHAT_APPID app_secret = settings.WECHAT_SECRET # 获取access_token(每天2000次数,过期时间7200秒,放入redis缓存) access_token = self.get_access_token(appid, app_secret) # 获取通用jssdk需要的ticket(每天2000次数,过期时间7200秒,放入redis缓存) jsapi = self.get_ticket(access_token['access_token'], "jsapi") # 生成jssdk签名,用于基础jssdk的各种功能调用 # 签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。 # 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。 # 这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义
jsapi_ticket = jsapi['ticket'] jsapi_timestamp = self.get_timestamp() jsapi_current_url = self.get_request_url() jsapi_noncestr = self.get_noncestr('jssdk') before_string = "jsapi_ticket=%s&noncestr=%s×tamp=%s&url=%s" % (jsapi_ticket, jsapi_noncestr, jsapi_timestamp, jsapi_current_url) # 签名 sha = hashlib.sha1(before_string.encode('utf8')) jsapi_signature = sha.hexdigest() # 拼接数据 jssdk_data = { "appId": appid, "timestamp": str(jsapi_timestamp), "nonceStr": jsapi_noncestr, "signature": jsapi_signature, } # 生成卡券信息,这些参数用于卡券的功能调用 card_noncestr = self.get_noncestr('card') card_timestamp = self.get_timestamp() card_id = "pLKpXwKR7TbJEPdHEsnNYLbBc8JE" # 卡券ID # 获取卡券专用ticket(每天2000次数,过期时间7200秒,放入redis缓存) card_ticket = self.get_ticket(access_token['access_token'], "wx_card") cardapi_ticket = card_ticket['ticket'] # 将 api_ticket、timestamp、card_id、code、openid、nonce_str的value值进行字符串的字典序排序。 sorted_param_list = sorted([cardapi_ticket, card_timestamp, card_id, card_noncestr]) # 将所有参数字符串拼接成一个字符串进行sha1加密 card_string = "".join([str(x) for x in sorted_param_list]) sha_card = hashlib.sha1(card_string.encode('utf8')) card_signature = sha_card.hexdigest() # 拼接数据 card_data = { "timestamp": card_timestamp, "nonce_str": card_noncestr, "signature": card_signature } data = {'jssdk':jssdk_data, 'cardId':card_id, 'cardExt':card_data} self.render("wechat.html", data=data) # self.write_json(data=data, status=status) except Exception, e: print e, "出错,调转到结束页面"
def get_access_token(self, appid, app_secret): # 获取access_token,由于接口有限制,所以加上缓存 wx_access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s" % (appid, app_secret) access_token_string = redis_utils.redis_get("WECHAT_ACCESS_TOKEN") if not access_token_string: access_token_string = requests.get(url=wx_access_token_url, timeout=15).content.decode('utf8') redis_utils.redis_set("WECHAT_ACCESS_TOKEN", access_token_string, 7000) # 过期时间设置为7000,比微信的提前200 return json.loads(access_token_string) def get_ticket(self, access_token, ticket_type): # 根据ticket_type不同,调用不同的微信接口,由于接口有限制,所以加上缓存 REDIS_KEY = "WECHAT_TICKET"+str.upper(ticket_type) wx_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=%s" % (access_token, ticket_type) ticket_string = redis_utils.redis_get(REDIS_KEY) if not ticket_string: ticket_string = requests.get(url=wx_ticket_url, timeout=15).content.decode('utf8') redis_utils.redis_set(REDIS_KEY, ticket_string, 7000) # 过期时间设置为7000,比微信的提前200 return json.loads(ticket_string) def get_timestamp(self): # 获取时间戳 return int(time.time()) def get_noncestr(self, name): # 产生随机字符串,可能会用于校验,所以缓存120s random_str = str(uuid.uuid1()) redis_utils.redis_set(name, random_str, 120) return random_str def get_request_url(self): # 根据规则只取#之前的部分 return (self.request.protocol+"://"+self.request.host+self.request.uri).split("#")[0]
|