107 行
3.6 KiB
PHP
107 行
3.6 KiB
PHP
<?php
|
|
if (!defined('IN_APP')) {
|
|
define('IN_APP', true);
|
|
}
|
|
require __DIR__ . '/config.php';
|
|
require __DIR__ . '/includes/db.php';
|
|
require __DIR__ . '/includes/functions.php';
|
|
$isCli = (PHP_SAPI === 'cli');
|
|
$dryRun = false;
|
|
$args = $isCli ? array_slice($argv, 1) : [];
|
|
if (in_array('--dry-run', $args, true)) {
|
|
$dryRun = true;
|
|
}
|
|
if (!$isCli) {
|
|
header('Content-Type: text/plain; charset=utf-8');
|
|
$validKey = getSetting('cron_notify_key', '');
|
|
if ($validKey === '') {
|
|
$validKey = defined('SITE_KEY') ? SITE_KEY : '';
|
|
}
|
|
$got = (string) ($_GET['key'] ?? '');
|
|
if ($validKey === '' || !hash_equals($validKey, $got)) {
|
|
http_response_code(403);
|
|
echo "Access denied\n";
|
|
exit;
|
|
}
|
|
if (isset($_GET['dry'])) {
|
|
$dryRun = true;
|
|
}
|
|
}
|
|
$notifyDays = 5;
|
|
$lo = date('Y-m-d H:i:s', strtotime('+' . ($notifyDays - 1) . ' days'));
|
|
$hi = date('Y-m-d H:i:s', strtotime('+' . ($notifyDays + 1) . ' days'));
|
|
$sql = 'SELECT o.id, o.order_no, o.expires_at, o.contact_email, u.email AS u_email, u.username, u.nickname
|
|
FROM ' . tn('orders') . ' o
|
|
LEFT JOIN ' . tn('users') . ' u ON u.id = o.user_id
|
|
WHERE o.expires_at IS NOT NULL
|
|
AND o.expires_at > NOW()
|
|
AND o.expires_at >= ? AND o.expires_at <= ?
|
|
AND o.expire_notify_sent = 0
|
|
AND o.status IN (\'paid\', \'shipped\', \'completed\')';
|
|
$stmt = db()->prepare($sql);
|
|
$stmt->execute([$lo, $hi]);
|
|
$rows = $stmt->fetchAll();
|
|
$sent = 0;
|
|
$skipped = 0;
|
|
$errors = [];
|
|
$preview = [];
|
|
foreach ($rows as $row) {
|
|
$to = !empty($row['contact_email']) ? $row['contact_email'] : $row['u_email'];
|
|
if (empty($to)) {
|
|
$skipped++;
|
|
$errors[] = '订单
|
|
continue;
|
|
}
|
|
$daysLeft = (int) ceil((strtotime($row['expires_at']) - time()) / 86400);
|
|
$name = $row['nickname'] ?: $row['username'];
|
|
$subject = '[' . SITE_NAME . '] 您的服务即将到期(剩余 ' . $daysLeft . ' 天),请及时续期';
|
|
$body = buildExpireMail($name, $row['order_no'], $row['expires_at'], $daysLeft);
|
|
if ($dryRun) {
|
|
$preview[] = '预览
|
|
$sent++;
|
|
continue;
|
|
}
|
|
$res = fnwSendMail($to, $subject, $body);
|
|
if (!empty($res['ok'])) {
|
|
db()->prepare('UPDATE ' . tn('orders') . ' SET expire_notify_sent = 1 WHERE id = ?')->execute([$row['id']]);
|
|
$sent++;
|
|
} else {
|
|
$errors[] = '订单
|
|
}
|
|
}
|
|
$out = [];
|
|
$out[] = '[' . date('Y-m-d H:i:s') . '] 到期前提醒任务' . ($dryRun ? '(预览模式)' : '');
|
|
$out[] = '扫描窗口:' . $lo . ' ~ ' . $hi . '(距到期约 ' . ($notifyDays - 1) . '~' . ($notifyDays + 1) . ' 天)';
|
|
$out[] = '命中订单:' . count($rows) . ' 笔;已发送:' . $sent . ';跳过:' . $skipped;
|
|
if ($dryRun && $preview) {
|
|
$out[] = '--- 预览列表 ---';
|
|
$out = array_merge($out, $preview);
|
|
}
|
|
if ($errors) {
|
|
$out[] = '--- 注意事项 ---';
|
|
$out = array_merge($out, $errors);
|
|
}
|
|
$out[] = '';
|
|
$text = implode("\n", $out);
|
|
if ($isCli) {
|
|
fwrite(STDOUT, $text);
|
|
} else {
|
|
echo $text;
|
|
}
|
|
function buildExpireMail($name, $orderNo, $expiresAt, $daysLeft)
|
|
{
|
|
$exp = date('Y-m-d H:i', strtotime($expiresAt));
|
|
$site = SITE_NAME;
|
|
return '<div style="font-family:Segoe UI,Helvetica,Arial,sans-serif;max-width:560px;margin:0 auto;padding:24px;'
|
|
. 'border:1px solid
|
|
. '<h2 style="color:
|
|
. '<p style="color:
|
|
. '<div style="background:
|
|
. '<p style="margin:4px 0;">到期时间:<strong>' . h($exp) . '</strong></p>'
|
|
. '<p style="margin:4px 0;">剩余天数:<strong style="color:
|
|
. '</div>'
|
|
. '<p style="color:
|
|
. '<p style="color:
|
|
. '</div>';
|
|
}
|