如何创建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">×</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"
相关产品推荐
相关产品推荐

