# sunderer_app/sunderer_app/api.py
import frappe
from frappe.utils import random_string, now_datetime, add_to_date
import secrets
import string
@frappe.whitelist(allow_guest=True)
def generate_verification_code(length=6):
"""生成指定长度的数字验证码"""
code = ''.join([str(secrets.randbelow(10)) for _ in range(length)])
return code
@frappe.whitelist(allow_guest=True)
def send_verification_email(email, verification_code):
"""发送验证码邮件"""
try:
# 邮件标题
subject = "决裂者终端 - 验证码"
# 邮件内容
message = f"""
决裂者终端
您好!
您的验证码是:
{verification_code}
此验证码将在 10 分钟内有效。
如果您没有请求此验证码,请忽略此邮件。
© 2026 Sunderer Games. All rights reserved.
"""
# 发送邮件
frappe.sendmail(
recipients=[email],
subject=subject,
message=message,
delayed=False # 立即发送
)
return {"success": True, "message": "验证码已发送到您的邮箱"}
except Exception as e:
frappe.log_error(f"发送验证码邮件失败: {str(e)}")
return {"success": False, "message": str(e)}
@frappe.whitelist(allow_guest=True)
def send_signup_code(email):
"""发送注册验证码的主函数"""
try:
# 验证邮箱格式
import re
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(pattern, email):
return {"exc": "请输入有效的邮箱地址!"}
# 生成验证码
verification_code = generate_verification_code(6)
# 将验证码存储到缓存中(有效期10分钟)
cache_key = f"signup_code_{email}"
frappe.cache().set_value(cache_key, verification_code, expires_in_sec=600) # 10分钟
# 发送邮件
result = send_verification_email(email, verification_code)
if result["success"]:
return {"message": "验证码已发送到您的邮箱"}
else:
return {"exc": f"发送失败: {result['message']}"}
except Exception as e:
frappe.log_error(f"发送注册验证码失败: {str(e)}")
return {"exc": f"发送失败: {str(e)}"}
@frappe.whitelist(allow_guest=True)
def verify_signup_code(email, code):
"""验证注册验证码"""
try:
cache_key = f"signup_code_{email}"
stored_code = frappe.cache().get_value(cache_key)
if not stored_code:
return {"exc": "验证码已过期,请重新获取"}
if str(stored_code) != str(code):
return {"exc": "验证码错误"}
# 验证成功,清除缓存
frappe.cache().delete_value(cache_key)
return {"success": True}
except Exception as e:
frappe.log_error(f"验证注册验证码失败: {str(e)}")
return {"exc": f"验证失败: {str(e)}"}