@carllee1983/newebpay
v1.5.0
Published
藍新金流 SDK - NewebPay Payment Gateway SDK for Node.js
Maintainers
Readme
藍新金流 Node.js SDK
藍新金流(NewebPay)Node.js SDK,提供簡潔易用的 API 整合藍新金流支付服務。
功能特色
- ✅ 支援全部支付方式:信用卡、ATM 轉帳、超商代碼/條碼繳費、LINE Pay、台灣 Pay 等
- ✅ 完整的 AES-256-CBC 加解密實作(使用 Node.js 原生 crypto)
- ✅ 支援交易查詢、退款、取消授權
- ✅ 完整的 TypeScript 型別定義
- ✅ ESM 和 CommonJS 雙重支援
- ✅ Node.js 18/20/22 LTS 支援
- ✅ Bun 原生支援(使用 Bun 原生 fetch 和 crypto API)
- ✅ Express、Fastify、Koa 框架整合
系統需求
- Node.js 18.0.0 或更高版本(支援 18.x、20.x、22.x LTS)
- 或 Bun 1.0.0 或更高版本(完全相容,使用 Bun 原生 API)
安裝
npm install @carllee1983/newebpay或使用 yarn / pnpm / bun:
yarn add @carllee1983/newebpay
# 或
pnpm add @carllee1983/newebpay
# 或
bun add @carllee1983/newebpay快速開始
基本使用
import { CreditPayment, FormBuilder } from '@carllee1983/newebpay'
// 建立信用卡付款
const payment = new CreditPayment('特店編號', 'HashKey', 'HashIV')
.setTestMode(true) // 測試環境
.setMerchantOrderNo('ORDER' + Date.now()) // 訂單編號
.setAmt(1000) // 金額
.setItemDesc('測試商品') // 商品描述
.setEmail('[email protected]') // 買家 Email
.setReturnURL('https://your-site.com/return') // 付款完成返回網址
.setNotifyURL('https://your-site.com/notify') // 付款結果通知網址
// 產生 HTML 表單(自動送出)
const form = FormBuilder.create(payment).build()
console.log(form)
// 或取得表單資料供前端使用
const formData = FormBuilder.create(payment).getFormData()
// { action: 'https://...', fields: { MerchantID: '...', TradeInfo: '...', ... } }Express 整合
import express from 'express'
import {
createNewebPayRouter,
loadConfigFromEnv,
NewebPayService,
} from '@carllee1983/newebpay/express'
const app = express()
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
// 從環境變數載入設定
const config = loadConfigFromEnv()
// 方式一:使用內建路由
app.use('/newebpay', createNewebPayRouter(config))
// 方式二:使用 NewebPayService
app.post('/api/payment/create', (req, res) => {
const { orderId, amount, itemDesc, email } = req.body
const newebpay = new NewebPayService(config)
const params = newebpay
.payment(orderId, amount, itemDesc, email)
.creditCard()
.setReturnUrl('https://your-site.com/return')
.setNotifyUrl('https://your-site.com/notify')
.getParams()
res.json({ success: true, data: params })
})
app.listen(3000)環境變數設定:
# .env
NEWEBPAY_MERCHANT_ID=MS12345678
NEWEBPAY_HASH_KEY=your_hash_key_32_chars
NEWEBPAY_HASH_IV=your_hash_iv_16_chars
NEWEBPAY_RETURN_URL=https://your-site.com/return
NEWEBPAY_NOTIFY_URL=https://your-site.com/notify
NEWEBPAY_TEST_MODE=true前端自訂表單
當你需要在前端框架(React、Vue 等)中自訂表單 UI 時,可以使用 FormBuilder 提供的資料取得方法,無需使用 HTML 表單。
取得表單資料
FormBuilder 提供以下方法來取得表單資料:
getFormData()或getData(): 取得完整的表單資料(包含action、method、fields)getFields(): 只取得表單欄位資料
import { CreditPayment, FormBuilder } from '@carllee1983/newebpay'
const payment = new CreditPayment('特店編號', 'HashKey', 'HashIV')
.setTestMode(true)
.setMerchantOrderNo('ORDER' + Date.now())
.setAmt(1000)
.setItemDesc('測試商品')
.setEmail('[email protected]')
.setReturnURL('https://your-site.com/return')
.setNotifyURL('https://your-site.com/notify')
const builder = FormBuilder.create(payment)
// 取得完整表單資料
const { action, method, fields } = builder.getFormData()
// 或使用別名
const { action, method, fields } = builder.getData()
// 只取得欄位資料
const fields = builder.getFields()
// 返回的資料結構:
// {
// action: 'https://ccore.newebpay.com/MPG/mpg_gateway',
// method: 'POST',
// fields: {
// MerchantID: 'MS12345678',
// TradeInfo: '...',
// TradeSha: '...',
// Version: '2.0'
// }
// }React 整合範例
使用 React Hook Form
import { useState, useEffect } from 'react'
import { CreditPayment, FormBuilder } from '@carllee1983/newebpay'
function PaymentForm() {
const [formData, setFormData] = useState<{
action: string
method: string
fields: Record<string, string>
} | null>(null)
useEffect(() => {
// 從後端 API 取得表單資料
fetch('/api/payment/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
orderId: 'ORDER' + Date.now(),
amount: 1000,
itemDesc: '測試商品',
email: '[email protected]',
}),
})
.then((res) => res.json())
.then((data) => setFormData(data.formData))
}, [])
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!formData) return
// 建立動態表單並提交
const form = document.createElement('form')
form.method = formData.method
form.action = formData.action
Object.entries(formData.fields).forEach(([name, value]) => {
const input = document.createElement('input')
input.type = 'hidden'
input.name = name
input.value = value
form.appendChild(input)
})
document.body.appendChild(form)
form.submit()
}
if (!formData) return <div>載入中...</div>
return (
<form onSubmit={handleSubmit}>
<button type="submit">前往付款</button>
</form>
)
}使用 Fetch API 直接提交
import { useState } from 'react'
function PaymentForm() {
const [loading, setLoading] = useState(false)
const handlePayment = async () => {
setLoading(true)
try {
// 從後端取得表單資料
const response = await fetch('/api/payment/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
orderId: 'ORDER' + Date.now(),
amount: 1000,
itemDesc: '測試商品',
email: '[email protected]',
}),
})
const { formData } = await response.json()
// 建立 FormData 並提交到藍新金流
const formDataToSubmit = new FormData()
Object.entries(formData.fields).forEach(([key, value]) => {
formDataToSubmit.append(key, value)
})
// 使用 fetch 提交(注意:藍新金流需要 POST 到指定 URL)
const form = document.createElement('form')
form.method = formData.method
form.action = formData.action
Object.entries(formData.fields).forEach(([name, value]) => {
const input = document.createElement('input')
input.type = 'hidden'
input.name = name
input.value = value
form.appendChild(input)
})
document.body.appendChild(form)
form.submit()
} catch (error) {
console.error('付款失敗:', error)
} finally {
setLoading(false)
}
}
return (
<button onClick={handlePayment} disabled={loading}>
{loading ? '處理中...' : '前往付款'}
</button>
)
}Vue 整合範例
使用 Vue 3 Composition API
<template>
<div>
<button @click="handlePayment" :disabled="loading">
{{ loading ? '處理中...' : '前往付款' }}
</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const loading = ref(false)
const handlePayment = async () => {
loading.value = true
try {
// 從後端 API 取得表單資料
const response = await fetch('/api/payment/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
orderId: 'ORDER' + Date.now(),
amount: 1000,
itemDesc: '測試商品',
email: '[email protected]',
}),
})
const { formData } = await response.json()
// 建立動態表單並提交
const form = document.createElement('form')
form.method = formData.method
form.action = formData.action
Object.entries(formData.fields).forEach(([name, value]) => {
const input = document.createElement('input')
input.type = 'hidden'
input.name = name
input.value = value as string
form.appendChild(input)
})
document.body.appendChild(form)
form.submit()
} catch (error) {
console.error('付款失敗:', error)
} finally {
loading.value = false
}
}
</script>使用響應式表單資料
<template>
<form @submit.prevent="submitForm">
<div v-if="formData">
<input
v-for="(value, name) in formData.fields"
:key="name"
type="hidden"
:name="name"
:value="value"
/>
<button type="submit">前往付款</button>
</div>
<div v-else>載入中...</div>
</form>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
interface FormData {
action: string
method: string
fields: Record<string, string>
}
const formData = ref<FormData | null>(null)
onMounted(async () => {
const response = await fetch('/api/payment/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
orderId: 'ORDER' + Date.now(),
amount: 1000,
itemDesc: '測試商品',
email: '[email protected]',
}),
})
const data = await response.json()
formData.value = data.formData
})
const submitForm = () => {
if (!formData.value) return
const form = document.createElement('form')
form.method = formData.value.method
form.action = formData.value.action
Object.entries(formData.value.fields).forEach(([name, value]) => {
const input = document.createElement('input')
input.type = 'hidden'
input.name = name
input.value = value
form.appendChild(input)
})
document.body.appendChild(form)
form.submit()
}
</script>原生 JavaScript 範例
使用 Fetch API
async function createPayment() {
try {
// 從後端 API 取得表單資料
const response = await fetch('/api/payment/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
orderId: 'ORDER' + Date.now(),
amount: 1000,
itemDesc: '測試商品',
email: '[email protected]',
}),
})
const { formData } = await response.json()
// 建立動態表單並提交
const form = document.createElement('form')
form.method = formData.method
form.action = formData.action
form.style.display = 'none'
Object.entries(formData.fields).forEach(([name, value]) => {
const input = document.createElement('input')
input.type = 'hidden'
input.name = name
input.value = value
form.appendChild(input)
})
document.body.appendChild(form)
form.submit()
} catch (error) {
console.error('付款失敗:', error)
}
}
// 使用範例
document.getElementById('pay-button').addEventListener('click', createPayment)使用 XMLHttpRequest
function createPayment() {
const xhr = new XMLHttpRequest()
xhr.open('POST', '/api/payment/create', true)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.onload = function () {
if (xhr.status === 200) {
const { formData } = JSON.parse(xhr.responseText)
// 建立動態表單並提交
const form = document.createElement('form')
form.method = formData.method
form.action = formData.action
Object.entries(formData.fields).forEach(([name, value]) => {
const input = document.createElement('input')
input.type = 'hidden'
input.name = name
input.value = value
form.appendChild(input)
})
document.body.appendChild(form)
form.submit()
}
}
xhr.send(
JSON.stringify({
orderId: 'ORDER' + Date.now(),
amount: 1000,
itemDesc: '測試商品',
email: '[email protected]',
})
)
}API 端點範例
Express
import express from 'express'
import { CreditPayment, FormBuilder } from '@carllee1983/newebpay'
const app = express()
app.use(express.json())
app.post('/api/payment/create', (req, res) => {
const { orderId, amount, itemDesc, email } = req.body
const payment = new CreditPayment(
process.env.NEWEBPAY_MERCHANT_ID!,
process.env.NEWEBPAY_HASH_KEY!,
process.env.NEWEBPAY_HASH_IV!
)
.setTestMode(process.env.NEWEBPAY_TEST_MODE === 'true')
.setMerchantOrderNo(orderId)
.setAmt(amount)
.setItemDesc(itemDesc)
.setEmail(email)
.setReturnURL(process.env.NEWEBPAY_RETURN_URL!)
.setNotifyURL(process.env.NEWEBPAY_NOTIFY_URL!)
const formData = FormBuilder.create(payment).getFormData()
res.json({
success: true,
formData: formData,
})
})
app.listen(3000)Fastify
import Fastify from 'fastify'
import { CreditPayment, FormBuilder } from '@carllee1983/newebpay'
const fastify = Fastify()
fastify.post('/api/payment/create', async (request, reply) => {
const { orderId, amount, itemDesc, email } = request.body as {
orderId: string
amount: number
itemDesc: string
email: string
}
const payment = new CreditPayment(
process.env.NEWEBPAY_MERCHANT_ID!,
process.env.NEWEBPAY_HASH_KEY!,
process.env.NEWEBPAY_HASH_IV!
)
.setTestMode(process.env.NEWEBPAY_TEST_MODE === 'true')
.setMerchantOrderNo(orderId)
.setAmt(amount)
.setItemDesc(itemDesc)
.setEmail(email)
.setReturnURL(process.env.NEWEBPAY_RETURN_URL!)
.setNotifyURL(process.env.NEWEBPAY_NOTIFY_URL!)
const formData = FormBuilder.create(payment).getFormData()
return {
success: true,
formData: formData,
}
})
fastify.listen({ port: 3000 })Koa
import Koa from 'koa'
import Router from '@koa/router'
import bodyParser from 'koa-bodyparser'
import { CreditPayment, FormBuilder } from '@carllee1983/newebpay'
const app = new Koa()
const router = new Router()
app.use(bodyParser())
router.post('/api/payment/create', async (ctx) => {
const { orderId, amount, itemDesc, email } = ctx.request.body
const payment = new CreditPayment(
process.env.NEWEBPAY_MERCHANT_ID!,
process.env.NEWEBPAY_HASH_KEY!,
process.env.NEWEBPAY_HASH_IV!
)
.setTestMode(process.env.NEWEBPAY_TEST_MODE === 'true')
.setMerchantOrderNo(orderId)
.setAmt(amount)
.setItemDesc(itemDesc)
.setEmail(email)
.setReturnURL(process.env.NEWEBPAY_RETURN_URL!)
.setNotifyURL(process.env.NEWEBPAY_NOTIFY_URL!)
const formData = FormBuilder.create(payment).getFormData()
ctx.body = {
success: true,
formData: formData,
}
})
app.use(router.routes())
app.listen(3000)支援的支付方式
| 支付方式 | 類別 | 說明 |
| -------------- | ------------------- | --------------------- |
| 信用卡一次付清 | CreditPayment | 支援紅利折抵、銀聯卡 |
| 信用卡分期 | CreditInstallment | 3/6/12/18/24/30 期 |
| WebATM | WebAtmPayment | 即時網路 ATM 轉帳 |
| ATM 轉帳 | AtmPayment | 虛擬帳號轉帳 |
| 超商代碼繳費 | CvsPayment | 金額限制 30~20,000 元 |
| 超商條碼繳費 | BarcodePayment | 金額限制 20~40,000 元 |
| LINE Pay | LinePayPayment | LINE Pay 電子錢包 |
| 台灣 Pay | TaiwanPayPayment | 台灣 Pay 行動支付 |
| 玉山 Wallet | EsunWalletPayment | 玉山銀行電子錢包 |
| BitoPay | BitoPayPayment | 加密貨幣支付 |
| TWQR | TwqrPayment | TWQR 共通支付 |
| 付啦 | FulaPayment | 先買後付 |
| 超商取貨付款 | CvscomPayment | 超商物流取貨付款 |
| 全支付方式 | AllInOnePayment | 自訂啟用多種支付 |
使用範例
信用卡分期
import { CreditInstallment, FormBuilder } from '@carllee1983/newebpay'
const payment = new CreditInstallment('特店編號', 'HashKey', 'HashIV')
.setTestMode(true)
.setMerchantOrderNo('INST' + Date.now())
.setAmt(3000)
.setItemDesc('分期商品')
.setEmail('[email protected]')
.setInstallment([3, 6, 12]) // 提供 3/6/12 期選項
.setReturnURL('https://your-site.com/return')
.setNotifyURL('https://your-site.com/notify')
const form = FormBuilder.create(payment).build()ATM 虛擬帳號
import { AtmPayment, BankType, FormBuilder } from '@carllee1983/newebpay'
const payment = new AtmPayment('特店編號', 'HashKey', 'HashIV')
.setTestMode(true)
.setMerchantOrderNo('ATM' + Date.now())
.setAmt(2000)
.setItemDesc('ATM 轉帳測試')
.setEmail('[email protected]')
.setExpireDate('2025-12-31') // 繳費期限
.setBankType(BankType.BOT) // 指定銀行(可選)
.setReturnURL('https://your-site.com/return')
.setNotifyURL('https://your-site.com/notify')
.setCustomerURL('https://your-site.com/customer') // 取號完成返回
const form = FormBuilder.create(payment).build()全支付方式(多種支付選項)
import { AllInOnePayment, FormBuilder } from '@carllee1983/newebpay'
const payment = new AllInOnePayment('特店編號', 'HashKey', 'HashIV')
.setTestMode(true)
.setMerchantOrderNo('ALL' + Date.now())
.setAmt(1000)
.setItemDesc('多元支付測試')
.setEmail('[email protected]')
.setReturnURL('https://your-site.com/return')
.setNotifyURL('https://your-site.com/notify')
// 啟用多種支付方式(依需求選擇)
.enableCredit() // 信用卡一次付清
.enableWebAtm() // WebATM 即時轉帳
.enableAtm() // ATM 虛擬帳號
.enableCvs() // 超商代碼繳費
.enableBarcode() // 超商條碼繳費
.enableLinePay() // LINE Pay
.enableTaiwanPay() // 台灣 Pay
.enableEsunWallet() // 玉山 Wallet
.enableBitoPay() // BitoPay 加密貨幣
.enableTwqr() // TWQR 共通支付
.enableFula() // 付啦(先買後付)
.enableInstallment([3, 6, 12]) // 信用卡分期(3/6/12 期)
.enableRedeem() // 信用卡紅利折抵
.enableUnionPay() // 銀聯卡
const form = FormBuilder.create(payment).build()AllInOnePayment 可用方法
| 方法 | 說明 |
| --------------------------- | ------------------------------ |
| .enableCredit() | 啟用信用卡一次付清 |
| .enableWebAtm() | 啟用 WebATM 即時轉帳 |
| .enableAtm() | 啟用 ATM 虛擬帳號轉帳 |
| .enableCvs() | 啟用超商代碼繳費 |
| .enableBarcode() | 啟用超商條碼繳費 |
| .enableLinePay() | 啟用 LINE Pay |
| .enableTaiwanPay() | 啟用台灣 Pay |
| .enableEsunWallet() | 啟用玉山 Wallet |
| .enableBitoPay() | 啟用 BitoPay 加密貨幣支付 |
| .enableTwqr() | 啟用 TWQR 共通支付 |
| .enableFula() | 啟用付啦(先買後付) |
| .enableInstallment([3,6]) | 啟用信用卡分期(指定可選期數) |
| .enableRedeem() | 啟用信用卡紅利折抵 |
| .enableUnionPay() | 啟用銀聯卡 |
所有
enable*()方法都可傳入false來停用該支付方式,例如:.enableCredit(false)
超商取貨付款
import { CvscomPayment, LgsType, FormBuilder } from '@carllee1983/newebpay'
const payment = new CvscomPayment('特店編號', 'HashKey', 'HashIV')
.setTestMode(true)
.setMerchantOrderNo('CVSCOM' + Date.now())
.setAmt(500)
.setItemDesc('超商取貨商品')
.setEmail('[email protected]')
.setLgsType(LgsType.B2C) // 大宗寄倉
.setReceiverName('收件人')
.setReceiverPhone('0912345678')
.setReceiverEmail('[email protected]')
.setReturnURL('https://your-site.com/return')
.setNotifyURL('https://your-site.com/notify')
const form = FormBuilder.create(payment).build()通知處理
付款完成通知
import { PaymentNotify } from '@carllee1983/newebpay'
app.post('/payment/notify', (req, res) => {
const notify = new PaymentNotify('HashKey', 'HashIV')
try {
notify.verifyOrFail(req.body)
if (notify.isSuccess()) {
const orderNo = notify.getMerchantOrderNo()
const amount = notify.getAmt()
const paymentType = notify.getPaymentType()
const tradeNo = notify.getTradeNo()
// 更新訂單狀態...
console.log(`訂單 ${orderNo} 付款成功,金額 ${amount}`)
}
res.send('OK')
} catch (error) {
console.error('驗證失敗:', error)
res.status(400).send('Verification failed')
}
})ATM 取號通知
import { AtmNotify } from '@carllee1983/newebpay'
app.post('/atm/notify', (req, res) => {
const notify = new AtmNotify('HashKey', 'HashIV')
if (notify.verify(req.body) && notify.isSuccess()) {
const orderNo = notify.getMerchantOrderNo()
const bankCode = notify.getBankCode() // 銀行代碼
const codeNo = notify.getCodeNo() // 虛擬帳號
const expireDate = notify.getExpireDate() // 繳費截止日
// 儲存繳費資訊,通知買家...
console.log(`ATM 帳號: ${bankCode}-${codeNo},截止日: ${expireDate}`)
}
res.send('OK')
})超商取號通知
import { CvsNotify } from '@carllee1983/newebpay'
app.post('/cvs/notify', (req, res) => {
const notify = new CvsNotify('HashKey', 'HashIV')
if (notify.verify(req.body) && notify.isSuccess()) {
const codeNo = notify.getCodeNo() // 繳費代碼
const storeType = notify.getStoreType() // 超商類型
const expireDate = notify.getExpireDate() // 繳費截止日
// 條碼繳費資訊
const barcode1 = notify.getBarcode1()
const barcode2 = notify.getBarcode2()
const barcode3 = notify.getBarcode3()
// 儲存繳費資訊...
}
res.send('OK')
})超商取貨付款通知
import { CvscomNotify } from '@carllee1983/newebpay'
app.post('/cvscom/notify', (req, res) => {
const notify = new CvscomNotify('HashKey', 'HashIV')
if (notify.verify(req.body) && notify.isSuccess()) {
const storeCode = notify.getStoreCode() // 門市代碼
const storeName = notify.getStoreName() // 門市名稱
const storeAddr = notify.getStoreAddr() // 門市地址
const lgsNo = notify.getLgsNo() // 物流編號
const lgsType = notify.getLgsType() // 物流類型
const receiverName = notify.getCVSCOMName() // 取貨人姓名
// 儲存物流資訊...
}
res.send('OK')
})交易查詢
一般交易查詢
import { QueryOrder } from '@carllee1983/newebpay'
const query = QueryOrder.create('特店編號', 'HashKey', 'HashIV').setTestMode(true)
try {
const result = await query.query('ORDER123456', 1000)
console.log('交易狀態:', result.TradeStatus)
console.log('付款方式:', result.PaymentType)
console.log('付款時間:', result.PayTime)
} catch (error) {
console.error('查詢失敗:', error.message)
}信用卡明細查詢
import { QueryCreditDetail } from '@carllee1983/newebpay'
const query = QueryCreditDetail.create('特店編號', 'HashKey', 'HashIV').setTestMode(true)
try {
const result = await query.query('ORDER123456', 1000)
console.log('請款狀態:', result.CloseStatus)
console.log('退款狀態:', result.BackStatus)
console.log('授權碼:', result.Auth)
console.log('卡號末四碼:', result.Card4No)
} catch (error) {
console.error('查詢失敗:', error.message)
}退款與取消
信用卡請款/退款
import { CreditClose } from '@carllee1983/newebpay'
const creditClose = CreditClose.create('特店編號', 'HashKey', 'HashIV').setTestMode(true)
// 請款(授權後請款)
const payResult = await creditClose.pay('ORDER123456', 1000)
// 退款
const refundResult = await creditClose.refund('ORDER123456', 500)
// 取消請退款
const cancelResult = await creditClose.cancelClose(
'ORDER123456',
500,
CreditClose.CLOSE_TYPE_REFUND,
)取消授權
import { CreditCancel } from '@carllee1983/newebpay'
const creditCancel = CreditCancel.create('特店編號', 'HashKey', 'HashIV').setTestMode(true)
const result = await creditCancel.cancel('ORDER123456', 1000)電子錢包退款
import { EWalletRefund } from '@carllee1983/newebpay'
const refund = EWalletRefund.create('特店編號', 'HashKey', 'HashIV').setTestMode(true)
// 支援 LINE Pay、台灣 Pay、玉山 Wallet 等
const result = await refund.refund('ORDER123456', 500, 'LINEPAY')錯誤處理
SDK 提供 NewebPayError 類別處理各種錯誤情況:
import { CreditPayment, NewebPayError } from '@carllee1983/newebpay'
try {
const payment = new CreditPayment('特店編號', 'HashKey', 'HashIV')
.setMerchantOrderNo('ORDER001')
.setAmt(-100) // 金額錯誤
} catch (error) {
if (error instanceof NewebPayError) {
console.log('錯誤代碼:', error.code) // 'INVALID_FIELD'
console.log('錯誤訊息:', error.message) // 'Amt 無效:金額必須大於 0'
}
}常見錯誤代碼
| 錯誤代碼 | 說明 |
| -------------------- | ------------------- |
| REQUIRED_FIELD | 必填欄位未填寫 |
| FIELD_TOO_LONG | 欄位值超過最大長度 |
| INVALID_FIELD | 欄位值無效 |
| DECRYPT_FAILED | 解密失敗 |
| CHECK_VALUE_FAILED | CheckValue 驗證失敗 |
| API_ERROR | API 請求錯誤 |
CLI 工具
套件提供 CLI 工具協助快速設定:
# 初始化環境變數設定檔
npx @carllee1983/newebpay init
# 產生 Express 整合範例專案
npx @carllee1983/newebpay express測試卡號
| 類型 | 卡號 | 說明 | | ----------------------- | ------------------- | --------- | | 信用卡(一次付清/分期) | 4000-2211-1111-1111 | 一般測試 | | 紅利折抵 | 4003-5511-1111-1111 | 紅利測試 | | 美國運通卡 | 3760-000000-00006 | AMEX 測試 |
測試卡號的有效月年及卡片背面末三碼可任意填寫。
API 文件
本套件依據藍新金流「線上交易-幕前支付技術串接手冊」(NDNF-1.1.9)開發。
環境網址
| 環境 | 網址 | | -------- | -------------------------- | | 測試環境 | https://ccore.newebpay.com | | 正式環境 | https://core.newebpay.com |
主要 API 端點
| API | 路徑 | 說明 | | ------------ | ---------------------- | --------------- | | MPG 交易 | /MPG/mpg_gateway | 幕前支付 | | 交易查詢 | /API/QueryTradeInfo | 查詢訂單狀態 | | 取消授權 | /API/CreditCard/Cancel | 取消信用卡授權 | | 請退款 | /API/CreditCard/Close | 信用卡請款/退款 | | 電子錢包退款 | /API/EWallet/Refund | LINE Pay 等退款 |
目錄結構
newebpay-node/
├── src/
│ ├── index.ts # 主要匯出
│ ├── content.ts # 基礎 Content 類別
│ ├── form-builder.ts # HTML 表單產生器
│ ├── infrastructure/ # 加解密器
│ ├── operations/ # 支付操作
│ ├── notifications/ # 通知處理器
│ ├── queries/ # 查詢 API
│ ├── actions/ # 退款/取消授權
│ ├── types/ # TypeScript 型別
│ ├── errors/ # 例外類別
│ └── frameworks/ # 框架整合
│ ├── express/ # Express 整合
│ ├── fastify/ # Fastify 整合
│ └── koa/ # Koa 整合
├── tests/ # 單元測試
├── examples/ # 範例程式
├── docs/ # API 文件
└── README.md開發
# 安裝依賴
npm install
# 建置
npm run build
# 執行測試(使用 Bun)
bun test
# 執行測試(監看模式)
bun test --watch
# 測試覆蓋率
bun test --coverage
# Lint 檢查
bun run lint
# 格式化程式碼
bun run format
# TypeScript 類型檢查
bun run typecheck注意:本專案使用 Bun 作為開發基底,所有測試和開發工具都使用 Bun 原生功能。若使用 Node.js,請確保 Node.js 版本為 18.0.0 或更高版本。
授權
MIT License
貢獻
歡迎提交 Issue 和 Pull Request。詳細資訊請參閱 CONTRIBUTING.md。
