You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建OpenCart Qpay借记卡支付网关模块?求技术支持

OpenCart QPay借记卡支付网关模块实现方案

针对你找不到适配OpenCart的QPay借记卡支付模块的问题,下面提供一套可直接基于OpenCart框架实现的核心代码和配置步骤,完美适配你提供的银行参数:

一、模块核心文件结构

以OpenCart 3.x版本为例,需在对应目录创建以下3类文件(2.x版本仅需调整少量语法):

1. 前台控制器文件(catalog/controller/payment/qpay_debit.php)

负责处理支付跳转、回调验证、查询退款逻辑:

<?php
class ControllerPaymentQpayDebit extends Controller {
    private $error = array();

    public function index() {
        $this->load->language('payment/qpay_debit');
        $this->document->setTitle($this->language->get('heading_title'));
        $this->load->model('setting/setting');

        if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
            $this->model_setting_setting->editSetting('qpay_debit', $this->request->post);
            $this->session->data['success'] = $this->language->get('text_success');
            $this->response->redirect($this->url->link('extension/payment', 'user_token=' . $this->session->data['user_token'], true));
        }

        // 加载语言与配置项
        $data['heading_title'] = $this->language->get('heading_title');
        $data['text_edit'] = $this->language->get('text_edit');
        $data['text_enabled'] = $this->language->get('text_enabled');
        $data['text_disabled'] = $this->language->get('text_disabled');

        $data['entry_bank_id'] = $this->language->get('entry_bank_id');
        $data['entry_merchant_id'] = $this->language->get('entry_merchant_id');
        $data['entry_merchant_name'] = $this->language->get('entry_merchant_name');
        $data['entry_username'] = $this->language->get('entry_username');
        $data['entry_password'] = $this->language->get('entry_password');
        $data['entry_pay_url'] = $this->language->get('entry_pay_url');
        $data['entry_inquiry_url'] = $this->language->get('entry_inquiry_url');
        $data['entry_order_status'] = $this->language->get('entry_order_status');
        $data['entry_status'] = $this->language->get('entry_status');
        $data['entry_sort_order'] = $this->language->get('entry_sort_order');

        $data['button_save'] = $this->language->get('button_save');
        $data['button_cancel'] = $this->language->get('button_cancel');

        // 错误提示
        $data['error_warning'] = $this->error['warning'] ?? '';

        // 面包屑导航
        $data['breadcrumbs'] = array(
            array('text' => $this->language->get('text_home'), 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true)),
            array('text' => $this->language->get('text_payment'), 'href' => $this->url->link('extension/payment', 'user_token=' . $this->session->data['user_token'], true)),
            array('text' => $this->language->get('heading_title'), 'href' => $this->url->link('payment/qpay_debit', 'user_token=' . $this->session->data['user_token'], true))
        );

        $data['action'] = $this->url->link('payment/qpay_debit', 'user_token=' . $this->session->data['user_token'], true);
        $data['cancel'] = $this->url->link('extension/payment', 'user_token=' . $this->session->data['user_token'], true);

        // 读取配置值
        $fields = ['bank_id', 'merchant_id', 'merchant_name', 'username', 'password', 'pay_url', 'inquiry_url', 'order_status_id', 'status', 'sort_order'];
        foreach ($fields as $field) {
            $data["qpay_debit_{$field}"] = $this->request->post["qpay_debit_{$field}"] ?? $this->config->get("qpay_debit_{$field}");
        }

        // 加载订单状态选项
        $this->load->model('localisation/order_status');
        $data['order_statuses'] = $this->model_localisation_order_status->getOrderStatuses();

        $data['header'] = $this->load->controller('common/header');
        $data['column_left'] = $this->load->controller('common/column_left');
        $data['footer'] = $this->load->controller('common/footer');

        $this->response->setOutput($this->load->view('payment/qpay_debit', $data));
    }

    private function validate() {
        if (!$this->user->hasPermission('modify', 'payment/qpay_debit')) {
            $this->error['warning'] = $this->language->get('error_permission');
        }
        if (!$this->request->post['qpay_debit_bank_id']) {
            $this->error['bank_id'] = $this->language->get('error_bank_id');
        }
        if (!$this->request->post['qpay_debit_merchant_id']) {
            $this->error['merchant_id'] = $this->language->get('error_merchant_id');
        }
        return !$this->error;
    }

    // 支付跳转处理
    public function pay() {
        $this->load->language('payment/qpay_debit');
        $this->load->model('checkout/order');
        $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);

        // 组装QPay请求参数(可根据银行文档补充必填项)
        $post_data = array(
            'BankID' => $this->config->get('qpay_debit_bank_id'),
            'MerchantID' => $this->config->get('qpay_debit_merchant_id'),
            'MerchantName' => $this->config->get('qpay_debit_merchant_name'),
            'Username' => $this->config->get('qpay_debit_username'),
            'Password' => $this->config->get('qpay_debit_password'),
            'OrderID' => $order_info['order_id'],
            'Amount' => $order_info['total'],
            'Currency' => $order_info['currency_code'],
            'ReturnURL' => $this->url->link('payment/qpay_debit/callback', '', true)
        );

        // 自动提交表单跳转至支付页面
        $html = '<html><body>';
        $html .= '<form id="qpay_payment_form" method="post" action="' . $this->config->get('qpay_debit_pay_url') . '">';
        foreach ($post_data as $key => $value) {
            $html .= '<input type="hidden" name="' . $key . '" value="' . htmlspecialchars($value) . '">';
        }
        $html .= '<button type="submit">' . $this->language->get('text_redirect') . '</button>';
        $html .= '</form><script>document.getElementById("qpay_payment_form").submit();</script></body></html>';
        $this->response->setOutput($html);
    }

    // 支付回调处理
    public function callback() {
        $this->load->model('checkout/order');
        $order_id = $this->request->post['OrderID'] ?? 0;

        if ($order_id && ($order_info = $this->model_checkout_order->getOrder($order_id))) {
            $payment_status = $this->request->post['PaymentStatus'] ?? '';
            if ($payment_status == 'SUCCESS') {
                $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('qpay_debit_order_status_id'), '', true);
                $this->response->redirect($this->url->link('checkout/success', '', true));
            } else {
                $this->session->data['error'] = $this->language->get('text_payment_failed');
                $this->response->redirect($this->url->link('checkout/failure', '', true));
            }
        }
    }

    // 订单查询/退款接口示例
    public function inquiry() {
        $this->load->model('checkout/order');
        $order_id = $this->request->get['order_id'] ?? 0;

        if ($order_id && ($order_info = $this->model_checkout_order->getOrder($order_id))) {
            $post_data = array(
                'BankID' => $this->config->get('qpay_debit_bank_id'),
                'MerchantID' => $this->config->get('qpay_debit_merchant_id'),
                'Username' => $this->config->get('qpay_debit_username'),
                'Password' => $this->config->get('qpay_debit_password'),
                'OrderID' => $order_id
            );

            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $this->config->get('qpay_debit_inquiry_url'));
            curl_setopt($curl, CURLOPT_POST, true);
            curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post_data));
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
            $response = curl_exec($curl);
            curl_close($curl);

            $result = json_decode($response, true);
            $this->response->setOutput(json_encode($result));
        }
    }
}
?>

2. 语言文件(catalog/language/en-gb/payment/qpay_debit.php)

用于后台界面文字展示:

<?php
// Heading
$_['heading_title']    = 'QPay 借记卡支付';

// Text
$_['text_edit']        = '编辑QPay借记卡支付';
$_['text_payment']     = '支付';
$_['text_success']     = '成功:您已修改QPay借记卡支付设置!';
$_['text_enabled']     = '启用';
$_['text_disabled']    = '禁用';
$_['text_redirect']    = '正在跳转至支付页面...';
$_['text_payment_failed'] = '支付失败,请重试或联系客服';

// Entry
$_['entry_bank_id']    = '银行ID';
$_['entry_merchant_id'] = '商户ID';
$_['entry_merchant_name'] = '商户名称';
$_['entry_username']   = '商户用户名/管理员';
$_['entry_password']   = '密码';
$_['entry_pay_url']    = 'PG跳转支付URL';
$_['entry_inquiry_url'] = 'PG查询&退款URL';
$_['entry_order_status'] = '支付成功订单状态';
$_['entry_status']     = '状态';
$_['entry_sort_order'] = '排序顺序';

// Error
$_['error_permission'] = '警告:您没有权限修改QPay借记卡支付设置!';
$_['error_bank_id']    = '必须填写银行ID!';
$_['error_merchant_id'] = '必须填写商户ID!';
?>

3. 后台视图文件(catalog/view/template/payment/qpay_debit.twig)

后台配置页面模板:

{{ header }}
{{ column_left }}
<div id="content">
  <div class="page-header">
    <div class="container-fluid">
      <div class="pull-right">
        <button type="submit" form="form-qpay-debit" data-toggle="tooltip" title="{{ button_save }}" class="btn btn-primary"><i class="fa fa-save"></i></button>
        <a href="{{ cancel }}" data-toggle="tooltip" title="{{ button_cancel }}" class="btn btn-default"><i class="fa fa-reply"></i></a>
      </div>
      <h1>{{ heading_title }}</h1>
      <ul class="breadcrumb">
        {% for breadcrumb in breadcrumbs %}
        <li><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
        {% endfor %}
      </ul>
    </div>
  </div>
  <div class="container-fluid">
    {% if error_warning %}
    <div class="alert alert-danger"><i class="fa fa-exclamation-circle"></i> {{ error_warning }}
      <button type="button" class="close" data-dismiss="alert">&times;</button>
    </div>
    {% endif %}
    <div class="panel panel-default">
      <div class="panel-heading">
        <h3 class="panel-title"><i class="fa fa-pencil"></i> {{ text_edit }}</h3>
      </div>
      <div class="panel-body">
        <form action="{{ action }}" method="post" enctype="multipart/form-data" id="form-qpay-debit" class="form-horizontal">
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-bank-id">{{ entry_bank_id }}</label>
            <div class="col-sm-10">
              <input type="text" name="qpay_debit_bank_id" value="{{ qpay_debit_bank_id }}" placeholder="{{ entry_bank_id }}" id="input-bank-id" class="form-control"/>
              {% if error_bank_id %}
              <div class="text-danger">{{ error_bank_id }}</div>
              {% endif %}
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-merchant-id">{{ entry_merchant_id }}</label>
            <div class="col-sm-10">
              <input type="text" name="qpay_debit_merchant_id" value="{{ qpay_debit_merchant_id }}" placeholder="{{ entry_merchant_id }}" id="input-merchant-id" class="form-control"/>
              {% if error_merchant_id %}
              <div class="text-danger">{{ error_merchant_id }}</div>
              {% endif %}
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-merchant-name">{{ entry_merchant_name }}</label>
            <div class="col-sm-10">
              <input type="text" name="qpay_debit_merchant_name" value="{{ qpay_debit_merchant_name }}" placeholder="{{ entry_merchant_name }}" id="input-merchant-name" class="form-control"/>
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-username">{{ entry_username }}</label>
            <div class="col-sm-10">
              <input type="text" name="qpay_debit_username" value="{{ qpay_debit_username }}" placeholder="{{ entry_username }}" id="input-username" class="form-control"/>
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-password">{{ entry_password }}</label>
            <div class="col-sm-10">
              <input type="password" name="qpay_debit_password" value="{{ qpay_debit_password }}" placeholder="{{ entry_password }}" id="input-password" class="form-control"/>
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-pay-url">{{ entry_pay_url }}</label>
            <div class="col-sm-10">
              <input type="text" name="qpay_debit_pay_url" value="{{ qpay_debit_pay_url }}" placeholder="{{ entry_pay_url }}" id="input-pay-url" class="form-control"/>
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-inquiry-url">{{ entry_inquiry_url }}</label>
            <div class="col-sm-10">
              <input type="text" name="qpay_debit_inquiry_url" value="{{ qpay_debit_inquiry_url }}" placeholder="{{ entry_inquiry_url }}" id="input-inquiry-url" class="form-control"/>
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-order-status">{{ entry_order_status }}</label>
            <div class="col-sm-10">
              <select name="qpay_debit_order_status_id" id="input-order-status" class="form-control">
                {% for order_status in order_statuses %}
                <option value="{{ order_status.order_status_id }}" {% if order_status.order_status_id == qpay_debit_order_status_id %}selected{% endif %}>{{ order_status.name }}</option>
                {% endfor %}
              </select>
            </div>
          </div>
          <div class="form-group">
            <label class="col-sm-2 control-label" for="input-status">{{ entry_status }}</label>
            <div class="col-sm-10">
              <select name="qpay_debit_status" id="input-status"
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 05:05:28