跳到內容

付款通知內容

在 ChatGPT 開啟在 Claude 開啟

付款通知的處理方式、重送規則與回查做法,請先看付款通知(webhook)。這一頁列出每一種通知的欄位。

  • POST 到你在 CRM 設定的「交易資料回傳網址位置」。
  • Header 有 Content-Type: application/json、OenPay-Event-Id、OenPay-Delivery-Attempt;在 CRM 產生簽章密鑰後另外帶 OenPay-Signature,驗證方式見確認通知的真假。charge、token、schedule_subscription 的 body 沒有事件編號,請依 OenPay-Event-Id 的算法由 body 重算;需要開啟的五種通知與 subscription_card_changed,body 的 id 本身就是事件編號。
  • 用 body 的 purpose 分辨是哪一種通知。
purpose 什麼時候送 預設會送嗎
charge 單次付款與定期定額每一期的結果;超商代碼、ATM 取號;LINE Pay 等待確認 會
token 綁卡頁完成或失敗 會
schedule_subscription 預約定期定額在結帳頁完成或失敗 會
refund 退款建立、完成或取消 要請應援開啟
subscription_cancelled 定期定額被取消(API 或 CRM) 要請應援開啟
subscription_retry 定期定額扣款失敗後,已排定重扣或重扣次數用完 要請應援開啟
invoice_issued API 交易的電子發票開立成功 要請應援開啟
invoice_voided API 交易的電子發票作廢成功 要請應援開啟
subscription_card_changed 消費者在換卡頁換卡成功 會

refund、subscription_cancelled、subscription_retry、invoice_issued、invoice_voided 五種共用同一個開關,要請應援在後台開啟「Webhook 新版事件」才會送出。開啟後五種都會收到,用不到的請依 purpose 略過;不認得的 purpose 也請一律略過,不要回錯誤。沒有開啟新版事件也可能收到新的 purpose(例如 subscription_card_changed)。

單次付款、定期定額每一期的結果。同一筆交易可能收到多則,例如超商代碼先送取號(charging),繳費後再送 charged。

欄位型別出現說明
purposestring一定有charge
idstring一定有交易的內部 id。用它呼叫 GET /transactions/{id} 回查
transactionIdstring一定有同 id
transactionHidstring一定有交易編號(P 開頭)
merchantIdstring一定有你的網域名稱
orderIdstring可能沒有你的訂單編號
actionstring可能沒有onetime 或 subscription
statusstring一定有交易狀態:charging、charged、claimed、authorized、failed 等
successboolean可能沒有只在最終結果才有:status 不是 failed 時為 true。取號、等待確認(charging)時沒有這個欄位
paymentMethodstring可能沒有card、applePay、linePay、cvs、atm
amountnumber可能沒有金額
currencystring可能沒有幣別,小寫,例如 twd
paymentInfostring | object可能沒有信用卡:卡號末四碼字串(Apple Pay 的付款通知可能不帶 paymentInfo);超商:{ cvsName, code, expiredAt };ATM:{ bankName, bankCode, account, expiredAt };LINE Pay:LINE Pay 交易編號
authCodestring可能沒有授權碼
customIdstring可能沒有你帶入的自訂資料
productDetailsarray可能沒有建立交易時的商品明細
userPhonestring可能沒有消費者在結帳頁填的手機
createdAtstring可能沒有交易建立時間,不是通知送出的時間
paidAtstring可能沒有付款完成時間
messagestring可能沒有失敗原因。超商代碼、ATM、LINE Pay 逾期時是 PAYMENT_EXPIRED;3D 驗證開始後 10 分鐘沒完成是 3DS_ABANDONED
subscriptionIdstring可能沒有定期定額編號(S 開頭),定期定額才有
periodinteger可能沒有定期定額的第幾期
numberOfPeriodsinteger可能沒有定期定額總期數
isRetryboolean可能沒有定期定額:這次是否為失敗後的重新扣款
failureCodestring可能沒有定期定額扣款失敗的原因:invalid_card_number、invalid_cvv、expired_card、exceeds_credit_limit、payment_refused、duplicate_payment、charge_failed
scheduleStatusstring可能沒有定期定額狀態:pending、trialing、active、retrying、error、cancelled、completed
nextChargeAtstring可能沒有定期定額下次扣款時間。請以查詢定期定額明細為準
firstPeriodDiscountobject可能沒有首期折扣 { method, value, label, discountAmount },使用首期折扣的第一期才有
originalAmountnumber可能沒有折扣前的每期金額,使用首期折扣的第一期才有

範例

{
"purpose": "charge",
"action": "onetime",
"merchantId": "ming",
"orderId": "A20260928001",
"id": "2HhndgEquCbDzC5OyVxWSGZmd2l",
"transactionId": "2HhndgEquCbDzC5OyVxWSGZmd2l",
"transactionHid": "P20260928AB12CD34",
"status": "charged",
"success": true,
"paymentMethod": "card",
"amount": 1200,
"currency": "twd",
"paymentInfo": "4242",
"authCode": "831000",
"customId": "cart-8812",
"createdAt": "2026-09-28T02:40:25.502Z",
"paidAt": "2026-09-28T02:41:03.118Z",
"productDetails": [
{
"productionCode": "SKU-001",
"description": "手沖咖啡豆 200g",
"quantity": 2,
"unit": "包",
"unitPrice": 600
}
],
"message": ""
}

超商代碼取號時(還沒繳費,沒有 success 欄位):

{
"purpose": "charge",
"action": "onetime",
"merchantId": "ming",
"orderId": "A20260928002",
"id": "2HhnkQ3vXy8LpA1cB0dE9fG2hIj",
"transactionId": "2HhnkQ3vXy8LpA1cB0dE9fG2hIj",
"transactionHid": "P20260928UV12WX34",
"status": "charging",
"paymentMethod": "cvs",
"amount": 500,
"currency": "twd",
"paymentInfo": {
"cvsName": "超商代碼繳費",
"code": "XXXXXXXXXXXX",
"expiredAt": "2026-09-30T02:00:00.000Z"
},
"message": ""
}

消費者繳費後,同一個 id 會再收到一則 status: charged、success: true 的通知。逾期未繳則是 status: failed、message: PAYMENT_EXPIRED。

建立綁卡頁後,消費者完成或放棄綁卡時送出。這是拿到 token 的唯一管道。

欄位型別出現說明
purposestring一定有token
idstring一定有建立綁卡頁時回傳的 id
transactionIdstring一定有同 id
merchantIdstring一定有你的網域名稱
successboolean一定有是否綁卡成功
tokenstring可能沒有成功時才有。用來呼叫用 token 扣款,請當成密碼一樣保存
paymentInfostring可能沒有卡號末四碼
customIdstring可能沒有建立綁卡頁時帶的自訂資料
messagestring可能沒有失敗原因。3D 驗證開始後 10 分鐘沒完成是 3DS_ABANDONED

範例

{
"purpose": "token",
"merchantId": "ming",
"id": "2HhngP9sVb3mK1xYdQe7Wc0RtUi",
"transactionId": "2HhngP9sVb3mK1xYdQe7Wc0RtUi",
"success": true,
"token": "2HhnhWm8Qe0sPz4LbXv9KdYt1Ra",
"paymentInfo": "4242",
"customId": "M001",
"message": ""
}

建立預約定期定額後,消費者在結帳頁完成或失敗時送出。之後每一期的扣款結果以 charge 通知送出。

欄位型別出現說明
purposestring一定有schedule_subscription
idstring一定有建立時回傳的 id
subscriptionIdstring一定有定期定額編號(S 開頭)
merchantIdstring一定有你的網域名稱
successboolean一定有是否成功
amountnumber可能沒有每期金額
currencystring可能沒有幣別(小寫)
periodinteger可能沒有已扣期數
numberOfPeriodsinteger可能沒有總期數
intervalinteger可能沒有每幾個月扣一次
startedAtstring可能沒有開始時間
nextChargeAtstring可能沒有下次扣款時間
paymentInfostring可能沒有成功時為卡號末四碼
customIdstring可能沒有你帶入的自訂資料
productDetailsarray可能沒有商品明細
messagestring可能沒有失敗原因

範例

{
"purpose": "schedule_subscription",
"merchantId": "ming",
"id": "2HhnfZ1kqRmA7cX0TQwq8vBn3Ls",
"subscriptionId": "S20260928EF56GH78",
"success": true,
"amount": 1500,
"currency": "twd",
"period": 0,
"numberOfPeriods": 4,
"interval": 3,
"startedAt": "2026-10-15T00:00:00.000Z",
"nextChargeAt": "2026-10-15T01:00:00.000Z",
"paymentInfo": "4242",
"message": ""
}

消費者在換卡頁換卡成功時送出。不需要開啟「Webhook 新版事件」,有設定通知網址就會收到。

欄位型別出現說明
purposestring一定有subscription_card_changed
idstring一定有換卡請求的 id。同一次換卡的 id 固定,可以用來判斷重複
transactionIdstring一定有同 id。不是交易編號
merchantIdstring一定有你的網域名稱
successboolean一定有固定是 true
statusstring一定有固定是 succeeded
subscriptionIdstring一定有定期定額編號(S 開頭)
periodinteger可能沒有已扣期數
nextChargeAtstring可能沒有下次扣款時間。請以查詢定期定額明細為準
paymentInfostring可能沒有新卡末四碼
cardBrandstring可能沒有新卡卡別
orderIdstring可能沒有你的訂單編號
userIdstring可能沒有你帶入的會員編號
customIdstring可能沒有你帶入的自訂資料
欄位 說明
purpose refund
id 這則退款事件的 id,每則都不同
refundId 退款單 id
chargeId、chargeHumanId 原交易的內部 id 與交易編號(P 開頭)
amount、origAmount 退款金額、原交易金額
currency 幣別(小寫)
refundStatus refunding(處理中)、refunded(完成)、cancelled(取消)
reason 退款原因
paymentMethod 原交易的付款方式
requestedAt、resolvedAt 申請時間、完成時間
customId 原交易的自訂資料
subscriptionId、period 定期定額交易才有
欄位 說明
purpose subscription_cancelled
subscriptionId 定期定額編號
source 誰取消的:merchant_api(API)或 crm(後台)
reason 取消原因
cancelledAt 取消時間
cancelledFromStatus 取消前的狀態
period、numberOfPeriods 已扣期數、總期數
customId 自訂資料
欄位 說明
purpose subscription_retry
outcome scheduled:已排定重新扣款;exhausted:重扣次數用完,定期定額停止
retryAttemptNumber 第幾次重扣
nextRetryAt 下次重扣時間(scheduled 才有)
failureCode 扣款失敗的原因
chargeId、chargeHumanId 失敗那一期的交易
subscriptionId、period 定期定額編號與期數

invoice_issued、invoice_voided(需開啟)

Section titled “invoice_issued、invoice_voided(需開啟)”

API 交易的電子發票開立成功(invoice_issued)或作廢成功(invoice_voided)時送出。要請應援開啟才會送,見電子發票號碼與狀態。

欄位型別出現說明
purposestring一定有invoice_issued 或 invoice_voided
idstring一定有這則通知的事件編號,格式是 invoice#<發票 id>#issued 或 invoice#<發票 id>#voided。同一張發票的同一種通知 id 固定,可以用來判斷重複
transactionIdstring一定有同 id。不是交易編號,交易請看 chargeId
merchantIdstring一定有你的網域名稱
chargeIdstring一定有發票所屬交易的內部 id(27 字元),和 charge 通知的 id 相同。用它呼叫 GET /transactions/{id} 回查
orderIdstring可能沒有你的訂單編號
invoiceNumberstring一定有發票號碼。invoice_voided 時是被作廢的那張
invoiceStatusstring一定有invoice_issued 固定是 issued,invoice_voided 固定是 voided。值和查詢 API 的 invoice.invoiceStatus 相同
invoiceDatestring一定有發票開立時間(UTC,ISO 8601)。換算成台北時間就是發票日期
randomNumberstring一定有4 碼隨機碼
invoiceAmountnumber | null一定有發票金額(含稅),是發票品項的加總。品項資料不完整時是 null
createdAtstring一定有這則通知建立的時間(和 charge 通知不同,不是交易建立時間)
messagestring可能沒有固定是空字串

範例

{
"purpose": "invoice_issued",
"id": "invoice#2HhnqT4cWz0mR8bLxN3vYs6KdPa#issued",
"transactionId": "invoice#2HhnqT4cWz0mR8bLxN3vYs6KdPa#issued",
"merchantId": "ming",
"chargeId": "2HhndgEquCbDzC5OyVxWSGZmd2l",
"orderId": "A20260928001",
"invoiceNumber": "ZZ00001234",
"invoiceStatus": "issued",
"invoiceDate": "2026-09-28T02:41:30.000Z",
"randomNumber": "0000",
"invoiceAmount": 1200,
"createdAt": "2026-09-28T02:41:31.204Z",
"message": ""
}

invoice_voided 的欄位相同,purpose 是 invoice_voided、invoiceStatus 是 voided,id 結尾是 #voided;invoiceNumber、invoiceDate、randomNumber 是被作廢的那張發票。什麼時候會送、什麼時候不會送,見電子發票號碼與狀態。