447 lines
18 KiB
Python
Executable File
447 lines
18 KiB
Python
Executable File
import re
|
||
|
||
from allauth.account.views import logout
|
||
from django.contrib.auth.decorators import login_required
|
||
from django.contrib.auth.hashers import make_password
|
||
from django.contrib.auth import login as auth_login
|
||
from django.core.exceptions import ValidationError
|
||
from django.core.validators import validate_email
|
||
import time
|
||
|
||
from django.db import connections
|
||
|
||
from .models import User, UserSource
|
||
import json
|
||
import logging
|
||
import requests
|
||
from django.http import JsonResponse, HttpResponse
|
||
from django.views.decorators.csrf import csrf_exempt
|
||
from .mail import send_verification_email, verify_code
|
||
from .aliyun_sms import send_verification_sms, verify_sms_code
|
||
|
||
# 定义积分奖励值
|
||
REWARD_POINTS = 50 # 例如奖励50积分
|
||
|
||
def check_and_reward_points(user, openid):
|
||
"""
|
||
根据 openid 查询原系统会员状态,为原系统的用户增加一天会员时长(不论是否为会员)。
|
||
同时在新系统中奖励积分,并做好记录防止重复赠送或刷量。
|
||
:param user: 当前新系统中的用户
|
||
:param openid: 用户的 openid
|
||
:return: JSON 响应,包含奖励结果
|
||
"""
|
||
try:
|
||
# 检查当前用户是否已经使用过 openid 获得奖励,防止重复赠送
|
||
if user.openid_used:
|
||
return JsonResponse({'code': 400, 'message': '该用户已经通过 openid 获得过奖励', 'data': {}})
|
||
|
||
# 检查 openid 是否已被其他用户使用过,防止刷量
|
||
if User.objects.filter(openid_used=openid).exists():
|
||
return JsonResponse({'code': 400, 'message': '该 openid 已经被使用过', 'data': {}})
|
||
|
||
# 查询原系统数据库中的会员信息
|
||
with connections['external_db'].cursor() as cursor:
|
||
# 查询用户的 id、is_member 和 member_end_time
|
||
query = """
|
||
SELECT id, is_member, member_end_time
|
||
FROM user
|
||
WHERE openid = %s
|
||
"""
|
||
cursor.execute(query, [openid])
|
||
result = cursor.fetchone()
|
||
|
||
if not result:
|
||
return JsonResponse({'code': 404, 'message': '未找到此用户', 'data': {}})
|
||
|
||
user_id, is_member, member_end_time = result
|
||
|
||
# 保存用户原始的会员状态,用于后续判断
|
||
original_is_member = is_member
|
||
|
||
# 获取当前时间戳
|
||
current_timestamp = int(time.time())
|
||
one_day_seconds = 86400 # 一天的秒数
|
||
|
||
# 不管用户是否是会员,都在原系统中增加一天会员时长
|
||
# 如果用户不是会员,需要将 is_member 设置为 1
|
||
if is_member == 0:
|
||
is_member = 1 # 设置为会员
|
||
|
||
# 计算新的会员结束时间
|
||
if member_end_time and member_end_time > current_timestamp:
|
||
# 会员未过期,延长一天
|
||
new_member_end_time = member_end_time + one_day_seconds
|
||
else:
|
||
# 会员已过期或从未开通过会员,从当前时间开始加一天
|
||
new_member_end_time = current_timestamp + one_day_seconds
|
||
|
||
# 更新原系统用户的会员状态和结束时间
|
||
update_query = """
|
||
UPDATE user
|
||
SET is_member = %s,
|
||
member_end_time = %s
|
||
WHERE id = %s
|
||
"""
|
||
cursor.execute(update_query, [is_member, new_member_end_time, user_id])
|
||
|
||
# 提交事务
|
||
connections['external_db'].commit()
|
||
|
||
|
||
|
||
# 如果用户在原系统中原本是会员,额外奖励积分
|
||
if original_is_member == 1:
|
||
user.points += REWARD_POINTS
|
||
user.source = 'old_website_member' # 来源于旧网站会员
|
||
else:
|
||
user.source = 'old_website' # 来源于旧网站非会员
|
||
|
||
# 标记新系统用户的 openid 已使用
|
||
user.openid_used = openid
|
||
|
||
user.save()
|
||
|
||
return JsonResponse({
|
||
'code': 200,
|
||
'message': '成功奖励积分,并为原系统用户增加一天会员时长',
|
||
'data': {
|
||
'points': user.points
|
||
}
|
||
})
|
||
|
||
except Exception as e:
|
||
return JsonResponse({'code': 500, 'message': f'系统错误: {str(e)}', 'data': {}})
|
||
|
||
|
||
#登录后获取用户信息
|
||
|
||
@csrf_exempt
|
||
def user_profile(request):
|
||
# 验证用户是否已登录
|
||
if not request.user.is_authenticated:
|
||
return JsonResponse({'code': 401, 'message': '用户未登录'})
|
||
try:
|
||
user = request.user
|
||
openid = request.COOKIES.get('openid', None)
|
||
|
||
if openid:
|
||
# 调用检查会员状态并奖励积分的函数
|
||
reward_response = check_and_reward_points(user, openid)
|
||
print(f'用户注册登录:{reward_response}')
|
||
user_data = {
|
||
'id': user.id,
|
||
'username': user.username,
|
||
'email': user.email,
|
||
'phone': user.phone,
|
||
'is_member': user.is_member,
|
||
'points': user.points,
|
||
'referral_code': user.referral_code,
|
||
'commission_rate': user.commission_rate,
|
||
'login_count': user.login_count,
|
||
'last_login_ip': user.last_login_ip,
|
||
'membership_start': user.membership_start,
|
||
'membership_end': user.membership_end
|
||
}
|
||
return JsonResponse({'code': 200, 'message': '获取成功', 'data': user_data})
|
||
except:
|
||
return JsonResponse({'code': 400, 'message': '非法参数'})
|
||
#邮箱号码发送和核验部分:
|
||
@csrf_exempt
|
||
def send_verification_email_view(request):
|
||
if request.method == 'POST':
|
||
try:
|
||
body = json.loads(request.body)
|
||
email = body.get('phone_number')
|
||
if not email:
|
||
return JsonResponse({'code': 400, 'message': '邮箱地址是必须的'})
|
||
|
||
response = send_verification_email(email)
|
||
return JsonResponse(response)
|
||
except json.JSONDecodeError:
|
||
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
|
||
except Exception as e:
|
||
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
|
||
else:
|
||
return JsonResponse({'code': 405, 'message': '方法不允许'})
|
||
|
||
@csrf_exempt
|
||
def verify_code_view(request):
|
||
if request.method == 'POST':
|
||
|
||
try:
|
||
body = json.loads(request.body)
|
||
email = body.get('phone_number')
|
||
code = body.get('code')
|
||
if not email or not code:
|
||
return JsonResponse({'code': 400, 'message': '邮箱和验证码是必须的'})
|
||
|
||
response = verify_code(email, code)
|
||
return JsonResponse(response)
|
||
except json.JSONDecodeError:
|
||
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
|
||
except Exception as e:
|
||
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
|
||
else:
|
||
return JsonResponse({'code': 405, 'message': '方法不允许'})
|
||
|
||
@csrf_exempt
|
||
def send_verification_sms_view(request):
|
||
if request.method == 'POST':
|
||
try:
|
||
body = json.loads(request.body)
|
||
phone_number = body.get('phone_number')
|
||
if not phone_number:
|
||
return JsonResponse({'code': 400, 'message': '手机号码是必须的'})
|
||
|
||
sign_name = "福铭科技" # 替换为实际的签名名称
|
||
template_code = "SMS_299200388" # 替换为实际的短信模板代码
|
||
|
||
response = send_verification_sms(phone_number, sign_name, template_code)
|
||
return JsonResponse(response)
|
||
except json.JSONDecodeError:
|
||
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
|
||
except Exception as e:
|
||
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
|
||
else:
|
||
return JsonResponse({'code': 405, 'message': '方法不允许'})
|
||
|
||
@csrf_exempt
|
||
def verify_sms_code_view(request):
|
||
if request.method == 'POST':
|
||
try:
|
||
body = json.loads(request.body)
|
||
phone_number = body.get('phone_number')
|
||
code = body.get('code')
|
||
if not phone_number or not code:
|
||
return JsonResponse({'code': 400, 'message': '手机号码和验证码是必须的'})
|
||
|
||
response = verify_sms_code(phone_number, code)
|
||
return JsonResponse(response)
|
||
except json.JSONDecodeError:
|
||
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
|
||
except Exception as e:
|
||
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
|
||
else:
|
||
return JsonResponse({'code': 405, 'message': '方法不允许'})
|
||
#邮箱号码发送和核验部分END:
|
||
|
||
#用户注册部分
|
||
@csrf_exempt
|
||
def register_view(request):
|
||
if request.method == 'POST':
|
||
try:
|
||
body = json.loads(request.body)
|
||
username = body.get('username')
|
||
password = body.get('password')
|
||
confirm_password = body.get('confirm_password')
|
||
email = body.get('email')
|
||
phone = body.get('phone')
|
||
code = body.get('code')
|
||
register_method = body.get('registerMethod')
|
||
|
||
if not username or not password or not confirm_password:
|
||
return JsonResponse({'code': 400, 'message': '用户名和密码是必须的'})
|
||
|
||
if password != confirm_password:
|
||
return JsonResponse({'code': 400, 'message': '两次密码输入不一致'})
|
||
|
||
if not validate_password_strength(password):
|
||
return JsonResponse({'code': 400, 'message': '密码强度不够'})
|
||
|
||
if User.objects.filter(phone=phone).exists():
|
||
return JsonResponse({'code': 400, 'message': '手机号已存在'})
|
||
|
||
if User.objects.filter(email=email).exists():
|
||
return JsonResponse({'code': 400, 'message': '此邮箱已存在'})
|
||
|
||
if User.objects.filter(username=username).exists():
|
||
return JsonResponse({'code': 400, 'message': '用户名已存在'})
|
||
|
||
if register_method == 'email':
|
||
if not email or not code:
|
||
return JsonResponse({'code': 400, 'message': '邮箱和验证码是必须的'})
|
||
try:
|
||
validate_email(email)
|
||
except ValidationError:
|
||
return JsonResponse({'code': 400, 'message': '无效的邮箱地址'})
|
||
|
||
email_verification_result = verify_code(email, code)
|
||
if email_verification_result['code'] != 200:
|
||
return JsonResponse(email_verification_result)
|
||
|
||
user = User.objects.create(username=username, email=email, password=make_password(password))
|
||
else:
|
||
if not phone or not code:
|
||
return JsonResponse({'code': 400, 'message': '手机号和验证码是必须的'})
|
||
|
||
sms_verification_result = verify_sms_code(phone, code)
|
||
if sms_verification_result['code'] != 200:
|
||
return JsonResponse(sms_verification_result)
|
||
|
||
user = User.objects.create(username=username, password=make_password(password))
|
||
user.phone = phone
|
||
user.save()
|
||
|
||
user.backend = 'allauth.account.auth_backends.AuthenticationBackend'
|
||
auth_login(request, user)
|
||
return JsonResponse({'code': 200, 'message': '注册成功'})
|
||
except json.JSONDecodeError:
|
||
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
|
||
except Exception as e:
|
||
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
|
||
else:
|
||
return JsonResponse({'code': 405, 'message': '方法不允许'})
|
||
|
||
def validate_password_strength(password):
|
||
if len(password) < 6:
|
||
return False
|
||
if not re.search(r"[A-Za-z]", password) or not re.search(r"[0-9]", password):
|
||
return False
|
||
return True
|
||
|
||
#注册部分结束
|
||
|
||
#登录部分开始
|
||
@csrf_exempt
|
||
def login_view(request):
|
||
if request.method == 'POST':
|
||
try:
|
||
body = json.loads(request.body)
|
||
login_type = body.get('login_type')
|
||
|
||
if login_type == 'password':
|
||
username = body.get('username')
|
||
password = body.get('password')
|
||
|
||
if not username or not password:
|
||
return JsonResponse({'code': 400, 'message': '用户名和密码是必须的'})
|
||
|
||
# 验证用户名可以是邮箱或手机号
|
||
user = None
|
||
if re.match(r'^\S+@\S+\.\S+$', username): # 判断是否为邮箱
|
||
user = User.objects.filter(email=username).first()
|
||
elif re.match(r'^\d{11}$', username): # 判断是否为手机号
|
||
user = User.objects.filter(phone=username).first()
|
||
|
||
if user and user.check_password(password):
|
||
user.backend = 'allauth.account.auth_backends.AuthenticationBackend'
|
||
auth_login(request, user)
|
||
return JsonResponse({'code': 200, 'message': '登录成功'})
|
||
else:
|
||
return JsonResponse({'code': 400, 'message': '用户名或密码错误'})
|
||
|
||
elif login_type == 'code':
|
||
phone = body.get('phone')
|
||
code = body.get('code')
|
||
|
||
if not phone or not code:
|
||
return JsonResponse({'code': 400, 'message': '手机号和验证码是必须的'})
|
||
|
||
# 调用验证码核验接口
|
||
sms_verification_result = verify_sms_code(phone, code)
|
||
if sms_verification_result['code'] != 200:
|
||
return JsonResponse(sms_verification_result)
|
||
|
||
try:
|
||
user = User.objects.get(phone=phone)
|
||
if user:
|
||
user.backend = 'allauth.account.auth_backends.AuthenticationBackend'
|
||
auth_login(request, user)
|
||
return JsonResponse({'code': 200, 'message': '登录成功'})
|
||
else:
|
||
return JsonResponse({'code': 400, 'message': '用户不存在'})
|
||
except User.DoesNotExist:
|
||
return JsonResponse({'code': 400, 'message': '用户不存在'})
|
||
except Exception as e:
|
||
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
|
||
|
||
else:
|
||
return JsonResponse({'code': 400, 'message': '无效的登录类型'})
|
||
|
||
except json.JSONDecodeError:
|
||
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
|
||
except Exception as e:
|
||
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
|
||
else:
|
||
return JsonResponse({'code': 405, 'message': '方法不允许'})
|
||
|
||
|
||
#找回密码开始
|
||
@csrf_exempt
|
||
def send_verification_code_view(request):
|
||
if request.method == 'POST':
|
||
try:
|
||
body = json.loads(request.body)
|
||
identifier = body.get('identifier')
|
||
if not identifier:
|
||
return JsonResponse({'code': 400, 'message': '手机号或邮箱是必须的'})
|
||
|
||
if '@' in identifier:
|
||
response = send_verification_email(identifier)
|
||
else:
|
||
response = send_verification_sms(identifier, "福铭科技", "SMS_299200388")
|
||
|
||
return JsonResponse(response)
|
||
except json.JSONDecodeError:
|
||
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
|
||
except Exception as e:
|
||
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
|
||
else:
|
||
return JsonResponse({'code': 405, 'message': '方法不允许'})
|
||
|
||
@csrf_exempt
|
||
def reset_password_view(request):
|
||
if request.method == 'POST':
|
||
try:
|
||
body = json.loads(request.body)
|
||
identifier = body.get('identifier')
|
||
code = body.get('code')
|
||
new_password = body.get('new_password')
|
||
|
||
if not identifier or not code or not new_password:
|
||
return JsonResponse({'code': 400, 'message': '所有字段都是必须的'})
|
||
|
||
if '@' in identifier:
|
||
verification_result = verify_code(identifier, code)
|
||
else:
|
||
verification_result = verify_sms_code(identifier, code)
|
||
|
||
if verification_result['code'] != 200:
|
||
return JsonResponse(verification_result)
|
||
|
||
if not validate_password_strength(new_password):
|
||
return JsonResponse({'code': 400, 'message': '密码强度不够'})
|
||
|
||
if '@' in identifier:
|
||
user = User.objects.get(email=identifier)
|
||
else:
|
||
user = User.objects.get(phone=identifier)
|
||
|
||
user.password = make_password(new_password)
|
||
user.save()
|
||
|
||
return JsonResponse({'code': 200, 'message': '密码重置成功'})
|
||
except User.DoesNotExist:
|
||
return JsonResponse({'code': 400, 'message': '用户不存在'})
|
||
except json.JSONDecodeError:
|
||
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
|
||
except Exception as e:
|
||
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
|
||
else:
|
||
return JsonResponse({'code': 405, 'message': '方法不允许'})
|
||
#找回密码结束
|
||
|
||
#退出登录开始
|
||
@csrf_exempt
|
||
def logout_view(request):
|
||
"""
|
||
用户退出登录接口
|
||
"""
|
||
if request.method == 'POST':
|
||
# 执行 Django 的内置 logout 函数,清除用户的 session
|
||
logout(request)
|
||
return JsonResponse({'code': 200, 'message': 'ok','data': {}})
|
||
|
||
return JsonResponse({'code': 405, 'message': 'no','data': {}})
|
||
#退出登录结束
|