建立單次付款
POST /checkout
- 正式環境:
https://payment-api.oen.tw/checkout - 測試環境:
https://payment-api.testing.oen.tw/checkout
建立一筆單次付款,回傳交易的 id。把消費者導到 https://{merchantId}.oen.tw/checkout/{id}(測試環境是 {merchantId}.testing.oen.tw)付款。結帳頁從呼叫這支 API 起 5 分鐘內有效,請在消費者按下付款時才建立。
Header 帶 Authorization: Bearer <token> 與 Content-Type: application/json 。token 的取得方式見驗證與 token。
Body 欄位
Section titled “Body 欄位”| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
merchantId | string | 必填 | 你的網域名稱。例如應援頁是 https://ming.oen.tw,就填 ming。必須與 token 所屬的網域相同,不同會回 400 V0001。範例: ming |
amount | integer | 必填 | 金額(新台幣元)。必須等於 productDetails 各品項「數量 × 單價」的合計。限制:1 以上的整數 範例: 1200 |
currency | string | 選填 | 幣別。目前只支援新台幣。 可用值: TWD預設: TWD |
orderId | string | 必填 | 你的訂單編號。之後可以用用訂單編號查詢找到這筆訂單的所有交易。 限制:不檢查重複。同一個 orderId 可以建立多筆交易範例: A20260928001 |
successUrl | string (uri) | null | 必填 | 付款成功後把消費者導回的網址。導回時不帶任何參數,請在網址裡放自己的訂單編號,例如 https://shop.example.com/thanks?order=A001。導回不代表付款成功,請以付款通知或查詢結果為準。限制:要寫完整網址(含 https://);可以是 null,但欄位一定要有 |
failureUrl | string (uri) | null | 必填 | 付款失敗或逾時後導回的網址,會加上 payment_error 參數,可能的值見錯誤碼一覽。限制:同 successUrl。建議不要自帶 ? 參數與 # 片段 |
productDetails | array | 必填 | 商品明細,用來開立電子發票與顯示在 CRM。所有品項「數量 × 單價」的合計必須等於 amount,否則回 400 V0001(PRODUCT_AMOUNT_NOT_MATCH)。 |
productionCodeproductDetails[].productionCode | string | 必填 | 商品代碼 |
descriptionproductDetails[].description | string | 必填 | 商品名稱。第一個品項的名稱也會當成交易的商品描述 |
quantityproductDetails[].quantity | integer | 必填 | 數量 限制:1 以上的整數 |
unitproductDetails[].unit | string | 必填 | 單位,例如「個」「份」 |
unitPriceproductDetails[].unitPrice | integer | 必填 | 單價(新台幣元) |
allowedPaymentMethods | array<string> | 選填 | 結帳頁可以選的付款方式。信用卡一定會出現,這裡是「加開」其他方式:['cvs'] 會顯示信用卡與超商。沒帶就只有信用卡。Apple Pay 不用指定,條件符合時自動出現。詳見付款方式。可用值: card、cvs、linePay、atm範例: ["cvs"] |
userId | string | 選填 | 你系統裡的會員編號。 |
userName | string | 條件必填 | 消費者姓名。網域有開通電子發票時必填。 |
userEmail | string (email) | 條件必填 | 消費者 Email。網域有開通電子發票時必填,發票通知會寄到這裡。 |
invoiceInfo | object | 選填 | 電子發票資訊。網域有開通電子發票時才有作用;沒帶時開立雲端發票。 |
invoiceTypeinvoiceInfo.invoiceType | string | 必填 | cloud:雲端發票;company:公司戶(打統編)可用值: cloud、company |
carrierTypeinvoiceInfo.carrierType | string | 雲端發票必填 | 載具類型:3J0002 手機條碼、CQ0001 自然人憑證、空字串為會員載具可用值: 3J0002、CQ0001、 |
carrierIdinvoiceInfo.carrierId | string | 選填 | 載具號碼。手機條碼格式為 / 加 7 碼,會即時向財政部驗證;自然人憑證為 2 個英文字母加 14 碼數字 |
buyerIdentifierinvoiceInfo.buyerIdentifier | string | 公司戶必填 | 買受人統一編號,8 碼,會檢查檢查碼 |
buyerNameinvoiceInfo.buyerName | string | 選填 | 買受人名稱 |
emailinvoiceInfo.email | string (email) | 選填 | 發票通知 Email |
customId | string | 選填 | 你自訂的資料,會原樣出現在付款通知與查詢結果中。 |
note | string | 選填 | 備註。 |
use3d | boolean | 選填 | 是否走 3D 驗證。網域被設定為一律 3D 時會強制開啟。 預設: false |
expectedPayoutDate | string | 選填 | 期望撥款日期(台北日期),會顯示在 CRM 金流明細。 限制: yyyy/MM/dd |
範例一律打測試環境。把 OEN_API_TOKEN 設成測試環境 CRM 產生的 token。
curl -X POST "https://payment-api.testing.oen.tw/checkout" \ -H "Authorization: Bearer $OEN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "merchantId": "ming", "amount": 1200, "currency": "TWD", "orderId": "A20260928001", "successUrl": "https://shop.example.com/payment/success?order=A20260928001", "failureUrl": "https://shop.example.com/payment/failure/A20260928001", "userName": "王小明", "userEmail": "ming@example.com", "productDetails": [ { "productionCode": "SKU-001", "description": "手沖咖啡豆 200g", "quantity": 2, "unit": "包", "unitPrice": 600 } ], "allowedPaymentMethods": [ "cvs" ], "customId": "cart-8812"}'const res = await fetch("https://payment-api.testing.oen.tw/checkout", { method: "POST", headers: { Authorization: `Bearer ${process.env.OEN_API_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ "merchantId": "ming", "amount": 1200, "currency": "TWD", "orderId": "A20260928001", "successUrl": "https://shop.example.com/payment/success?order=A20260928001", "failureUrl": "https://shop.example.com/payment/failure/A20260928001", "userName": "王小明", "userEmail": "ming@example.com", "productDetails": [ { "productionCode": "SKU-001", "description": "手沖咖啡豆 200g", "quantity": 2, "unit": "包", "unitPrice": 600 } ], "allowedPaymentMethods": [ "cvs" ], "customId": "cart-8812" }),});
const result = await res.json();if (result.code !== "S0000") { throw new Error(`${result.code} ${result.message}`);}<?php$ch = curl_init('https://payment-api.testing.oen.tw/checkout');curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('OEN_API_TOKEN'), 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'merchantId' => 'ming', 'amount' => 1200, 'currency' => 'TWD', 'orderId' => 'A20260928001', 'successUrl' => 'https://shop.example.com/payment/success?order=A20260928001', 'failureUrl' => 'https://shop.example.com/payment/failure/A20260928001', 'userName' => '王小明', 'userEmail' => 'ming@example.com', 'productDetails' => [ [ 'productionCode' => 'SKU-001', 'description' => '手沖咖啡豆 200g', 'quantity' => 2, 'unit' => '包', 'unitPrice' => 600, ], ], 'allowedPaymentMethods' => [ 'cvs', ], 'customId' => 'cart-8812', ]),]);
$result = json_decode(curl_exec($ch), true);if ($result['code'] !== 'S0000') { throw new Exception($result['code'] . ' ' . $result['message']);}import osimport requests
res = requests.request( "POST", "https://payment-api.testing.oen.tw/checkout", headers={"Authorization": f"Bearer {os.environ['OEN_API_TOKEN']}"}, json={ "merchantId": "ming", "amount": 1200, "currency": "TWD", "orderId": "A20260928001", "successUrl": "https://shop.example.com/payment/success?order=A20260928001", "failureUrl": "https://shop.example.com/payment/failure/A20260928001", "userName": "王小明", "userEmail": "ming@example.com", "productDetails": [ { "productionCode": "SKU-001", "description": "手沖咖啡豆 200g", "quantity": 2, "unit": "包", "unitPrice": 600, }, ], "allowedPaymentMethods": [ "cvs", ], "customId": "cart-8812", }, timeout=30,)
result = res.json()if result["code"] != "S0000": raise RuntimeError(f"{result['code']} {result['message']}")| HTTP | 說明 |
|---|---|
200 | 建立成功。data.id 用來組結帳頁網址,data.transactionHid 用來退款與對帳 |
400 | 參數錯誤、金流未開通或風控拒絕,見下方錯誤表 |
401 | token 錯誤,回 A0001 |
403 | 正式環境的 IP 還沒綁定,見固定 IP 白名單 |
| 欄位 | 型別 | 出現 | 說明 |
|---|---|---|---|
id | string | 一定有 | 交易的內部 id(27 字元),組結帳頁網址用,也是付款通知裡的 id |
transactionHid | string | 一定有 | 交易編號,P 開頭共 17 字元。退款要用這個 |
{ "code": "S0000", "data": { "id": "2HhndgEquCbDzC5OyVxWSGZmd2l", "transactionHid": "P20260928AB12CD34" }, "message": ""}| 錯誤碼 | HTTP | 什麼時候會發生 |
|---|---|---|
V0001 | 400 | 欄位不符規則;merchantId 與 token 不符;品項合計不等於金額(PRODUCT_AMOUNT_NOT_MATCH);開通電子發票但缺姓名或 Email(USER_NAME_AND_EMAIL_REQUIRED);發票資訊錯誤;指定 linePay 但 LINE Pay 未開通(LINE_PAY_NOT_ACTIVE) |
V0002 | 400 | 網域的金流服務尚未開通(PAYMENT_SERVICE_NOT_ACTIVATE) |
K0001 | 400 | 個人身分商家的交易金額超過風控門檻 |
A0001 | 401 | token 錯誤或已被重新產生 |
F0001 | 500 | 系統錯誤,或 body 不是合法的 JSON |
完整清單與處理方式見錯誤碼一覽。
導覽助手暫停服務中。請使用右上角的搜尋,或聯絡客服。
我可以幫你選擇收款方式、回答 API 串接與 CRM 操作問題,並附上文件出處。
