Files
points-mall/supplied-service/netlify/functions/order-pay.ts
T

149 lines
3.9 KiB
TypeScript

import type { Context } from '@netlify/functions'
import { guardMethod } from '../utils/method.js'
import { fail, ok } from '../utils/http.js'
import { readJson } from '../utils/request.js'
import { prisma } from '../utils/prisma.js'
import { withErrorBoundary } from '../utils/handler.js'
type OrderPayRequest = {
supplierId?: string
token?: string
orderId?: string
amount?: number
totalPrice?: number
wPayOrAPay?: number
pointsPrice?: number
}
type BridgePayResponse = {
resultCode?: number
message?: string
}
const normalizeBase = (base: string) => base.replace(/\/$/, '')
const centsToYuan = (value?: number) => Number((Number(value || 0) / 100).toFixed(2))
export default withErrorBoundary(async (request: Request, _context: Context) => {
const methodResponse = guardMethod(request, ['POST'])
if (methodResponse) return methodResponse
const body = await readJson<OrderPayRequest>(request)
const supplierId = String(body.supplierId || '').trim()
const token = String(body.token || '').trim()
const orderId = String(body.orderId || '').trim()
const totalPrice = Number(body.totalPrice ?? centsToYuan(body.amount))
const wPayOrAPay = Number(body.wPayOrAPay ?? 0)
const pointsPrice = Number(body.pointsPrice ?? totalPrice)
if (!supplierId || !token || !orderId) {
return fail('供应商、授权或订单信息不能为空')
}
if (totalPrice <= 0) {
return fail('支付金额必须大于0')
}
const apiBase = normalizeBase(process.env.POINTS_MALL_OPEN_API_BASE || '')
if (!apiBase) {
return fail('平台积分商城接口地址未配置', 500, 'OPEN_API_BASE_MISSING')
}
const order = await prisma.supplierOrderMain.findUnique({
where: { orderId }
})
if (!order || order.deleted === 1) {
return fail('待支付订单不存在', 404, 'ORDER_NOT_FOUND')
}
const bridgeResponse = await fetch(`${apiBase}/pointOrder/confirmPurchase`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
token
},
body: JSON.stringify({
supplierId,
orderId,
totalPrice,
wPayOrAPay,
pointsPrice,
token
})
})
const bridgePayload = (await bridgeResponse.json().catch(() => ({}))) as BridgePayResponse
if (!bridgeResponse.ok || bridgePayload.resultCode !== 0) {
return fail(bridgePayload.message || '确认购买失败', 502, 'BRIDGE_CONFIRM_PURCHASE_FAILED')
}
await prisma.$transaction(async tx => {
await tx.supplierOrderMain.update({
where: { orderId },
data: {
orderState: 1,
totalPrice,
wPayOrAPay,
pointsPrice,
updateTime: new Date()
}
})
await tx.supplierOrderSub.updateMany({
where: { mainOrderId: orderId, deleted: 0 },
data: {
orderState: 1,
totalPrice,
wPayOrAPay,
pointsPrice,
updateTime: new Date()
}
})
})
const subOrders = await prisma.supplierOrderSub.findMany({
where: {
mainOrderId: orderId,
deleted: 0
},
select: {
orderId: true
}
})
const subOrderIds = subOrders.map(item => item.orderId).filter(Boolean).join(',')
if (subOrderIds) {
const splitResponse = await fetch(`${apiBase}/pointOrder/pushOrderInfoMsg`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
token
},
body: JSON.stringify({
supplierId,
orderType: 2,
orderId: subOrderIds,
mainOrderId: orderId,
userId: order.userId,
time: Date.now(),
token
})
})
const splitPayload = (await splitResponse.json().catch(() => ({}))) as BridgePayResponse
if (!splitResponse.ok || splitPayload.resultCode !== 0) {
return fail(splitPayload.message || '推送拆单信息失败', 502, 'BRIDGE_SPLIT_ORDER_FAILED')
}
}
return ok({
orderId,
subOrderIds,
totalPrice,
wPayOrAPay,
pointsPrice
})
})