fix(user-center): complete certification and order flows

Fix modal scroll ownership and certification modal styling, store evidence as Media Library attachments, reconcile missed provider callbacks, validate currencies, and complete digital fulfillment only after durable entitlement delivery.
This commit is contained in:
kate522 committed 2026-07-29 10:29:59 +08:00
1 parent b945c6e835
commit 815e83bac0
26 files changed
+613 -148

No files matched your search

+64 -22
View File
@@ -65,7 +65,7 @@ trait Part3 {
];
}
public function execute_auto_delivery(int $product_id, string $options_key, int $qty, int $user_id, string $order_number): string {
public function execute_auto_delivery(int $product_id, string $options_key, int $qty, int $user_id, string $order_number, int $order_item_id = 0): string {
$config = $this->get_auto_delivery_config($product_id);
$type = $config['type'];
@@ -77,7 +77,7 @@ trait Part3 {
return (string) ($config['opts'][$key] ?? $config['content']);
}
if ($type === 'card_pass') {
return $this->consume_card_keys($product_id, $options_key, $qty, $user_id, $order_number);
return $this->consume_card_keys($product_id, $options_key, $qty, $user_id, $order_number, $order_item_id);
}
if ($type === 'invit_code') {
return $this->create_invite_codes($qty, $user_id, $order_number);
@@ -85,10 +85,20 @@ trait Part3 {
return '';
}
private function consume_card_keys(int $product_id, string $options_key, int $qty, int $user_id, string $order_number): string {
private function auto_delivery_succeeded(int $product_id, string $content, int $qty): bool {
$config = $this->get_auto_delivery_config($product_id);
if (in_array($config['type'], ['card_pass', 'invit_code'], true)) {
$lines = array_values(array_filter(array_map('trim', preg_split('/\r\n|\r|\n/', $content) ?: [])));
return count($lines) === max(1, $qty)
&& !in_array($content, [__('卡密已售罄', 'aksrt'), __('邀请系统不可用', 'aksrt')], true);
}
return trim($content) !== '';
}
private function consume_card_keys(int $product_id, string $options_key, int $qty, int $user_id, string $order_number, int $order_item_id): string {
global $wpdb;
$table = \AKSRT\Core\DBMigrator::table('card_key');
if ($table === '') return '';
if ($table === '' || $order_item_id <= 0 || $wpdb->query('START TRANSACTION') === false) return '';
$where_opt = '';
$params = [$product_id];
@@ -101,28 +111,39 @@ trait Part3 {
$params[] = $qty;
$keys = $wpdb->get_results($wpdb->prepare(
"SELECT id, card_code FROM {$table} WHERE product_id = %d AND status = 'available'{$where_opt} ORDER BY id ASC LIMIT %d",
"SELECT id, card_code FROM {$table} WHERE product_id = %d AND status = 'available'{$where_opt} ORDER BY id ASC LIMIT %d FOR UPDATE",
...$params
), ARRAY_A);
if (empty($keys)) {
if (count((array) $keys) !== $qty) {
$wpdb->query('ROLLBACK');
return __('卡密已售罄', 'aksrt');
}
$codes = [];
$ids = [];
foreach ($keys as $k) {
$codes[] = $k['card_code'];
$ids[] = (int) $k['id'];
foreach ($keys as $key) {
$codes[] = (string) $key['card_code'];
$ids[] = (int) $key['id'];
}
if (!empty($ids)) {
$placeholders = implode(',', array_fill(0, count($ids), '%d'));
$wpdb->query($wpdb->prepare(
"UPDATE {$table} SET status = 'used', order_number = %s, used_by = %d, used_at = %s WHERE id IN ({$placeholders})",
array_merge([$order_number, $user_id, current_time('mysql')], $ids)
));
$placeholders = implode(',', array_fill(0, count($ids), '%d'));
$updated = $wpdb->query($wpdb->prepare(
"UPDATE {$table} SET status = 'used', order_number = %s, used_by = %d, used_at = %s WHERE status = 'available' AND id IN ({$placeholders})",
array_merge([$order_number, $user_id, current_time('mysql')], $ids)
));
$content = implode("\n", $codes);
$item_table = $this->order_item_table();
$persisted = $item_table !== '' ? $wpdb->update(
$item_table,
['auto_delivery_content' => $content],
['id' => $order_item_id, 'order_number' => $order_number],
['%s'],
['%d', '%s']
) : false;
if ($updated !== $qty || $persisted === false || $wpdb->query('COMMIT') === false) {
$wpdb->query('ROLLBACK');
return '';
}
return implode("\n", $codes);
return $content;
}
private function create_invite_codes(int $qty, int $user_id, string $order_number): string {
@@ -221,6 +242,7 @@ trait Part3 {
$user_id = (int) ($order['user_id'] ?? 0);
$auto_delivery_parts = [];
$auto_delivery_successes = 0;
foreach ($items as $item) {
$pid = (int) $item['product_id'];
@@ -235,10 +257,16 @@ trait Part3 {
$shipping_type = (string) get_post_meta($pid, '_aksrt_shipping_type', true);
if ($shipping_type === 'auto') {
$content = $this->execute_auto_delivery($pid, $opt_key, $qty, $user_id, $order_number);
$content = $this->execute_auto_delivery($pid, $opt_key, $qty, $user_id, $order_number, (int) $item['id']);
if ($content !== '') {
$auto_delivery_parts[] = $content;
$this->update_order_item_delivery($item['id'], $content);
$config = $this->get_auto_delivery_config($pid);
$persisted = $config['type'] === 'card_pass'
? true
: $this->update_order_item_delivery($item['id'], $content);
if ($persisted && $this->auto_delivery_succeeded($pid, $content, $qty)) {
$auto_delivery_successes++;
}
}
}
}
@@ -250,14 +278,28 @@ trait Part3 {
$this->send_auto_delivery_notification($user_id, $order_number, $auto_delivery_parts);
}
if ($auto_delivery_successes === count($items) && class_exists('\AKSRT\Payment\OrderRepository')) {
\AKSRT\Payment\OrderRepository::get_instance()->update_status(
$order_number,
\AKSRT\Payment\Order::STATUS_COMPLETED,
['note' => __('自动发货订单已完成。', 'aksrt')]
);
}
do_action('aksrt_shop_fulfillment_done', $order_number, $order, $items);
}
private function update_order_item_delivery(int $item_id, string $content): void {
private function update_order_item_delivery(int $item_id, string $content): bool {
global $wpdb;
$table = $this->order_item_table();
if ($table === '') return;
$wpdb->update($table, ['auto_delivery_content' => $content], ['id' => $item_id], ['%s'], ['%d']);
if ($table === '') return false;
$updated = $wpdb->update($table, ['auto_delivery_content' => $content], ['id' => $item_id], ['%s'], ['%d']);
if ($updated === false) return false;
if ($updated === 0) {
$stored = $wpdb->get_var($wpdb->prepare("SELECT auto_delivery_content FROM {$table} WHERE id = %d", $item_id));
return is_string($stored) && hash_equals($stored, $content);
}
return true;
}
private function send_auto_delivery_notification(int $user_id, string $order_number, array $parts): void {