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

自定义WHMCS Clover支付网关开发故障求助

WHMCS自定义Clover网关开发问题求助

问题背景

我尝试解决这个问题已经有一段时间了,但一直没能修复。我的支付处理器是Clover,WHMCS没有预构建的对应网关,所以我自己动手开发,但遇到了未知问题——我是这个领域的新手。

我在modules/gateways目录和modules/gateways/callbacks目录中各创建了一个clovergateway.php文件。

modules/gateways/clovergateway.php代码

<?php

if (!defined("WHMCS")) {
    die("This file cannot be accessed directly");
}

function clovergateway_MetaData()
{
    return [
        'DisplayName' => 'Clover Gateway',
        'APIVersion' => '1.0',
        'DisableLocalCredtCardInput' => true,
        'TokenisedStorage' => true,
    ];
}

function clovergateway_config()
{
    return [
        'FriendlyName' => [
            'Type' => 'System',
            'Value' => 'Clover Gateway',
        ],
        'apiKey' => [
            'FriendlyName' => 'API Key',
            'Type' => 'text',
            'Size' => '25',
            'Default' => '',
            'Description' => 'Enter your Clover API Key here.',
        ],
        'merchantId' => [
            'FriendlyName' => 'Merchant ID',
            'Type' => 'text',
            'Size' => '25',
            'Default' => '',
            'Description' => 'Enter your Clover Merchant ID here.',
        ],
        'publicKey' => [
            'FriendlyName' => 'Public Key',
            'Type' => 'text',
            'Size' => '25',
            'Default' => '',
            'Description' => 'Enter your Clover Public Key here.',
        ],
    ];
}
function clovergateway_remoteinput($params)
{
    $tokenForm = <<<HTML
<form id="paymentfrm" method="post" action="{$params['systemurl']}/creditcard.php">
    <input type="hidden" name="invoiceid" value="{$params['invoiceid']}" />
    <input type="hidden" name="gatewayid" value="{$params['gatewayid']}" />

    <label for="cardNumber">Card Number</label>
    <input type="text" id="cardNumber" />

    <label for="cardExpiryMonth">Expiry Month</label>
    <input type="text" id="cardExpiryMonth" />

    <label for="cardExpiryYear">Expiry Year</label>
    <input type="text" id="cardExpiryYear" />

    <label for="cardCVV">CVV</label>
    <input type="text" id="cardCVV" />

    <button type="button" id="submitButton">Submit</button>
</form>
<script src="https://checkout.clover.com/sdk.js"></script>
<script>
    // Replace with your public key
    const publicKey = "{$params['publicKey']}";
    const clover = new Clover(publicKey);
    const elements = clover.elements();

    document.getElementById('submitButton').addEventListener('click', function() {
        clover.createToken({
            cardNumber: document.getElementById('cardNumber').value,
            expMonth: document.getElementById('cardExpiryMonth').value,
            expYear: document.getElementById('cardExpiryYear').value,
            cvv: document.getElementById('cardCVV').value
        }).then(function(response) {
            document.getElementById('gatewayid').value = response.token;
            document.getElementById('paymentfrm').submit();
        }).catch(function(error) {
            // Handle the error
            alert(error.message);
        });
    });
</script>
HTML;

    return $tokenForm;
}


function clovergateway_storeremote($params)
{
    // Store the remote token and return success
    return [
        'success' => true,
        'gatewayid' => $params['card_token'],
    ];
}

function clovergateway_capture($params)
{
    // Fetch the API Key, Merchant ID, and other required parameters
    $apiKey = $params['apiKey'];
    $merchantId = $params['merchantId'];
    $cloverApiUrl = "https://api.clover.com"; // Replace with the appropriate API URL

    // Fetch the card details and invoice amount
    $token = $params['gatewayid'];
    $amount = $params['amount'];

    // Set the required headers for Clover API requests
    $headers = [
        "Content-Type: application/json",
        "Authorization: Bearer {$apiKey}"
    ];

    // Create the charge
    $url = "{$cloverApiUrl}/v1/merchant/{$merchantId}/charges";
    $method = "POST";
    $data = [
        'token' => $token,
        'amount' => $amount * 100 // Convert to cents
    ];

    $response = cloverApiRequest($url, $method, $headers, $data);

    // Check if the charge was successful
    if (isset($response['id'])) {
        return [
            'status' => 'success',
            'transid' => $response['id'],
            'rawdata' => $response,
        ];
    } else {
        return [
            'status' => 'error',
            'rawdata' => $response,
        ];
    }
}

function cloverApiRequest($url, $method, $headers, $data)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    $response = curl_exec($ch);

    if (curl_errno($ch)) {
        throw new Exception('Curl error: ' . curl_error($ch));
    }

    curl_close($ch);

    return json_decode($response, true);
}

modules/gateways/callbacks/clovergateway.php代码

<?php

use WHMCS\Database\Capsule;

require '../../../init.php';
require '../../../includes/gatewayfunctions.php';
require '../../../includes/invoicefunctions.php';

$gatewayModuleName = basename(__FILE__, '.php');

$gatewayParams = getGatewayVariables($gatewayModuleName);

if (!$gatewayParams['type']) {
    die('Module not activated');
}

$invoiceId = $_POST['invoiceid'];
$gatewayId = $_POST['gatewayid'];

$invoiceData = Capsule::table('tblinvoices')
    ->where('id', $invoiceId)
    ->first();

$userId = $invoiceData->userid;

$success = checkCbInvoiceID($invoiceId, $gatewayParams['name']);

if ($success) {
    $result = Capsule::table('tblclients')
        ->where('id', $userId)
        ->update([
            'gatewayid' => $gatewayId,
        ]);

    header('Location: ' . $gatewayParams['systemurl'] . '/clientarea.php?action=invoices');
} else {
    header('Location: ' . $gatewayParams['systemurl'] . '/clientarea.php?action=invoices&status=error');
}

问题现象

我已成功激活并配置该模块,但在客户端测试支付发票时出现问题:点击“Pay Now”按钮进入支付信息页面后,页面下方出现奇怪的页面嵌套,且支付表单无效,点击提交按钮无任何反应。

支付页面截图:
支付页面截图

参考资料

Clover官方文档(使用Clover托管iframe相关内容)


内容的提问来源于stack exchange,提问作者Jason Levine

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 06:12:08