api.3 / app /gm_crate.py
Celeskry's picture
Update app/gm_crate.py
45384c5 verified
# app/gm_crate.py
import os
import base64
import uuid
from email.utils import formataddr
from email.message import EmailMessage
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from google.auth.transport.requests import Request
from datetime import datetime
class GmailLogic:
def __init__(self):
self.client_id = os.getenv("GMAIL_CLIENT_ID")
self.client_secret = os.getenv("GMAIL_CLIENT_SECRET")
self.refresh_token = os.getenv("GMAIL_REFRESH_TOKEN")
self.user_email = os.getenv("GMAIL_USER")
self.display_name = "Celeste Store"
def get_service(self):
creds = Credentials(
None,
refresh_token=self.refresh_token,
token_uri="https://oauth2.googleapis.com/token",
client_id=self.client_id,
client_secret=self.client_secret,
)
if not creds.valid:
creds.refresh(Request())
return build('gmail', 'v1', credentials=creds)
def generate_random_order_id(self):
random_suffix = uuid.uuid4().hex[:4].upper()
return f"CS-2026-{random_suffix}"
async def send_order_email(
self,
to_email: str,
subject: str,
customer_name: str,
order_id: str,
status: str,
products: list,
total_price: str,
from_name: str = "Celeste Store"
):
try:
service = self.get_service()
date_now = datetime.now().strftime("%d/%m/%Y")
display_status = status if status else "Đang chờ duyệt"
product_names = ", ".join([p.get('name') for p in products])
html_content = f"""
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<style>
body{{margin:0;padding:0;background:#f3f4f6;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Arial;color:#333}}
.container{{max-width:560px;margin:20px auto;background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 6px 20px rgba(0,0,0,.05)}}
.header{{text-align:center;padding:35px 20px;border-bottom:1px solid #eee}}
.header h1{{margin:0;font-size:24px;color:#111}}
.content{{padding:30px}}
.order-box{{background:#f9fafb;border-radius:10px;padding:20px;border:1px solid #eee;margin-bottom:25px}}
table{{width:100%;border-collapse:collapse;font-size:14px}}
td{{padding:10px 0;border-bottom:1px solid #eee}}
.label{{color:#666}}
.value{{text-align:right;font-weight:500}}
.status-pending{{color:#f59e0b;font-weight:600}}
.total{{font-size:18px;font-weight:700;color:#e91e63;border:none}}
.footer{{text-align:center;background:#f3f4f6;padding:22px;font-size:13px;color:#888;border-top:1px solid #eee}}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>ĐƠN HÀNG ĐÃ ĐẶT</h1>
<p>Cảm ơn bạn đã tin tưởng shop ♡</p>
</div>
<div class="content">
<p>Chào <strong>{customer_name}</strong>,</p>
<p>Chúng mình đã nhận được yêu cầu đặt hàng của bạn. Đơn hàng sẽ sớm được xử lý!</p>
<div class="order-box">
<table>
<tr><td class="label">Mã đơn hàng</td><td class="value"><strong>#{order_id}</strong></td></tr>
<tr><td class="label">Ngày</td><td class="value">{date_now}</td></tr>
<tr><td class="label">Sản phẩm</td><td class="value">{product_names}</td></tr>
<tr><td class="label">Trạng thái</td><td class="value status-pending">{display_status}</td></tr>
<tr><td class="label">Tổng tiền</td><td class="value total">{total_price}</td></tr>
</table>
</div>
<p style="text-align:center; color:#666; font-size:14px;">Shop đang kiểm tra thanh toán, thông tin tài khoản sẽ được gửi đến bạn sớm nhất qua email này.</p>
</div>
<div class="footer">Celeste Store • Trà Vinh • Việt Nam<br>© 2026 Celeste Store</div>
</div>
</body>
</html>
"""
message = EmailMessage()
message['To'] = to_email
message['From'] = formataddr((from_name, self.user_email))
message['Subject'] = subject
message.add_alternative(html_content, subtype='html')
raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
service.users().messages().send(userId="me", body={'raw': raw_message}).execute()
return {"ok": True, "order_id": order_id}
except Exception as e:
return {"ok": False, "error": str(e)}
async def send_complete_email(
self,
to_email: str,
customer_name: str,
order_id: str,
product_name: str,
price: str,
tk: str,
mk: str
):
try:
service = self.get_service()
date_now = datetime.now().strftime("%d/%m/%Y")
html_content = f"""
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<style>
body{{margin:0;padding:0;background:#f3f4f6;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Arial;color:#333}}
.container{{max-width:560px;margin:20px auto;background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 6px 20px rgba(0,0,0,.05)}}
.header{{text-align:center;padding:35px 20px;border-bottom:1px solid #eee}}
.header h1{{margin:0;font-size:24px;color:#111}}
.content{{padding:30px}}
.order-box{{background:#f9fafb;border-radius:10px;padding:20px;border:1px solid #eee;margin-bottom:25px}}
table{{width:100%;border-collapse:collapse;font-size:14px}}
td{{padding:10px 0;border-bottom:1px solid #eee}}
.label{{color:#666}}
.value{{text-align:right;font-weight:500}}
.status-done{{color:#10b981;font-weight:600}}
.total{{font-size:18px;font-weight:700;color:#e91e63;border:none}}
.account-box{{background:#f5f6fa;border:1px solid #e5e7eb;border-radius:10px;padding:18px;margin-top:10px}}
.account-title{{font-size:14px;color:#666;font-weight:600;margin-bottom:10px}}
.footer{{text-align:center;background:#f3f4f6;padding:22px;font-size:13px;color:#888;border-top:1px solid #eee}}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>ĐƠN HÀNG HOÀN THÀNH</h1>
<p>Cảm ơn bạn đã mua hàng tại shop ♡</p>
</div>
<div class="content">
<p>Chào <strong>{customer_name}</strong>,</p>
<p>Đơn hàng của bạn đã được xử lý thành công. Thông tin chi tiết bên dưới:</p>
<div class="order-box">
<table>
<tr><td class="label">Mã đơn hàng</td><td class="value"><strong>#{order_id}</strong></td></tr>
<tr><td class="label">Ngày</td><td class="value">{date_now}</td></tr>
<tr><td class="label">Sản phẩm</td><td class="value">{product_name}</td></tr>
<tr><td class="label">Trạng thái</td><td class="value status-done">Hoàn Thành</td></tr>
<tr><td class="label">Tổng tiền</td><td class="value total">{price}</td></tr>
</table>
</div>
<div class="account-box">
<div class="account-title">Thông tin tài khoản</div>
<table style="width:100%;">
<tr><td style="width:90px;color:#777;">Tài khoản</td><td style="font-weight:600;">{tk}</td></tr>
<tr><td style="color:#777;">Mật khẩu</td><td style="font-weight:600;">{mk}</td></tr>
</table>
<div style="margin-top:14px;padding:10px;background:#fff;border:1px dashed #ddd;border-radius:6px;font-family:monospace;font-size:13px;word-break:break-all">
{tk}:{mk}
</div>
</div>
<p style="font-size:13px;color:#777;margin-top:15px;">Lưu ý:<br>1. KHÔNG đăng nhập vào iCloud<br>2. KHÔNG thêm SĐT<br>3. KHÔNG đổi mật khẩu</p>
</div>
<div class="footer">Celeste Store • Trà Vinh • Việt Nam<br>© 2026 Celeste Store</div>
</div>
</body>
</html>
"""
message = EmailMessage()
message['To'] = to_email
message['From'] = formataddr((self.display_name, self.user_email))
message['Subject'] = f"Đơn hàng #{order_id} đã hoàn thành"
message.add_alternative(html_content, subtype='html')
raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
service.users().messages().send(userId="me", body={'raw': raw_message}).execute()
return {"ok": True}
except Exception as e:
return {"ok": False, "error": str(e)}