积分与余额账务系统硬切重构
This commit is contained in:
1 parent
ca12226b39
commit
5cae5b5c93
159 files changed
+7275
-4718
No files matched your search
@@ -46,11 +46,11 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
? \AKSRT\Payment\OrderRepository::provider_out_trade_no($order)
|
||||
: $order_number;
|
||||
}
|
||||
$amount = (float) ($order['amount'] ?? 0);
|
||||
$amount = $this->amount_string($order['amount'] ?? null);
|
||||
$subject = (string) ($order['subject'] ?? __('订单支付', 'aksrt'));
|
||||
$payment_type = $this->get_config()['payment_type'];
|
||||
|
||||
if ($order_number === '' || $out_trade_no === '' || $amount <= 0) {
|
||||
if ($order_number === '' || $out_trade_no === '' || $amount === '') {
|
||||
return ['success' => false, 'message' => __('订单参数无效', 'aksrt')];
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
$payload = [
|
||||
'_method' => 'GET',
|
||||
'out_trade_no' => $out_trade_no,
|
||||
'total_amount' => number_format($amount, 2, '.', ''),
|
||||
'total_amount' => $amount,
|
||||
'subject' => mb_substr($subject, 0, 256),
|
||||
];
|
||||
|
||||
@@ -109,16 +109,17 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
$order_number = (string) ($data['out_trade_no'] ?? '');
|
||||
$trade_no = (string) ($data['trade_no'] ?? '');
|
||||
|
||||
$amount = $this->amount_string($data['total_amount'] ?? null);
|
||||
if (($data['app_id'] ?? '') !== $config['app_id']
|
||||
|| $order_number === ''
|
||||
|| ($paid && ($trade_no === '' || (float) ($data['total_amount'] ?? 0) <= 0))) {
|
||||
|| ($paid && ($trade_no === '' || $amount === ''))) {
|
||||
return ['success' => false, 'message' => __('支付宝回调身份或订单数据无效', 'aksrt')];
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'order_number' => $order_number,
|
||||
'amount' => (float) ($data['total_amount'] ?? 0),
|
||||
'amount' => $amount,
|
||||
'currency' => 'CNY',
|
||||
'transaction_id' => $trade_no,
|
||||
'status' => $paid ? 'paid' : 'pending',
|
||||
@@ -171,7 +172,7 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
'success' => true,
|
||||
// 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),
|
||||
'amount' => $this->amount_string($data['total_amount'] ?? null),
|
||||
'currency' => 'CNY',
|
||||
'transaction_id' => (string) ($data['trade_no'] ?? ''),
|
||||
'status' => $status,
|
||||
@@ -200,8 +201,13 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
}
|
||||
}
|
||||
|
||||
public function refund(string $order_number, float $amount, string $request_id = ''): array {
|
||||
if ($amount <= 0) {
|
||||
public function refund(string $order_number, string $amount, string $request_id = ''): array {
|
||||
try {
|
||||
$refund_amount = \AKSRT\Ledger\AssetAmount::balance($amount);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return ['success' => false, 'status' => 'failed', 'message' => __('退款金额无效', 'aksrt')];
|
||||
}
|
||||
if ($refund_amount->minor() <= 0) {
|
||||
return ['success' => false, 'status' => 'failed', 'message' => __('退款金额无效', 'aksrt')];
|
||||
}
|
||||
if (!$this->is_configured()) {
|
||||
@@ -219,14 +225,14 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
);
|
||||
$result = Pay::alipay()->refund([
|
||||
'out_trade_no' => $out_trade_no,
|
||||
'refund_amount' => number_format($amount, 2, '.', ''),
|
||||
'refund_amount' => $refund_amount->decimal(),
|
||||
'refund_reason' => __('用户申请退款', 'aksrt'),
|
||||
'out_request_no' => $refund_request_id,
|
||||
]);
|
||||
$data = YansongdaPayFactory::to_array($result);
|
||||
|
||||
$fund_change = strtoupper((string) ($data['fund_change'] ?? ''));
|
||||
$status = ($fund_change === 'Y' || (float) ($data['refund_fee'] ?? 0) > 0)
|
||||
$status = ($fund_change === 'Y' || $this->amount_string($data['refund_fee'] ?? null) !== '')
|
||||
? 'succeeded'
|
||||
: 'unknown';
|
||||
|
||||
@@ -256,8 +262,8 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
$result = Pay::alipay()->query($params);
|
||||
$data = YansongdaPayFactory::to_array($result);
|
||||
$refund_status = strtoupper((string) ($data['refund_status'] ?? ''));
|
||||
$refund_amount = (float) ($data['refund_amount'] ?? 0);
|
||||
$status = ($refund_status === 'REFUND_SUCCESS' || $refund_amount > 0)
|
||||
$refund_amount = $this->amount_string($data['refund_amount'] ?? null);
|
||||
$status = ($refund_status === 'REFUND_SUCCESS' || $refund_amount !== '')
|
||||
? 'succeeded'
|
||||
: ($refund_status === 'REFUND_FAIL' ? 'failed' : 'pending');
|
||||
return [
|
||||
@@ -291,6 +297,18 @@ class AlipayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
];
|
||||
}
|
||||
|
||||
private function amount_string(mixed $value): string {
|
||||
if (!is_string($value)) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
$amount = \AKSRT\Ledger\AssetAmount::balance(trim($value));
|
||||
return $amount->minor() > 0 ? $amount->decimal() : '';
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map local order_number → provider out_trade_no (supports resume attempts).
|
||||
*/
|
||||
|
||||
@@ -50,9 +50,9 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
? \AKSRT\Payment\OrderRepository::provider_out_trade_no($order)
|
||||
: $order_number;
|
||||
}
|
||||
$amount = (float) ($order['amount'] ?? 0);
|
||||
$amount = $this->amount_string($order['amount'] ?? null);
|
||||
$subject = (string) ($order['subject'] ?? __('订单支付', 'aksrt'));
|
||||
if ($order_number === '' || $out_trade_no === '' || $amount <= 0) {
|
||||
if ($order_number === '' || $out_trade_no === '' || $amount === null) {
|
||||
return ['success' => false, 'message' => __('订单参数无效', 'aksrt')];
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
'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),
|
||||
'money' => number_format($amount, 2, '.', ''),
|
||||
'money' => $amount,
|
||||
];
|
||||
$params['sign'] = $this->sign($params, $config['key']);
|
||||
$params['sign_type'] = 'MD5';
|
||||
@@ -147,7 +147,7 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
|
||||
$order_number = sanitize_text_field((string) ($params['out_trade_no'] ?? ''));
|
||||
$transaction_id = sanitize_text_field((string) ($params['trade_no'] ?? ''));
|
||||
$amount = (float) ($params['money'] ?? 0);
|
||||
$amount = $this->amount_string($params['money'] ?? null);
|
||||
$trade_status = (string) ($params['trade_status'] ?? '');
|
||||
$type = sanitize_key((string) ($params['type'] ?? ''));
|
||||
|
||||
@@ -157,14 +157,14 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
}
|
||||
|
||||
$paid = ($trade_status === '' || $trade_status === 'TRADE_SUCCESS');
|
||||
if ($order_number === '' || ($paid && ($transaction_id === '' || $amount <= 0))) {
|
||||
if ($order_number === '' || ($paid && ($transaction_id === '' || $amount === null))) {
|
||||
return ['success' => false, 'message' => __('易支付回调数据无效', 'aksrt')];
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'order_number' => $order_number,
|
||||
'amount' => $amount,
|
||||
'amount' => $amount ?? '0.00',
|
||||
'currency' => 'CNY',
|
||||
'transaction_id' => $transaction_id,
|
||||
'status' => $paid ? 'paid' : 'pending',
|
||||
@@ -209,20 +209,20 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
$status = (int) ($body['status'] ?? $body['trade_status'] ?? 0);
|
||||
$paid = $code === 1 && ((string) $status === '1' || (string) ($body['trade_status'] ?? '') === 'TRADE_SUCCESS');
|
||||
|
||||
$amount = (float) ($body['money'] ?? $body['amount'] ?? 0);
|
||||
$amount = $this->amount_string($body['money'] ?? $body['amount'] ?? null);
|
||||
$tx = (string) ($body['trade_no'] ?? $body['api_trade_no'] ?? '');
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'order_number' => (string) ($body['out_trade_no'] ?? $out_trade_no),
|
||||
'amount' => $amount,
|
||||
'amount' => $amount ?? '0.00',
|
||||
'currency' => 'CNY',
|
||||
'transaction_id' => $tx,
|
||||
'status' => $paid ? 'paid' : 'pending',
|
||||
];
|
||||
}
|
||||
|
||||
public function refund(string $order_number, float $amount, string $request_id = ''): array {
|
||||
public function refund(string $order_number, string $amount, string $request_id = ''): array {
|
||||
return [
|
||||
'success' => false,
|
||||
'status' => 'failed',
|
||||
@@ -288,6 +288,18 @@ class EpayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
return rtrim($apiurl, '/') . '/' . ltrim($file, '/');
|
||||
}
|
||||
|
||||
private function amount_string(mixed $value): ?string {
|
||||
if (!is_string($value)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
$amount = \AKSRT\Ledger\AssetAmount::balance(trim($value));
|
||||
return $amount->minor() > 0 ? $amount->decimal() : null;
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function prefer_mobile(string $device): bool {
|
||||
if ($device === 'mobile') {
|
||||
return true;
|
||||
|
||||
@@ -40,13 +40,16 @@ class PayPalGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
? \AKSRT\Payment\OrderRepository::provider_out_trade_no($order)
|
||||
: $order_number;
|
||||
}
|
||||
$amount = (float) ($order['amount'] ?? 0);
|
||||
$amount = $this->amount_string($order['amount'] ?? null);
|
||||
$subject = $order['subject'] ?? __('订单支付', 'aksrt');
|
||||
$order_currency = strtoupper((string) ($order['currency'] ?? ''));
|
||||
$currency = strtoupper((string) ($config['currency'] ?? 'USD'));
|
||||
if ($order_currency === '' || !hash_equals($order_currency, $currency)) {
|
||||
return ['success' => false, 'message' => __('PayPal 币种与订单币种不一致', 'aksrt')];
|
||||
}
|
||||
if ($order_number === '' || $out_trade_no === '' || $amount === null) {
|
||||
return ['success' => false, 'message' => __('订单金额无效', 'aksrt')];
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->api_request('POST', '/v2/checkout/orders', [
|
||||
@@ -56,7 +59,7 @@ class PayPalGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
'description' => $subject,
|
||||
'amount' => [
|
||||
'currency_code' => $currency,
|
||||
'value' => number_format($amount, 2, '.', ''),
|
||||
'value' => $amount,
|
||||
],
|
||||
]],
|
||||
'application_context' => [
|
||||
@@ -142,7 +145,7 @@ class PayPalGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
}
|
||||
}
|
||||
|
||||
public function refund(string $order_number, float $amount, string $request_id = ''): array {
|
||||
public function refund(string $order_number, string $amount, string $request_id = ''): array {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => __('PayPal 退款需要通过后台手动处理', 'aksrt'),
|
||||
@@ -167,7 +170,7 @@ class PayPalGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
* 用户在 return_url 返回后调用,确认真正扣款。
|
||||
*
|
||||
* @param string $paypal_order_id PayPal 订单 ID(create 时返回的 id)
|
||||
* @return array{success:bool, order_number?:string, amount?:float, transaction_id?:string, status?:string, message?:string}
|
||||
* @return array{success:bool, order_number?:string, amount?:string, transaction_id?:string, status?:string, message?:string}
|
||||
*/
|
||||
public function capture_order(string $paypal_order_id): array {
|
||||
if ($paypal_order_id === '') {
|
||||
@@ -192,16 +195,32 @@ class PayPalGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
private function completed_order_evidence(array $body): array {
|
||||
$unit = $body['purchase_units'][0] ?? [];
|
||||
$capture = $unit['payments']['captures'][0] ?? [];
|
||||
$amount = $this->amount_string($capture['amount']['value'] ?? null);
|
||||
if ($amount === null) {
|
||||
return ['success' => false, 'message' => __('PayPal 返回金额无效', 'aksrt')];
|
||||
}
|
||||
return [
|
||||
'success' => true,
|
||||
'order_number' => (string) ($unit['reference_id'] ?? ''),
|
||||
'amount' => (float) ($capture['amount']['value'] ?? 0),
|
||||
'amount' => $amount,
|
||||
'currency' => strtoupper((string) ($capture['amount']['currency_code'] ?? '')),
|
||||
'transaction_id' => (string) ($capture['id'] ?? ($body['id'] ?? '')),
|
||||
'status' => 'paid',
|
||||
];
|
||||
}
|
||||
|
||||
private function amount_string(mixed $value): ?string {
|
||||
if (!is_string($value)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
$amount = \AKSRT\Ledger\AssetAmount::balance(trim($value));
|
||||
return $amount->minor() > 0 ? $amount->decimal() : null;
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 OAuth2 access token(v2 REST 必需)。
|
||||
*/
|
||||
|
||||
@@ -42,13 +42,17 @@ class StripeGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
? \AKSRT\Payment\OrderRepository::provider_out_trade_no($order)
|
||||
: $order_number;
|
||||
}
|
||||
$amount = (float) ($order['amount'] ?? 0);
|
||||
$amount = is_string($order['amount'] ?? null) ? trim($order['amount']) : '';
|
||||
$subject = $order['subject'] ?? __('订单支付', 'aksrt');
|
||||
$order_currency = strtoupper((string) ($order['currency'] ?? ''));
|
||||
$currency = strtolower($config['currency'] ?? 'usd');
|
||||
if ($order_currency === '' || !hash_equals($order_currency, strtoupper($currency))) {
|
||||
return ['success' => false, 'message' => __('Stripe 币种与订单币种不一致', 'aksrt')];
|
||||
}
|
||||
$smallest_amount = $this->to_smallest_unit($amount, $currency);
|
||||
if ($order_number === '' || $out_trade_no === '' || $smallest_amount === null || $smallest_amount <= 0) {
|
||||
return ['success' => false, 'message' => __('订单金额无效', 'aksrt')];
|
||||
}
|
||||
|
||||
try {
|
||||
$stripe = $this->create_client($config);
|
||||
@@ -62,7 +66,7 @@ class StripeGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
'product_data' => [
|
||||
'name' => $subject,
|
||||
],
|
||||
'unit_amount' => $this->to_smallest_unit($amount, $currency),
|
||||
'unit_amount' => $smallest_amount,
|
||||
],
|
||||
'quantity' => 1,
|
||||
]],
|
||||
@@ -204,7 +208,15 @@ class StripeGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
}
|
||||
}
|
||||
|
||||
public function refund(string $order_number, float $amount, string $request_id = ''): array {
|
||||
public function refund(string $order_number, string $amount, string $request_id = ''): array {
|
||||
try {
|
||||
$refund_amount = \AKSRT\Ledger\AssetAmount::balance($amount);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return ['success' => false, 'message' => __('退款金额无效', 'aksrt')];
|
||||
}
|
||||
if ($refund_amount->minor() <= 0) {
|
||||
return ['success' => false, 'message' => __('退款金额无效', 'aksrt')];
|
||||
}
|
||||
if (!$this->is_configured()) {
|
||||
return ['success' => false, 'message' => __('Stripe 未配置', 'aksrt')];
|
||||
}
|
||||
@@ -228,6 +240,10 @@ class StripeGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
}
|
||||
|
||||
$currency = strtolower((string) ($found->currency ?? $config['currency'] ?? 'usd'));
|
||||
$refund_smallest = $this->to_smallest_unit($refund_amount->decimal(), $currency);
|
||||
if ($refund_smallest === null || $refund_smallest <= 0) {
|
||||
return ['success' => false, 'message' => __('退款金额与币种精度不匹配', 'aksrt')];
|
||||
}
|
||||
|
||||
$options = ['api_key' => $config['secret_key']];
|
||||
if ($request_id !== '') {
|
||||
@@ -235,7 +251,7 @@ class StripeGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
}
|
||||
$refund = \Stripe\Refund::create([
|
||||
'payment_intent' => $paymentIntentId,
|
||||
'amount' => $this->to_smallest_unit($amount, $currency),
|
||||
'amount' => $refund_smallest,
|
||||
'reason' => 'requested_by_customer',
|
||||
'metadata' => [
|
||||
'aksrt_request_id' => $request_id,
|
||||
@@ -390,26 +406,37 @@ class StripeGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
return array_values(array_intersect($methods, $valid)) ?: ['card'];
|
||||
}
|
||||
|
||||
private function from_smallest_unit(int $amount, string $currency): float {
|
||||
private function from_smallest_unit(int $amount, string $currency): string {
|
||||
if ($amount < 0) {
|
||||
return '0.00';
|
||||
}
|
||||
$zero_decimal = ['bif', 'clp', 'djf', 'gnf', 'jpy', 'kmf', 'krw', 'mga', 'pyg', 'rwf', 'ugx', 'vnd', 'vuv', 'xaf', 'xof', 'xpf'];
|
||||
if (in_array(strtolower($currency), $zero_decimal, true)) {
|
||||
return (float) $amount;
|
||||
if ($amount > intdiv(PHP_INT_MAX, 100)) {
|
||||
return '0.00';
|
||||
}
|
||||
return \AKSRT\Ledger\AssetAmount::from_minor(\AKSRT\Ledger\AssetType::BALANCE, $amount * 100)->decimal();
|
||||
}
|
||||
|
||||
return $amount / 100;
|
||||
return \AKSRT\Ledger\AssetAmount::from_minor(\AKSRT\Ledger\AssetType::BALANCE, $amount)->decimal();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将金额转换为最小单位(分/cent)。
|
||||
*/
|
||||
private function to_smallest_unit(float $amount, string $currency): int {
|
||||
private function to_smallest_unit(string $amount, string $currency): ?int {
|
||||
try {
|
||||
$parsed = \AKSRT\Ledger\AssetAmount::balance($amount);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return null;
|
||||
}
|
||||
// 零小数货币(日元、韩元等)
|
||||
$zeroDecimal = ['bif', 'clp', 'djf', 'gnf', 'jpy', 'kmf', 'krw', 'mga', 'pyg', 'rwf', 'ugx', 'vnd', 'vuv', 'xaf', 'xof', 'xpf'];
|
||||
|
||||
if (in_array(strtolower($currency), $zeroDecimal, true)) {
|
||||
return (int) $amount;
|
||||
return $parsed->minor() % 100 === 0 ? intdiv($parsed->minor(), 100) : null;
|
||||
}
|
||||
|
||||
return (int) round($amount * 100);
|
||||
return $parsed->minor();
|
||||
}
|
||||
}
|
||||
@@ -47,10 +47,13 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
? \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);
|
||||
try {
|
||||
$total_fen = \AKSRT\Ledger\AssetAmount::balance(is_string($order['amount'] ?? null) ? trim($order['amount']) : '')->minor();
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$total_fen = 0;
|
||||
}
|
||||
|
||||
if ($order_number === '' || $out_trade_no === '' || $total_fen <= 0) {
|
||||
return ['success' => false, 'message' => __('订单参数无效', 'aksrt')];
|
||||
@@ -178,7 +181,7 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
return [
|
||||
'success' => true,
|
||||
'order_number' => $order_number,
|
||||
'amount' => $total_fen > 0 ? ($total_fen / 100) : 0.0,
|
||||
'amount' => $this->fen_decimal($total_fen),
|
||||
'currency' => strtoupper((string) YansongdaPayFactory::dig($data, 'amount.currency', 'CNY')),
|
||||
'transaction_id' => $transaction_id,
|
||||
'status' => $paid ? 'paid' : 'pending',
|
||||
@@ -242,7 +245,7 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
'success' => true,
|
||||
// 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,
|
||||
'amount' => $this->fen_decimal((int) YansongdaPayFactory::dig($data, 'amount.total', 0)),
|
||||
'currency' => strtoupper((string) YansongdaPayFactory::dig($data, 'amount.currency', 'CNY')),
|
||||
'transaction_id' => (string) ($data['transaction_id'] ?? ''),
|
||||
'status' => $status,
|
||||
@@ -271,7 +274,15 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
}
|
||||
}
|
||||
|
||||
public function refund(string $order_number, float $amount, string $request_id = ''): array {
|
||||
public function refund(string $order_number, string $amount, string $request_id = ''): array {
|
||||
try {
|
||||
$refund_amount = \AKSRT\Ledger\AssetAmount::balance($amount);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return ['success' => false, 'status' => 'failed', 'message' => __('退款金额无效', 'aksrt')];
|
||||
}
|
||||
if ($refund_amount->minor() <= 0) {
|
||||
return ['success' => false, 'status' => 'failed', 'message' => __('退款金额无效', 'aksrt')];
|
||||
}
|
||||
if (!$this->is_configured()) {
|
||||
return ['success' => false, 'message' => __('微信支付未配置', 'aksrt')];
|
||||
}
|
||||
@@ -288,7 +299,7 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
]);
|
||||
$q = YansongdaPayFactory::to_array($query);
|
||||
$total_fen = (int) YansongdaPayFactory::dig($q, 'amount.total', 0);
|
||||
$refund_fen = (int) round($amount * 100);
|
||||
$refund_fen = $refund_amount->minor();
|
||||
if ($total_fen <= 0) {
|
||||
return ['success' => false, 'status' => 'failed', 'message' => __('无法确认原订单金额', 'aksrt')];
|
||||
}
|
||||
@@ -387,6 +398,13 @@ class WechatPayGateway implements \AKSRT\Payment\GatewayInterface {
|
||||
return $map[$type] ?? 'native';
|
||||
}
|
||||
|
||||
private function fen_decimal(int $amount): string {
|
||||
return \AKSRT\Ledger\AssetAmount::from_minor(
|
||||
\AKSRT\Ledger\AssetType::BALANCE,
|
||||
max(0, $amount)
|
||||
)->decimal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Map local order_number → provider out_trade_no (supports resume attempts).
|
||||
*/
|
||||
|
||||
Reference in new issue
Block a user