PAYATHON 2026

如何在 PrestaShop 1.7 中禁用付款功能?

支付阿杰

结论

PrestaShop 1.7 不能靠”禁用所有付款模块”实现只下单、不付款。付款模块除了收款,还会在结账时调用 PaymentModule::validateOrder(),把购物车转换为正式订单。如果关闭所有付款方式,客户通常会停在付款步骤,系统也不会生成订单。

合适的处理方式是提供一种”线下付款”方式。它不连接支付网关,也不扣款,只负责创建订单,并把订单设为”等待 ERP 处理”等状态。可以先考虑使用现有的货到付款模块。如果前台文案和流程需要准确对应业务,再开发一个简单的线下付款模块。

方案一:使用现有的货到付款模块

如果当前安装的 PrestaShop 包含 ps_cashondelivery,使用它最方便。

进入后台并完成以下设置:

  1. 打开”模块管理”。
  2. 搜索并安装”Cash on delivery”或”货到付款”模块。
  3. 检查模块对国家、货币、客户组和配送方式的限制,确保目标客户可以使用。
  4. 通过后台翻译功能,把前台显示的”货到付款”改成”线下付款”或”提交订单”。
  5. 按照业务需要,把对应的订单状态重命名为”等待 ERP 处理”。

结账时,客户仍需选择一次这种付款方式,但系统不会跳转到第三方支付页面,也不会发起在线支付。客户确认后,PrestaShop 会照常创建订单,ERP 再读取或同步这笔订单。

不要直接修改 modules/ps_cashondelivery 里的翻译文本,因为模块升级可能覆盖这些改动。应优先使用后台的国际化翻译功能。

方案二:创建专用的线下付款模块

如果”货到付款”不符合实际业务含义,可以创建自己的 PaymentModule。模块只显示一个”线下结算”选项,客户确认后立即创建订单。

下面是一个精简示例。正式项目还需要补充订单状态安装、异常处理、日志和 ERP 同步逻辑。

目录结构可以是:

modules/
└── erpofflinepayment/
    ├── erpofflinepayment.php
    ├── controllers/
    │   └── front/
    │       └── validation.php
    └── views/
        └── templates/
            └── front/
                └── payment_info.tpl

模块主文件

modules/erpofflinepayment/erpofflinepayment.php:

<?php

if (!defined('_PS_VERSION_')) {
    exit;
}

use PrestaShop\PrestaShop\Core\Payment\PaymentOption;

class ErpOfflinePayment extends PaymentModule
{
    public function __construct()
    {
        $this->name = 'erpofflinepayment';
        $this->tab = 'payments_gateways';
        $this->version = '1.0.0';
        $this->author = 'Your Company';
        $this->bootstrap = true;
        $this->controllers = ['validation'];

        parent::__construct();

        $this->displayName = $this->l('Offline ERP payment');
        $this->description = $this->l(
            'Creates an order without collecting an online payment.'
        );
    }

    public function install()
    {
        return parent::install()
            && $this->registerHook('paymentOptions');
    }

    public function hookPaymentOptions($params)
    {
        if (!$this->active) {
            return [];
        }

        $option = new PaymentOption();
        $option->setCallToActionText($this->l('Place order without online payment'))
            ->setAction(
                $this->context->link->getModuleLink(
                    $this->name,
                    'validation',
                    [],
                    true
                )
            )
            ->setAdditionalInformation(
                $this->fetch(
                    'module:' . $this->name
                    . '/views/templates/front/payment_info.tpl'
                )
            );

        return [$option];
    }
}

创建订单的控制器

modules/erpofflinepayment/controllers/front/validation.php:

<?php

class ErpOfflinePaymentValidationModuleFrontController
    extends ModuleFrontController
{
    public function postProcess()
    {
        $cart = $this->context->cart;

        if (
            !$cart->id
            || !$cart->id_customer
            || !$cart->id_address_delivery
            || !$cart->id_address_invoice
        ) {
            Tools::redirect('index.php?controller=order');
        }

        $customer = new Customer((int) $cart->id_customer);

        if (
            !Validate::isLoadedObject($customer)
            || $customer->secure_key !== $cart->secure_key
        ) {
            Tools::redirect('index.php?controller=order');
        }

        $currency = new Currency((int) $cart->id_currency);
        $total = (float) $cart->getOrderTotal(true, Cart::BOTH);

        /*
         * 示例暂用 PrestaShop 已有的“等待银行转账”状态。
         * 正式项目建议由模块安装程序创建专用的
         * “等待 ERP 处理”订单状态,并从 Configuration 中读取其 ID。
         */
        $orderStateId = (int) Configuration::get('PS_OS_BANKWIRE');

        if ($orderStateId <= 0) {
            throw new PrestaShopException(
                'Offline payment order state is not configured.'
            );
        }

        $this->module->validateOrder(
            (int) $cart->id,
            $orderStateId,
            $total,
            $this->module->displayName,
            null,
            [],
            (int) $currency->id,
            false,
            $customer->secure_key
        );

        Tools::redirect(
            'index.php?controller=order-confirmation'
            . '&id_cart=' . (int) $cart->id
            . '&id_module=' . (int) $this->module->id
            . '&id_order=' . (int) $this->module->currentOrder
            . '&key=' . urlencode($customer->secure_key)
        );
    }
}

付款方式说明模板

modules/erpofflinepayment/views/templates/front/payment_info.tpl:

<p>
  提交订单后无需在线付款,款项将由 ERP 系统在线下处理。
</p>

模块安装并启用后,还要检查”模块管理 → 付款 → 偏好设置”中的国家、货币、客户组和配送方式限制。如果当前条件不符合限制,结账页面不会显示这种付款方式。

是否可以彻底隐藏付款步骤

PrestaShop 1.7 的标准结账流程要求客户选择一个付款选项,有时还要接受服务条款。更稳妥的处理是保留付款步骤,只显示一个”提交订单,无需在线付款”的选项。

可以修改主题 JavaScript,让页面自动选择唯一的付款方式,少一次手动点击。不过,这种做法容易受主题、结账模块和 PrestaShop 升级影响。直接删除付款步骤的风险更高,可能跳过服务条款确认、付款选项校验或订单创建逻辑。

如果业务要求客户点击”提交订单”后直接完成结账,可以定制结账组件,让它自动选中线下付款模块。订单最终仍应由该模块调用 validateOrder() 创建,不要直接向 orders 数据表写入记录。

注意事项

  • 不要禁用所有付款模块,否则购物车通常无法转换成订单。
  • 不要修改 PrestaShop 核心控制器。这类改动升级时会丢失,也可能破坏其他结账功能。
  • validateOrder() 创建的是正式订单,不只是保存购物车。
  • 示例中的 PS_OS_BANKWIRE 只是临时复用了现有状态。生产环境最好创建独立的”等待 ERP 处理”状态。
  • ERP 同步需要具备幂等机制,重复推送同一个订单时,不能在 ERP 中重复创建。
  • ERP 接收成功后,可以通过 Webservice、模块接口或定时任务更新 PrestaShop 的订单状态。
  • 页面上的”已下单”不能显示为”已付款”。订单邮件、订单状态名称和客户中心文案也要一并调整。
  • 上线前应分别测试游客结账、注册客户、优惠券、免运费、多币种和不同配送方式。

备注:内容仅供参考。