# 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)}"}