feat(payment): 售后申请表单结构化入库(预置原因/申请资料/申请说明独立存储)
This commit is contained in:
1 parent
a0f59826fe
commit
00a087b1a4
1 file changed
+64
-4
@@ -30,6 +30,18 @@ final class AfterSaleService {
|
|||||||
['methods' => \WP_REST_Server::CREATABLE, 'callback' => [$this, 'rest_submit'], 'permission_callback' => [$this, 'require_user'], 'args' => [
|
['methods' => \WP_REST_Server::CREATABLE, 'callback' => [$this, 'rest_submit'], 'permission_callback' => [$this, 'require_user'], 'args' => [
|
||||||
'order_number' => ['required' => true, 'sanitize_callback' => 'sanitize_text_field'],
|
'order_number' => ['required' => true, 'sanitize_callback' => 'sanitize_text_field'],
|
||||||
'reason' => ['required' => true, 'sanitize_callback' => 'sanitize_textarea_field'],
|
'reason' => ['required' => true, 'sanitize_callback' => 'sanitize_textarea_field'],
|
||||||
|
'reason_label' => ['required' => false, 'sanitize_callback' => 'sanitize_text_field'],
|
||||||
|
'materials' => ['required' => false, 'type' => 'array', 'validate_callback' => static function ($value): bool {
|
||||||
|
if (!is_array($value) || count($value) > 10) return false;
|
||||||
|
foreach ($value as $item) {
|
||||||
|
if (!is_array($item)) return false;
|
||||||
|
foreach (['label', 'value'] as $key) {
|
||||||
|
if (isset($item[$key]) && !is_string($item[$key])) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}],
|
||||||
|
'description' => ['required' => false, 'sanitize_callback' => 'sanitize_textarea_field'],
|
||||||
'images' => ['required' => false, 'type' => 'array', 'validate_callback' => static function ($value): bool {
|
'images' => ['required' => false, 'type' => 'array', 'validate_callback' => static function ($value): bool {
|
||||||
return is_array($value) && count($value) <= 3;
|
return is_array($value) && count($value) <= 3;
|
||||||
}],
|
}],
|
||||||
@@ -82,7 +94,18 @@ final class AfterSaleService {
|
|||||||
|
|
||||||
public function rest_submit(\WP_REST_Request $request) {
|
public function rest_submit(\WP_REST_Request $request) {
|
||||||
$images = $request->get_param('images');
|
$images = $request->get_param('images');
|
||||||
$result = $this->create(get_current_user_id(), (string) $request->get_param('order_number'), (string) $request->get_param('reason'), is_array($images) ? $images : []);
|
$materials = $request->get_param('materials');
|
||||||
|
$result = $this->create(
|
||||||
|
get_current_user_id(),
|
||||||
|
(string) $request->get_param('order_number'),
|
||||||
|
(string) $request->get_param('reason'),
|
||||||
|
is_array($images) ? $images : [],
|
||||||
|
[
|
||||||
|
'reason_label' => (string) $request->get_param('reason_label'),
|
||||||
|
'materials' => is_array($materials) ? $materials : [],
|
||||||
|
'description' => (string) $request->get_param('description'),
|
||||||
|
]
|
||||||
|
);
|
||||||
return is_wp_error($result) ? $result : rest_ensure_response(['success' => true, 'data' => $result]);
|
return is_wp_error($result) ? $result : rest_ensure_response(['success' => true, 'data' => $result]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,9 +120,11 @@ final class AfterSaleService {
|
|||||||
return is_wp_error($result) ? $result : rest_ensure_response(['success' => true, 'data' => $result]);
|
return is_wp_error($result) ? $result : rest_ensure_response(['success' => true, 'data' => $result]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(int $user_id, string $order_number, string $reason, array $images = []) {
|
/** @param array<string,mixed> $apply_form */
|
||||||
|
public function create(int $user_id, string $order_number, string $reason, array $images = [], array $apply_form = []) {
|
||||||
$reason = sanitize_textarea_field($reason);
|
$reason = sanitize_textarea_field($reason);
|
||||||
$images = $this->sanitize_images($images);
|
$images = $this->sanitize_images($images);
|
||||||
|
$apply_form = $this->sanitize_apply_form($apply_form);
|
||||||
if ($user_id <= 0 || !preg_match('/^(?:\d{20}|\d{22})$/', $order_number) || $reason === '' || mb_strlen($reason) > 2000) {
|
if ($user_id <= 0 || !preg_match('/^(?:\d{20}|\d{22})$/', $order_number) || $reason === '' || mb_strlen($reason) > 2000) {
|
||||||
return new \WP_Error('aksrt_after_sale_invalid', __('请填写有效的售后原因', 'aksrt'), ['status' => 400]);
|
return new \WP_Error('aksrt_after_sale_invalid', __('请填写有效的售后原因', 'aksrt'), ['status' => 400]);
|
||||||
}
|
}
|
||||||
@@ -120,9 +145,11 @@ final class AfterSaleService {
|
|||||||
if ($amount === null) return new \WP_Error('aksrt_after_sale_amount', __('订单退款金额无效', 'aksrt'), ['status' => 400]);
|
if ($amount === null) return new \WP_Error('aksrt_after_sale_amount', __('订单退款金额无效', 'aksrt'), ['status' => 400]);
|
||||||
$inserted = $wpdb->insert($this->table(), [
|
$inserted = $wpdb->insert($this->table(), [
|
||||||
'order_number' => $order_number, 'user_id' => $user_id, 'aftersale_type' => 'refund',
|
'order_number' => $order_number, 'user_id' => $user_id, 'aftersale_type' => 'refund',
|
||||||
'reason' => $reason, 'images' => wp_json_encode($images), 'refund_amount' => $amount,
|
'reason' => $reason,
|
||||||
|
'apply_form' => $apply_form === [] ? null : wp_json_encode($apply_form, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
|
||||||
|
'images' => wp_json_encode($images), 'refund_amount' => $amount,
|
||||||
'status' => self::STATUS_PENDING, 'created_at' => current_time('mysql'),
|
'status' => self::STATUS_PENDING, 'created_at' => current_time('mysql'),
|
||||||
], ['%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s']);
|
], ['%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s']);
|
||||||
return $inserted === 1 ? $this->get((int) $wpdb->insert_id) : new \WP_Error('aksrt_after_sale_db', __('售后申请保存失败', 'aksrt'), ['status' => 500]);
|
return $inserted === 1 ? $this->get((int) $wpdb->insert_id) : new \WP_Error('aksrt_after_sale_db', __('售后申请保存失败', 'aksrt'), ['status' => 500]);
|
||||||
} finally {
|
} finally {
|
||||||
$wpdb->get_var($wpdb->prepare('SELECT RELEASE_LOCK(%s)', $lock));
|
$wpdb->get_var($wpdb->prepare('SELECT RELEASE_LOCK(%s)', $lock));
|
||||||
@@ -144,6 +171,37 @@ final class AfterSaleService {
|
|||||||
return $clean;
|
return $clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结构化申请表单(预置原因 / 申请资料 / 申请说明),供售后详细弹窗分行展示;
|
||||||
|
* 融合字符串 reason 保持原样入库,保证后台列表与历史数据兼容。
|
||||||
|
*
|
||||||
|
* @param array<string,mixed> $form
|
||||||
|
* @return array<string,mixed>
|
||||||
|
*/
|
||||||
|
private function sanitize_apply_form(array $form): array {
|
||||||
|
$reason_label = sanitize_text_field((string) ($form['reason_label'] ?? ''));
|
||||||
|
if (mb_strlen($reason_label) > 120) $reason_label = mb_substr($reason_label, 0, 120);
|
||||||
|
$materials = [];
|
||||||
|
if (is_array($form['materials'] ?? null)) {
|
||||||
|
foreach ($form['materials'] as $item) {
|
||||||
|
if (!is_array($item) || count($materials) >= 10) continue;
|
||||||
|
$label = sanitize_text_field((string) ($item['label'] ?? ''));
|
||||||
|
$value = sanitize_text_field((string) ($item['value'] ?? ''));
|
||||||
|
if ($label === '' || $value === '') continue;
|
||||||
|
if (mb_strlen($label) > 120) $label = mb_substr($label, 0, 120);
|
||||||
|
if (mb_strlen($value) > 500) $value = mb_substr($value, 0, 500);
|
||||||
|
$materials[] = ['label' => $label, 'value' => $value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$description = sanitize_textarea_field((string) ($form['description'] ?? ''));
|
||||||
|
if (mb_strlen($description) > 2000) $description = mb_substr($description, 0, 2000);
|
||||||
|
$clean = [];
|
||||||
|
if ($reason_label !== '') $clean['reason_label'] = $reason_label;
|
||||||
|
if ($materials !== []) $clean['materials'] = $materials;
|
||||||
|
if ($description !== '') $clean['description'] = $description;
|
||||||
|
return $clean;
|
||||||
|
}
|
||||||
|
|
||||||
/** 最新一条售后工单(列表视图只取最新态,避免整表拉取)。 */
|
/** 最新一条售后工单(列表视图只取最新态,避免整表拉取)。 */
|
||||||
public function latest_for_order(string $order_number): ?array {
|
public function latest_for_order(string $order_number): ?array {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
@@ -615,6 +673,8 @@ final class AfterSaleService {
|
|||||||
$row['images'] = is_array($images)
|
$row['images'] = is_array($images)
|
||||||
? array_values(array_filter($images, static fn($url): bool => is_string($url) && $url !== ''))
|
? array_values(array_filter($images, static fn($url): bool => is_string($url) && $url !== ''))
|
||||||
: [];
|
: [];
|
||||||
|
$apply_form = json_decode((string) ($row['apply_form'] ?? ''), true);
|
||||||
|
$row['apply_form'] = is_array($apply_form) ? $apply_form : null;
|
||||||
return $row;
|
return $row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user