官方文档流程有点复杂,不过这个比较重要。只有通过授权获取用户openid,用户才能主动推送消息等功能。特别注意:这里必须要微信公众号(个人订阅号不能使用此功能)微信认证才能使用。另外,回调域名需要是https。现在有地方可以免费申请https证书。可以参考我的文章百度智能云免费SSL证书的应用与部署(nginxHTTPS配置,HTTP请求重定向)数据库(模型)创建一个字段保存用户的openid因为我们用户授权的目的是获取openid。得到openid后,必须存入数据库,并与用户建立对应关系。我用的是django自带的用户系统。官方推荐创建一个类似UserProfile的自定义Model来保存用户相关信息。从django.db导入模型从django.contrib.auth.models导入UserclassUserProfile(models.Model):user=models.OneToOneField(User,on_delete=models.CASCADE,null=True,default=None)openid=models.CharField("WeChatopenid",max_length=32)openid的长度好像是28位,这里定义的最大长度32应该够用了。参考跳转到用户授权页面。本页面为微信页面。我们需要添加参数让用户跳转到它。url为https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirectappid去公众号平台->开发->基本配置找到它.redirect_uri是成功后的回调地址,是自己的url,需要通过urlEncode对response_type进行编码,写codescope,可选snsapi_base或者snsapi_userinfostate可选,不要直接加这个参数。对于python的urlEncode,可以使用:importurllib。parses='https://xxx.com/api/weixin_bind_callback/'urllib.parse.quote(s)结果是:'https%3A//xxx.com/api/weixin_bind_callback/'它不处理斜杠,添加一个safe参数可以处理斜杠importurllib.parses='https://xxx.com/api/wexin_bind_callback/'urllib.parse.quote(s,safe='')结果是:'https%3A%2F%2Fxxx.com%2Fapi%2Fwexin_bind_callback%2F'我的url最终结果是:https://open.weixin.qq.com/connect/oauth2/authorize?appid=XXXX&redirect_uri=https%3A%2F%2FXXXX.com%2Fweixin%2Fbind%2Fcallback%2F&response_type=code&scope=snsapi_userinfo#wechat_redirect用户授权后,下面通过代码获取access_token的逻辑要写在用户访问上面url的回调页面中。请求url为:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_codeAPPID和secret去公众号平台->开发->基础配置。code是返回的codegrant_type,只写authorization_code这里需要用到http客户端库,比如python3的requests或者python2的urllib2,请求微信接口的例子python3:importrequestAPPID=''secret=''r=requests.get('https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code')请求结果为:{"access_token":"ACCESS_TOKEN","expires_in":7200,"refresh_token":"REFRESH_TOKEN","openid":"OPENID","scope":"SCOPE"}这时候需要再发起一次请求获取用户的信息。本次请求url:https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN返回结果为:{"openid":"OPENID","nickname":NICKNAME,"sex":"1","province":"PROVINCE","city":"CITY","country":"COUNTRY","headimgurl":"http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLxieJbHxeQbERQ46","privilege":["PRIVILEGE1""PRIVILEGE2"],"unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL"}最终查看为:defweixinbind_callback(request):code=request.GET.get('code')state=request.GET.get('state')#print(code,state)APPID='xxxxxx'secret='xxxxx'r=requests.get('https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code'%(APPID,secret,code))print(r.text)d=json.loads(r.text)#{#"access_token":"ACCESS_TOKEN",#"expires_in":7200,#"refresh_token":"REFRESH_TOKEN",#"openid":"OPENID",#"scope":"SCOPE"#}r=request.get('https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN'%(d['access_token'],d['openid']))#print(r.text)dd=json.load(r.text)#{#"openid":"OPENID",#"昵称":NICKNAME,#"性别":"1",#"省":"PROVINCE",#"城市":"CITY",#"国家":"COUNTRY",#"headimgurl":"http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",#"privilege":["PRIVILEGE1""PRIVILEGE2"],#"unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL"#}request.user.userprofile.openid=dd['openid']request.user.userprofile.nickname=dd['昵称']request.user.userprofile.wsex=dd['sex']request.user.userprofile.province=dd['省']request.user.userprofile.city=dd['城市']request.user.userprofile.country=dd['国家']request.user.userprofile.headimgurl=dd['headimgurl']request.user.userprofile.privilege=dd['特权']request.user.userprofile.unionid=dd['unionid']request.user.userprofile.save()returnHttpResponseRedirect('/weixin/')添加回调域名到公众号平台设置->公众号设置->功能设置->网页授权域名配置选项,添加刚才回调url的域名,里面有一个认证文件,他说的是该文件要发送到服务器,但是这个不是很方便django,你可以直接写一个view返回这个文件的内容就可以了,我直接放在urls文件里面。fromdjango.urlsimportpathfromdjango.httpimportHttpResponsedefweixin_verify(request):returnHttpResponse('PJRLUusp1NXyuD70')urlpatterns=[#微信开发path('weixin/',account.views.weixin_page),path('weixin/bind/',account.views.weixinbind),path('weixin/bind/callback/',account.views.weixinbind_callback),path('MP_verify_PJRLUusp1NXyuD70.txt',weixin_verify),]最终代码总览urls.pyfromdjango.urlsimportpathfromdjango.httpimportHttpResponsedefweixin_verify(request):returnHttpResponse('PJRLUusp1NXyuD70')urlpatterns=[#微信开发path('weixin/',account.views.weixin_page),path('weixin/bind/',account.views.weixinbind),path('weixin/bind/callback/',account.views.weixinbind_callback),path('MP_verify_PJRLUusp1NXyuD70.txt',weixin_verify),]views.pyimportrequestsfromdjango.shortcutsimportrenderfromdjango.httpimportHttpResponse,HttpResponseRedirectimport时间导入jsondefweixin_page(request):返回render(request,'weixin_index.html')defweixinbind(request):returnHttpResponseRedirect('https://open.weixin.qq.com/connect/oauth2/authorize?appid=XXXXX&redirect_uri=https%3A%2F%2FXXXXX.com%2Fweixin%2Fbind%2Fcallback%2F&response_type=code&scope=snsapi_userinfo#wechat_redirect')defweixinbind_callback(request):code=request.GET.get('code')state=request.GET.get('state')打印(代码,state)APPID='xxxxx'secret='xxxxx'r=requests.get('https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code'%(APPID,secret,code))print(r.text)d=json.loads(r.text)#{#"access_token":"ACCESS_TOKEN",#"expires_in":7200,#"refresh_token":"REFRESH_TOKEN",#"openid":"OPENID",#"scope":"SCOPE"#}r=requests.get('https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN'%(d['access_token'],d['openid']))print(r.content)dd=json.loads(r.content.decode('utf8'))#{#"openid":"OPENID",#"nickname":NICKNAME,#"sex":"1",#"province":"PROVINCE",#"city":"CITY",#"country":"COUNTRY",#"headimgurl":"http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",#"privilege":["PRIVILEGE1""PRIVILEGE2"],#"unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL"#}request.user.userprofile.openid=dd['openid']request.user.userprofile.nickname=dd['昵称']request.user.userprofile.wsex=dd['sex']request.user.userprofile.province=dd['province']request.user.userprofile.city=dd['city']request.user.userprofile.country=dd['country']request.user.userprofile.headimgurl=dd['headimgurl']request.user.userprofile.privilege=json.dumps(dd['privilege'])#request.user.userprofile.unionid=dd['unionid']request.user.userprofile.refresh_token_time=time.time()request.user.userprofile.save()returnHttpResponseRedirect('/weixin/')models.pyfromdjango.dbimportmodelsfromdjango.contrib.auth.modelsimportUserclassUserProfile(models.Model):user=models.OneToOneField(User,on_delete=models.CASCADE,null=True,default=None)#微信开发openid=models.CharField("微信openid",max_length=32,default='')nickname=models.CharField("微信昵称",max_length=256,default='')wsex=models.CharField("微信性别",max_length=3,default='')province=models.CharField("WeChatprovince",max_length=50,default='')city=models.CharField("WeChatcity",max_length=50,default='')country=models.CharField("微信国家",max_length=50,default='')headimgurl=models.CharField("微信头像",max_length=200,default='')privilege=models.CharField("微信权限",max_length=3,default='')unionid=models.CharField("WeChatunionid",max_length=32,default='')refresh_token=models.CharField("WeChatrefresh_token",max_length=512,default='')refresh_token_time=models.IntegerField(default=0)html部分是省略报错解决微信登录失败redirect_uri域名与后台配置不一致,错误码10003到公众号平台设置->公众号设置->功能设置->网页授权域名配置选项,修改授权回调域名见上面添加回调域名。欢迎来到我的博客:https://codeplot.top/技术分类篇微信公众号开发分类篇
