diff --git a/src/AKSRT/Payment/Gateway.php b/src/AKSRT/Payment/Gateway.php index 5ec22dd5..dd741ec5 100644 --- a/src/AKSRT/Payment/Gateway.php +++ b/src/AKSRT/Payment/Gateway.php @@ -227,16 +227,21 @@ class Gateway { * @return bool */ public function complete_order(string $gateway_id, array $verify): bool { - $order_number = sanitize_text_field((string) ($verify['order_number'] ?? '')); - if ($order_number === '' || !class_exists('AKSRT\\Payment\\OrderRepository')) { + $provider_out_trade_no = sanitize_text_field((string) ($verify['order_number'] ?? '')); + if ($provider_out_trade_no === '' || !class_exists('AKSRT\\Payment\\OrderRepository')) { return false; } $repo = OrderRepository::get_instance(); - $order = $repo->get($order_number); + // Callbacks may carry attempt-suffixed out_trade_no (…P2); map back to local order. + $order = $repo->resolve_by_out_trade_no($provider_out_trade_no); if (!$order) { return false; } + $order_number = sanitize_text_field((string) ($order['order_number'] ?? '')); + if ($order_number === '') { + return false; + } $stored_gateway = sanitize_key((string) ($order['payment_method'] ?? '')); if ($stored_gateway === '' || !hash_equals($stored_gateway, sanitize_key($gateway_id))) { @@ -253,8 +258,9 @@ class Gateway { || abs($expected - $paid_amount) > 0.01) { if (defined('WP_DEBUG') && WP_DEBUG) { error_log(sprintf( - '[AKSRT Payment] invalid completion order=%s expected=%.2f paid=%.2f transaction=%s gateway=%s', + '[AKSRT Payment] invalid completion order=%s out_trade_no=%s expected=%.2f paid=%.2f transaction=%s gateway=%s', $order_number, + $provider_out_trade_no, $expected, $paid_amount, $transaction_id !== '' ? 'present' : 'missing', diff --git a/src/AKSRT/Payment/Gateways/AlipayGateway.php b/src/AKSRT/Payment/Gateways/AlipayGateway.php index c920203d..1246e15d 100644 --- a/src/AKSRT/Payment/Gateways/AlipayGateway.php +++ b/src/AKSRT/Payment/Gateways/AlipayGateway.php @@ -40,11 +40,17 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface { } $order_number = (string) ($order['order_number'] ?? ''); + $out_trade_no = (string) ($order['out_trade_no'] ?? ''); + if ($out_trade_no === '') { + $out_trade_no = class_exists('\AKSRT\Payment\OrderRepository') + ? \AKSRT\Payment\OrderRepository::provider_out_trade_no($order) + : $order_number; + } $amount = (float) ($order['amount'] ?? 0); $subject = (string) ($order['subject'] ?? __('订单支付', 'aksrt')); $payment_type = $this->get_config()['payment_type']; - if ($order_number === '' || $amount <= 0) { + if ($order_number === '' || $out_trade_no === '' || $amount <= 0) { return ['success' => false, 'message' => __('订单参数无效', 'aksrt')]; } @@ -53,7 +59,7 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface { $payload = [ '_method' => 'GET', - 'out_trade_no' => $order_number, + 'out_trade_no' => $out_trade_no, 'total_amount' => number_format($amount, 2, '.', ''), 'subject' => mb_substr($subject, 0, 256), ]; @@ -70,7 +76,10 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface { return [ 'success' => true, 'payment_url' => $payment_url, - 'payment_data' => ['order_number' => $order_number], + 'payment_data' => [ + 'order_number' => $order_number, + 'out_trade_no' => $out_trade_no, + ], 'message' => __('支付宝支付链接已生成', 'aksrt'), ]; } catch (\Throwable $e) { @@ -140,10 +149,12 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface { return ['success' => false, 'message' => __('支付宝未配置', 'aksrt')]; } + $out_trade_no = $this->resolve_out_trade_no($order_number); + try { YansongdaPayFactory::boot_alipay(); $result = Pay::alipay()->query([ - 'out_trade_no' => $order_number, + 'out_trade_no' => $out_trade_no, ]); $data = YansongdaPayFactory::to_array($result); @@ -157,7 +168,8 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface { return [ 'success' => true, - 'order_number' => (string) ($data['out_trade_no'] ?? $order_number), + // Keep provider out_trade_no for Gateway::complete_order resolve. + 'order_number' => (string) ($data['out_trade_no'] ?? $out_trade_no), 'amount' => (float) ($data['total_amount'] ?? 0), 'transaction_id' => (string) ($data['trade_no'] ?? ''), 'status' => $status, @@ -167,6 +179,25 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface { } } + /** + * Best-effort close of a previous provider trade before re-pay. + */ + public function close_trade(string $out_trade_no): void { + $out_trade_no = sanitize_text_field($out_trade_no); + if ($out_trade_no === '' || !$this->is_configured()) { + return; + } + try { + YansongdaPayFactory::boot_alipay(); + // alipay.trade.close — supported by yansongda as close(). + Pay::alipay()->close([ + 'out_trade_no' => $out_trade_no, + ]); + } catch (\Throwable $e) { + // ignore + } + } + public function refund(string $order_number, float $amount, string $request_id = ''): array { if ($amount <= 0) { return ['success' => false, 'status' => 'failed', 'message' => __('退款金额无效', 'aksrt')]; @@ -175,6 +206,8 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface { return ['success' => false, 'message' => __('支付宝未配置', 'aksrt')]; } + $out_trade_no = $this->resolve_out_trade_no($order_number); + try { YansongdaPayFactory::boot_alipay(); $refund_request_id = (string) preg_replace( @@ -183,7 +216,7 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface { $request_id !== '' ? $request_id : $order_number . '_refund' ); $result = Pay::alipay()->refund([ - 'out_trade_no' => $order_number, + 'out_trade_no' => $out_trade_no, 'refund_amount' => number_format($amount, 2, '.', ''), 'refund_reason' => __('用户申请退款', 'aksrt'), 'out_request_no' => $refund_request_id, @@ -216,7 +249,7 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface { YansongdaPayFactory::boot_alipay(); $params = ['out_request_no' => $request_id, '_action' => 'refund']; if ($order_number !== '') { - $params['out_trade_no'] = $order_number; + $params['out_trade_no'] = $this->resolve_out_trade_no($order_number); } $result = Pay::alipay()->query($params); $data = YansongdaPayFactory::to_array($result); @@ -255,4 +288,17 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface { 'payment_type' => $type, ]; } + + /** + * Map local order_number → provider out_trade_no (supports resume attempts). + */ + private function resolve_out_trade_no(string $order_number): string { + if (class_exists('\AKSRT\Payment\OrderRepository')) { + $order = \AKSRT\Payment\OrderRepository::get_instance()->get($order_number); + if ($order) { + return \AKSRT\Payment\OrderRepository::provider_out_trade_no($order); + } + } + return $order_number; + } } diff --git a/src/AKSRT/Payment/Gateways/EpayGateway.php b/src/AKSRT/Payment/Gateways/EpayGateway.php index 716a7c9e..4e40cedf 100644 --- a/src/AKSRT/Payment/Gateways/EpayGateway.php +++ b/src/AKSRT/Payment/Gateways/EpayGateway.php @@ -44,9 +44,15 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface { } $order_number = (string) ($order['order_number'] ?? ''); + $out_trade_no = (string) ($order['out_trade_no'] ?? ''); + if ($out_trade_no === '') { + $out_trade_no = class_exists('\AKSRT\Payment\OrderRepository') + ? \AKSRT\Payment\OrderRepository::provider_out_trade_no($order) + : $order_number; + } $amount = (float) ($order['amount'] ?? 0); $subject = (string) ($order['subject'] ?? __('订单支付', 'aksrt')); - if ($order_number === '' || $amount <= 0) { + if ($order_number === '' || $out_trade_no === '' || $amount <= 0) { return ['success' => false, 'message' => __('订单参数无效', 'aksrt')]; } @@ -54,7 +60,7 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface { $params = [ 'pid' => $config['pid'], 'type' => $this->channel, - 'out_trade_no' => $order_number, + 'out_trade_no' => $out_trade_no, 'notify_url' => rest_url('aksrt/v1/payment/' . $this->get_id() . '/notify'), 'return_url' => rest_url('aksrt/v1/payment/' . $this->get_id() . '/return'), 'name' => mb_substr(wp_strip_all_tags($subject), 0, 127), @@ -78,7 +84,7 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface { $body = json_decode((string) wp_remote_retrieve_body($response), true); if (!is_array($body)) { // Fall back to browser submit if mapi is unavailable. - return $this->browser_submit_result($config['apiurl'], $params, $order_number); + return $this->browser_submit_result($config['apiurl'], $params, $order_number, $out_trade_no); } $code = (int) ($body['code'] ?? 0); if ($code !== 1) { @@ -94,6 +100,7 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface { 'success' => true, 'payment_data' => [ 'order_number' => $order_number, + 'out_trade_no' => $out_trade_no, 'code_url' => $qrcode, 'channel' => $this->channel, ], @@ -107,7 +114,7 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface { return $result; } - return $this->browser_submit_result($config['apiurl'], $params, $order_number); + return $this->browser_submit_result($config['apiurl'], $params, $order_number, $out_trade_no); } public function verify_callback(\WP_REST_Request $request): array { @@ -177,13 +184,14 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface { return ['success' => false, 'message' => __('易支付未配置', 'aksrt')]; } + $out_trade_no = $this->resolve_out_trade_no($order_number); $config = $this->get_config(); // Common compatible query: api.php?act=order&pid&key&out_trade_no $url = add_query_arg([ 'act' => 'order', 'pid' => $config['pid'], 'key' => $config['key'], - 'out_trade_no' => $order_number, + 'out_trade_no' => $out_trade_no, ], $this->endpoint($config['apiurl'], 'api.php')); $response = wp_remote_get($url, ['timeout' => 20]); @@ -205,7 +213,7 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface { return [ 'success' => true, - 'order_number' => (string) ($body['out_trade_no'] ?? $order_number), + 'order_number' => (string) ($body['out_trade_no'] ?? $out_trade_no), 'amount' => $amount, 'transaction_id' => $tx, 'status' => $paid ? 'paid' : 'pending', @@ -297,16 +305,34 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface { * @param array $params * @return array{success:bool,payment_url?:string,payment_data?:array,message?:string} */ - private function browser_submit_result(string $apiurl, array $params, string $order_number): array { + /** + * @param array $params + * @return array{success:bool,payment_url?:string,payment_data?:array,message?:string} + */ + private function browser_submit_result(string $apiurl, array $params, string $order_number, string $out_trade_no = ''): array { $url = add_query_arg($params, $this->endpoint($apiurl, 'submit.php')); return [ 'success' => true, 'payment_url' => $url, 'payment_data' => [ 'order_number' => $order_number, + 'out_trade_no' => $out_trade_no !== '' ? $out_trade_no : $order_number, 'channel' => $this->channel, ], 'message' => __('易支付支付链接已生成', 'aksrt'), ]; } + + /** + * Map local order_number → provider out_trade_no (supports resume attempts). + */ + private function resolve_out_trade_no(string $order_number): string { + if (class_exists('\AKSRT\Payment\OrderRepository')) { + $order = \AKSRT\Payment\OrderRepository::get_instance()->get($order_number); + if ($order) { + return \AKSRT\Payment\OrderRepository::provider_out_trade_no($order); + } + } + return $order_number; + } } diff --git a/src/AKSRT/Payment/Gateways/WechatPayGateway.php b/src/AKSRT/Payment/Gateways/WechatPayGateway.php index 95b2af22..0a2ef90d 100644 --- a/src/AKSRT/Payment/Gateways/WechatPayGateway.php +++ b/src/AKSRT/Payment/Gateways/WechatPayGateway.php @@ -40,12 +40,19 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface { } $order_number = (string) ($order['order_number'] ?? ''); + // Prefer attempt-specific out_trade_no so re-pay does not reuse a frozen provider order. + $out_trade_no = (string) ($order['out_trade_no'] ?? ''); + if ($out_trade_no === '') { + $out_trade_no = class_exists('\AKSRT\Payment\OrderRepository') + ? \AKSRT\Payment\OrderRepository::provider_out_trade_no($order) + : $order_number; + } $amount = (float) ($order['amount'] ?? 0); $subject = (string) ($order['subject'] ?? __('订单支付', 'aksrt')); $payment_type = $this->get_config()['payment_type']; $total_fen = (int) round($amount * 100); - if ($order_number === '' || $total_fen <= 0) { + if ($order_number === '' || $out_trade_no === '' || $total_fen <= 0) { return ['success' => false, 'message' => __('订单参数无效', 'aksrt')]; } @@ -53,7 +60,7 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface { YansongdaPayFactory::boot_wechat(); $payload = [ - 'out_trade_no' => $order_number, + 'out_trade_no' => $out_trade_no, 'description' => mb_substr($subject, 0, 127), 'amount' => [ 'total' => $total_fen, @@ -76,7 +83,10 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface { } $data = YansongdaPayFactory::to_array($result); - $payment_data = array_merge($data, ['order_number' => $order_number]); + $payment_data = array_merge($data, [ + 'order_number' => $order_number, + 'out_trade_no' => $out_trade_no, + ]); $result_data = [ 'success' => true, @@ -206,11 +216,13 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface { return ['success' => false, 'message' => __('微信支付未配置', 'aksrt')]; } + $out_trade_no = $this->resolve_out_trade_no($order_number); + try { YansongdaPayFactory::boot_wechat(); $action = $this->query_action(); $result = Pay::wechat()->query([ - 'out_trade_no' => $order_number, + 'out_trade_no' => $out_trade_no, '_action' => $action, ]); $data = YansongdaPayFactory::to_array($result); @@ -227,7 +239,8 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface { return [ 'success' => true, - 'order_number' => (string) ($data['out_trade_no'] ?? $order_number), + // Keep provider out_trade_no so Gateway::complete_order can resolve the local order. + 'order_number' => (string) ($data['out_trade_no'] ?? $out_trade_no), 'amount' => ((int) YansongdaPayFactory::dig($data, 'amount.total', 0)) / 100, 'transaction_id' => (string) ($data['transaction_id'] ?? ''), 'status' => $status, @@ -237,17 +250,38 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface { } } + /** + * Best-effort close of a previous provider trade before re-pay. + */ + public function close_trade(string $out_trade_no): void { + $out_trade_no = sanitize_text_field($out_trade_no); + if ($out_trade_no === '' || !$this->is_configured()) { + return; + } + try { + YansongdaPayFactory::boot_wechat(); + Pay::wechat()->close([ + 'out_trade_no' => $out_trade_no, + '_action' => $this->query_action(), + ]); + } catch (\Throwable $e) { + // ignore — new attempt still uses a fresh out_trade_no + } + } + public function refund(string $order_number, float $amount, string $request_id = ''): array { if (!$this->is_configured()) { return ['success' => false, 'message' => __('微信支付未配置', 'aksrt')]; } + $out_trade_no = $this->resolve_out_trade_no($order_number); + try { YansongdaPayFactory::boot_wechat(); $action = $this->query_action(); $query = Pay::wechat()->query([ - 'out_trade_no' => $order_number, + 'out_trade_no' => $out_trade_no, '_action' => $action, ]); $q = YansongdaPayFactory::to_array($query); @@ -267,7 +301,7 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface { ); $result = Pay::wechat()->refund([ '_action' => 'refund_' . $action, - 'out_trade_no' => $order_number, + 'out_trade_no' => $out_trade_no, 'out_refund_no' => $refund_request_id, 'reason' => __('用户申请退款', 'aksrt'), 'amount' => [ @@ -350,4 +384,17 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface { $type = $this->get_config()['payment_type']; return $map[$type] ?? 'native'; } + + /** + * Map local order_number → provider out_trade_no (supports resume attempts). + */ + private function resolve_out_trade_no(string $order_number): string { + if (class_exists('\AKSRT\Payment\OrderRepository')) { + $order = \AKSRT\Payment\OrderRepository::get_instance()->get($order_number); + if ($order) { + return \AKSRT\Payment\OrderRepository::provider_out_trade_no($order); + } + } + return $order_number; + } } diff --git a/src/AKSRT/Payment/OrderRepositoryCore.php b/src/AKSRT/Payment/OrderRepositoryCore.php index eb68cddc..c5493805 100644 --- a/src/AKSRT/Payment/OrderRepositoryCore.php +++ b/src/AKSRT/Payment/OrderRepositoryCore.php @@ -510,4 +510,135 @@ trait OrderRepositoryCore { return 'AKS' . date('YmdHis') . str_pad((string) random_int(0, 9999), 4, '0', STR_PAD_LEFT); } + /** + * Merge keys into the order note JSON payload (meta_payload). + * + * @param array $patch + */ + public function merge_meta(string $order_number, array $patch): bool { + global $wpdb; + + $order = $this->get($order_number); + if (!$order) { + return false; + } + + $meta = is_array($order['meta_payload'] ?? null) ? $order['meta_payload'] : []; + foreach ($patch as $key => $value) { + $meta[(string) $key] = $value; + } + + $encoded = wp_json_encode($meta, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + if (!is_string($encoded)) { + return false; + } + + $updated = $wpdb->update( + $this->table(), + ['note' => $encoded], + ['order_number' => $order_number], + ['%s'], + ['%s'] + ); + + return $updated !== false; + } + + /** + * Resolve a local order from a provider out_trade_no (base or attempt-suffixed). + */ + public function resolve_by_out_trade_no(string $out_trade_no): ?array { + $out_trade_no = sanitize_text_field($out_trade_no); + if ($out_trade_no === '') { + return null; + } + + $direct = $this->get($out_trade_no); + if ($direct) { + return $direct; + } + + // Resume attempts: {order_number}P{n} + if (preg_match('/^(AKS[0-9]{10,})P([0-9]{1,3})$/', $out_trade_no, $m)) { + $base = $this->get($m[1]); + if ($base) { + return $base; + } + } + + return null; + } + + /** + * Provider out_trade_no currently bound to this order (falls back to order_number). + * + * @param array $order + */ + public static function provider_out_trade_no(array $order): string { + $meta = is_array($order['meta_payload'] ?? null) ? $order['meta_payload'] : []; + $out = sanitize_text_field((string) ($meta['provider_out_trade_no'] ?? '')); + if ($out !== '') { + return $out; + } + return sanitize_text_field((string) ($order['order_number'] ?? '')); + } + + /** + * Allocate a new provider out_trade_no for a payment attempt. + * First attempt uses bare order_number; later attempts append Pn (WeChat limit 32). + * + * @return array{out_trade_no:string,attempt:int,previous:string}|null + */ + public function allocate_payment_attempt(string $order_number): ?array { + $order = $this->get($order_number); + if (!$order) { + return null; + } + + $meta = is_array($order['meta_payload'] ?? null) ? $order['meta_payload'] : []; + $previous = sanitize_text_field((string) ($meta['provider_out_trade_no'] ?? '')); + $history = is_array($meta['provider_out_trade_nos'] ?? null) ? $meta['provider_out_trade_nos'] : []; + + // First provider submission keeps the bare order number. + // Re-pay (provider_out_trade_no already set) always mints a new suffix so + // WeChat/Alipay/Epay accept the order when amount/subject/notify changed. + if ($previous === '') { + $attempt = 1; + $out = $order_number; + } else { + $attempt = max(1, (int) ($meta['pay_attempt'] ?? 1)) + 1; + $suffix = 'P' . $attempt; + $base = $order_number; + if (strlen($base) + strlen($suffix) > 32) { + $base = substr($base, 0, 32 - strlen($suffix)); + } + $out = $base . $suffix; + if ($previous !== '' && !in_array($previous, $history, true)) { + $history[] = $previous; + } + } + + if (!in_array($out, $history, true)) { + $history[] = $out; + } + if (count($history) > 20) { + $history = array_slice($history, -20); + } + + $ok = $this->merge_meta($order_number, [ + 'pay_attempt' => $attempt, + 'provider_out_trade_no' => $out, + 'provider_out_trade_nos' => array_values($history), + ]); + if (!$ok) { + return null; + } + + return [ + 'out_trade_no' => $out, + 'attempt' => $attempt, + 'previous' => $previous, + ]; + } + } diff --git a/src/AKSRT/Payment/UserOrders.php b/src/AKSRT/Payment/UserOrders.php index ab4ac488..83f4911b 100644 --- a/src/AKSRT/Payment/UserOrders.php +++ b/src/AKSRT/Payment/UserOrders.php @@ -337,6 +337,26 @@ class UserOrders { try { $order['subject'] = $order['subject'] ?? sprintf(__('订单 %s', 'aksrt'), $order_number); + + $needs_attempt = !in_array($payment_method, ['balance', 'points'], true); + if ($needs_attempt) { + $attempt = $repo->allocate_payment_attempt($order_number); + if ($attempt === null) { + return ['success' => false, 'message' => __('无法生成支付单号,请稍后重试。', 'aksrt')]; + } + $order = $repo->get_user_order($user_id, $order_number) ?: $order; + $order['out_trade_no'] = (string) $attempt['out_trade_no']; + if (!empty($attempt['previous']) + && $attempt['previous'] !== $attempt['out_trade_no'] + && method_exists($gateway, 'close_trade')) { + try { + $gateway->close_trade((string) $attempt['previous']); + } catch (\Throwable $e) { + // best-effort + } + } + } + $payment_result = $gateway->create_payment($order); if (empty($payment_result['success'])) { return ['success' => false, 'message' => $payment_result['message'] ?? __('支付失败。', 'aksrt')]; diff --git a/src/AKSRT/Shop/CheckoutService.php b/src/AKSRT/Shop/CheckoutService.php index 6677d7e9..13837b9f 100644 --- a/src/AKSRT/Shop/CheckoutService.php +++ b/src/AKSRT/Shop/CheckoutService.php @@ -226,6 +226,28 @@ class CheckoutService { return $this->pay_with_points($user_id, $order_number, $order); } + // External gateways: allocate a fresh out_trade_no so re-pay works when + // the provider rejects "same order number with changed params". + $needs_attempt = !in_array($payment_method, ['balance', 'points'], true); + if ($needs_attempt && class_exists('\AKSRT\Payment\OrderRepository')) { + $attempt = $repo->allocate_payment_attempt($order_number); + if ($attempt === null) { + return ['success' => false, 'message' => __('无法生成支付单号,请稍后重试。', 'aksrt')]; + } + $order = $repo->get_user_order($user_id, $order_number) ?: $order; + $order['out_trade_no'] = (string) $attempt['out_trade_no']; + // Close previous provider trade when possible (WeChat/Alipay) so the new attempt is clean. + if (!empty($attempt['previous']) + && $attempt['previous'] !== $attempt['out_trade_no'] + && method_exists($gateway, 'close_trade')) { + try { + $gateway->close_trade((string) $attempt['previous']); + } catch (\Throwable $e) { + // best-effort + } + } + } + $payment_result = $gateway->create_payment($order); if (empty($payment_result['success'])) { return ['success' => false, 'message' => $payment_result['message'] ?? __('支付失败。', 'aksrt')];