PAYATHON 2026

如何将 eWAY payment gateway 集成到 PHP 网站?

支付阿杰

结论

这段交易参数本身没有明显问题。报错“eWAY library has encountered a problem connecting to Rapid”通常说明 PHP SDK 无法建立 HTTPS 连接,并不代表交易遭到拒绝。建议先检查:

  1. 服务器是否启用了 PHP cURL 和 OpenSSL。
  2. 服务器能否通过 HTTPS 访问 eWAY Sandbox API。
  3. CA 根证书是否配置正确。
  4. API Key、Password 是否与 Sandbox 或 Production 环境对应。
  5. eWAY PHP SDK 是否过旧,能否兼容当前的 PHP 和 TLS 配置。

问题中已经公开了 API 凭据。即使这些只是测试凭据,也应立即在 eWAY 后台撤销并重新生成。新凭据应通过环境变量读取,不要继续写入 PHP 文件。

推荐的集成流程

普通 PHP 网站可以使用 eWAY Responsive Shared Page。完整流程如下:

  1. 网站后端创建交易。
  2. eWAY 返回 SharedPaymentUrl。
  3. 浏览器跳转到 eWAY 托管的支付页面。
  4. 支付完成后,eWAY 将用户重定向到 RedirectUrl。
  5. 网站后端使用返回的 AccessCode 查询交易结果。
  6. 服务端确认交易成功后,再更新订单状态。

支付结果必须由服务器向 eWAY 查询确认,不能只根据浏览器的跳转参数判断付款成功。

安装并加载 SDK

使用 Composer 的项目应直接安装 SDK,不要手动复制旧版源码:

composer require eway/eway-rapid-php

然后加载 Composer 自动加载器:

require_once __DIR__ . '/vendor/autoload.php';

如果必须使用手动下载的 SDK,请确认:

  • include_eway.php 路径正确;
  • SDK 版本支持当前 PHP 版本;
  • SDK 没有使用服务器已禁用的旧 TLS 协议;
  • 项目中没有另一套 eWAY 类库与其发生冲突。

创建 Sandbox 交易

下面的示例更适合实际项目。环境常量的名称可能因 SDK 版本而异。如果当前版本没有 Client::MODE_SANDBOX,请使用该版本文档规定的 Sandbox 参数。

<?php

declare(strict_types=1);

require_once __DIR__ . '/vendor/autoload.php';

$apiKey = getenv('EWAY_API_KEY');
$apiPassword = getenv('EWAY_API_PASSWORD');

if (!$apiKey || !$apiPassword) {
    throw new RuntimeException('Missing eWAY API credentials.');
}

$client = \Eway\Rapid::createClient(
    $apiKey,
    $apiPassword,
    \Eway\Rapid\Client::MODE_SANDBOX
);

$baseUrl = 'https://example.com';

$transaction = [
    'Customer' => [
        'FirstName'  => 'John',
        'LastName'   => 'Smith',
        'Street1'    => 'Level 5',
        'Street2'    => '369 Queen Street',
        'City'       => 'Sydney',
        'State'      => 'NSW',
        'PostalCode' => '2000',
        'Country'    => 'au',
        'Email'      => 'demo@example.org',
    ],
    'RedirectUrl' => $baseUrl . '/payment/eway-response.php',
    'CancelUrl' => $baseUrl . '/checkout.php',
    'TransactionType' => \Eway\Rapid\Enum\TransactionType::PURCHASE,
    'Payment' => [
        'TotalAmount' => 1000,
        'InvoiceNumber' => 'ORDER-10001',
        'InvoiceDescription' => 'Order ORDER-10001',
        'CurrencyCode' => 'AUD',
    ],
];

try {
    $response = $client->createTransaction(
        \Eway\Rapid\Enum\ApiMethod::RESPONSIVE_SHARED,
        $transaction
    );

    $errors = $response->getErrors();

    if ($errors) {
        foreach ($errors as $error) {
            error_log(
                'eWAY error ' . $error . ': ' .
                \Eway\Rapid::getMessage($error)
            );
        }

        http_response_code(502);
        exit('暂时无法创建支付,请稍后重试。');
    }

    $sharedPaymentUrl = $response->SharedPaymentUrl ?? null;

    if (!$sharedPaymentUrl) {
        throw new RuntimeException('eWAY did not return SharedPaymentUrl.');
    }

    header('Location: ' . $sharedPaymentUrl, true, 302);
    exit;
} catch (\Throwable $e) {
    error_log('eWAY connection exception: ' . $e->getMessage());

    http_response_code(502);
    exit('支付服务暂时不可用,请稍后重试。');
}

TotalAmount 使用最小货币单位。对于澳元,1000 表示 AUD 10.00,不是 AUD 1000.00。

不要这样直接拼接回调地址:

"http://$_SERVER[HTTP_HOST]"

HTTP_HOST 来自请求头,使用不当可能带来 Host Header 风险。支付回调也应使用固定的 HTTPS 地址。生产环境中的站点基础 URL 应从可信配置中读取。

在返回页面确认支付结果

支付完成后,从 eWAY 返回的数据中读取 AccessCode,再由服务端查询交易。下面是通用写法,具体字段和方法签名请以已安装的 SDK 版本为准:

<?php

declare(strict_types=1);

require_once __DIR__ . '/vendor/autoload.php';

$apiKey = getenv('EWAY_API_KEY');
$apiPassword = getenv('EWAY_API_PASSWORD');

$client = \Eway\Rapid::createClient(
    $apiKey,
    $apiPassword,
    \Eway\Rapid\Client::MODE_SANDBOX
);

$accessCode = $_GET['AccessCode'] ?? '';

if ($accessCode === '') {
    http_response_code(400);
    exit('Missing AccessCode.');
}

try {
    $response = $client->queryTransaction($accessCode);

    if ($response->getErrors()) {
        foreach ($response->getErrors() as $error) {
            error_log(
                'eWAY query error ' . $error . ': ' .
                \Eway\Rapid::getMessage($error)
            );
        }

        exit('无法确认支付结果。');
    }

    $transaction = $response->Transactions[0] ?? null;

    if (!$transaction) {
        exit('未找到对应交易。');
    }

    if (!empty($transaction->TransactionStatus)) {
        /*
         * 在这里核对:
         * 1. InvoiceNumber 是否属于当前订单
         * 2. TotalAmount 是否与订单金额一致
         * 3. 该订单是否已经处理过
         *
         * 核对完成后,再以幂等方式更新订单状态。
         */
        echo '支付成功。';
    } else {
        echo '支付未成功。';
    }
} catch (\Throwable $e) {
    error_log('eWAY query exception: ' . $e->getMessage());

    http_response_code(502);
    exit('暂时无法确认支付结果。');
}

不要向用户直接显示异常、API 响应正文或凭据。详细错误信息应写入服务器日志。

排查无法连接到 Rapid

1. 检查 PHP 扩展

可以创建临时诊断页,或通过服务器配置确认以下扩展已经启用:

<?php

var_dump([
    'curl' => extension_loaded('curl'),
    'openssl' => extension_loaded('openssl'),
    'curl_version' => function_exists('curl_version')
        ? curl_version()
        : null,
]);

正常情况下,curl 和 openssl 都应为 true。检查结束后要删除诊断页,以免泄露服务器信息。

还要留意,命令行 PHP 和 Web 服务器使用的 PHP 可能加载不同的 php.ini。命令行中启用了 cURL,不代表 PHP-FPM 或 Apache 模块也启用了它。

2. 检查 DNS、防火墙和代理

服务器需要能够解析 eWAY API 的域名,并通过 TCP 443 端口访问它。连接可能因以下原因受阻:

  • 主机禁止出站 HTTPS;
  • 公司防火墙限制访问外部支付域名;
  • 服务器必须通过代理联网,但 PHP cURL 没有配置代理;
  • DNS 解析异常;
  • 容器或虚拟主机无法访问外网。

如果代码在本地开发环境中可以运行,到了生产服务器却出现连接错误,应重点检查服务器的网络策略和 CA 证书配置。

3. 检查 CA 根证书

常见错误包括:

SSL certificate problem: unable to get local issuer certificate

遇到这个错误时,应安装或更新操作系统的 CA 根证书,并确认 PHP 的 curl.cainfo 和 openssl.cafile 指向有效的 CA 文件。

不要通过关闭证书校验来处理,例如:

CURLOPT_SSL_VERIFYPEER => false

关闭校验会让支付连接面临中间人攻击,而且只会掩盖真正的配置问题。

4. 检查 TLS 和运行环境

旧操作系统、旧版 cURL、OpenSSL 或 eWAY SDK 可能无法与服务端协商当前要求的 TLS。请升级:

  • eWAY PHP SDK;
  • PHP;
  • cURL;
  • OpenSSL;
  • 操作系统 CA 证书包。

如果升级 SDK 后连接恢复,通常说明旧库使用的接口地址、TLS 设置或底层 HTTP 依赖已经不适合当前环境。

5. 检查凭据和环境是否一致

Sandbox 凭据只能用于 Sandbox,生产凭据只能用于 Production。例如,不要将下面的配置:

$apiEndpoint = 'Sandbox';

与生产账号的凭据混用。

API Key 或 Password 错误一般会引发认证错误。不过,一些旧版 SDK 会将底层响应包装成较为笼统的错误,所以仍要确认凭据有效。复制凭据时,也要检查是否混入了空格、换行或不可见字符。

环境参数应使用 SDK 定义的常量,以免受到大小写或字符串解析方式的影响:

\Eway\Rapid\Client::MODE_SANDBOX

切换到生产环境时,应使用当前 SDK 对应的 Production 常量,同时换成生产凭据。

6. 记录底层异常

原代码只检查了 $response->getErrors(),但网络、DNS 和 TLS 问题可能直接抛出异常,因此还要加入异常处理:

try {
    $response = $client->createTransaction(
        \Eway\Rapid\Enum\ApiMethod::RESPONSIVE_SHARED,
        $transaction
    );
} catch (\Throwable $e) {
    error_log($e->getMessage());
    throw $e;
}

在受控的测试环境中查看日志里的原始异常,重点关注:

  • Could not resolve host
  • Connection timed out
  • Connection refused
  • SSL certificate problem
  • Unsupported protocol
  • HTTP 401 或 403

根据这些信息,可以判断问题出在网络、证书还是身份验证。

上线前注意事项

  • 所有支付入口、RedirectUrl 和 CancelUrl 都应使用 HTTPS。
  • API 密钥只能保存在服务端,建议使用环境变量或密钥管理服务。
  • 不要使用浏览器传来的最终金额。金额应由服务端根据订单重新计算。
  • 查询支付结果后,需要核对订单号、金额、币种和交易状态。
  • 更新订单时必须保证幂等,避免用户刷新回调页面后重复发货或重复记账。
  • 日志中不要记录 API Password、完整支付信息或其他敏感数据。
  • 完成 Sandbox 测试后再切换到 Production,并分别保存两套配置。
  • 如果真实凭据曾经出现在代码仓库、日志、工单或公开页面中,应立即轮换,不能只从代码中删除。

备注:内容仅供参考。