準備工作:Sandbox 環境
- 註冊 PayPal Developer 帳號
- 建立兩個測試帳號:Business(收款)、Personal(付款)
- 啟用 IPN:Business 帳號 → Profile → Instant Payment Notification → 設定通知 URL
- 測試時表單 action 指向
https://www.sandbox.paypal.com/cgi-bin/webscr
標準付款表單(_xclick 模式)
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post" target="_blank">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="seller@sandbox.example.com">
<input type="hidden" name="item_name" value="產品名稱">
<input type="hidden" name="amount" value="99.00">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="return" value="https://yoursite.com/payment/success">
<input type="hidden" name="cancel_return" value="https://yoursite.com/payment/cancel">
<input type="hidden" name="notify_url" value="https://yoursite.com/payment/ipn">
<input type="hidden" name="custom" value="order_12345">
<input type="hidden" name="rm" value="2"> <!-- POST 方式返回 -->
<input type="image" src="https://www.sandbox.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal 付款">
</form>
關鍵參數說明
| 參數 | 說明 |
cmd | _xclick=單筆付款、_cart=購物車 |
business | 收款方 PayPal Email |
item_name | 商品名稱 |
amount | 金額(_xclick 模式為總額) |
currency_code | USD、EUR、GBP、JPY、CAD 等 |
return | 付款成功後導向頁面 |
cancel_return | 用戶取消付款導向頁面 |
notify_url | IPN 非同步通知 URL(伺服器間) |
custom | 自訂參數,原樣回傳,可存訂單編號 |
rm | 返回方式:1=GET、2=POST(建議 2) |
IPN 驗證流程(核心安全步驟)
<?php
// ipn.php
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $val) {
$val = urlencode(stripslashes($val));
$req .= "&$key=$val";
}
$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $req,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_HEADER => false,
]);
$res = curl_exec($ch);
curl_close($ch);
if (strcmp($res, "VERIFIED") === 0) {
// 必須再做四項檢查:
// 1. payment_status == 'Completed'
// 2. txn_id 未重複(查資料庫)
// 3. receiver_email == 你的商家信箱
// 4. 金額/幣別/商品編號與訂單一致
// 通過後更新訂單狀態、發貨、發送通知
error_log("IPN VERIFIED: " . print_r($_POST, true));
} elseif (strcmp($res, "INVALID") === 0) {
error_log("IPN INVALID: " . print_r($_POST, true));
}
?>
上線前檢查清單
- 將所有 Sandbox URL 改為正式環境
https://www.paypal.com/cgi-bin/webscr
- 確認 IPN URL 可公開存取(HTTPS、無需登入、回應 200 OK)
- 啟用 PayPal 帳號的「自動返回」與「付款資料傳遞」(PDT)
- 測試退款、爭議、部分付款等邊界狀況