摘要:借著這個需求體會了下微信開發的兩種不同類型非端口的兩種開發,以及的一些正確姿勢。關于用戶微信登錄的事情我們通過已經解決了參考我的上一篇博客微信公眾號開發小記接入三方登錄,所以可以直接用的裝飾器完成這種事情。
描述
假設的我們的服務號有這么一些功能,比如底部有按鈕,點擊會有一些復雜的功能,這時候可能就需要一個用戶系統,有用戶系統就經常想要做什么分享邀請新用戶之類的,這時候就又有幾種方式,1.直接一個連接,讓其他用戶點;2.有一個二維碼,讓離得近的朋友掃。
借著這個需求體會了下微信開發的兩種不同類型(80非80端口的兩種開發),以及python-social-auth的一些正確姿勢。
而這個需求其實就對應了兩種開發模式,比如有個需求可以在公眾號內直接回復,或者在一個頁面里面讓用戶提交表單等等。
首先,理解需求:用戶在微信點擊我們的邀請連接后,會引導用戶做一個有綠色按鈕的微信登錄,用戶登陸后成為我們的用戶,并且跳轉到某個頁面。
關于用戶微信登錄的事情我們通過python-social-auth已經解決了(參考我的上一篇博客微信公眾號開發小記——3.接入三方登錄),所以可以直接用django的login_required裝飾器完成這種事情。
由于微信號的登錄只有微信,所以LOGIN_URL = "/login/weixinapp/"
class InviteUserView(View): """邀請注冊""" @method_decorator(login_required) def get(self, request): return HttpResponseRedirect(reverse("myauth:personal-center"))
上面的代碼只是保證用戶點解邀請鏈接會成為我們的用戶,但是沒有記錄對應的邀請者信息等等,由于邀請這個事情其實是一個登錄的流程,所以可以寫在pipeline里面
def invite_user(backend, user, response, *args, **kwargs): is_new = kwargs["is_new"] if not is_new or not user: return # 二維碼掃描 ... # 點擊邀請鏈接 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}通過掃碼邀請
首先,掃碼是一個服務號80端口的事件,所以代碼添加在weixin_server/views.py 微信公眾號開發小記——2.80端口上的服務
難點在于這里,微信掃碼后是直接進入公眾號的,如果你想要讓用戶進入公眾號之后就變成我們的用戶而不是讓他在點一個東西這里是比較蛋疼的,因為你的服務器在這時候做302微信是不認得。這就導致了幾個問題:
由于不引導用戶登錄,我這里沒辦法直接用python-social-auth里面的do_complete方法(因為拿不到用戶的access_token),不過好處是使用微信服務器的access_token以及用戶的openid我可以直接拿到這個用戶的用戶信息。這個問題就變成了python-social-auth的do_complete有用戶response后執行pipeline的邏輯了。
然后我扒了下代碼,用了幾個小時從單測里面找到了這個邏輯,具體見handle_invite_scan,這段代碼才是這篇博客里面難度最大的東西
def weixin_handler_event_scan(self, request, parsed_wechat, *args, **kwargs): key = parsed_wechat.message.key # 對應生成二維碼的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"感謝您的加入,邀請者是 {}".format(user._inviter.username) response_xml = parsed_wechat.response_text(content=content) return HttpResponse(response_xml, content_type="application/xml")
然后就可以正常的執行了,由于二維碼的機制跟url不同,所以需要多帶帶的二維碼處理邏輯
下面先把pipeline的那段代碼貼過來,這里沒什么特殊的
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} ....微信二維碼
二維碼有兩種大的類型,永久二維碼、臨時二維碼,永久上線10萬張,scenen_id為1~10萬,然而他又有scenen_str這種字符串的形式,那肯定選第二種字符串了;臨時二維碼則scenen_id為1~2^10,這點需要注意,超過這個限制secen_id都是2^10-1,而且蛋疼的是,臨時二維碼會有過期時間需要維護這個二維碼。為了方便我們的業務邏輯查詢,我添加了一個action_type的字段,來做業務上的區別,方便查詢。
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時上限為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) # 臨時二維碼判斷是否過期 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 # 臨時二維碼判斷是否過期 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
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/45431.html
摘要:微信在做一些操作是需要用到生成二維碼等而每天接口的調用上限為,需要自己做緩存文檔講了幾種方式,我覺得放在中拿比較妥當。微信菜單會緩存分鐘,你可以取消關注,然后在關注查看菜單變化效果。 描述 微信公眾號開發基本分為2大種類型 1.用戶直接做了某些操作(回復信息、訂閱、掃碼、發語音、點按鈕等),此時這些信息微信會發送到微信服務器的80端口,這是一種開發類型;2.通過連接(按鈕、文章)引導用...
摘要:在現如今的游戲市場寒冬中,擁有微信龐大的用戶量以及更好兼容性的小程序游戲,優勢就顯得格外明顯。掃描二維碼即可報名您在現場將有這些體驗來自騰訊云云開發團隊與微信團隊聯合打造干貨分享,內容包括微信小游戲首發經驗分享。 有人說微信小程序游戲的百花齊放 活像十幾年前的4399小游戲稱霸互聯網的景象 歪,斗地主嗎,三缺二, 不用下app,小程序就能玩,我保證不搶地主讓你搶! ...... ‘...
摘要:本文是淺析微信支付系列文章的第十五篇,主要講解如何開通免充值產品功能流程和其中的注意事項,對于接口升級會重要講解,避免爬坑。 本文是【淺析微信支付】系列文章的第十五篇,主要講解如何開通免充值產品功能流程和其中的注意事項,對于接口升級會重要講解,避免爬坑。 淺析微信支付系列已經更新十五篇了喲~,沒有看過的朋友們可以看一下哦。 淺析微信支付:商戶平臺代金券或立減優惠開通、指定用戶代金券發...
摘要:函數節流用途如調整瀏覽器大小,或者用戶輸入信息,導致反復提交接口調用方法判斷手機端訪問獲取地址欄參數返回頂部當滾動條的位置處于距頂部像素以下時,跳轉鏈接出現,否則消失當點擊跳轉鏈接后,回到頁面頂部位置正則檢測手機號郵箱 1.JavaScript 函數節流用途:如調整瀏覽器大小,或者用戶輸入信息,導致反復提交接口 function throttle(method,context) { ...
摘要:特點,永久免費,數據中心多達個,之前好用的首爾和東京因為眾多的涌入導致線路擁堵不堪此外機型可自由分配個,內存,最大空間容量和的帶寬。是烏克蘭官方為個人提供的免費二級域名后綴,任何人都可以申請。由烏克蘭官方運行,穩定性有保障。作為一個mjj,最喜歡做的事情就是薅羊毛,這篇文章就來整理一些特別優質的,不容錯過的羊毛!算是薅羊毛的一個指南!! 一:永久VPS篇 這里整理一些永久...
閱讀 1357·2021-11-24 09:39
閱讀 1346·2021-11-04 16:12
閱讀 2686·2021-09-24 09:47
閱讀 3337·2021-09-01 10:50
閱讀 1477·2019-08-30 15:55
閱讀 1423·2019-08-30 15:43
閱讀 642·2019-08-30 11:08
閱讀 3578·2019-08-23 18:33