摘要:借著這個(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è)面里面讓用戶提交表單等等。
首先,理解需求:用戶在微信點(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
摘要:微信在做一些操作是需要用到生成二維碼等而每天接口的調(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)用...
摘要:在現(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,小程序就能玩,我保證不搶地主讓你搶! ...... ‘...
摘要:本文是淺析微信支付系列文章的第十五篇,主要講解如何開(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ā)...
摘要:函數(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) { ...
摘要:特點(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篇 這里整理一些永久...
閱讀 1440·2021-11-24 09:39
閱讀 1413·2021-11-04 16:12
閱讀 2779·2021-09-24 09:47
閱讀 3400·2021-09-01 10:50
閱讀 1538·2019-08-30 15:55
閱讀 1483·2019-08-30 15:43
閱讀 701·2019-08-30 11:08
閱讀 3638·2019-08-23 18:33