feat(moneris): 添加详细日志记录以增强支付流程调试能力

在支付流程关键节点添加错误日志记录,包括卡片字段验证、API请求响应、令牌创建和支付处理等环节
优化IDE类型提示支持,新增支付方法类型占位文件
改进支付数据处理逻辑,优先使用Blocks/Store API提供的数据
This commit is contained in:
tikkhun 2025-11-05 14:10:42 +08:00
parent 1c50907957
commit a9acdacf80
4 changed files with 129 additions and 27 deletions

View File

@ -19,6 +19,7 @@ function yoone_moneris_store_payment_data($order, $result, $request) {
} elseif (is_array($result) && isset($result['payment_method'])) { } elseif (is_array($result) && isset($result['payment_method'])) {
$pm = (string) $result['payment_method']; $pm = (string) $result['payment_method'];
} }
error_log('【Yoone Moneris Blocks】订单处理 hookpayment_method=' . ($pm ?: '未提供'));
if ('yoone_moneris' !== $pm) { if ('yoone_moneris' !== $pm) {
return; return;
} }
@ -34,14 +35,21 @@ function yoone_moneris_store_payment_data($order, $result, $request) {
} else { } else {
$payload = is_array($data) ? $data : array(); $payload = is_array($data) ? $data : array();
} }
error_log('【Yoone Moneris Blocks】解析 payment_method_data' . print_r($payload, true));
if (! empty($payload)) { if (! empty($payload)) {
$order->update_meta_data('_yoone_moneris_pm_data', $payload); $order->update_meta_data('_yoone_moneris_pm_data', $payload);
$order->save(); $order->save();
error_log('【Yoone Moneris Blocks】已保存 Blocks 支付数据到订单 _yoone_moneris_pm_data');
} else {
error_log('【Yoone Moneris Blocks】未收到有效的 payment_method_data');
} }
} }
// Only declare the Blocks payment method class when the Blocks base type exists to prevent type resolution issues. // Only declare the Blocks payment method class when the Blocks base type exists to prevent type resolution issues.
if (class_exists('Automattic\WooCommerce\Blocks\Payments\PaymentMethodType') && ! class_exists('Yoone_Moneris_Blocks_Payment_Method')) { if (class_exists('Automattic\WooCommerce\Blocks\Payments\PaymentMethodType') && ! class_exists('Yoone_Moneris_Blocks_Payment_Method')) {
/**
* 使用 use 导入基类,避免 IDE Undefined type
*/
class Yoone_Moneris_Blocks_Payment_Method extends Automattic\WooCommerce\Blocks\Payments\PaymentMethodType { class Yoone_Moneris_Blocks_Payment_Method extends Automattic\WooCommerce\Blocks\Payments\PaymentMethodType {
/** /**
* Unique name of the payment method in Blocks. * Unique name of the payment method in Blocks.

View File

@ -0,0 +1,34 @@
<?php
/**
* IDE/Linter stub for WooCommerce Blocks classes.
*
* 重要说明此文件仅用于静态分析IDE/代码检查以消除“Undefined type”告警
* 不会也不应该在 WordPress 运行时被 include/require
* 请勿在任何运行时路径中加载此文件。
*/
namespace Automattic\WooCommerce\Blocks\Payments;
// 如果真实类不存在,则为 IDE 提供一个最小的占位定义,避免类型未定义告警。
if (! class_exists(\Automattic\WooCommerce\Blocks\Payments\PaymentMethodType::class)) {
/**
* 最小占位基类:仅用于 IDE 类型解析。
* 注意:方法签名仅为常见实现提供参考,并不代表真实 Woo Blocks 行为。
*/
abstract class PaymentMethodType {
/** @return string */
abstract public function get_name();
/** @return bool */
public function is_active() { return true; }
/** @return array */
abstract public function get_payment_method_script_handles();
/** @return array */
public function get_payment_method_data() { return []; }
/** @return array */
public function get_supported_features() { return []; }
}
}

View File

@ -296,8 +296,10 @@ class Yoone_Gateway_Moneris extends WC_Payment_Gateway_CC
// 新卡:需要确保卡片字段完整 // 新卡:需要确保卡片字段完整
$card = $this->get_posted_card(); $card = $this->get_posted_card();
error_log('【Yoone Moneris】validate_fields 读取到卡片字段:' . print_r($card, true));
if (empty($card['number']) || empty($card['exp_month']) || empty($card['exp_year']) || empty($card['cvc'])) { if (empty($card['number']) || empty($card['exp_month']) || empty($card['exp_year']) || empty($card['cvc'])) {
wc_add_notice(__('请填写完整的银行卡信息。' . $card, 'yoone-moneris'), 'error'); wc_add_notice(__('请填写完整的银行卡信息。', 'yoone-moneris'), 'error');
error_log('【Yoone Moneris】validate_fields 缺少字段number=' . (empty($card['number']) ? '空' : '已填') . ' exp_month=' . (empty($card['exp_month']) ? '空' : $card['exp_month']) . ' exp_year=' . (empty($card['exp_year']) ? '空' : $card['exp_year']) . ' cvc=' . (empty($card['cvc']) ? '空' : '已填'));
return false; return false;
} }
return true; return true;
@ -329,9 +331,13 @@ class Yoone_Gateway_Moneris extends WC_Payment_Gateway_CC
*/ */
protected function get_posted_card() protected function get_posted_card()
{ {
// 记录原始支付方式选择
$raw_pm = isset($_POST['payment_method']) ? wc_clean(wp_unslash($_POST['payment_method'])) : '';
error_log('【Yoone Moneris】get_posted_card payment_method=' . ($raw_pm ?: '未提交') . ' 当前网关=' . $this->id);
// 如果当前提交并非选择我们网关,直接返回空卡数据,避免误读其他网关字段 // 如果当前提交并非选择我们网关,直接返回空卡数据,避免误读其他网关字段
$pm = isset($_POST['payment_method']) ? wc_clean(wp_unslash($_POST['payment_method'])) : ''; $pm = $raw_pm;
if ($pm && $pm !== $this->id) { if ($pm && $pm !== $this->id) {
error_log('【Yoone Moneris】get_posted_card 非本网关提交,返回空卡数据');
return array('number' => '', 'exp_month' => '', 'exp_year' => '', 'cvc' => ''); return array('number' => '', 'exp_month' => '', 'exp_year' => '', 'cvc' => '');
} }
@ -377,6 +383,8 @@ class Yoone_Gateway_Moneris extends WC_Payment_Gateway_CC
'card_cvc', 'card_cvc',
)); ));
error_log('【Yoone Moneris】get_posted_card 原始读取number=' . (isset($number) ? ('len=' . strlen((string)$number)) : '未读') . ' expiry_raw=' . ($expiry_raw ?: '空') . ' cvc=' . ($cvc ? ('len=' . strlen((string)$cvc)) : '空'));
// 如果没有组合有效期,尝试读取分拆的 月/年 字段 // 如果没有组合有效期,尝试读取分拆的 月/年 字段
$exp_month = $read_post(array( $exp_month = $read_post(array(
$this->id . '-exp-month', $this->id . '-exp-month',
@ -396,6 +404,7 @@ class Yoone_Gateway_Moneris extends WC_Payment_Gateway_CC
'card-expiry-year', 'card-expiry-year',
'expiry_year', 'expiry_year',
)); ));
error_log('【Yoone Moneris】get_posted_card 原始读取exp_month=' . ($exp_month ?: '空') . ' exp_year=' . ($exp_year ?: '空'));
// 规范化:仅保留数字 // 规范化:仅保留数字
$number = preg_replace('/\D+/', '', (string) $number); $number = preg_replace('/\D+/', '', (string) $number);
@ -420,6 +429,9 @@ class Yoone_Gateway_Moneris extends WC_Payment_Gateway_CC
$exp_year = '20' . $exp_year; $exp_year = '20' . $exp_year;
} }
$masked = $number ? str_repeat('*', max(strlen($number) - 4, 0)) . substr($number, -4) : '';
error_log('【Yoone Moneris】get_posted_card 规范化card=' . ($masked ?: '空') . ' len=' . strlen($number) . ' exp_month=' . ($exp_month ?: '空') . ' exp_year=' . ($exp_year ?: '空') . ' cvc_len=' . ($cvc ? strlen($cvc) : 0));
return array( return array(
'number' => $number, 'number' => $number,
'exp_month' => $exp_month, 'exp_month' => $exp_month,
@ -441,10 +453,15 @@ class Yoone_Gateway_Moneris extends WC_Payment_Gateway_CC
// 当用户选择“已保存的卡”,此字段会传递一个 token 的 ID当选择“使用新卡”该字段值为 'new'。 // 当用户选择“已保存的卡”,此字段会传递一个 token 的 ID当选择“使用新卡”该字段值为 'new'。
// 注意:此字段由 Woo 默认信用卡表单生成,适用于经典结账;如果使用 Blocks 结账,需要对应 Blocks 集成来产生等效数据。 // 注意:此字段由 Woo 默认信用卡表单生成,适用于经典结账;如果使用 Blocks 结账,需要对应 Blocks 集成来产生等效数据。
$field = 'wc-' . $this->id . '-payment-token'; $field = 'wc-' . $this->id . '-payment-token';
if (isset($_POST[$field])) {
$posted = wc_clean(wp_unslash($_POST[$field]));
error_log('【Yoone Moneris】get_selected_token_id 提交字段 ' . $field . ' = ' . $posted);
}
if (isset($_POST[$field]) && 'new' !== $_POST[$field]) { if (isset($_POST[$field]) && 'new' !== $_POST[$field]) {
// 将提交的令牌 ID 转为整数,后续用 WC_Payment_Tokens::get( $id ) 读取具体令牌对象 // 将提交的令牌 ID 转为整数,后续用 WC_Payment_Tokens::get( $id ) 读取具体令牌对象
return absint($_POST[$field]); return absint($_POST[$field]);
} }
error_log('【Yoone Moneris】get_selected_token_id 未选择已保存令牌或选择了新卡');
return 0; return 0;
} }
@ -484,15 +501,29 @@ class Yoone_Gateway_Moneris extends WC_Payment_Gateway_CC
*/ */
protected function create_wc_token($res, $user_id) protected function create_wc_token($res, $user_id)
{ {
error_log('【yoone moneris 】创建 WC 支付令牌tokenize_card 返回结果' . print_r($res, true));
$token = new WC_Payment_Token_CC(); $token = new WC_Payment_Token_CC();
// 兼容 data_key 命名
if (empty($res['token']) && ! empty($res['data_key'])) {
$res['token'] = $res['data_key'];
error_log('【Yoone Moneris】create_wc_token 使用 data_key 作为 token');
}
$token->set_token($res['token']); $token->set_token($res['token']);
$token->set_gateway_id($this->id); $token->set_gateway_id($this->id);
$token->set_user_id($user_id); $token->set_user_id($user_id);
$token->set_last4(substr(preg_replace('/\D+/', '', (string) $res['last4'] ?? ''), -4) ?: '0000'); $token->set_last4(substr(preg_replace('/\D+/', '', (string) $res['last4'] ?? ''), -4) ?: '0000');
$token->set_expiry_month(preg_replace('/\D+/', '', (string) ($res['exp_month'] ?? '')) ?: '01'); $token->set_expiry_month(preg_replace('/\D+/', '', (string) ($res['exp_month'] ?? '')) ?: '01');
$token->set_expiry_year(preg_replace('/\D+/', '', (string) ($res['exp_year'] ?? '')) ?: (date('Y') + 1)); $token->set_expiry_year(preg_replace('/\D+/', '', (string) ($res['exp_year'] ?? '')) ?: (date('Y') + 1));
// 设置卡类型(若有),避免 Woo 对必填字段校验失败
if (! empty($res['brand'])) {
$token->set_card_type((string) $res['brand']);
}
$token->save(); $token->save();
return $token->get_id(); $tid = $token->get_id();
if (! $tid) {
error_log('【Yoone Moneris】create_wc_token 保存失败WC_Token 未生成 ID检查必填字段。');
}
return $tid;
} }
/** /**
@ -504,17 +535,22 @@ class Yoone_Gateway_Moneris extends WC_Payment_Gateway_CC
*/ */
public function process_payment($order_id) public function process_payment($order_id)
{ {
error_log('【Yoone Moneris】process_payment 开始order_id=' . $order_id);
$order = wc_get_order($order_id); $order = wc_get_order($order_id);
if (! $order) {
error_log('【Yoone Moneris】无法获取订单对象终止');
return array('result' => 'fail');
}
$user_id = $order->get_user_id(); $user_id = $order->get_user_id();
$pm_meta = $order->get_meta('_yoone_moneris_pm_data', true);
// 支持 Blocks若从 Store API 捕获到支付数据,优先使用该数据 if (! empty($pm_meta)) {
$blocks_data = is_object($order) && method_exists($order, 'get_meta') ? (array) $order->get_meta('_yoone_moneris_pm_data') : array(); error_log('【Yoone Moneris】订单存在 Blocks/Store API 支付数据 _yoone_moneris_pm_data=' . print_r($pm_meta, true));
} else {
error_log('【Yoone Moneris】订单未找到 _yoone_moneris_pm_data 元数据');
}
// 选择已保存的令牌或创建新令牌 // 选择已保存的令牌或创建新令牌
$selected_token_id = $this->get_selected_token_id(); $selected_token_id = $this->get_selected_token_id();
if (! $selected_token_id && ! empty($blocks_data['saved_token_id']) && 'new' !== $blocks_data['saved_token_id']) {
$selected_token_id = absint($blocks_data['saved_token_id']);
}
$token_string = ''; $token_string = '';
if ($selected_token_id) { if ($selected_token_id) {
@ -527,31 +563,40 @@ class Yoone_Gateway_Moneris extends WC_Payment_Gateway_CC
} }
} else { } else {
// 创建新令牌(占位) // 创建新令牌(占位)
$card = $this->get_posted_card(); // 优先使用 Blocks/Store API 保存到订单的支付数据
// 若 Blocks 提供了卡片数据,使用其值覆盖经典表单读取结果 $card = array();
if (! empty($blocks_data)) { if (is_array($pm_meta) && ! empty($pm_meta)) {
$normalize = function($v){ return preg_replace('/\D+/', '', (string) $v); };
$number = isset($blocks_data['number']) ? $normalize($blocks_data['number']) : '';
$cvc = isset($blocks_data['cvc']) ? $normalize($blocks_data['cvc']) : '';
$exp_month = isset($blocks_data['exp_month']) ? $normalize($blocks_data['exp_month']) : '';
$exp_year = isset($blocks_data['exp_year']) ? $normalize($blocks_data['exp_year']) : '';
if (strlen($exp_year) === 2) { $exp_year = '20' . $exp_year; }
$card = array( $card = array(
'number' => $number ?: $card['number'], 'number' => preg_replace('/\D+/', '', (string) ($pm_meta['number'] ?? '')),
'exp_month' => $exp_month ?: $card['exp_month'], 'exp_month' => preg_replace('/\D+/', '', (string) ($pm_meta['exp_month'] ?? '')),
'exp_year' => $exp_year ?: $card['exp_year'], 'exp_year' => preg_replace('/\D+/', '', (string) ($pm_meta['exp_year'] ?? '')),
'cvc' => $cvc ?: $card['cvc'], 'cvc' => preg_replace('/\D+/', '', (string) ($pm_meta['cvc'] ?? '')),
); );
error_log('【Yoone Moneris】使用 Blocks/Store API 数据作为卡片来源:' . print_r($card, true));
}
if (empty($card['number']) || empty($card['exp_month']) || empty($card['exp_year']) || empty($card['cvc'])) {
// 退回到经典结账表单的 POST 字段
$card = $this->get_posted_card();
error_log('【Yoone Moneris】使用经典结账 POST 字段作为卡片来源:' . print_r($card, true));
} }
$res = $this->api()->tokenize_card($card); $res = $this->api()->tokenize_card($card);
error_log('【Yoone Moneris】tokenize_card 返回=' . print_r($res, true));
if (empty($res['success'])) { if (empty($res['success'])) {
wc_add_notice(__('令牌化失败:', 'yoone-moneris') . $res['error'], 'error'); wc_add_notice(__('令牌化失败:', 'yoone-moneris') . $res['error'], 'error');
error_log('【Yoone Moneris】令牌化失败' . ($res['error'] ?? '未知错误'));
return array('result' => 'fail'); return array('result' => 'fail');
} }
// 兼容 data_key 命名
if (empty($res['token']) && ! empty($res['data_key'])) {
$res['token'] = $res['data_key'];
error_log('【Yoone Moneris】tokenize_card 返回使用 data_key 作为 token');
}
$token_string = $res['token']; $token_string = $res['token'];
error_log('【Yoone Moneris】新令牌创建成功token_len=' . strlen($token_string) . ' last4=' . ($res['last4'] ?? ''));
// 保存到用户 // 保存到用户
if ($user_id) { if ($user_id) {
$wc_token_id = $this->create_wc_token($res + ['exp_month' => $card['exp_month'], 'exp_year' => $card['exp_year']], $user_id); $wc_token_id = $this->create_wc_token($res + ['exp_month' => $card['exp_month'], 'exp_year' => $card['exp_year']], $user_id);
error_log('【Yoone Moneris】已保存令牌到用户wc_token_id=' . $wc_token_id . ' user_id=' . $user_id);
$order->add_payment_token($wc_token_id); $order->add_payment_token($wc_token_id);
} }
} }
@ -559,15 +604,19 @@ class Yoone_Gateway_Moneris extends WC_Payment_Gateway_CC
// 首笔扣款 // 首笔扣款
$amount = $order->get_total(); $amount = $order->get_total();
$currency = $order->get_currency(); $currency = $order->get_currency();
error_log('【Yoone Moneris】准备扣款amount=' . $amount . ' currency=' . $currency . ' order_id=' . $order_id);
$charge = $this->api()->charge_token($token_string, $amount, $currency, $order_id); $charge = $this->api()->charge_token($token_string, $amount, $currency, $order_id);
error_log('【Yoone Moneris】charge_token 返回=' . print_r($charge, true));
if (empty($charge['success'])) { if (empty($charge['success'])) {
wc_add_notice(__('支付失败:', 'yoone-moneris') . ($charge['error'] ?? ''), 'error'); wc_add_notice(__('支付失败:', 'yoone-moneris') . ($charge['error'] ?? ''), 'error');
error_log('【Yoone Moneris】支付失败' . ($charge['error'] ?? '未知错误'));
return array('result' => 'fail'); return array('result' => 'fail');
} }
// 标记订单已支付 // 标记订单已支付
$order->payment_complete($charge['transaction_id'] ?? ''); $order->payment_complete($charge['transaction_id'] ?? '');
$order->add_order_note(sprintf('Moneris 首付成功,交易号:%s', $charge['transaction_id'] ?? 'N/A')); $order->add_order_note(sprintf('Moneris 首付成功,交易号:%s', $charge['transaction_id'] ?? 'N/A'));
error_log('【Yoone Moneris】支付成功transaction_id=' . ($charge['transaction_id'] ?? ''));
return array( return array(
'result' => 'success', 'result' => 'success',

View File

@ -49,7 +49,7 @@ class Yoone_Moneris_API implements Yoone_Moneris_API_Interface {
$this->http_method = isset( $config['http_method'] ) ? strtoupper( (string) $config['http_method'] ) : $this->http_method; $this->http_method = isset( $config['http_method'] ) ? strtoupper( (string) $config['http_method'] ) : $this->http_method;
$this->timeout = isset( $config['timeout'] ) ? absint( $config['timeout'] ) : $this->timeout; $this->timeout = isset( $config['timeout'] ) ? absint( $config['timeout'] ) : $this->timeout;
} }
yoone_moneris_log_debug( 'Moneris API 配置', array( error_log( 'Moneris API 配置' . print_r( array(
'store_id' => $this->store_id, 'store_id' => $this->store_id,
'sandbox' => $this->sandbox, 'sandbox' => $this->sandbox,
'country_code' => $this->country_code, 'country_code' => $this->country_code,
@ -61,7 +61,7 @@ class Yoone_Moneris_API implements Yoone_Moneris_API_Interface {
'path_override'=> $this->path_override, 'path_override'=> $this->path_override,
'http_method' => $this->http_method, 'http_method' => $this->http_method,
'timeout' => $this->timeout, 'timeout' => $this->timeout,
) ); ) ,true));
} }
/** /**
@ -88,7 +88,11 @@ class Yoone_Moneris_API implements Yoone_Moneris_API_Interface {
'cvdValue' => preg_replace( '/\D+/', '', (string) $card['cvc'] ), 'cvdValue' => preg_replace( '/\D+/', '', (string) $card['cvc'] ),
); );
} }
$num = isset($card['number']) ? preg_replace('/\D+/', '', (string) $card['number']) : '';
$masked = $num ? str_repeat('*', max(strlen($num) - 4, 0)) . substr($num, -4) : '';
error_log('【Yoone Moneris API】tokenize_card 请求last4=' . ($num ? substr($num, -4) : '') . ' len=' . strlen($num) . ' expdate=' . $payload['expdate'] . ' cryptType=' . $payload['cryptType']);
$res = $this->send_moneris_xml( 'res_add_cc', $payload ); $res = $this->send_moneris_xml( 'res_add_cc', $payload );
error_log('$res11111111'. print_r($res, true));
if ( $res['ok'] ) { if ( $res['ok'] ) {
return array( return array(
'success' => true, 'success' => true,
@ -124,6 +128,7 @@ class Yoone_Moneris_API implements Yoone_Moneris_API_Interface {
'amount' => $this->format_amount( $amount ), 'amount' => $this->format_amount( $amount ),
'cryptType' => $this->crypt_type, 'cryptType' => $this->crypt_type,
); );
error_log('【Yoone Moneris API】charge_token 请求type=' . $type . ' token_len=' . strlen($token) . ' amount=' . $payload['amount'] . ' currency=' . $currency . ' orderId=' . $order_id);
$res = $this->send_moneris_xml( $type, $payload ); $res = $this->send_moneris_xml( $type, $payload );
if ( $res['ok'] ) { if ( $res['ok'] ) {
return array( return array(
@ -176,6 +181,7 @@ class Yoone_Moneris_API implements Yoone_Moneris_API_Interface {
if ( ! $endpoint ) { if ( ! $endpoint ) {
return array( 'ok' => false, 'error' => 'Endpoint not configured' ); return array( 'ok' => false, 'error' => 'Endpoint not configured' );
} }
error_log('【Yoone Moneris API】发送 XMLtype=' . $type . ' endpoint=' . $endpoint);
// 构建请求体 // 构建请求体
$body = array( $body = array(
@ -203,26 +209,31 @@ class Yoone_Moneris_API implements Yoone_Moneris_API_Interface {
// 仅支持 POST // 仅支持 POST
$resp = wp_remote_post( $endpoint, $args ); $resp = wp_remote_post( $endpoint, $args );
if ( is_wp_error( $resp ) ) { if ( is_wp_error( $resp ) ) {
error_log('【Yoone Moneris API】HTTP 错误:' . $resp->get_error_message());
return array( 'ok' => false, 'error' => $resp->get_error_message() ); return array( 'ok' => false, 'error' => $resp->get_error_message() );
} }
$code = wp_remote_retrieve_response_code( $resp ); $code = wp_remote_retrieve_response_code( $resp );
$raw = wp_remote_retrieve_body( $resp ); $raw = wp_remote_retrieve_body( $resp );
if ( $code < 200 || $code >= 300 ) { if ( $code < 200 || $code >= 300 ) {
error_log('【Yoone Moneris API】HTTP 非 2xxcode=' . $code . ' body=' . substr($raw, 0, 200));
return array( 'ok' => false, 'error' => 'HTTP ' . $code . ' ' . $raw ); return array( 'ok' => false, 'error' => 'HTTP ' . $code . ' ' . $raw );
} }
// 解析 XML // 解析 XML
$parsed = $this->parse_moneris_xml( $raw ); $parsed = $this->parse_moneris_xml( $raw );
if ( ! $parsed['parsed'] ) { if ( ! $parsed['parsed'] ) {
error_log('【Yoone Moneris API】XML 解析失败:' . ($parsed['error'] ?? 'Unknown'));
return array( 'ok' => false, 'error' => 'Parse error: ' . ( $parsed['error'] ?? 'Unknown' ) ); return array( 'ok' => false, 'error' => 'Parse error: ' . ( $parsed['error'] ?? 'Unknown' ) );
} }
$receipt = $parsed['receipt']; $receipt = $parsed['receipt'];
$approved = $this->is_approved( $receipt ); $approved = $this->is_approved( $receipt );
if ( ! $approved ) { if ( ! $approved ) {
$message = isset( $receipt['message'] ) ? $receipt['message'] : ( $receipt['Message'] ?? 'Declined' ); $message = isset( $receipt['message'] ) ? $receipt['message'] : ( $receipt['Message'] ?? 'Declined' );
error_log('【Yoone Moneris API】交易未批准ResponseCode=' . ($receipt['responseCode'] ?? $receipt['response_code'] ?? '') . ' message=' . $message);
return array( 'ok' => false, 'error' => $message ); return array( 'ok' => false, 'error' => $message );
} }
error_log('【Yoone Moneris API】交易批准ResponseCode=' . ($receipt['responseCode'] ?? $receipt['response_code'] ?? '') . ' txnNumber=' . ($receipt['txnNumber'] ?? $receipt['txn_number'] ?? ''));
error_log('receipt'. print_r($receipt,true));
return array( 'ok' => true, 'receipt' => $receipt ); return array( 'ok' => true, 'receipt' => $receipt );
} }