亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

微信公眾號(hào)開(kāi)發(fā)小記——4.兩種邀請(qǐng)用戶的方式 掃碼&&鏈接

BDEEFE / 1154人閱讀

摘要:借著這個(gè)需求體會(huì)了下微信開(kāi)發(fā)的兩種不同類(lèi)型非端口的兩種開(kāi)發(fā),以及的一些正確姿勢(shì)。關(guān)于用戶微信登錄的事情我們通過(guò)已經(jīng)解決了參考我的上一篇博客微信公眾號(hào)開(kāi)發(fā)小記接入三方登錄,所以可以直接用的裝飾器完成這種事情。

描述

假設(shè)的我們的服務(wù)號(hào)有這么一些功能,比如底部有按鈕,點(diǎn)擊會(huì)有一些復(fù)雜的功能,這時(shí)候可能就需要一個(gè)用戶系統(tǒng),有用戶系統(tǒng)就經(jīng)常想要做什么分享邀請(qǐng)新用戶之類(lèi)的,這時(shí)候就又有幾種方式,1.直接一個(gè)連接,讓其他用戶點(diǎn);2.有一個(gè)二維碼,讓離得近的朋友掃。

借著這個(gè)需求體會(huì)了下微信開(kāi)發(fā)的兩種不同類(lèi)型(80非80端口的兩種開(kāi)發(fā)),以及python-social-auth的一些正確姿勢(shì)。

而這個(gè)需求其實(shí)就對(duì)應(yīng)了兩種開(kāi)發(fā)模式,比如有個(gè)需求可以在公眾號(hào)內(nèi)直接回復(fù),或者在一個(gè)頁(yè)面里面讓用戶提交表單等等。


通過(guò)連接邀請(qǐng)

首先,理解需求:用戶在微信點(diǎn)擊我們的邀請(qǐng)連接后,會(huì)引導(dǎo)用戶做一個(gè)有綠色按鈕的微信登錄,用戶登陸后成為我們的用戶,并且跳轉(zhuǎn)到某個(gè)頁(yè)面。

關(guān)于用戶微信登錄的事情我們通過(guò)python-social-auth已經(jīng)解決了(參考我的上一篇博客微信公眾號(hào)開(kāi)發(fā)小記——3.接入三方登錄),所以可以直接用django的login_required裝飾器完成這種事情。

由于微信號(hào)的登錄只有微信,所以LOGIN_URL = "/login/weixinapp/"

class InviteUserView(View):
    """邀請(qǐng)注冊(cè)"""

    @method_decorator(login_required)
    def get(self, request):
        return HttpResponseRedirect(reverse("myauth:personal-center"))
        
        

上面的代碼只是保證用戶點(diǎn)解邀請(qǐng)鏈接會(huì)成為我們的用戶,但是沒(méi)有記錄對(duì)應(yīng)的邀請(qǐng)者信息等等,由于邀請(qǐng)這個(gè)事情其實(shí)是一個(gè)登錄的流程,所以可以寫(xiě)在pipeline里面

def invite_user(backend, user, response, *args, **kwargs):
    is_new = kwargs["is_new"]
    if not is_new or not user:
        return
    # 二維碼掃描
    ...
    # 點(diǎn)擊邀請(qǐng)鏈接
    next_url = backend.strategy.session_get("next")
    if next_url:
        params = parse_url(next_url)["params"]
        inviter_id = params.get("inviter_id")
        if inviter_id and user:
            try:
                inviter = User.objects.get(id=inviter_id)
                UserInvite.invite_user(inviter_id, user, only_allow_invited_by_one_user=True)
            except:
                return
            user._inviter = inviter
        return {"inviter": inviter}
        
通過(guò)掃碼邀請(qǐng)

首先,掃碼是一個(gè)服務(wù)號(hào)80端口的事件,所以代碼添加在weixin_server/views.py 微信公眾號(hào)開(kāi)發(fā)小記——2.80端口上的服務(wù)

難點(diǎn)在于這里,微信掃碼后是直接進(jìn)入公眾號(hào)的,如果你想要讓用戶進(jìn)入公眾號(hào)之后就變成我們的用戶而不是讓他在點(diǎn)一個(gè)東西這里是比較蛋疼的,因?yàn)槟愕姆?wù)器在這時(shí)候做302微信是不認(rèn)得。這就導(dǎo)致了幾個(gè)問(wèn)題:

由于不引導(dǎo)用戶登錄,我這里沒(méi)辦法直接用python-social-auth里面的do_complete方法(因?yàn)槟貌坏接脩舻腶ccess_token),不過(guò)好處是使用微信服務(wù)器的access_token以及用戶的openid我可以直接拿到這個(gè)用戶的用戶信息。這個(gè)問(wèn)題就變成了python-social-auth的do_complete有用戶response后執(zhí)行pipeline的邏輯了。

然后我扒了下代碼,用了幾個(gè)小時(shí)從單測(cè)里面找到了這個(gè)邏輯,具體見(jiàn)handle_invite_scan這段代碼才是這篇博客里面難度最大的東西

def weixin_handler_event_scan(self, request, parsed_wechat, *args, **kwargs):
    key = parsed_wechat.message.key # 對(duì)應(yīng)生成二維碼的key
    ticket = parsed_wechat.message.ticket
    if ticket:
        response = self.handle_invite_scan(request, parsed_wechat, key)
        if response:
            return response
    return self.weixin_handler_event(
            request, parsed_wechat, *args, **kwargs)
            
def handle_invite_scan(self, request, parsed_wechat, scene_id):
    try:
        qrcode = QRCode.objects.get(scene_id=scene_id, action_type="invite_user")
    except QRCode.DoesNotExist:
        return
    openid = parsed_wechat.message.source
    user_info = parsed_wechat.get_user_info(openid)
    strategy = load_strategy(request)
    backend = WeixinOAuth2APP()
    backend.strategy = strategy
    idx, backend, xargs, xkwargs = strategy.partial_from_session(
        {
            "next":0,
            "backend": backend,
            "args":[],
            "kwargs":{"qrcode": qrcode},
        }
    )
    xkwargs.update({"response": user_info})
    user = backend.continue_pipeline(pipeline_index=idx, *xargs, **xkwargs)
            if not user:
        return
    if user.is_new and hasattr(user, "_inviter"):
        content = u"感謝您的加入,邀請(qǐng)者是 {}".format(user._inviter.username)
        response_xml = parsed_wechat.response_text(content=content)
        return HttpResponse(response_xml, content_type="application/xml")
        

然后就可以正常的執(zhí)行了,由于二維碼的機(jī)制跟url不同,所以需要多帶帶的二維碼處理邏輯

下面先把pipeline的那段代碼貼過(guò)來(lái),這里沒(méi)什么特殊的

def invite_user(backend, user, response, *args, **kwargs):
    is_new = kwargs["is_new"]
    if not is_new or not user:
        return
    # 二維碼掃描
    qrcode = kwargs.get("qrcode")
    if qrcode and qrcode.userprofile_set.all().exists():
        inviter = qrcode.userprofile_set.all()[0].user
        try:
            UserInvite.invite_user(inviter.id, user, only_allow_invited_by_one_user=True)
        except:
            return
        user._inviter = inviter
        return {"inviter": inviter}
    ....
微信二維碼

二維碼有兩種大的類(lèi)型,永久二維碼、臨時(shí)二維碼,永久上線10萬(wàn)張,scenen_id為1~10萬(wàn),然而他又有scenen_str這種字符串的形式,那肯定選第二種字符串了;臨時(shí)二維碼則scenen_id為1~2^10,這點(diǎn)需要注意,超過(guò)這個(gè)限制secen_id都是2^10-1,而且蛋疼的是,臨時(shí)二維碼會(huì)有過(guò)期時(shí)間需要維護(hù)這個(gè)二維碼。為了方便我們的業(yè)務(wù)邏輯查詢,我添加了一個(gè)action_type的字段,來(lái)做業(yè)務(wù)上的區(qū)別,方便查詢。

class QRCode(models.Model):

    TEMP_QRCODE_UPDATE_DAYS = 7

    QR_SCENE = "QR_SCENE"
    QR_LIMIT_SCENE = "QR_LIMIT_SCENE"
    QR_LIMIT_STR_SCENE = "QR_LIMIT_STR_SCENE"
    ACTION_NAME_CHOICES = (
        (QR_SCENE, QR_SCENE),
        (QR_LIMIT_SCENE, QR_LIMIT_SCENE),
        (QR_LIMIT_STR_SCENE, QR_LIMIT_STR_SCENE),
    )
    url = models.URLField(blank=True, max_length=255, default="")
    # QR_SCENE時(shí)上限為2**32
    scene_id = models.CharField(blank=True, max_length=255, db_index=True, default="")
    update_time = models.DateTimeField(blank=True, null=True)
    action_name = models.CharField(max_length=30,
            choices=ACTION_NAME_CHOICES, default=QR_SCENE, db_index=True)
    action_type = models.CharField(max_length=255, default="", db_index=True)

    @classmethod
    def get_qrcode(cls, action_name, scene_id, action_type=None):
        now = timezone.now()
        qrcode = None
        try:
            qrcode = cls.objects.get(action_name=action_name, scene_id=scene_id)
            # 臨時(shí)二維碼判斷是否過(guò)期
            if qrcode.action_name == cls.QR_SCENE:
                if qrcode.update_time and qrcode.url:
                    _delta = now - qrcode.update_time
                    if _delta.days < qrcode.TEMP_QRCODE_UPDATE_DAYS:
                        return qrcode
            else:
                return qrcode
        except cls.DoesNotExist:
            pass
        if not qrcode:
            qrcode = cls(
                    action_name=action_name,
                    scene_id=scene_id,
                    action_type=action_type)
        qrcode.update_time = now
        if action_name == cls.QR_SCENE:
            qrcode.url = create_temp_qrcode(scene_id)
        else:
            qrcode.url = create_permanent_qrcode(scene_id)
        qrcode.save()
        return qrcode

    @classmethod
    def generate_temp_scene_id(cls, obj_id):
        """max id: 2 ** 32 = 4294967296"""
        return int("{}{}{}".format(randint(1, 3), obj_id, uuid4().int)[:9])

    @property
    def qrcode_url(self):
        if not self.action_name or not self.scene_id:
            raise Exception(u"qrcode object must have action_name and scene_id value")
        now = timezone.now()
        # 永久化的二維碼不必更新
        if self.action_name != self.QR_SCENE:
            if not self.url:
                self.update_time = now
                self.url = create_permanent_qrcode(self.scene_id)
                self.save()
            return self.url
        # 臨時(shí)二維碼判斷是否過(guò)期
        if self.update_time and self.url:
            _delta = now - self.update_time
            if _delta.days < self.TEMP_QRCODE_UPDATE_DAYS:
                return self.url
        self.update_time = now
        self.url = create_temp_qrcode(self.scene_id)
        self.save()
        return self.url

       

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/45431.html

相關(guān)文章

  • 微信公眾號(hào)開(kāi)發(fā)小記——2.80端口上服務(wù)

    摘要:微信在做一些操作是需要用到生成二維碼等而每天接口的調(diào)用上限為,需要自己做緩存文檔講了幾種方式,我覺(jué)得放在中拿比較妥當(dāng)。微信菜單會(huì)緩存分鐘,你可以取消關(guān)注,然后在關(guān)注查看菜單變化效果。 描述 微信公眾號(hào)開(kāi)發(fā)基本分為2大種類(lèi)型 1.用戶直接做了某些操作(回復(fù)信息、訂閱、掃碼、發(fā)語(yǔ)音、點(diǎn)按鈕等),此時(shí)這些信息微信會(huì)發(fā)送到微信服務(wù)器的80端口,這是一種開(kāi)發(fā)類(lèi)型;2.通過(guò)連接(按鈕、文章)引導(dǎo)用...

    frank_fun 評(píng)論0 收藏0
  • 【沙龍報(bào)名中】與微信&amp;云開(kāi)發(fā)官方團(tuán)隊(duì)零距離互動(dòng),揭秘爆款微信小游戲背后技術(shù)!

    摘要:在現(xiàn)如今的游戲市場(chǎng)寒冬中,擁有微信龐大的用戶量以及更好兼容性的小程序游戲,優(yōu)勢(shì)就顯得格外明顯。掃描二維碼即可報(bào)名您在現(xiàn)場(chǎng)將有這些體驗(yàn)來(lái)自騰訊云云開(kāi)發(fā)團(tuán)隊(duì)與微信團(tuán)隊(duì)聯(lián)合打造干貨分享,內(nèi)容包括微信小游戲首發(fā)經(jīng)驗(yàn)分享。 有人說(shuō)微信小程序游戲的百花齊放 活像十幾年前的4399小游戲稱霸互聯(lián)網(wǎng)的景象 歪,斗地主嗎,三缺二, 不用下app,小程序就能玩,我保證不搶地主讓你搶! ...... ‘...

    zhonghanwen 評(píng)論0 收藏0
  • 淺析微信支付:開(kāi)通免充值產(chǎn)品功能及如何進(jìn)行接口升級(jí)指引

    摘要:本文是淺析微信支付系列文章的第十五篇,主要講解如何開(kāi)通免充值產(chǎn)品功能流程和其中的注意事項(xiàng),對(duì)于接口升級(jí)會(huì)重要講解,避免爬坑。 本文是【淺析微信支付】系列文章的第十五篇,主要講解如何開(kāi)通免充值產(chǎn)品功能流程和其中的注意事項(xiàng),對(duì)于接口升級(jí)會(huì)重要講解,避免爬坑。 淺析微信支付系列已經(jīng)更新十五篇了喲~,沒(méi)有看過(guò)的朋友們可以看一下哦。 淺析微信支付:商戶平臺(tái)代金券或立減優(yōu)惠開(kāi)通、指定用戶代金券發(fā)...

    NicolasHe 評(píng)論0 收藏0
  • JavaScript &amp; jQuery 常用方法小記

    摘要:函數(shù)節(jié)流用途如調(diào)整瀏覽器大小,或者用戶輸入信息,導(dǎo)致反復(fù)提交接口調(diào)用方法判斷手機(jī)端訪問(wèn)獲取地址欄參數(shù)返回頂部當(dāng)滾動(dòng)條的位置處于距頂部像素以下時(shí),跳轉(zhuǎn)鏈接出現(xiàn),否則消失當(dāng)點(diǎn)擊跳轉(zhuǎn)鏈接后,回到頁(yè)面頂部位置正則檢測(cè)手機(jī)號(hào)郵箱 1.JavaScript 函數(shù)節(jié)流用途:如調(diào)整瀏覽器大小,或者用戶輸入信息,導(dǎo)致反復(fù)提交接口 function throttle(method,context) { ...

    codeGoogle 評(píng)論0 收藏0
  • 捋一捋這些年一起薅過(guò)羊毛 &amp;#8211; 包含永久免費(fèi)vps、域名等

    摘要:特點(diǎn),永久免費(fèi),數(shù)據(jù)中心多達(dá)個(gè),之前好用的首爾和東京因?yàn)楸姸嗟挠咳雽?dǎo)致線路擁堵不堪此外機(jī)型可自由分配個(gè),內(nèi)存,最大空間容量和的帶寬。是烏克蘭官方為個(gè)人提供的免費(fèi)二級(jí)域名后綴,任何人都可以申請(qǐng)。由烏克蘭官方運(yùn)行,穩(wěn)定性有保障。作為一個(gè)mjj,最喜歡做的事情就是薅羊毛,這篇文章就來(lái)整理一些特別優(yōu)質(zhì)的,不容錯(cuò)過(guò)的羊毛!算是薅羊毛的一個(gè)指南?。? 一:永久VPS篇 這里整理一些永久...

    mrli2016 評(píng)論0 收藏1

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<