def get_code(self): args = request.args.to_dict() code = args.get('code') state = args.get('state') print code, state login = WeixinLogin(APP_ID, APP_SECRET) data = login.access_token(code) openid = data.openid update = {} update['openid'] = openid state_list = str(state).split('$$$') self.suser.update_user_by_state(state_list[0], update) # response = import_status("get_openid_success", "OK") return flask.redirect(state_list[1])
class WxPay(http.Controller): def __init__(self): self.app_id = config.APPID self.app_secret = config.APP_SECRTET self.mch_id = config.MCH_ID self.mch_key = config.MCH_KEY # url处理 self.encodeURL = config.ENCODE_URL # self.URL = config.URL self.base_url = config.BASE_URL self.notify_url = config.WEIXIN_NOTIFY_URL # 初始化 self.wx_login = WeixinLogin(self.app_id, self.app_secret) self.wx_pay = WeixinPay(self.app_id, self.mch_id, self.mch_key, self.notify_url) @http.route("/odoo/login/<param>", auth="public", website=True) def login(self, param, **kwargs): """ 微信获取code :param param: 传入参数名(非字典、列表) :return: """ redirect_url = self.base_url + param openid = request.httprequest.cookies.get("openid") next = request.httprequest.args.get("next") or redirect_url if openid: return request.redirect(next) # callback = url_for("authorized", next=next, _external=True) callback = self.encodeURL + "?next=" + next url = self.wx_login.authorize( callback, "snsapi_base") # 引导用户跳转到授权页面,callback = redirect_uri return request.redirect(url) @http.route("/odoo/authorized", auth="public", website=True) def authorized(self, **kwargs): """ 微信验证获取openid :return: """ code = request.httprequest.args.get("code") if not code: return "ERR_INVALID_CODE", 400 next = request.httprequest.args.get("next") data = self.wx_login.access_token(code) # 通过code换取网页授权access_token openid = data.openid resp = request.redirect(next) expires = datetime.now() + timedelta(days=1) resp.set_cookie("openid", openid, expires=expires) return resp @http.route("/odoo/pay/create", type="json", auth="public", website=True) def pay_create(self, **kwargs): """ 微信JSAPI创建统一订单,并且生成参数给JS调用 必填参数: out_trade_no 商户订单号 body 商品描述 total_fee 商品描述 openid 用户标识 """ # 网页端调起支付API try: remote_addr = request.httprequest.environ[ 'REMOTE_ADDR'] # 获取远程客户端IP openid = request.httprequest.cookies.get("openid") out_trade_no = self.wx_pay.nonce_str # 商户订单号设定为随机字符串 raw = self.wx_pay.jsapi(openid=openid, body=u"测试", out_trade_no=out_trade_no, total_fee=1, spbill_create_ip=remote_addr) # 外部传入openid return json.dumps(raw) # 直接返回包含Json格式数据响应的方法 except WeixinPayError as e: print(e.message) return e.message, 400 @http.route("/odoo/pay/notify", auth="public", website=True) def pay_notify(self, **kwargs): """ 微信异步通知 """ data = self.wx_pay.to_dict(request.data) if not self.wx_pay.check(data): return self.wx_pay.reply("签名验证失败", False) return self.wx_pay.reply("OK", True) # 处理业务逻辑
def wx_auth(request, app_name): try: app = WxApp.objects.get(name=app_name) request.session['wx_app_name'] = app.name request.session['wx_app_id'] = app.app_id except ObjectDoesNotExist: raise Http404 code = request.GET.get("code", None) if code is None: return HttpResponse('No Code Provided.') wx_login = WeixinLogin(app.app_id, app.app_secret) data = wx_login.access_token(code) openid = data.openid request.session['wx_openid'] = openid scope = data.scope token = data.access_token # 网页授权access_token和公众号的access_token不一样 # 关于网页授权access_token和普通access_token的区别 # 1、微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息; # 2、其他微信接口,需要通过基础支持中的“获取access_token”接口来获取到的普通access_token调用。 if (scope == conf.SCOPE_USERINFO): # continue to get userinfo userinfo = wx_login.user_info(token, openid) wx_user = WxUser.objects.filter(openid=openid).first() or WxUser() # update user info wx_user.openid = openid wx_user.nickname = userinfo.nickname wx_user.headimg_url = userinfo.headimgurl wx_user.sex = userinfo.sex wx_user.province = userinfo.province wx_user.city = userinfo.city wx_user.country = userinfo.country wx_user.unionid = userinfo.get('unionid', None) wx_user.privilege = json.dumps(userinfo.privilege) wx_user.language = userinfo.language # 关于UnionID机制 # 1、请注意,网页授权获取用户基本信息也遵循UnionID机制。即如果开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。 # 2、UnionID机制的作用说明:如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号),unionid是相同的。 if not wx_user.auth_user: user, created = AuthUser.objects.get_or_create( type=AuthUser.WEIXIN, mobile=wx_user.openid) if created or getattr(user, 'customer', None): customer = Customer(name=wx_user.nickname) customer.auth_user = user wx_user.auth_user = user wx_user.save() user.backend = 'django.contrib.auth.backends.ModelBackend' login(request, user) state = request.GET.get('state', None) # next url if state: url = urlunquote(state) else: url = reverse('weixin:index', args=[app_name]) return HttpResponseRedirect(url)
def wx_auth(request): code = request.GET.get("code", None) if code is None: return HttpResponse('No Code Provided.') wx_login = WeixinLogin(conf.APP_ID, conf.APP_SECRET) data = wx_login.access_token(code) openid = data.openid scope = data.scope token = data.access_token # 网页授权access_token和公众号的access_token不一样 # 关于网页授权access_token和普通access_token的区别 # 1、微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息; # 2、其他微信接口,需要通过基础支持中的“获取access_token”接口来获取到的普通access_token调用。 wx_user, created = WxUser.objects.get_or_create(openid=openid) if created or wx_user.need_update(): # continue to get userinfo userinfo = wx_login.user_info(token, openid) wx_user = WxUser.objects.filter(openid=openid).first() or WxUser() # update user info wx_user.openid = openid nickname = userinfo.nickname nickname = ''.join(c for c in unicodedata.normalize('NFC', nickname) if c <= '\uFFFF') # remove emoji wx_user.nickname = nickname wx_user.headimg_url = userinfo.headimgurl wx_user.sex = userinfo.sex wx_user.province = userinfo.province wx_user.city = userinfo.city wx_user.country = userinfo.country wx_user.unionid = userinfo.get('unionid', '') wx_user.privilege = json.dumps(userinfo.privilege) wx_user.language = userinfo.language wx_user.save() # 关于UnionID机制 # 1、请注意,网页授权获取用户基本信息也遵循UnionID机制。即如果开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。 # 2、UnionID机制的作用说明:如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号),unionid是相同的。 user = wx_user.auth_user if not user: user = AuthUser.objects.filter(username=wx_user.openid).first() if not user: user = AuthUser.objects.create_user(username=wx_user.openid, password=wx_user.openid) wx_user.auth_user = user wx_user.save() user.backend = 'django.contrib.auth.backends.ModelBackend' login(request, user) request.session['wx_openid'] = openid state = request.GET.get('state', None) if state: url = urlunquote(state) else: url = reverse('weixin:index') return HttpResponseRedirect(url)
def weixin_callback(self): """回调, 通过code, 获取用户信息""" try: args = request.args.to_dict() code = args.get('code') state = args.get('url') # state = state.replace('$', '#').replace('~', '?').replace('+', '=') wxlogin = WeixinLogin(APP_ID, APP_SECRET_KEY) data = wxlogin.access_token(code) # 这是本人的openid openid = data.openid access_token = data.access_token user = self.suser.get_user_by_openid(openid) # 是否关注 todo wx_subscribe = self.get_wx_response( get_subscribe.format(access_token, openid), "get subscribe") generic_log(wx_subscribe) # if "subscribe" not in wx_subscribe: # logger.error("get subscribe error %s", wx_subscribe) # raise WeixinError(u'get subscribe error') # wx_subscribe = dict() subscribe = wx_subscribe.get("subscribe", 0) data = wxlogin.user_info(data.access_token, data.openid) head = self.get_local_head(data.get('headimgurl'), openid) if not user: # 新用户 # 这是上级openid, 而非本人openid, 根据openid获取上级身份 upper_list = re.findall(r'openid=(.*?)&?', state) upper = upper_list[0] if upper_list else None upperd = self.suser.get_user_by_openid(upper) if upperd: # todo 记录邀请成功时间(如果活动进行中的话 upperd_id = upperd.USid else: upperd_id = None # 添加用户 usid = str(uuid.uuid1()) self.suser.add_model( "User", **{ "USid": usid, "openid": openid, "USlastlogin": datetime.datetime.now().strftime(format_for_db), "USheader": head, "USlevel": 0, "USgender": data.get('sex'), "USname": data.get('nickname'), "UPPerd": upperd_id, "unionid": data.get('openid'), "subscribe": subscribe, }) else: # 老用户 usid = user.USid print(usid) update_dict = { "USlastlogin": datetime.datetime.now().strftime(format_for_db), "USheader": head, "USgender": data.get("sex"), "USname": data.get("nickname"), "unionid": data.get("unionid"), "subscribe": subscribe, } update_result = self.suser.update_user(usid, update_dict) if not update_result: raise SYSTEM_ERROR() # 生成token token = usid_to_token(usid) userlogintime = self.suser.get_user_login_time(usid) now = datetime.datetime.now().strftime(format_for_db) is_today_first = True if userlogintime: is_today_first = bool( userlogintime.USTcreatetime[:-6] < now[:-6]) self.suser.add_model( "UserLoginTime", **{ "ULTid": str(uuid.uuid1()), "USid": usid, "USTip": request.remote_addr, "USTcreatetime": now, }) params_data = { "is_first": int(bool(user)), "subscribe": subscribe, "newtoken": token, "openid": openid, "access_token": access_token, "wximg": wximg, 'user_level': 0 if bool(user) else user.USlevel, "is_today_first": int(is_today_first), "token": usid_to_token(usid), "icon": icon } # params_str = urllib.urlencode(params_data, doseq=True) # redirect_url = state + "?"+params_str # logger.debug("get loggin redirect_url %s", redirect_url) # return redirect(redirect_url) return params_data except WeixinError as e: generic_log(e) return SYSTEM_ERROR(u'code error')
def get_accesstoken(self): args = request.args.to_dict() logger.info("args", args) true_params = ["code"] for key in true_params: if key not in args: return PARAMS_MISS # from WeiDian.config.urlconfig import get_access_toke, get_user_info, get_subscribe # 获取access_token openid # request_url = get_access_toke.format(APP_ID, APP_SECRET_KEY, args["code"]) # strResult = None # try: # # req = urllib2.Request(request_url) # response = urllib2.urlopen(req) # strResult = response.read() # response.close() # logger.debug(strResult) # except Exception as e: # print(e) # return NETWORK_ERROR # jsonResult = self.get_wx_response(request_url, "get access_token") # if "access_token" not in jsonResult or "openid" not in jsonResult: # logger.error("get access token and openid error %s", jsonResult) # return jsonResult # access_token = jsonResult["access_token"] # openid = jsonResult['openid'] wxlogin = WeixinLogin(APP_ID, APP_SECRET_KEY) try: data = wxlogin.access_token(args["code"]) except WeixinLoginError as e: logger.error('login error %s', e.message) return import_status('welcome', 'OK') openid = data.openid access_token = data.access_token logger.debug('get openid %s, access_token %s', openid, access_token) user = self.suser.get_user_by_openid(openid) is_first = not bool(user) print get_subscribe.format(mp.accesstoken(), openid) wx_subscribe = self.get_wx_response( get_subscribe.format(mp.accesstoken(), openid), "get subscribe") if "subscribe" not in wx_subscribe: logger.error("get subscribe error %s", wx_subscribe) # return wx_subscribe mp.update_access_token_and_jsticket(refresh=True) wx_subscribe = self.get_wx_response( get_subscribe.format(mp.accesstoken(), openid), "get subscribe retry") if "subscribe" not in wx_subscribe: logger.error("get subscribe retry error %s", wx_subscribe) return wx_subscribe subscribe = wx_subscribe.get("subscribe", 0) # user_info = self.get_wx_response(get_user_info.format(access_token, openid), "get user info") # if "errcode" in user_info or "errmsg" in user_info: # response = import_status("get_user_info_error", "WD_ERROR", "error_get_user_info") # response['data'] = user_info # return response user_info = wxlogin.userinfo(access_token, openid) upperd = self.suser.get_user_by_openid(args.get("UPPerd", "")) upperd_id = upperd.USid if upperd else None user_level = 0 if is_first else user.USlevel ushead = self.get_local_head(user_info.get("headimgurl"), openid) if is_first: usid = str(uuid.uuid1()) self.suser.add_model( "User", **{ "USid": usid, "openid": openid, "USlastlogin": datetime.datetime.now().strftime(format_for_db), "USheader": user_info.get("headimgurl"), "USlevel": 0, "USgender": user_info.get("sex"), "USname": user_info.get("nickname"), "UPPerd": upperd_id, "unionid": user_info.get("unionid"), "accesstoken": access_token, "subscribe": subscribe, }) # self.smycenter.add_model("MyCenter", **{ # "MYid": str(uuid.uuid1()), # "USid": usid, # "MYranking": '0', # "MYrewards": '0' # }) tasl_level = self.stask.get_tasklevel_by_level(1) task_list = self.stask.get_task_by_tlid(tasl_level.TLid) for task in task_list: self.suser.add_model( "TaskUser", **{ "TUid": str(uuid.uuid1()), "USid": usid, "TAid": task.TAid, "TUstatus": 0, "TUnumber": 0 }) else: usid = user.USid update_result = self.suser.update_user( usid, { "USlastlogin": datetime.datetime.now().strftime(format_for_db), "USheader": ushead, "USgender": user_info.get("sex"), "USname": user_info.get("nickname"), "unionid": user_info.get("unionid"), "accesstoken": access_token, "subscribe": subscribe, }) if not update_result: return SYSTEM_ERROR userlogintime = self.suser.get_user_login_time(usid) now = datetime.datetime.now().strftime(format_for_db) is_today_first = True if userlogintime: is_today_first = bool(userlogintime.USTcreatetime[:-6] < now[:-6]) self.suser.add_model( "UserLoginTime", **{ "ULTid": str(uuid.uuid1()), "USid": usid, "USTip": request.remote_addr, "USTcreatetime": now, }) response = import_status("SUCCESS_GET_OPENID", "OK") # from WeiDian.config.enums import icon response["data"] = { "is_first": int(is_first), "subscribe": subscribe, "openid": openid, "access_token": access_token, "wximg": wximg, 'user_level': user_level, "is_today_first": int(is_today_first), "token": usid_to_token(usid), "icon": icon } logger.debug("get loggin response %s", response) return response