文件
freeshop/cron_expire_notify.php
T
2026-08-16 17:03:10 +08:00

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>';
}