147 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import re
from random import randint
from typing import Any, Dict, Optional
import urllib
import poplib
from appPublic.log import debug
from appPublic.dictObject import DictObject
from appPublic.timeUtils import curDateString, timestampstr
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
from ..core import Gateway
def guess_charset(msg):
charset = msg.get_charset()
if charset is None:
content_type = msg.get('Content-Type', '').lower()
pos = content_type.find('charset=')
if pos >= 0:
charset = content_type[pos + 8:].strip()
return charset
class EmailClient:
def __init__(self, pop3_server, emailaddress, password):
self.client = poplib.POP3(pop3_server)
self.client.user(emailaddress)
self.client.pass_(password)
def stat(self):
return self.client.stat()
def mail_list(self):
resp, mails, octets = self.client.list()
def get_mail(self, index):
resp, lines, octets = self.client.retr(index)
debug(f'{resp=}, {octets=}')
msg_content = b'\r\n'.join(lines).decode('utf-8')
msg = Parser().parsestr(msg_content)
mail = {
"mailfrom": msg.get('From'),
"mailto": msg.get('To'),
"subject": msg.get('Subject'),
"body": self.get_body(msg)
}
return DictObject(**mail)
def get_body(self, msg):
if msg.is_multipart():
parts = msg.get_payload()
content = ''
for part in parts:
content += self.get_body(part)
return content
else:
content_type = msg.get_content_type()
content = msg.get_payload(decode=True)
charset = guess_charset(msg)
if charset:
content = content.decode(charset)
else:
content = content.decode('utf-8')
return content
class TransferGateway(Gateway):
def __init__(self, from_mail="", pop3server="", email="", password="", account_no=""):
self.from_email = from_email
self.pop3server = pop3server
self.email = email
self.password = password
self.account_no = account_no
self.running = False
async def new_tcode(self, sor):
tcode = self.gen_mailcode()
sql = "select * from transfercode where tcode=${tcode}$ and status='0'"
while True:
recs = await sor.sqlExe(sql, {'tcode': tcode})
if len(recs) == 0:
break
tcode = self.gen_mailcode()
return tcode
async def create_payment(self, payload: Dict[str, Any]) -> str:
"""
返回一个可以在 H5 里直接重定向的支付宝支付 URL
"""
ns = {
"id": payload.out_trade_no,
"customerid": payload.customerid,
"amount": payload.amount,
"curdate": curDateString(),
"curtime": timestampstr(),
"status": '0'
}
ns = DictObject(**ns)
ns.account_no = self.account_no
env = payload.request._run_ns
db = DBPools()
dbname = env.get_module_dbname('unipay')
async with db.sqlorContext(dbname) as sor:
sql = "select * from transfercode where tcode=${tcode}$ and status='0'"
ns.tcoce = await self.new_tcode(sor)
await sor.C('transfercode', ns.copy())
url = env.entire_url('transfer_info.ui')
query_str = urllib.parse.urlencode(ns)
return f'{url}?{query_str}'
return None
def get_transfer_data(self, mail):
assert mail.mailfrom == '95555@message.cmbchina.com'
assert mail.mailto == self.email
assert mail.body.startswith('动账业务通知')
ns = DictObject()
match = re.search(r'交易金额\s*[:]?\s*(\d+(?:\.\d+)?)', mail.body)
if match:
ns.amount = float(match.group(1))
p = r'摘要[:]\s*(\d{7})(?!\d)'
match = re.search(r'摘要[:]\s*(\d{7})(?!\d)', mail.body)
if match:
ns.code = match.group(1)
assert ns.amount
assert ns.code
return ns
def gen_mailcode(self):
c = '1'
for i in range(6):
c += randint(0,9)
return c
def run(self):
self.running = True
while self.running:
ec = EmailClient(self.pop3server, self.email, self.password)
mail = ec.get_mail(1)
async def query(self, out_trade_no: str) -> Dict[str, Any]:
pass
async def refund(self, *, out_trade_no: str, refund_amount: str, out_request_no: str) -> Dict[str, Any]:
pass
async def handle_notify(self, request) -> Dict[str, Any]:
pass