如何将 eWAY payment gateway 集成到 PHP 网站?
结论
这段交易参数本身没有明显问题。报错“eWAY library has encountered a problem connecting to Rapid”通常说明 PHP SDK 无法建立 HTTPS 连接,并不代表交易遭到拒绝。建议先检查:
- 服务器是否启用了 PHP cURL 和 OpenSSL。
- 服务器能否通过 HTTPS 访问 eWAY Sandbox API。
- CA 根证书是否配置正确。
- API Key、Password 是否与 Sandbox 或 Production 环境对应。
- eWAY PHP SDK 是否过旧,能否兼容当前的 PHP 和 TLS 配置。
问题中已经公开了 API 凭据。即使这些只是测试凭据,也应立即在 eWAY 后台撤销并重新生成。新凭据应通过环境变量读取,不要继续写入 PHP 文件。
推荐的集成流程
普通 PHP 网站可以使用 eWAY Responsive Shared Page。完整流程如下:
- 网站后端创建交易。
- eWAY 返回
SharedPaymentUrl。 - 浏览器跳转到 eWAY 托管的支付页面。
- 支付完成后,eWAY 将用户重定向到
RedirectUrl。 - 网站后端使用返回的
AccessCode查询交易结果。 - 服务端确认交易成功后,再更新订单状态。
支付结果必须由服务器向 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 hostConnection timed outConnection refusedSSL certificate problemUnsupported protocol- HTTP
401或403
根据这些信息,可以判断问题出在网络、证书还是身份验证。
上线前注意事项
- 所有支付入口、
RedirectUrl和CancelUrl都应使用 HTTPS。 - API 密钥只能保存在服务端,建议使用环境变量或密钥管理服务。
- 不要使用浏览器传来的最终金额。金额应由服务端根据订单重新计算。
- 查询支付结果后,需要核对订单号、金额、币种和交易状态。
- 更新订单时必须保证幂等,避免用户刷新回调页面后重复发货或重复记账。
- 日志中不要记录 API Password、完整支付信息或其他敏感数据。
- 完成 Sandbox 测试后再切换到 Production,并分别保存两套配置。
- 如果真实凭据曾经出现在代码仓库、日志、工单或公开页面中,应立即轮换,不能只从代码中删除。
备注:内容仅供参考。
