102 lines
4.1 KiB
JavaScript
102 lines
4.1 KiB
JavaScript
// 支付管理路由:/api/payment/*(查询授信额度/发起支付)+ /api/payment-management/*(查询支付记录/详情)。
|
|
import express from 'express'
|
|
import { paymentRecords } from '../db/seedPayment.js'
|
|
import { balances, walletAccounts } from '../db/seedWallet.js'
|
|
import { nextId } from '../utils/id.js'
|
|
import { paginate } from '../utils/pagination.js'
|
|
import { sendOk, sendFail } from '../utils/response.js'
|
|
import { requireAuth } from '../middleware/requireAuth.js'
|
|
|
|
const router = express.Router()
|
|
router.use(requireAuth)
|
|
|
|
function nowStr() {
|
|
return new Date().toISOString().slice(0, 19).replace('T', ' ')
|
|
}
|
|
|
|
// ---------------- 查询授信额度(响应结构未文档化,mock 自行假设) ----------------
|
|
router.post('/payment/query-credit-quota', (req, res) => {
|
|
const { accountNo } = req.body || {}
|
|
if (!accountNo) return sendFail(res, '钱包账号不能为空', 400)
|
|
// mock 自行假设的响应结构:{accountNo, creditLimit, usedAmount, availableAmount}
|
|
sendOk(res, {
|
|
accountNo,
|
|
creditLimit: '1500000.00',
|
|
usedAmount: '150000.00',
|
|
availableAmount: '1350000.00'
|
|
})
|
|
})
|
|
|
|
// ---------------- 发起支付 ----------------
|
|
router.post('/payment/order-pay', (req, res) => {
|
|
const body = req.body || {}
|
|
if (!body.walletAccountId) return sendFail(res, '付款钱包账户不能为空', 400)
|
|
if (!body.paymentMethod) return sendFail(res, '支付方式不能为空', 400)
|
|
if (!body.payeeInfo?.payeeName || !body.payeeInfo?.payeeAccountNo) return sendFail(res, '收款方信息不能为空', 400)
|
|
|
|
const account = walletAccounts.find((a) => a.id === body.walletAccountId)
|
|
if (!account) return sendFail(res, '付款钱包账户不存在', 404)
|
|
|
|
const balanceAmount = Number(body.balanceAmount || 0)
|
|
if (body.paymentMethod === 'BALANCE' || body.paymentMethod === 'COMBINED') {
|
|
const currentBalance = Number(balances[account.accountNo] || 0)
|
|
if (balanceAmount > currentBalance) return sendFail(res, '余额支付金额超出可用余额', 400)
|
|
balances[account.accountNo] = (currentBalance - balanceAmount).toFixed(2)
|
|
}
|
|
|
|
const id = nextId('paymentRecord')
|
|
const entity = {
|
|
id,
|
|
walletAccountId: body.walletAccountId,
|
|
loanApplyId: body.loanApplyId,
|
|
paymentMethod: body.paymentMethod,
|
|
payeeInfo: body.payeeInfo,
|
|
totalAmount: body.totalAmount,
|
|
balanceAmount: body.balanceAmount,
|
|
financeAmount: body.financeAmount,
|
|
status: 'PENDING_VERIFICATION',
|
|
frchainSerialNo: '',
|
|
paidAt: '',
|
|
failedReason: '',
|
|
remark: body.remark || '',
|
|
detailList: (body.paymentDetailBtoList || []).map((item) => ({
|
|
id: nextId('paymentDetail'),
|
|
fundChannel: item.fundChannel,
|
|
channelAmount: item.channelAmount,
|
|
remark: ''
|
|
}))
|
|
}
|
|
paymentRecords.push(entity)
|
|
|
|
// 模拟异步状态流转:待验证 -> 支付成功(3秒后)
|
|
setTimeout(() => {
|
|
entity.status = 'SUCCESS'
|
|
entity.frchainSerialNo = `FR${nowStr().replace(/[-: ]/g, '')}${String(id).padStart(4, '0')}`
|
|
entity.paidAt = nowStr()
|
|
}, 3000)
|
|
|
|
sendOk(res, { id }, '支付请求已提交')
|
|
})
|
|
|
|
// ---------------- 支付记录查询/详情 ----------------
|
|
router.post('/payment-management/query-payment-record', (req, res) => {
|
|
const { walletAccountIdIs, paymentMethodList, statusList, paidAtStart, paidAtEnd, page, pageSize } = req.body || {}
|
|
let list = paymentRecords
|
|
if (walletAccountIdIs) list = list.filter((p) => p.walletAccountId === walletAccountIdIs)
|
|
if (paymentMethodList?.length) list = list.filter((p) => paymentMethodList.includes(p.paymentMethod))
|
|
if (statusList?.length) list = list.filter((p) => statusList.includes(p.status))
|
|
if (paidAtStart) list = list.filter((p) => p.paidAt && p.paidAt >= paidAtStart)
|
|
if (paidAtEnd) list = list.filter((p) => p.paidAt && p.paidAt <= paidAtEnd)
|
|
list = [...list].sort((a, b) => (a.id < b.id ? 1 : -1))
|
|
sendOk(res, paginate(list, page, pageSize))
|
|
})
|
|
|
|
router.post('/payment-management/query-payment-detail', (req, res) => {
|
|
const { id } = req.body || {}
|
|
const record = paymentRecords.find((p) => p.id === id)
|
|
if (!record) return sendFail(res, '支付记录不存在', 404)
|
|
sendOk(res, record)
|
|
})
|
|
|
|
export default router
|