重要,微信登录 大版本更新,上一个版本更新

alter table api_userinfo drop column notify_available_downloads;
alter table api_userinfo drop column notify_available_signs;

drop table api_notifyconfig_sender;
drop table api_notifyreceiver;
drop table api_notifyconfig;
drop table api_thirdwechatuserinfo;
pull/37/head
nineven 3 years ago
parent 63e09c1925
commit 2bfd694f23
  1. 38
      fir_client/src/components/FirLogin.vue
  2. 3
      fir_ser/admin/views/user.py
  3. 16
      fir_ser/api/migrations/0001_initial.py
  4. 48
      fir_ser/api/migrations/0004_auto_20220329_1736.py
  5. 25
      fir_ser/api/migrations/0005_auto_20220329_1131.py
  6. 28
      fir_ser/api/models.py
  7. 15
      fir_ser/api/utils/modelutils.py
  8. 16
      fir_ser/api/utils/serializer.py
  9. 21
      fir_ser/api/views/login_wx.py
  10. 2
      fir_ser/api/views/notify.py
  11. 91
      fir_ser/api/views/thirdlogin.py
  12. 74
      fir_ser/common/libs/mp/wechat.py
  13. 40
      fir_ser/common/notify/notify.py
  14. 9
      fir_ser/common/notify/ntasks.py
  15. 4
      fir_ser/common/notify/utils.py
  16. 49
      fir_ser/tests/django_test.py
  17. 5
      fir_ser/xsign/utils/ctasks.py
  18. 7
      fir_ser/xsign/utils/supersignutils.py

@ -75,18 +75,18 @@
<div v-if="allow_ways.third && JSON.stringify(allow_ways.third).indexOf('true')!==-1" class="other-way">
<hr>
<el-popover
v-model="showuserlist"
placement="top"
title="该微信绑定了多个用户,请选择账户,并点击登录"
width="400"
trigger="manual"
v-model="showuserlist">
width="400">
<el-row style="margin-top: 20px">
<el-col v-for="userinfo in userinfo_list" :key="userinfo.uid" :span="8" style="margin-left: 40px">
<div @click="weixinlogin(userinfo)">
<el-card :body-style="{textAlign:'center',padding:'8px',width:'120px'}" shadow="hover" >
<el-card :body-style="{textAlign:'center',padding:'8px',width:'120px'}" shadow="hover">
<!-- <el-image :src="userinfo.head_img"></el-image>-->
<el-avatar :src="userinfo.head_img" :size="100"></el-avatar>
<el-avatar :size="100" :src="userinfo.head_img"></el-avatar>
<div style="margin: 5px 0 5px">
<span>{{ userinfo.first_name }}</span>
</div>
@ -95,7 +95,7 @@
</el-col>
</el-row>
<span class="info" slot="reference">或使用以下账户登录</span>
<span slot="reference" class="info">或使用以下账户登录</span>
</el-popover>
<el-popover
@ -150,25 +150,25 @@ export default {
wx_visible: false,
loop_flag: false,
unique_key: '',
userinfo_list:[],
unique_wid:'',
showuserlist:false
userinfo_list: [],
unique_wid: '',
showuserlist: false
}
},
methods: {
weixinlogin(userinfo){
wxLoginFun(data=>{
if(data.code === 1000){
weixinlogin(userinfo) {
wxLoginFun(data => {
if (data.code === 1000) {
this.set_cookie_and_token(data);
}else if(data.code ===1005) {
} else if (data.code === 1005) {
this.$message.error(data.msg)
}else {
this.showuserlist=false
} else {
this.showuserlist = false
this.$message.error(data.msg)
}
},{
'methods':'PUT',
'data':{uid:userinfo.uid,token:userinfo.token,'wid':this.unique_wid}
}, {
'methods': 'PUT',
'data': {uid: userinfo.uid, token: userinfo.token, 'wid': this.unique_wid}
})
},
set_cookie_and_token(data) {
@ -207,12 +207,12 @@ export default {
this.loop_flag = false;
} else if (data.code === 1006) {
return this.loop_get_wx_info(wx_login_ticket, c_count, unique_key)
} else if (data.code === 2000){
} else if (data.code === 2000) {
this.wx_visible = false;
this.loop_flag = false;
this.userinfo_list = data.data;
this.unique_wid = data.wid;
this.showuserlist=true
this.showuserlist = true
}
}, {
"methods": "POST",

@ -106,6 +106,9 @@ class UserCertificationInfoView(APIView):
class ThirdWxAccountFilter(filters.FilterSet):
user_id = filters.NumberFilter(field_name="user_id__id")
openid = filters.CharFilter(field_name="weixin__openid")
nickname = filters.CharFilter(field_name="weixin__nickname")
subscribe = filters.BooleanFilter(field_name="weixin__subscribe")
class Meta:
model = ThirdWeChatUserInfo

@ -244,22 +244,6 @@ class Migration(migrations.Migration):
to=settings.AUTH_USER_MODEL, verbose_name='关联用户')),
],
),
migrations.CreateModel(
name='ThirdWeChatUserInfo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('openid', models.CharField(max_length=64, unique=True, verbose_name='普通用户的标识,对当前公众号唯一')),
('nickname', models.CharField(blank=True, max_length=64, verbose_name='昵称')),
('sex', models.SmallIntegerField(default=0, help_text='值为1时是男性,值为2时是女性,值为0时是未知', verbose_name='性别')),
('subscribe_time', models.BigIntegerField(verbose_name='订阅时间')),
('head_img_url', models.CharField(blank=True, max_length=256, null=True, verbose_name='用户头像')),
('address', models.CharField(blank=True, max_length=128, null=True, verbose_name='地址')),
('subscribe', models.BooleanField(default=0, verbose_name='是否订阅公众号')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='授权时间')),
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL,
verbose_name='用户ID')),
],
),
migrations.CreateModel(
name='Price',
fields=[

@ -1,4 +1,4 @@
# Generated by Django 3.2.3 on 2022-03-26 18:47
# Generated by Django 3.2.3 on 2022-03-29 17:36
import django.db.models.deletion
from django.conf import settings
@ -11,15 +11,23 @@ class Migration(migrations.Migration):
]
operations = [
migrations.AddField(
model_name='thirdwechatuserinfo',
name='enable_login',
field=models.BooleanField(default=0, verbose_name='是否允许登录'),
),
migrations.AddField(
model_name='thirdwechatuserinfo',
name='enable_notify',
field=models.BooleanField(default=0, verbose_name='是否允许推送消息'),
migrations.CreateModel(
name='WeChatInfo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('openid', models.CharField(max_length=64, unique=True, verbose_name='普通用户的标识,对当前公众号唯一')),
('nickname', models.CharField(blank=True, max_length=64, verbose_name='昵称')),
('sex', models.SmallIntegerField(default=0, help_text='值为1时是男性,值为2时是女性,值为0时是未知', verbose_name='性别')),
('subscribe_time', models.BigIntegerField(verbose_name='订阅时间')),
('head_img_url', models.CharField(blank=True, max_length=256, null=True, verbose_name='用户头像')),
('address', models.CharField(blank=True, max_length=128, null=True, verbose_name='地址')),
('subscribe', models.BooleanField(default=0, verbose_name='是否订阅公众号')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='授权时间')),
],
options={
'verbose_name': '微信信息',
'verbose_name_plural': '微信信息',
},
),
migrations.AddField(
model_name='userinfo',
@ -31,6 +39,24 @@ class Migration(migrations.Migration):
name='notify_available_signs',
field=models.IntegerField(blank=True, default=0, null=True, verbose_name='签名余额不足通知'),
),
migrations.CreateModel(
name='ThirdWeChatUserInfo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('enable_login', models.BooleanField(default=0, verbose_name='是否允许登录')),
('enable_notify', models.BooleanField(default=0, verbose_name='是否允许推送消息')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='授权时间')),
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL,
verbose_name='用户ID')),
('weixin', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.wechatinfo',
verbose_name='微信信息')),
],
options={
'verbose_name': '微信登录通知相关信息',
'verbose_name_plural': '微信登录通知相关信息',
'unique_together': {('user_id', 'weixin')},
},
),
migrations.CreateModel(
name='NotifyReceiver',
fields=[
@ -58,7 +84,7 @@ class Migration(migrations.Migration):
('config_name', models.CharField(max_length=128, unique=True, verbose_name='通知名称')),
('message_type', models.SmallIntegerField(
choices=[(0, '签名余额不足'), (1, '下载次数不足'), (2, '应用签名限额'), (3, '应用签名失败'), (4, '充值到账提醒'), (5, '优惠活动通知'),
(6, '证书到期消息')], default=5, verbose_name='消息类型')),
(6, '证书到期消息'), (7, '系统提醒')], default=5, verbose_name='消息类型')),
('enable_weixin', models.BooleanField(default=True, verbose_name='是否启用该配置项')),
('enable_email', models.BooleanField(default=True, verbose_name='是否启用该配置项')),
('description', models.CharField(blank=True, default='', max_length=256, verbose_name='备注')),

@ -1,25 +0,0 @@
# Generated by Django 3.2.3 on 2022-03-29 11:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0004_auto_20220326_1847'),
]
operations = [
migrations.AlterModelOptions(
name='thirdwechatuserinfo',
options={'verbose_name': '微信相关信息', 'verbose_name_plural': '微信相关信息'},
),
migrations.AlterField(
model_name='thirdwechatuserinfo',
name='openid',
field=models.CharField(max_length=64, verbose_name='普通用户的标识,对当前公众号唯一'),
),
migrations.AlterUniqueTogether(
name='thirdwechatuserinfo',
unique_together={('user_id', 'openid')},
),
]

@ -70,26 +70,38 @@ class UserInfo(AbstractUser):
super(UserInfo, self).save(*args, **kwargs)
class ThirdWeChatUserInfo(models.Model):
user_id = models.ForeignKey(to=UserInfo, verbose_name="用户ID", on_delete=models.CASCADE)
openid = models.CharField(max_length=64, null=False, verbose_name="普通用户的标识,对当前公众号唯一")
class WeChatInfo(models.Model):
openid = models.CharField(max_length=64, unique=True, verbose_name="普通用户的标识,对当前公众号唯一")
nickname = models.CharField(max_length=64, verbose_name="昵称", blank=True)
sex = models.SmallIntegerField(default=0, verbose_name="性别", help_text="值为1时是男性,值为2时是女性,值为0时是未知")
subscribe_time = models.BigIntegerField(verbose_name="订阅时间")
head_img_url = models.CharField(max_length=256, verbose_name="用户头像", blank=True, null=True)
address = models.CharField(max_length=128, verbose_name="地址", blank=True, null=True)
subscribe = models.BooleanField(verbose_name="是否订阅公众号", default=0)
created_time = models.DateTimeField(auto_now_add=True, verbose_name="授权时间")
class Meta:
verbose_name = '微信信息'
verbose_name_plural = "微信信息"
def __str__(self):
return f"{self.nickname}-{self.openid}"
class ThirdWeChatUserInfo(models.Model):
user_id = models.ForeignKey(to=UserInfo, verbose_name="用户ID", on_delete=models.CASCADE)
weixin = models.ForeignKey(to=WeChatInfo, verbose_name="微信信息", on_delete=models.CASCADE)
enable_login = models.BooleanField(verbose_name="是否允许登录", default=0)
enable_notify = models.BooleanField(verbose_name="是否允许推送消息", default=0)
created_time = models.DateTimeField(auto_now_add=True, verbose_name="授权时间")
class Meta:
verbose_name = '微信相关信息'
verbose_name_plural = "微信相关信息"
unique_together = (('user_id', 'openid'),)
verbose_name = '微信登录通知相关信息'
verbose_name_plural = "微信登录通知相关信息"
unique_together = (('user_id', 'weixin'),)
def __str__(self):
return f"{self.user_id}-{self.nickname}-{self.openid}"
return f"{self.user_id}-{self.weixin} enable_notify:{self.enable_notify} enable_login:{self.enable_login}"
class Token(models.Model):
@ -502,7 +514,7 @@ class NotifyConfig(models.Model):
config_name = models.CharField(max_length=128, unique=True, verbose_name="通知名称")
message_type_choices = (
(0, '签名余额不足'), (1, '下载次数不足'), (2, '应用签名限额'), (3, '应用签名失败'),
(4, '充值到账提醒'), (5, '优惠活动通知'), (6, '证书到期消息'))
(4, '充值到账提醒'), (5, '优惠活动通知'), (6, '证书到期消息'), (7, '系统提醒'))
message_type = models.SmallIntegerField(choices=message_type_choices, default=5, verbose_name="消息类型")
sender = models.ManyToManyField(to=NotifyReceiver, verbose_name="通知接受者方式")
enable_weixin = models.BooleanField(default=True, verbose_name="是否启用该配置项")

@ -13,7 +13,7 @@ from django.db.models import Count
from rest_framework.pagination import PageNumberPagination
from api.models import AppReleaseInfo, UserDomainInfo, DomainCnameInfo, UserAdDisplayInfo, RemoteClientInfo, \
AppBundleIdBlackList, NotifyReceiver, ThirdWeChatUserInfo
AppBundleIdBlackList, NotifyReceiver, WeChatInfo
from common.base.baseutils import get_server_domain_from_request, get_user_default_domain_name, get_real_ip_address, \
get_origin_domain_name
@ -210,8 +210,9 @@ def get_notify_wx_queryset(user_obj, message_type):
notifyconfig__enable_weixin=True, weixin__isnull=False,
user_id=user_obj).values('weixin').distinct()
return ThirdWeChatUserInfo.objects.filter(subscribe=True, user_id=user_obj, enable_notify=True,
pk__in=notify_weixin_ids).all()
return WeChatInfo.objects.filter(subscribe=True, thirdwechatuserinfo__enable_notify=True,
thirdwechatuserinfo__user_id=user_obj,
thirdwechatuserinfo__pk__in=notify_weixin_ids).all().distinct()
def get_notify_email_queryset(user_obj, message_type):
@ -219,3 +220,11 @@ def get_notify_email_queryset(user_obj, message_type):
notifyconfig__message_type=message_type,
notifyconfig__enable_email=True, email__isnull=False,
user_id=user_obj).values('email').distinct()
def get_wx_nickname(openid):
nickname = ''
obj = WeChatInfo.objects.filter(openid=openid).first()
if obj:
nickname = obj.nickname
return nickname if nickname else '亲爱哒'

@ -421,10 +421,24 @@ class UserCertificationSerializer(serializers.ModelSerializer):
exclude = ["id", "user_id", "created_time"]
class WeixinInfoSerializer(serializers.ModelSerializer):
class Meta:
model = models.WeChatInfo
exclude = ["id", "sex", "address"]
class ThirdWxSerializer(serializers.ModelSerializer):
class Meta:
model = models.ThirdWeChatUserInfo
exclude = ["id", "sex", "address", "user_id"]
exclude = ["id", "user_id", "weixin"]
openid = serializers.CharField(source="weixin.openid", read_only=True)
nickname = serializers.CharField(source="weixin.nickname", read_only=True)
address = serializers.CharField(source="weixin.address", read_only=True)
subscribe_time = serializers.IntegerField(source="weixin.subscribe_time", read_only=True)
head_img_url = serializers.CharField(source="weixin.head_img_url", read_only=True)
subscribe = serializers.BooleanField(source="weixin.subscribe", read_only=True)
created_time = serializers.DateTimeField(source="weixin.created_time", read_only=True)
class DomainNameSerializer(serializers.ModelSerializer):

@ -4,7 +4,8 @@ from django.http import HttpResponse
from rest_framework.response import Response
from rest_framework.views import APIView
from api.models import UserInfo, ThirdWeChatUserInfo
from api.models import UserInfo, ThirdWeChatUserInfo, WeChatInfo
from api.utils.modelutils import get_wx_nickname
from api.utils.response import BaseResponse
from api.utils.serializer import UserInfoSerializer, UserInfoWeiXinSerializer
from api.utils.utils import set_user_token
@ -70,7 +71,7 @@ class WeChatLoginView(APIView):
user = UserInfo.objects.filter(uid=uid).first()
if user and user.is_active:
wx_user_obj = ThirdWeChatUserInfo.objects.filter(openid=wid, enable_login=True,
wx_user_obj = ThirdWeChatUserInfo.objects.filter(weixin__openid=wid, enable_login=True,
user_id=user).first()
if wx_user_obj:
key, user_info = set_user_token(user, request)
@ -79,7 +80,7 @@ class WeChatLoginView(APIView):
ret.userinfo = data
ret.token = key
ret.msg = "验证成功!"
WxTemplateMsg(wid, wx_user_obj.nickname).login_success_msg(user.first_name)
WxTemplateMsg(wid, get_wx_nickname(wid)).login_success_msg(user.first_name)
else:
ret.msg = "微信状态异常,请重新登录"
ret.code = 1006
@ -153,16 +154,16 @@ class WeChatLoginCheckView(APIView):
return Response(ret.dict)
user = UserInfo.objects.filter(pk=wx_ticket_data['pk']).first()
wx_obj = ThirdWeChatUserInfo.objects.filter(user_id=user, openid=to_user,
enable_login=True).filter()
if not wx_obj:
ret.msg = "还未绑定用户,请通过手机或者邮箱登录账户之后进行绑定"
ret.code = 1005
return Response(ret.dict)
if user.is_active:
if to_user and w_type:
ret.data = {'uid': user.uid, 'to_user': to_user, 'w_type': w_type}
else:
wx_obj = ThirdWeChatUserInfo.objects.filter(user_id=user, weixin__openid=to_user,
enable_login=True).filter()
if not wx_obj:
ret.msg = "还未绑定用户,请通过手机或者邮箱登录账户之后进行绑定"
ret.code = 1005
else:
key, user_info = set_user_token(user, request)
serializer = UserInfoSerializer(user_info)
@ -202,7 +203,7 @@ class WeChatWebLoginView(APIView):
# 'subscribe': wx_user_info.get('subscribe', 0),
}
logger.info(f'{wx_user_info}')
ThirdWeChatUserInfo.objects.filter(openid=wx_user_info.get('openid')).update(**wx_user_info)
WeChatInfo.objects.filter(openid=wx_user_info.get('openid')).update(**wx_user_info)
return HttpResponse('<h2>更新成功</h2>')
ret.data = wx_login_obj.make_auth_uri()
return Response(ret.dict)

@ -156,7 +156,7 @@ class NotifyReceiverView(APIView):
}
wx_obj = None
if wxopenid:
wx_obj = ThirdWeChatUserInfo.objects.filter(user_id=request.user, openid=wxopenid).first()
wx_obj = ThirdWeChatUserInfo.objects.filter(user_id=request.user, weixin__openid=wxopenid).first()
if wx_obj:
data_info['weixin'] = wx_obj
if email:

@ -12,10 +12,10 @@ from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_xml.parsers import XMLParser
from api.models import ThirdWeChatUserInfo, UserInfo, UserCertificationInfo
from api.utils.modelutils import PageNumber
from api.models import ThirdWeChatUserInfo, UserInfo, UserCertificationInfo, WeChatInfo
from api.utils.modelutils import PageNumber, get_wx_nickname
from api.utils.response import BaseResponse
from api.utils.serializer import ThirdWxSerializer
from api.utils.serializer import WeixinInfoSerializer
from api.views.login import get_login_type
from common.core.auth import ExpiringTokenAuthentication
from common.libs.mp.chat import reply, receive
@ -47,7 +47,7 @@ def reply_login_msg(rec_msg, to_user, from_user):
content = f'还未绑定用户,请通过手机或者邮箱登录账户之后进行绑定'
u_data_id = -1
ids = []
wx_user_obj_queryset = ThirdWeChatUserInfo.objects.filter(openid=to_user, enable_login=True).all()
wx_user_obj_queryset = ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user, enable_login=True).all()
wx_ticket_info = get_wx_ticket_login_info_cache(rec_msg.Ticket)
@ -55,12 +55,13 @@ def reply_login_msg(rec_msg, to_user, from_user):
if 0 <= wx_user_count <= 1:
wx_user_obj = wx_user_obj_queryset.first()
if wx_user_obj:
u_data_id = wx_user_obj.user_id.pk
content = f'用户 {wx_user_obj.user_id.first_name} 登录成功'
WxTemplateMsg(to_user, wx_user_obj.nickname).login_success_msg(wx_user_obj.user_id.first_name)
else:
wx_user_info = update_or_create_wx_userinfo(to_user)
WxTemplateMsg(to_user, wx_user_info.get('nickname', '')).login_failed_msg()
user_obj = wx_user_obj.user_id
u_data_id = user_obj.pk
content = f'用户 {user_obj.first_name} 登录成功'
WxTemplateMsg(to_user, get_wx_nickname(to_user)).login_success_msg(user_obj.first_name)
# else:
# wx_user_info = update_or_create_wx_userinfo(to_user)
# WxTemplateMsg(to_user, wx_user_info.get('nickname', '')).login_failed_msg()
elif wx_user_count > 1:
ids = [x['user_id__id'] for x in wx_user_obj_queryset.values('user_id__id')]
u_data_id = wx_user_obj_queryset.first().user_id.pk
@ -75,36 +76,37 @@ def reply_login_msg(rec_msg, to_user, from_user):
def update_or_create_wx_userinfo(to_user, user_obj=None, w_type=''):
code, wx_user_info = get_userinfo_from_openid(to_user)
code, wx_info = get_userinfo_from_openid(to_user)
logger.info(f"get openid:{to_user} info:{to_user} code:{code}")
if code:
wx_user_info = {
'openid': wx_user_info.get('openid'),
wx_info = {
'openid': wx_info.get('openid'),
# 'nickname': wx_user_info.get('nickname'), # 最新微信接口已经取消该字段
# 'sex': wx_user_info.get('sex'), # 最新微信接口已经取消该字段
'subscribe_time': wx_user_info.get('subscribe_time'),
'subscribe_time': wx_info.get('subscribe_time'),
# 'head_img_url': wx_user_info.get('headimgurl'), # 最新微信接口已经取消该字段
'address': f"{wx_user_info.get('country')}-{wx_user_info.get('province')}-{wx_user_info.get('city')}",
'subscribe': wx_user_info.get('subscribe'),
'address': f"{wx_info.get('country')}-{wx_info.get('province')}-{wx_info.get('city')}",
'subscribe': wx_info.get('subscribe'),
}
if user_obj:
wx_obj, _ = WeChatInfo.objects.update_or_create(openid=to_user, defaults=wx_info)
wx_user_info = {'weixin': wx_obj}
if w_type == 'login':
wx_user_info['enable_login'] = True
if w_type == 'notify':
wx_user_info['enable_notify'] = True
ThirdWeChatUserInfo.objects.update_or_create(user_id=user_obj, openid=to_user, defaults=wx_user_info)
return wx_user_info
ThirdWeChatUserInfo.objects.update_or_create(user_id=user_obj, weixin=wx_obj, defaults=wx_user_info)
return wx_obj
def wx_bind_utils(rec_msg, to_user, from_user, content):
w_type = rec_msg.Eventkey.split('.')[-1]
uid = rec_msg.Eventkey.split('.')[-2]
user_obj = UserInfo.objects.filter(uid=uid).first()
wx_user_obj = ThirdWeChatUserInfo.objects.filter(openid=to_user, user_id__uid=uid).first()
wx_user_obj = ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user, user_id__uid=uid).first()
if wx_user_obj:
wx_template_msg_obj = WxTemplateMsg(to_user, wx_user_obj.nickname)
wx_template_msg_obj = WxTemplateMsg(to_user, get_wx_nickname(to_user))
if user_obj and user_obj.uid == wx_user_obj.user_id.uid:
content = f'账户 {wx_user_obj.user_id.first_name} 已经绑定成功,感谢您的使用'
update_or_create_wx_userinfo(to_user, user_obj, w_type)
@ -114,9 +116,9 @@ def wx_bind_utils(rec_msg, to_user, from_user, content):
wx_template_msg_obj.bind_failed_msg(content)
else:
if user_obj:
wx_user_info = update_or_create_wx_userinfo(to_user, user_obj, w_type)
update_or_create_wx_userinfo(to_user, user_obj, w_type)
content = f'账户绑定 {user_obj.first_name} 成功'
WxTemplateMsg(to_user, wx_user_info.get('nickname', '')).bind_success_msg(user_obj.first_name)
WxTemplateMsg(to_user, get_wx_nickname(to_user)).bind_success_msg(user_obj.first_name)
if user_obj:
set_wx_ticket_login_info_cache(rec_msg.Ticket, {'pk': user_obj.pk, 'w_type': w_type, 'to_user': to_user})
reply_msg = reply.TextMsg(to_user, from_user, content)
@ -152,7 +154,8 @@ class ValidWxChatToken(APIView):
msg_list = msg.split(' ')
if len(msg_list) == 2:
uid = msg_list[-1]
wx_user_obj = ThirdWeChatUserInfo.objects.filter(openid=to_user, user_id__uid=uid).first()
wx_user_obj = ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user,
user_id__uid=uid).first()
data = {}
w_msg = []
if msg.startswith('解除登录绑定'):
@ -162,14 +165,15 @@ class ValidWxChatToken(APIView):
w_msg.append('消息推送')
data.update({'enable_notify': False})
if data:
ThirdWeChatUserInfo.objects.filter(openid=to_user, user_id__uid=uid).update(**data)
WxTemplateMsg(to_user, wx_user_obj.nickname).unbind_success_msg(
ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user, user_id__uid=uid).update(
**data)
WxTemplateMsg(to_user, get_wx_nickname(to_user)).unbind_success_msg(
wx_user_obj.user_id.first_name, f"{' '.join(w_msg)} 解绑成功",
"如需重新绑定,请登陆平台,进行绑定。感谢您的关注")
return HttpResponse("success")
content = random.choices([*GOOD_XX, content, rec_msg.Content.decode('utf-8')])[0]
reply_msg = reply.TextMsg(to_user, from_user, content)
reply_msg = reply.TextMsg(to_user, from_user, f'{get_wx_nickname(to_user)}{content}')
result = reply_msg.send()
elif rec_msg.MsgType == 'image':
@ -186,7 +190,7 @@ class ValidWxChatToken(APIView):
if rec_msg.Event == 'CLICK': # 公众号点击事件
if rec_msg.Eventkey == 'good':
content = random.choices(GOOD_XX)[0]
reply_msg = reply.TextMsg(to_user, from_user, content)
reply_msg = reply.TextMsg(to_user, from_user, f'{get_wx_nickname(to_user)}{content}')
result = reply_msg.send()
logger.info(f"replay msg: {result}")
return HttpResponse(result)
@ -196,7 +200,7 @@ class ValidWxChatToken(APIView):
logger.info(f"replay msg: {result}")
return HttpResponse(result)
elif rec_msg.Eventkey in ['query_bind', 'unbind', 'unbind_all']:
wx_user_obj_queryset = ThirdWeChatUserInfo.objects.filter(openid=to_user).filter(
wx_user_obj_queryset = ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user).filter(
Q(enable_login=True) | Q(enable_notify=True)).all()
if rec_msg.Eventkey == 'query_bind':
for wx_user_obj in wx_user_obj_queryset:
@ -220,33 +224,30 @@ class ValidWxChatToken(APIView):
description += " 消息通知 "
description += "功能。"
WxTemplateMsg(to_user, wx_user_obj.nickname).bind_query_success_msg(
WxTemplateMsg(to_user, get_wx_nickname(to_user)).bind_query_success_msg(
user_obj.first_name,
name,
user_obj.mobile,
user_obj.email,
description)
if wx_user_obj_queryset.count() == 0:
content = '暂无绑定信息'
wx_user_info = update_or_create_wx_userinfo(to_user)
WxTemplateMsg(to_user, wx_user_info.get('nickname')).query_bind_info_failed_msg(
"查询绑定", content)
WxTemplateMsg(to_user, get_wx_nickname(to_user)).query_bind_info_failed_msg(
"查询绑定", '暂无绑定信息')
elif rec_msg.Eventkey == 'unbind_all':
for wx_user_obj in wx_user_obj_queryset:
if wx_user_obj:
content = f'解绑用户 {wx_user_obj.user_id.first_name} 成功'
WxTemplateMsg(to_user, wx_user_obj.nickname).unbind_success_msg(
WxTemplateMsg(to_user, get_wx_nickname(to_user)).unbind_success_msg(
wx_user_obj.user_id.first_name,
"解除绑定成功,您将无法使用微信扫描登录平台和微信消息推送功能",
"如需重新绑定,请登陆平台,在个人资料进行登录绑定。感谢您的关注")
ThirdWeChatUserInfo.objects.filter(openid=to_user).update(enable_login=False,
ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user).update(
enable_login=False,
enable_notify=False)
if wx_user_obj_queryset.count() == 0:
content = f'暂无绑定信息'
wx_user_info = update_or_create_wx_userinfo(to_user)
WxTemplateMsg(to_user, wx_user_info.get('nickname')).query_bind_info_failed_msg(
"解除绑定", content)
WxTemplateMsg(to_user, get_wx_nickname(to_user)).query_bind_info_failed_msg(
"解除绑定", '暂无绑定信息')
elif rec_msg.Eventkey == 'unbind':
if wx_user_obj_queryset.count() == 0:
content = f'暂无绑定信息'
@ -284,7 +285,7 @@ class ValidWxChatToken(APIView):
elif rec_msg.Eventkey.startswith('qrscene_web.bind.'):
result = wx_bind_utils(rec_msg, to_user, from_user, content)
if rec_msg.Event == 'unsubscribe':
ThirdWeChatUserInfo.objects.filter(openid=to_user).update(subscribe=False)
WeChatInfo.objects.filter(openid=to_user).update(subscribe=False)
elif rec_msg.Event == 'SCAN':
if rec_msg.Eventkey == 'web.login': # 已经关注,然后再次扫码,登录认证操作
@ -305,12 +306,13 @@ class ThirdWxAccount(APIView):
def get(self, request):
res = BaseResponse()
if get_login_type().get('third', '').get('wxp'):
wx_obj_lists = ThirdWeChatUserInfo.objects.filter(user_id=request.user, enable_login=True)
wx_obj_lists = WeChatInfo.objects.filter(thirdwechatuserinfo__user_id=request.user,
thirdwechatuserinfo__enable_login=True)
page_obj = PageNumber()
info_serializer = page_obj.paginate_queryset(queryset=wx_obj_lists.order_by("-subscribe_time"),
request=request,
view=self)
wx_user_info = ThirdWxSerializer(info_serializer, many=True, )
wx_user_info = WeixinInfoSerializer(info_serializer, many=True, )
res.data = wx_user_info.data
res.count = wx_obj_lists.count()
return Response(res.dict)
@ -320,7 +322,8 @@ class ThirdWxAccount(APIView):
openid = data.get("openid")
if get_login_type().get('third', '').get('wxp') and openid:
if request.user.check_password(data.get('confirm_pwd', '')):
ThirdWeChatUserInfo.objects.filter(user_id=request.user, openid=openid).update(enable_login=False)
ThirdWeChatUserInfo.objects.filter(user_id=request.user, weixin__openid=openid).update(
enable_login=False)
else:
res = BaseResponse()
res.code = 1001

@ -345,33 +345,8 @@ class WxTemplateMsg(object):
def bind_query_success_msg(self, username, name, mobile, email, description):
msg_id = 'yU15jLNSULagJTff01X67mDtDytBSs3iBpOBi8c7dvs'
content_data = {
"first": {
"value": f"您的微信账户“{self.wx_nick_name}”绑定信息结果",
"color": "#173177"
},
"keyword1": {
"value": username,
"color": "#173177"
},
"keyword2": {
"value": name,
"color": "#173177"
},
"keyword3": {
"value": mobile,
"color": "#173177"
},
"keyword4": {
"value": email,
"color": "#173177"
},
"remark": {
"value": f"{description}感谢您的关注",
"color": "#173177"
},
}
return self.send_msg(msg_id, content_data)
title = f"您的微信账户“{self.wx_nick_name}”绑定信息结果"
return self.__operate_base_msg(msg_id, title, username, name, mobile, email, description)
def query_bind_info_failed_msg(self, action_msg, failed_msg):
now_time = get_format_time()
@ -516,27 +491,58 @@ class WxTemplateMsg(object):
}
return self.send_msg(msg_id, content_data)
def operate_failed_msg(self, first_name, operate_context, failed_msg, operate_time, description):
msg_id = 'Hnrk5iXRjbaCTVpSIyC5KC8cwFNDgplNUzPsnyDXRLo'
def __operate_base_msg(self, msg_id, title, username, context, key1, key2, description):
content_data = {
"first": {
"value": f'你好,“{self.wx_nick_name}“,签名失败了',
"value": title,
"color": "#173177"
},
"keyword1": {
"value": first_name,
"value": username,
"color": "#173177"
},
"keyword2": {
"value": operate_context,
"value": context,
"color": "#173177"
},
"keyword3": {
"value": failed_msg,
"value": key1,
"color": "#173177"
},
"keyword4": {
"value": operate_time,
"value": key2,
"color": "#173177"
},
"remark": {
"value": f"{description},感谢您的关注",
"color": "#173177"
},
}
return self.send_msg(msg_id, content_data)
def operate_failed_msg(self, first_name, operate_context, failed_msg, operate_time, description):
msg_id = 'Hnrk5iXRjbaCTVpSIyC5KC8cwFNDgplNUzPsnyDXRLo'
title = f'你好,“{self.wx_nick_name}“,签名失败了'
return self.__operate_base_msg(msg_id, title, first_name, operate_context, failed_msg, operate_time,
description)
def task_finished_msg(self, title, first_name, task_status, task_time, description):
msg_id = 'ILQYHzrHSleN4sSbKZTQVLWk_7_EwZZDcDJWlIvNwiQ'
content_data = {
"first": {
"value": title,
"color": "#173177"
},
"keyword1": {
"value": first_name,
"color": "#173177"
},
"keyword2": {
"value": task_status,
"color": "#173177"
},
"keyword3": {
"value": task_time,
"color": "#173177"
},
"remark": {

@ -6,7 +6,7 @@
# data: 2022/3/26
import logging
from api.utils.modelutils import get_notify_wx_queryset
from api.utils.modelutils import get_notify_wx_queryset, get_wx_nickname
from common.base.baseutils import get_format_time
from common.core.sysconfig import Config
from common.libs.mp.wechat import WxTemplateMsg
@ -29,7 +29,7 @@ def pay_success_notify(user_obj, order_obj):
title = f'{title} 【赠送 {order_obj.actual_download_gift_times}'
msg = f"用户 {user_obj.first_name} 您好,{order_obj.description}。您购买了 {title}。感谢有你!"
for wx_user_obj in get_notify_wx_queryset(user_obj, message_type):
res = WxTemplateMsg(wx_user_obj.openid, wx_user_obj.nickname).pay_success_msg(
res = WxTemplateMsg(wx_user_obj.openid, get_wx_nickname(wx_user_obj.openid)).pay_success_msg(
title,
f'{str(order_obj.actual_amount / 100)}',
order_obj.get_payment_type_display(),
@ -52,7 +52,7 @@ def sign_failed_notify(user_obj, developer_obj, app_obj):
user_obj.first_name, app_obj.name, now_time, developer_obj.issuer_id, developer_obj.description)
for wx_user_obj in get_notify_wx_queryset(user_obj, message_type):
res = WxTemplateMsg(wx_user_obj.openid, wx_user_obj.nickname).operate_failed_msg(
res = WxTemplateMsg(wx_user_obj.openid, get_wx_nickname(wx_user_obj.openid)).operate_failed_msg(
user_obj.first_name, f'应用 {app_obj.name} 签名失败了',
f'开发者{developer_obj.issuer_id} 状态 {developer_obj.get_status_dispaly()}', now_time,
f'开发者备注:{developer_obj.description},请登录后台查看具体信息')
@ -61,7 +61,7 @@ def sign_failed_notify(user_obj, developer_obj, app_obj):
notify_by_email(user_obj, message_type, msg)
def sign_unavailable_developer(user_obj, app_obj):
def sign_unavailable_developer_notify(user_obj, app_obj):
"""
3, '应用签名失败'
:return:
@ -70,7 +70,7 @@ def sign_unavailable_developer(user_obj, app_obj):
now_time = get_format_time().replace('_', ' ')
msg = Config.MSG_NOT_EXIST_DEVELOPER % (user_obj.first_name, app_obj.name, now_time)
for wx_user_obj in get_notify_wx_queryset(user_obj, message_type):
res = WxTemplateMsg(wx_user_obj.openid, wx_user_obj.nickname).operate_failed_msg(
res = WxTemplateMsg(wx_user_obj.openid, get_wx_nickname(wx_user_obj.openid)).operate_failed_msg(
user_obj.first_name, f'应用 {app_obj.name} 签名失败了',
f'苹果开发者总设备量已经超限', now_time, '添加新的苹果开发者或者修改开发者设备数量')
logger.info(f'user_obj {user_obj} weixin notify pay success result: {res}')
@ -78,7 +78,7 @@ def sign_unavailable_developer(user_obj, app_obj):
notify_by_email(user_obj, message_type, msg)
def sign_app_over_limit(user_obj, app_obj, used_num, limit_number):
def sign_app_over_limit_notify(user_obj, app_obj, used_num, limit_number):
"""
0, '签名余额不足'
:param limit_number:
@ -91,8 +91,34 @@ def sign_app_over_limit(user_obj, app_obj, used_num, limit_number):
now_time = get_format_time().replace('_', ' ')
msg = Config.MSG_SING_APP_OVER_LIMIT % (user_obj.first_name, app_obj.name, now_time, used_num, limit_number)
for wx_user_obj in get_notify_wx_queryset(user_obj, message_type):
res = WxTemplateMsg(wx_user_obj.openid, wx_user_obj.nickname).operate_failed_msg(
res = WxTemplateMsg(wx_user_obj.openid, get_wx_nickname(wx_user_obj.openid)).operate_failed_msg(
user_obj.first_name, f'应用 {app_obj.name} 签名失败了', f'超过该应用的签名限额 {limit_number}', now_time,
f'该应用已经使用设备数 {used_num},已超过您设置该应用的签名限额 {limit_number},当前已经无法安装新设备,为了避免业务使用,您可以修改该应用签名限额')
logger.info(f'user_obj {user_obj} sign devices not enough result: {res}')
notify_by_email(user_obj, message_type, msg)
def check_developer_status_notify(user_obj, developer_obj_list, content):
"""
7, '系统提醒'
:return:
"""
message_type = 7
now_time = get_format_time().replace('_', ' ')
status_msg = {}
for developer_obj in developer_obj_list:
status = developer_obj.get_status_display()
status_msg[status] = status_msg.get(status, 0) + 1
msg = []
for key, value in status_msg.items():
msg.append(f'{value}{key}状态')
description = f'开发者状态 {",".join(msg)}。详细信息请查看邮件通知或者登录后台查看'
for wx_user_obj in get_notify_wx_queryset(user_obj, message_type):
nick_name = get_wx_nickname(wx_user_obj.openid)
title = f'你好,“{nick_name}“,苹果开发者状态检测结果'
res = WxTemplateMsg(wx_user_obj.openid, nick_name).task_finished_msg(title, '苹果开发者状态检测', '完成',
now_time, description)
logger.info(f'user_obj {user_obj} sign devices not enough result: {res}')
notify_by_email(user_obj, message_type, html=content)

@ -7,7 +7,7 @@
import datetime
import logging
from api.utils.modelutils import get_notify_wx_queryset
from api.utils.modelutils import get_notify_wx_queryset, get_wx_nickname
from common.base.magic import magic_wrapper, magic_notify
from common.cache.storage import NotifyLoopCache
from common.core.sysconfig import Config
@ -28,7 +28,7 @@ def download_times_not_enough(user_obj, msg):
"""
message_type = 1
for wx_user_obj in get_notify_wx_queryset(user_obj, message_type):
res = WxTemplateMsg(wx_user_obj.openid, wx_user_obj.nickname).download_times_not_enough_msg(
res = WxTemplateMsg(wx_user_obj.openid, get_wx_nickname(wx_user_obj.openid)).download_times_not_enough_msg(
user_obj.first_name, user_obj.download_times, msg)
logger.info(f'user_obj {user_obj} download times not enough result: {res}')
notify_by_email(user_obj, message_type, msg)
@ -43,7 +43,8 @@ def apple_developer_devices_not_enough(user_obj, device_count):
message_type = 0
msg = f"您当前账户超级签名可用设备仅剩 {device_count},已超过您设置的阈值 {user_obj.notify_available_signs},为了避免业务使用,望您尽快添加苹果开发者!"
for wx_user_obj in get_notify_wx_queryset(user_obj, message_type):
res = WxTemplateMsg(wx_user_obj.openid, wx_user_obj.nickname).apple_developer_devices_not_enough_msg(
res = WxTemplateMsg(wx_user_obj.openid,
get_wx_nickname(wx_user_obj.openid)).apple_developer_devices_not_enough_msg(
user_obj.first_name, device_count, msg)
logger.info(f'user_obj {user_obj} sign devices not enough result: {res}')
notify_by_email(user_obj, message_type, msg)
@ -70,7 +71,7 @@ def apple_developer_cert_expired(user_obj, developer_queryset):
msg = f"用户 {user_obj.first_name} 您好,您苹果开发者 {issuer_id} ,证书 {cert_id} 即将到期,到期时间 {expired_time},为了保证您开发者可用,请您尽快更新开发者证书,感谢您的关注 "
for wx_user_obj in get_notify_wx_queryset(user_obj, message_type):
res = WxTemplateMsg(wx_user_obj.openid, wx_user_obj.nickname).cert_expired_msg(issuer_id,
res = WxTemplateMsg(wx_user_obj.openid, get_wx_nickname(wx_user_obj.openid)).cert_expired_msg(issuer_id,
cert_id,
expired_time)
logger.info(f'user_obj {user_obj} apple developer cert expired result: {res}')

@ -12,8 +12,8 @@ from common.utils.sendmsg import get_sender_email_token
logger = logging.getLogger(__name__)
def notify_by_email(user_obj, message_type, msg):
def notify_by_email(user_obj, message_type, msg='', html=None):
for notify_email in get_notify_email_queryset(user_obj, message_type):
email = notify_email.get('email')
if email:
get_sender_email_token('email', email, 'msg', f'您好,{user_obj.first_name}{msg}')
get_sender_email_token('email', email, 'msg', html if html else f'您好,{user_obj.first_name}{msg}')

@ -55,16 +55,53 @@ django.setup()
# order_obj.get_payment_type_display(),
# order_obj.pay_time.strftime("%Y/%m/%d %H:%M:%S"),
# order_obj.order_number, order_obj.description)
from api.models import UserInfo, NotifyReceiver, NotifyConfig
#
# a = WeChatInfo.objects.filter(openid='11').values('nickname')
# print(a)
from xsign.utils.ctasks import auto_check_ios_developer_active
auto_check_ios_developer_active()
# from common.notify.wx import check_apple_developer_devices
#
user_obj = UserInfo.objects.filter(uid='47ed855a8e6411ec83f100163e1bfc45').first()
# user_obj = UserInfo.objects.filter(uid='47ed855a8e6411ec83f100163e1bfc45').first()
# wx_user_obj_queryset = ThirdWeChatUserInfo.objects.filter(enable_login=True).all()
# print(wx_user_obj_queryset.values('user_id__id'))
# wx_user_obj_queryset = ThirdWeChatUserInfo.objects.filter(openid='opTae6mrV-MY1UOLahIVXaCDJhUU').filter(
# Q(enable_login=True) | Q(enable_notify=True)).all()
# for wx_obj in wx_user_obj_queryset:
# print(wx_obj.__dict__)
# ThirdWeChatUserInfo.objects.filter().delete()
# class AesBaseCrypt(object):
#
# def __init__(self):
# print(self.__class__.__name__)
# self.cipher = AESCipher(self.__class__.__name__)
#
# def get_encrypt_uid(self, raw):
# return self.cipher.encrypt(raw.encode('utf-8')).decode('utf-8')
#
# def get_decrypt_uid(self, enc):
# return self.cipher.decrypt(enc)
#
#
# class AppleDeveloperUid(AesBaseCrypt):
# pass
# class aaaa():
# def __init__(self):
# self.a=11
#
# obj = aaaa()
# def cc(obj):
# obj.a = 222
#
# cc(obj)
# print(obj.a)
# print(AppleDeveloperUid().cipher)
# check_apple_developer_devices(user_obj)
notify_config_obj = NotifyConfig.objects.create(user_id=user_obj, message_type=0,
config_name='下载次数不足3323',
enable_email=True, enable_weixin=True, description='次数不足')
notify_config_obj.sender.set(NotifyReceiver.objects.filter(user_id=user_obj).all())
# notify_config_obj = NotifyConfig.objects.create(user_id=user_obj, message_type=0,
# config_name='下载次数不足3323',
# enable_email=True, enable_weixin=True, description='次数不足')
# notify_config_obj.sender.set(NotifyReceiver.objects.filter(user_id=user_obj).all())
#
# developer_obj = AppIOSDeveloperInfo.objects.filter(issuer_id='69a6de96-c16e-47e3-e053-5b8c7c11a4d1').first()
#

@ -13,11 +13,11 @@ from concurrent.futures import ThreadPoolExecutor
from django.template import loader
from common.core.sysconfig import Config
from common.notify.notify import check_developer_status_notify
from fir_ser.settings import SUPER_SIGN_ROOT, SYNC_CACHE_TO_DATABASE
from xsign.models import UserInfo, AppIOSDeveloperInfo, APPSuperSignUsedInfo
from xsign.utils.modelutils import get_developer_devices
from xsign.utils.supersignutils import IosUtils
from xsign.utils.utils import send_ios_developer_active_status
logger = logging.getLogger(__name__)
@ -79,4 +79,5 @@ def auto_check_ios_developer_active():
'developer_used_info': developer_used_info,
'yesterday_used_number': yesterday_used_number,
})
send_ios_developer_active_status(userinfo, content)
# send_ios_developer_active_status(userinfo, content)
check_developer_status_notify(userinfo, developer_obj_list, content)

@ -22,7 +22,7 @@ from common.base.baseutils import file_format_path, delete_app_profile_file, get
from common.base.magic import run_function_by_locker, call_function_try_attempts, magic_wrapper
from common.cache.state import CleanErrorBundleIdSignDataState
from common.core.sysconfig import Config
from common.notify.notify import sign_failed_notify, sign_unavailable_developer, sign_app_over_limit
from common.notify.notify import sign_failed_notify, sign_unavailable_developer_notify, sign_app_over_limit_notify
from common.utils.caches import del_cache_response_by_short, send_msg_over_limit, check_app_permission, \
consume_user_download_times_by_app_obj, add_udid_cache_queue, get_and_clean_udid_cache_queue
from common.utils.storage import Storage
@ -414,7 +414,7 @@ class IosUtils(object):
if self.user_obj.email:
if send_msg_over_limit("get", self.user_obj.email):
send_msg_over_limit("set", self.user_obj.email)
sign_unavailable_developer(self.user_obj, self.app_obj)
sign_unavailable_developer_notify(self.user_obj, self.app_obj)
else:
logger.error(f"user {self.user_obj} send msg failed. over limit")
@ -533,7 +533,8 @@ class IosUtils(object):
d_result['msg'] = "app_id %s used over limit.now %s limit: %s" % (
self.app_obj, used_num, self.app_obj.supersign_limit_number)
logger.error(d_result)
sign_app_over_limit(self.app_obj.user_id, self.app_obj, used_num, self.app_obj.supersign_limit_number)
sign_app_over_limit_notify(self.app_obj.user_id, self.app_obj, used_num,
self.app_obj.supersign_limit_number)
return False, d_result
res = check_app_permission(self.app_obj, BaseResponse())

Loading…
Cancel
Save