如何整合代码实现Drupal中uc_paypal.module的PayPal订单退款按钮?
Drupal Ubercart PayPal 订单退款按钮实现方案
1. 在订单详情页添加退款按钮
在Ubercart订单详情模板(如uc-order.tpl.php)或自定义模块中,针对已完成且存在有效PayPal交易的订单显示退款按钮:
<?php // 校验订单状态与用户退款权限 if ($order->order_status == 'completed' && user_access('refund paypal orders')) { // 生成带CSRF校验的退款链接 $refund_link = url('uc_paypal/refund/' . $order->order_id, ['query' => ['token' => drupal_get_token($order->order_id)]]); print '<a href="' . $refund_link . '" class="button confirm">PayPal 退款</a>'; } ?>
2. 注册退款路由与回调
在自定义模块(如uc_paypal_refund.module)中通过hook_menu注册退款处理路由:
/** * Implements hook_menu(). */ function uc_paypal_refund_menu() { $items = []; $items['uc_paypal/refund/%'] = [ 'title' => 'PayPal 退款处理', 'page callback' => 'uc_paypal_refund_process', 'page arguments' => [2], 'access arguments' => ['refund paypal orders'], 'type' => MENU_CALLBACK, ]; return $items; }
3. 核心退款逻辑实现
整合交易ID查询、PayPal API请求与结果处理:
/** * 处理PayPal退款请求 */ function uc_paypal_refund_process($order_id) { // CSRF校验 if (!drupal_valid_token($_GET['token'], $order_id)) { drupal_set_message('无效请求', 'error'); drupal_goto('admin/store/orders/' . $order_id); } $order = uc_order_load($order_id); if (!$order || $order->order_status != 'completed') { drupal_set_message('订单状态不支持退款', 'error'); drupal_goto('admin/store/orders/' . $order_id); } // 1. 查询订单对应的PayPal交易ID(TxnId) $txn_id = db_select('uc_paypal_ipn', 'ipn') ->fields('ipn', ['txn_id']) ->condition('order_id', $order_id) ->condition('payment_status', 'Completed') ->execute() ->fetchField(); if (!$txn_id) { drupal_set_message('未找到有效PayPal交易记录', 'error'); drupal_goto('admin/store/orders/' . $order_id); } // 2. 构造PayPal v2退款API参数 $refund_amount = [ 'value' => uc_currency_format($order->order_total, FALSE, FALSE, FALSE), 'currency_code' => uc_store_currency(), ]; $request_data = [ 'amount' => $refund_amount, 'note_to_payer' => '订单#' . $order_id . ' 退款', ]; // 3. 调用uc_paypal模块内置API请求函数 // PayPal v2退款端点:/v2/payments/captures/{capture_id}/refund $endpoint = '/v2/payments/captures/' . $txn_id . '/refund'; $response = uc_paypal_api_request($endpoint, $request_data, 'POST'); // 4. 处理API响应 if (isset($response['status']) && $response['status'] == 'COMPLETED') { uc_order_update_status($order_id, 'refunded', 'PayPal退款完成,退款ID:' . $response['id']); drupal_set_message('退款已成功提交至PayPal', 'status'); } else { $error_msg = isset($response['message']) ? $response['message'] : '退款请求失败'; drupal_set_message('退款失败:' . $error_msg, 'error'); } drupal_goto('admin/store/orders/' . $order_id); }
4. 添加退款权限配置
通过hook_permission添加权限控制,确保仅授权用户可执行退款:
/** * Implements hook_permission(). */ function uc_paypal_refund_permission() { return [ 'refund paypal orders' => [ 'title' => t('Refund PayPal orders'), 'description' => t('Allow users to refund completed PayPal orders.'), ], ]; }
关键注意事项
- 确认
uc_paypal_api_request函数支持PayPal v2 API格式,若原模块仅兼容v1,需调整函数请求头(添加Content-Type: application/json) - 测试阶段请使用PayPal沙箱环境,避免真实资金损失
- 如需支持部分退款,修改
$refund_amount['value']为指定金额即可
内容的提问来源于stack exchange,提问作者Vel
相关产品推荐
相关产品推荐

