feat(transfer): process ALL matching emails, not just current tcode
This commit is contained in:
parent
baffcaa043
commit
c0c04b2bd0
@ -221,14 +221,15 @@ class TransferGateway(Gateway):
|
||||
await asyncio.sleep(30)
|
||||
|
||||
async def check_transfer(self, tcode: str, env):
|
||||
"""扫描最近2天邮件,查找指定转账码并完成入账。
|
||||
"""扫描最近2天邮件,对所有匹配的转账码完成入账。
|
||||
返回: (title, message)"""
|
||||
from datetime import datetime, timedelta
|
||||
from email.utils import parsedate_to_datetime
|
||||
cutoff = datetime.now() - timedelta(days=2)
|
||||
|
||||
ec = EmailClient(self.pop3server, self.email, self.password)
|
||||
count, _ = ec.stat()
|
||||
debug(f'check_transfer: tcode={tcode}, total {count} mails, cutoff={cutoff}')
|
||||
debug('check_transfer: tcode=' + tcode + ' total=' + str(count) + ' mails, cutoff=' + str(cutoff))
|
||||
|
||||
db = DBPools()
|
||||
dbname = env.get_module_dbname('unipay')
|
||||
@ -240,8 +241,8 @@ class TransferGateway(Gateway):
|
||||
tc = recs[0]
|
||||
return ('已入账', '转账码 ' + tcode + ' 已入账 ' + str(tc.amount) + ' 元')
|
||||
|
||||
log_lines = []
|
||||
matched = None
|
||||
done = []
|
||||
failed = []
|
||||
scanned = 0
|
||||
|
||||
for i in range(count, 0, -1):
|
||||
@ -250,12 +251,10 @@ class TransferGateway(Gateway):
|
||||
scanned += 1
|
||||
idx = str(i)
|
||||
|
||||
# 日期过滤
|
||||
mail_date_str = getattr(mail, 'date', None)
|
||||
skip_date = False
|
||||
if mail_date_str:
|
||||
try:
|
||||
from email.utils import parsedate_to_datetime
|
||||
mail_date = parsedate_to_datetime(mail_date_str)
|
||||
if mail_date < cutoff:
|
||||
skip_date = True
|
||||
@ -284,52 +283,60 @@ class TransferGateway(Gateway):
|
||||
|
||||
code = str(data.code)
|
||||
amount = data.amount
|
||||
debug('mail[' + idx + '] code=' + code + ' amount=' + str(amount) + ' looking_for=' + tcode)
|
||||
debug('mail[' + idx + '] code=' + code + ' amount=' + str(amount))
|
||||
|
||||
if code == tcode:
|
||||
matched = data
|
||||
debug('mail[' + idx + '] *** MATCHED tcode=' + tcode + ' amount=' + str(amount) + ' ***')
|
||||
break
|
||||
debug('mail[' + idx + '] EXIT: code mismatch ' + code + ' != ' + tcode)
|
||||
# 在transfercode表中查找 status=0 的记录并入账
|
||||
async with db.sqlorContext(dbname) as sor:
|
||||
recs = await sor.R('transfercode', {'tcode': code, 'status': '0'})
|
||||
if len(recs) < 1:
|
||||
debug('mail[' + idx + '] EXIT: code ' + code + ' not in transfercode or already processed')
|
||||
continue
|
||||
|
||||
tc = recs[0]
|
||||
diff = abs(float(amount) - float(tc.amount))
|
||||
if diff > 0.01:
|
||||
await sor.U('transfercode', {'id': tc.id, 'status': '9',
|
||||
'remark': '金额不匹配: 到账' + str(amount) + ' 期望' + str(tc.amount)})
|
||||
debug('mail[' + idx + '] amount mismatch: ' + str(amount) + ' != ' + str(tc.amount))
|
||||
failed.append(code + '(金额不匹配)')
|
||||
continue
|
||||
|
||||
biz_date = await env.get_business_date(sor)
|
||||
await sor.U('transfercode', {'id': tc.id, 'status': '1'})
|
||||
|
||||
recs2 = await sor.R('payment_log', {'id': tc.id, 'payment_status': '0'})
|
||||
if len(recs2) > 0:
|
||||
plog = recs2[0]
|
||||
await env.recharge_accounting(sor,
|
||||
plog.customerid, 'RECHARGE', plog.id,
|
||||
biz_date, plog.amount_total, plog.pay_feerate)
|
||||
await sor.U('payment_log', {
|
||||
'id': plog.id,
|
||||
'payment_status': '1',
|
||||
'payed_timestamp': timestampstr()
|
||||
})
|
||||
|
||||
done.append(code + '(' + str(amount) + '元)')
|
||||
debug('mail[' + idx + '] ACCOUNTING DONE: code=' + code + ' amount=' + str(amount))
|
||||
|
||||
except Exception as e:
|
||||
debug('mail[' + str(i) + '] ERROR: ' + str(e))
|
||||
|
||||
debug('check_transfer: scanned ' + str(scanned) + ' mails, matched=' + str(matched is not None))
|
||||
debug('check_transfer: scanned=' + str(scanned) + ' done=' + str(done) + ' failed=' + str(failed))
|
||||
|
||||
if matched is None:
|
||||
# 构造返回消息
|
||||
msg_parts = []
|
||||
if done:
|
||||
msg_parts.append('入账成功 ' + str(len(done)) + ' 笔: ' + ', '.join(done))
|
||||
if failed:
|
||||
msg_parts.append('失败 ' + str(len(failed)) + ' 笔: ' + ', '.join(failed))
|
||||
|
||||
if tcode in [d.split('(')[0] for d in done]:
|
||||
return ('充值成功', '\n'.join(msg_parts))
|
||||
if not done and not failed:
|
||||
return ('尚未到账', '扫描了 ' + str(scanned) + ' 封邮件,暂未收到转账码 ' + tcode + ' 的到账通知')
|
||||
|
||||
# 执行入账
|
||||
async with db.sqlorContext(dbname) as sor:
|
||||
recs = await sor.R('transfercode', {'tcode': tcode, 'status': '0'})
|
||||
if len(recs) < 1:
|
||||
return ('已处理', '转账码 ' + tcode + ' 已处理或不存在')
|
||||
|
||||
tc = recs[0]
|
||||
diff = abs(float(matched.amount) - float(tc.amount))
|
||||
if diff > 0.01:
|
||||
await sor.U('transfercode', {'id': tc.id, 'status': '9',
|
||||
'remark': '金额不匹配: 到账' + str(matched.amount) + ' 期望' + str(tc.amount)})
|
||||
return ('金额不匹配', '到账金额 ' + str(matched.amount) + ' 与充值金额 ' + str(tc.amount) + ' 不一致')
|
||||
|
||||
biz_date = await env.get_business_date(sor)
|
||||
await sor.U('transfercode', {'id': tc.id, 'status': '1'})
|
||||
|
||||
recs2 = await sor.R('payment_log', {'id': tc.id, 'payment_status': '0'})
|
||||
if len(recs2) > 0:
|
||||
plog = recs2[0]
|
||||
await env.recharge_accounting(sor,
|
||||
plog.customerid, 'RECHARGE', plog.id,
|
||||
biz_date, plog.amount_total, plog.pay_feerate)
|
||||
await sor.U('payment_log', {
|
||||
'id': plog.id,
|
||||
'payment_status': '1',
|
||||
'payed_timestamp': timestampstr()
|
||||
})
|
||||
debug('check_transfer: ACCOUNTING DONE for ' + tcode + ' amount=' + str(matched.amount))
|
||||
|
||||
return ('充值成功', '转账码 ' + tcode + ' 已确认到账 ' + str(matched.amount) + ' 元')
|
||||
return ('转账检查结果', '\n'.join(msg_parts) + '\n\n当前转账码 ' + tcode + ' 尚未到账')
|
||||
|
||||
async def query(self, out_trade_no: str) -> Dict[str, Any]:
|
||||
pass
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user