Example #1
0
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)
Example #2
0
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)
Example #3
0
    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')