仰望星辰工作室

better-staridc-MNBT

better-staridc-MNBT/ wp_seller_plugin/includes/services/class-billing.php 5.8 KB · 176 行 原始文件
Z zfhsh first commit 2 天前
1<?php
2/**
3 * 计费:续费处理与到期维护(暂停/提醒)。
4 *
5 * @package MnbtWp
6 */
7
8namespace MnbtWp\Services;
9
10use MnbtWp\Helpers;
11
12if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14}
15
16/**
17 * 计费服务。
18 */
19class Billing {
20
21 /**
22 * 续费订单支付完成后处理:xf 更新到期时间,必要时恢复主机。
23 *
24 * @param int $order_id 订单 ID(含 _mnbtwp_renew_host_id / _mnbtwp_renew_months meta)。
25 * @return array
26 *
27 * @throws \Exception 续费失败。
28 */
29 public static function renew_order( $order_id ) {
30 $host_id = (int) get_post_meta( $order_id, '_mnbtwp_renew_host_id', true );
31 if ( ! $host_id ) {
32 throw new \Exception( __( '续费订单缺少主机信息', 'wp-seller-plugin' ) );
33 }
34 if ( get_post_meta( $order_id, '_mnbtwp_renewed', true ) ) {
35 return array( 'ok' => true, 'msg' => __( '该订单已续费', 'wp-seller-plugin' ) );
36 }
37
38 $host = Helpers::get_host( $host_id );
39 if ( ! $host ) {
40 throw new \Exception( __( '主机不存在', 'wp-seller-plugin' ) );
41 }
42
43 $months = max( 1, (int) get_post_meta( $order_id, '_mnbtwp_renew_months', true ) ?: 1 );
44 $base = ( $host['expire_date'] && '0000-00-00' !== $host['expire_date'] && strtotime( $host['expire_date'] ) > time() )
45 ? $host['expire_date']
46 : date( 'Y-m-d' );
47 $new_date = date( 'Y-m-d', strtotime( "+{$months} months", strtotime( $base ) ) );
48
49 $provider = Helpers::get_provider( $host['provider_id'] );
50 if ( ! $provider ) {
51 throw new \Exception( __( '节点配置不存在', 'wp-seller-plugin' ) );
52 }
53
54 $client = Helpers::client_for_provider( $provider );
55 $client->renewHost( $host['username'], $new_date );
56
57 global $wpdb;
58 $wpdb->update(
59 $wpdb->prefix . 'mnbt_hosts',
60 array(
61 'expire_date' => $new_date,
62 'updated_at' => current_time( 'mysql' ),
63 ),
64 array( 'id' => (int) $host['id'] )
65 );
66
67 // 已到期/暂停的主机续费后恢复。
68 if ( in_array( $host['status'], array( 'expired', 'suspended' ), true ) ) {
69 try {
70 $client->resumeHost( $host['username'] );
71 $wpdb->update(
72 $wpdb->prefix . 'mnbt_hosts',
73 array( 'status' => 'active', 'updated_at' => current_time( 'mysql' ) ),
74 array( 'id' => (int) $host['id'] )
75 );
76 } catch ( \Exception $e ) { // 恢复失败不影响续费结果。
77 }
78 }
79
80 update_post_meta( $order_id, '_mnbtwp_renewed', '1' );
81 self::notify_renew( $host, $new_date );
82
83 return array( 'ok' => true, 'msg' => __( '续费成功', 'wp-seller-plugin' ), 'expire_date' => $new_date );
84 }
85
86 /**
87 * 每日到期维护:过期自动暂停 + 到期提醒。
88 */
89 public static function expire_maintenance() {
90 global $wpdb;
91
92 $settings = get_option( 'mnbtwp_settings', array() );
93 $grace_days = max( 0, (int) ( $settings['grace_days'] ?? 0 ) );
94 $remind_days = max( 0, (int) ( $settings['expire_days'] ?? 3 ) );
95
96 $hosts = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}mnbt_hosts WHERE status='active'", ARRAY_A );
97 $now = time();
98
99 foreach ( $hosts as $host ) {
100 if ( empty( $host['expire_date'] ) || '0000-00-00' === $host['expire_date'] ) {
101 continue;
102 }
103 $expire_ts = strtotime( $host['expire_date'] . ' 23:59:59' );
104
105 // 已过期且超宽限期 → 暂停。
106 if ( $expire_ts + $grace_days * DAY_IN_SECONDS < $now ) {
107 $provider = Helpers::get_provider( $host['provider_id'] );
108 if ( $provider ) {
109 try {
110 Helpers::client_for_provider( $provider )->suspendHost( $host['username'] );
111 $wpdb->update(
112 $wpdb->prefix . 'mnbt_hosts',
113 array( 'status' => 'expired', 'updated_at' => current_time( 'mysql' ) ),
114 array( 'id' => (int) $host['id'] )
115 );
116 } catch ( \Exception $e ) {
117 // 暂停失败留待下次维护重试。
118 }
119 }
120 continue;
121 }
122
123 // 到期前提醒(仅一次/每周期一次)。
124 if ( $remind_days > 0 ) {
125 $remind_ts = $expire_ts - $remind_days * DAY_IN_SECONDS;
126 if ( $now >= $remind_ts && $now < $expire_ts ) {
127 $last = $host['last_remind'] ? strtotime( $host['last_remind'] ) : 0;
128 if ( $last < $remind_ts ) {
129 self::send_expire_remind( $host );
130 $wpdb->update(
131 $wpdb->prefix . 'mnbt_hosts',
132 array( 'last_remind' => current_time( 'mysql' ) ),
133 array( 'id' => (int) $host['id'] )
134 );
135 }
136 }
137 }
138 }
139 }
140
141 /**
142 * 发送到期提醒邮件。
143 *
144 * @param array $host 主机行。
145 */
146 private static function send_expire_remind( array $host ) {
147 $user = get_userdata( (int) $host['user_id'] );
148 if ( ! $user || empty( $user->user_email ) ) {
149 return;
150 }
151 $subject = sprintf( __( '【%s】主机即将到期', 'wp-seller-plugin' ), get_bloginfo( 'name' ) );
152 $body = '<p>' . esc_html__( '您的主机即将到期,请及时续费以免暂停服务:', 'wp-seller-plugin' ) . '</p>'
153 . '<p>主机账号:<code>' . esc_html( $host['username'] ) . '</code></p>'
154 . '<p>' . esc_html__( '到期时间:', 'wp-seller-plugin' ) . esc_html( $host['expire_date'] ) . '</p>'
155 . '<p>' . esc_html__( '请在「我的主机」中点击续费完成支付。', 'wp-seller-plugin' ) . '</p>';
156 Helpers::send_mail( $user->user_email, $subject, $body );
157 }
158
159 /**
160 * 发送续费成功邮件。
161 *
162 * @param array $host 主机行。
163 * @param string $new_date 新到期日期。
164 */
165 private static function notify_renew( array $host, $new_date ) {
166 $user = get_userdata( (int) $host['user_id'] );
167 if ( ! $user || empty( $user->user_email ) ) {
168 return;
169 }
170 $subject = sprintf( __( '【%s】主机续费成功', 'wp-seller-plugin' ), get_bloginfo( 'name' ) );
171 $body = '<p>' . esc_html__( '您的主机已成功续费:', 'wp-seller-plugin' ) . '</p>'
172 . '<p>主机账号:<code>' . esc_html( $host['username'] ) . '</code></p>'
173 . '<p>' . esc_html__( '新到期时间:', 'wp-seller-plugin' ) . esc_html( $new_date ) . '</p>';
174 Helpers::send_mail( $user->user_email, $subject, $body );
175 }
176}