feat(payment): rebuild order details and asset records

This commit is contained in:
kate522 committed 2026-10-05 16:42:25 +08:00
1 parent 476e2f961d
commit 7b55cfb190
57 files changed
+2080 -1294

No files matched your search

+18 -23
View File
@@ -19,7 +19,7 @@ trait PayOrders {
*/
public function fulfill_paid_order(string $order_number, array $paid_order) {
$product_type = sanitize_key((string) ($paid_order['product_type'] ?? ''));
if ($product_type !== \AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE) {
if (!\AKSRT\Core\DomainModel::is_resource_product_type($product_type)) {
return true;
}
$post_id = (int) ($paid_order['product_id'] ?? 0);
@@ -131,7 +131,8 @@ trait PayOrders {
return $assert;
}
$priced = $assert['priced'];
$priced = $assert['priced'];
$content_type = \AKSRT\Core\DomainModel::resolve_order_product_type(\AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE, ['pay_type' => $assert['meta']['pay_type'] ?? '']);
if ((($priced['modo'] ?? '0') !== 'points')) {
return new \WP_Error('aksrt_wrong_modo', __('该内容不支持积分支付。', 'aksrt'), ['status' => 400]);
}
@@ -164,6 +165,7 @@ trait PayOrders {
$note = wp_json_encode([
'content_pay' => 1,
'pay_type' => (string) ($assert['meta']['pay_type'] ?? ''),
'pay_modo' => 'points',
'post_id' => $post_id,
'price_type' => $price_type,
@@ -178,7 +180,7 @@ trait PayOrders {
if (is_array($existing)) {
$existing_meta = $this->decode_order_note_meta($existing);
if ((int) ($existing['user_id'] ?? 0) !== $user_id
|| sanitize_key((string) ($existing['product_type'] ?? '')) !== \AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE
|| sanitize_key((string) ($existing['product_type'] ?? '')) !== $content_type
|| (int) ($existing['product_id'] ?? 0) !== $post_id
|| (string) ($existing['currency'] ?? '') !== 'points'
|| (int) ($existing['amount'] ?? 0) !== $amount
@@ -224,12 +226,12 @@ trait PayOrders {
sprintf(__('积分购买《%s》', 'aksrt'), get_the_title($post_id)),
$user_id,
['post_id' => $post_id],
static function () use ($is_new_order, $repo, $order_number, $operation_key, $user_id, $post_id, $amount, $note) {
static function () use ($is_new_order, $repo, $order_number, $operation_key, $user_id, $post_id, $amount, $note, $content_type) {
if ($is_new_order) {
$created = $repo->create([
'order_number' => $order_number,
'user_id' => $user_id,
'product_type' => \AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
'product_type' => $content_type,
'product_id' => $post_id,
'amount' => $amount,
'currency' => 'points',
@@ -245,7 +247,6 @@ trait PayOrders {
}
$paid = \AKSRT\Payment\Order::get_instance()->update_status($order_number, \AKSRT\Payment\Order::STATUS_PAID, [
'payment_method' => 'points',
'payment_transaction_id' => 'points_' . $order_number,
'note' => sprintf(__('积分支付 %d 积分。', 'aksrt'), $amount),
'require_transition' => true,
]);
@@ -264,9 +265,7 @@ trait PayOrders {
'amount' => $amount,
'pay_modo' => 'points',
'balance' => $ledger->balance($user_id, \AKSRT\Ledger\AssetType::POINTS),
'transaction_id' => $deducted->transaction_id,
'flow_number' => $deducted->flow_number,
'replayed' => $deducted->replayed,
'replayed' => $deducted->replayed,
'message' => __('支付成功', 'aksrt'),
'reload' => true,
],
@@ -289,6 +288,7 @@ trait PayOrders {
$post = $assert['post'];
$meta = $assert['meta'];
$priced = $assert['priced'];
$content_type = \AKSRT\Core\DomainModel::resolve_order_product_type(\AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE, ['pay_type' => $meta['pay_type'] ?? '']);
if ((($priced['modo'] ?? '0') === 'points')) {
return new \WP_Error('aksrt_wrong_modo', __('该内容仅支持积分支付。', 'aksrt'), ['status' => 400]);
}
@@ -331,6 +331,7 @@ trait PayOrders {
}
$note = wp_json_encode([
'content_pay' => 1,
'pay_type' => (string) ($meta['pay_type'] ?? ''),
'pay_modo' => '0',
'post_id' => $post_id,
'price_type' => $price_type,
@@ -355,7 +356,7 @@ trait PayOrders {
$replayed = is_array($existing);
if (is_array($existing)) {
if ((int) ($existing['user_id'] ?? 0) !== max(0, $user_id)
|| sanitize_key((string) ($existing['product_type'] ?? '')) !== \AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE
|| sanitize_key((string) ($existing['product_type'] ?? '')) !== $content_type
|| (int) ($existing['product_id'] ?? 0) !== $post_id
|| sanitize_key((string) ($existing['payment_method'] ?? '')) !== 'free'
|| (string) ($existing['amount'] ?? '') !== '0.00'
@@ -366,7 +367,7 @@ trait PayOrders {
} else {
$order_number = $repo->create([
'user_id' => max(0, $user_id),
'product_type' => \AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
'product_type' => $content_type,
'product_id' => $post_id,
'amount' => '0.00',
'currency' => 'CNY',
@@ -384,7 +385,7 @@ trait PayOrders {
if ($status !== \AKSRT\Payment\Order::STATUS_PAID) {
$paid = \AKSRT\Payment\Order::get_instance()->update_status($order_number, \AKSRT\Payment\Order::STATUS_PAID, [
'payment_method' => 'free',
'payment_transaction_id' => 'free_' . $order_number,
'payment_transaction_id' => '',
'note' => __('优惠后无需支付。', 'aksrt'),
]);
if (!$paid) {
@@ -398,7 +399,7 @@ trait PayOrders {
'amount' => '0.00',
'pay_modo' => '0',
'free' => true,
'transaction_id' => 'free_' . $order_number,
'transaction_id' => '',
'replayed' => $replayed,
'message' => __('无需支付,已可访问。', 'aksrt'),
'reload' => true,
@@ -430,7 +431,7 @@ trait PayOrders {
$pending_coupon = (string) ($pending_meta['coupon']['code'] ?? $pending_coupon);
}
$can_resume = (int) ($pending['user_id'] ?? 0) === max(0, $user_id)
&& sanitize_key((string) ($pending['product_type'] ?? '')) === \AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE
&& sanitize_key((string) ($pending['product_type'] ?? '')) === $content_type
&& (int) ($pending['product_id'] ?? 0) === $post_id
&& (string) ($pending['amount'] ?? '') === $amount_decimal
&& strtoupper((string) ($pending['currency'] ?? '')) === 'CNY'
@@ -448,6 +449,7 @@ trait PayOrders {
} else {
$note = wp_json_encode([
'content_pay' => 1,
'pay_type' => (string) ($meta['pay_type'] ?? ''),
'pay_modo' => '0',
'post_id' => $post_id,
'price_type' => $price_type,
@@ -469,7 +471,7 @@ trait PayOrders {
$order_number = \AKSRT\Payment\OrderRepository::get_instance()->create([
'user_id' => max(0, $user_id),
'product_type' => \AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
'product_type' => $content_type,
'product_id' => $post_id,
'amount' => $amount_decimal,
'currency' => 'CNY',
@@ -495,16 +497,12 @@ trait PayOrders {
$payment_method = $user_id > 0 ? 'balance' : 'alipay';
}
if ($can_resume && (string) ($order['status'] ?? '') === \AKSRT\Payment\Order::STATUS_PAID) {
$ledger_key = \AKSRT\Ledger\OperationKey::deterministic('order-payment', [$order_number]);
$history = \AKSRT\Ledger\LedgerQuery::get_instance()->history(['operation_key' => $ledger_key, 'page' => 1, 'per_page' => 1]);
return [
'success' => true,
'data' => [
'order_number' => $order_number,
'amount' => $amount_decimal,
'pay_modo' => '0',
'transaction_id' => (int) ($history['items'][0]['id'] ?? 0),
'flow_number' => \AKSRT\Finance\FinancialFlowQuery::get_instance()->order_payment_number($order_number),
'replayed' => true,
'balance' => \AKSRT\Ledger\LedgerService::get_instance()->balance_decimal($user_id),
'message' => __('支付成功', 'aksrt'),
@@ -559,7 +557,6 @@ trait PayOrders {
'message' => $payment_result['message'],
'reload' => false,
'poll' => true,
'transaction_id' => 0,
'replayed' => false,
],
];
@@ -571,7 +568,6 @@ trait PayOrders {
'order_number' => $order_number,
'amount' => $amount_decimal,
'pay_modo' => '0',
'transaction_id' => (int) ($payment_result['ledger_transaction_id'] ?? 0),
'replayed' => !empty($payment_result['replayed']),
'balance' => $user_id > 0 ? \AKSRT\Ledger\LedgerService::get_instance()->balance_decimal($user_id) : '0.00',
'message' => $payment_result['message'],
@@ -590,13 +586,12 @@ trait PayOrders {
return null;
}
$orders = \AKSRT\Payment\OrderRepository::get_instance()->get_user_orders($user_id, [
'product_type' => \AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
'status' => \AKSRT\Core\DomainModel::ORDER_STATUS_PENDING,
'limit' => 20,
'offset' => 0,
]);
foreach ($orders as $order) {
if ((int) ($order['product_id'] ?? 0) === $post_id) {
if ((int) ($order['product_id'] ?? 0) === $post_id && \AKSRT\Core\DomainModel::is_resource_product_type((string) ($order['product_type'] ?? ''))) {
return $order;
}
}
+1 -3
View File
@@ -179,9 +179,7 @@ trait PayRest {
$order = $repo->get($order_number);
// Guest may only poll own guest cash orders (user_id=0): content resource.
$ptype = sanitize_key((string) ($order['product_type'] ?? ''));
$guest_types = [
\AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
];
$guest_types = \AKSRT\Core\DomainModel::resource_order_product_types();
if ($order && ((int) ($order['user_id'] ?? -1) !== 0 || !in_array($ptype, $guest_types, true))) {
$order = null;
}
+10 -11
View File
@@ -411,8 +411,6 @@ trait VipServicePurchase {
return new \WP_Error('aksrt_order_create_failed', __('创建订单失败', 'aksrt'), ['status' => 500]);
}
if (is_array($existing) && (string) ($existing['status'] ?? '') === \AKSRT\Payment\Order::STATUS_PAID) {
$ledger_key = \AKSRT\Ledger\OperationKey::deterministic('order-payment', [$order_number]);
$history = \AKSRT\Ledger\LedgerQuery::get_instance()->history(['operation_key' => $ledger_key, 'page' => 1, 'per_page' => 1]);
return [
'success' => true,
'data' => [
@@ -421,8 +419,6 @@ trait VipServicePurchase {
'level' => $level,
'days' => $days,
'action' => $action,
'transaction_id' => (int) ($history['items'][0]['id'] ?? 0),
'flow_number' => \AKSRT\Finance\FinancialFlowQuery::get_instance()->order_payment_number($order_number),
'replayed' => true,
'balance' => \AKSRT\Ledger\LedgerService::get_instance()->balance_decimal($user_id),
'message' => __('会员购买已完成', 'aksrt'),
@@ -491,7 +487,6 @@ trait VipServicePurchase {
'message' => $payment_result['message'],
'reload' => false,
'poll' => true,
'transaction_id' => 0,
'replayed' => false,
],
];
@@ -505,7 +500,6 @@ trait VipServicePurchase {
'level' => $level,
'days' => $days,
'action' => $action,
'transaction_id' => (int) ($payment_result['ledger_transaction_id'] ?? 0),
'replayed' => !empty($payment_result['replayed']),
'balance' => \AKSRT\Ledger\LedgerService::get_instance()->balance_decimal($user_id),
'message' => $action === 'renew'
@@ -549,6 +543,7 @@ trait VipServicePurchase {
if (!empty($meta['card_pass']) || sanitize_key((string) ($meta['vip_pay_type'] ?? '')) === 'card_pass') {
return true;
}
$vip_before = $this->get_membership_snapshot($user_id);
$level = (int) ($meta['level'] ?? 0);
$days = (int) ($meta['days'] ?? 0);
@@ -611,9 +606,16 @@ trait VipServicePurchase {
$fulfilled = (int) get_user_meta($user_id, 'aksrt_vip_level', true) >= max($previous_level, $level)
&& ($new_expiry === 0 || $days <= 0 || $new_expiry >= max($previous_expiry, time()) + ($days * DAY_IN_SECONDS));
}
if (!$fulfilled) {
if (!$fulfilled) {
return new \WP_Error('aksrt_vip_fulfillment_failed', __('会员权益发放失败。', 'aksrt'), ['status' => 500]);
}
$vip_after = $this->get_membership_snapshot($user_id);
if (!\AKSRT\Payment\OrderRepository::get_instance()->merge_meta($order_number, [
'vip_before' => $vip_before,
'vip_after' => $vip_after,
])) {
return new \WP_Error('aksrt_vip_snapshot_failed', __('会员订单快照保存失败。', 'aksrt'), ['status' => 500]);
}
return true;
}
@@ -860,7 +862,6 @@ trait VipServicePurchase {
}
$paid = \AKSRT\Payment\Order::get_instance()->update_status($order_number, \AKSRT\Payment\Order::STATUS_PAID, [
'payment_method' => 'points',
'payment_transaction_id' => 'points_' . $order_number,
'note' => sprintf(__('积分兑换会员 %d 积分。', 'aksrt'), $cost),
'require_transition' => true,
]);
@@ -880,9 +881,7 @@ trait VipServicePurchase {
'level' => $level,
'days' => $days,
'balance' => $ledger->balance($user_id, \AKSRT\Ledger\AssetType::POINTS),
'transaction_id' => $deducted->transaction_id,
'flow_number' => $deducted->flow_number,
'replayed' => $deducted->replayed,
'replayed' => $deducted->replayed,
'message' => __('兑换成功', 'aksrt'),
'reload' => true,
],