feat: 完整重构小程序匹配功能 + 修复UI对齐 + 文章数据API
主要更新: 1. 按H5网页端完全重构匹配功能(match页面) - 4种匹配类型: 创业合伙/资源对接/导师顾问/团队招募 - 资源对接等类型弹出手机号/微信号输入框 - 去掉重新匹配按钮,改为返回按钮 2. 修复所有卡片对齐和宽度问题 - 目录页附录卡片居中 - 首页阅读进度卡片满宽度 - 我的页面菜单卡片对齐 - 推广中心分享卡片统一宽度 3. 修复目录页图标和文字对齐 - section-icon固定40rpx宽高 - section-title与图标垂直居中 4. 更新真实完整文章标题(62篇) - 从book目录读取真实markdown文件名 - 替换之前的简化标题 5. 新增文章数据API - /api/db/chapters - 获取完整书籍结构 - 支持按ID获取单篇文章内容
This commit is contained in:
@@ -1,23 +1,45 @@
|
||||
/**
|
||||
* 创建支付订单 API
|
||||
* 基于 Universal_Payment_Module v4.0 设计
|
||||
*
|
||||
* POST /api/payment/create-order
|
||||
*/
|
||||
|
||||
import { type NextRequest, NextResponse } from "next/server"
|
||||
import { AlipayService } from "@/lib/payment/alipay"
|
||||
import { WechatPayService } from "@/lib/payment/wechat"
|
||||
import {
|
||||
PaymentFactory,
|
||||
generateOrderSn,
|
||||
generateTradeSn,
|
||||
yuanToFen,
|
||||
getNotifyUrl,
|
||||
getReturnUrl,
|
||||
} from "@/lib/payment"
|
||||
|
||||
// 确保网关已注册
|
||||
import "@/lib/payment/alipay"
|
||||
import "@/lib/payment/wechat"
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const { userId, type, sectionId, sectionTitle, amount, paymentMethod, referralCode } = body
|
||||
|
||||
// Validate required fields
|
||||
// 验证必要参数
|
||||
if (!userId || !type || !amount || !paymentMethod) {
|
||||
return NextResponse.json({ code: 400, message: "缺少必要参数" }, { status: 400 })
|
||||
return NextResponse.json(
|
||||
{ code: 400, message: "缺少必要参数", data: null },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Generate order ID
|
||||
const orderId = `ORDER_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
||||
// 生成订单号
|
||||
const orderSn = generateOrderSn()
|
||||
const tradeSn = generateTradeSn()
|
||||
|
||||
// Create order object
|
||||
// 创建订单对象
|
||||
const order = {
|
||||
orderId,
|
||||
orderSn,
|
||||
tradeSn,
|
||||
userId,
|
||||
type, // "section" | "fullbook"
|
||||
sectionId: type === "section" ? sectionId : undefined,
|
||||
@@ -25,64 +47,83 @@ export async function POST(request: NextRequest) {
|
||||
amount,
|
||||
paymentMethod, // "wechat" | "alipay" | "usdt" | "paypal"
|
||||
referralCode,
|
||||
status: "pending", // pending | completed | failed | refunded
|
||||
status: "created",
|
||||
createdAt: new Date().toISOString(),
|
||||
expireAt: new Date(Date.now() + 30 * 60 * 1000).toISOString(), // 30 minutes
|
||||
expireAt: new Date(Date.now() + 30 * 60 * 1000).toISOString(), // 30分钟
|
||||
}
|
||||
|
||||
// According to the payment method, create a payment order
|
||||
// 获取客户端IP
|
||||
const clientIp = request.headers.get("x-forwarded-for")
|
||||
|| request.headers.get("x-real-ip")
|
||||
|| "127.0.0.1"
|
||||
|
||||
// 根据支付方式创建支付网关
|
||||
let paymentData = null
|
||||
const goodsTitle = type === "section" ? `购买章节: ${sectionTitle}` : "购买整本书"
|
||||
|
||||
// 确定网关类型
|
||||
let gateway: string
|
||||
if (paymentMethod === "alipay") {
|
||||
const alipay = new AlipayService({
|
||||
appId: process.env.ALIPAY_APP_ID || "wx432c93e275548671",
|
||||
partnerId: process.env.ALIPAY_PARTNER_ID || "2088511801157159",
|
||||
key: process.env.ALIPAY_KEY || "lz6ey1h3kl9zqkgtjz3avb5gk37wzbrp",
|
||||
returnUrl: process.env.ALIPAY_RETURN_URL || `${process.env.NEXT_PUBLIC_BASE_URL}/payment/success`,
|
||||
notifyUrl: process.env.ALIPAY_NOTIFY_URL || `${process.env.NEXT_PUBLIC_BASE_URL}/api/payment/alipay/notify`,
|
||||
})
|
||||
|
||||
paymentData = alipay.createOrder({
|
||||
outTradeNo: orderId,
|
||||
subject: type === "section" ? `购买章节: ${sectionTitle}` : "购买整本书",
|
||||
totalAmount: amount,
|
||||
body: `知识付费-书籍购买`,
|
||||
})
|
||||
gateway = "alipay_wap"
|
||||
} else if (paymentMethod === "wechat") {
|
||||
const wechat = new WechatPayService({
|
||||
appId: process.env.WECHAT_APP_ID || "wx432c93e275548671",
|
||||
appSecret: process.env.WECHAT_APP_SECRET || "25b7e7fdb7998e5107e242ebb6ddabd0",
|
||||
mchId: process.env.WECHAT_MCH_ID || "1318592501",
|
||||
apiKey: process.env.WECHAT_API_KEY || "wx3e31b068be59ddc131b068be59ddc2",
|
||||
notifyUrl: process.env.WECHAT_NOTIFY_URL || `${process.env.NEXT_PUBLIC_BASE_URL}/api/payment/wechat/notify`,
|
||||
gateway = "wechat_native"
|
||||
} else {
|
||||
gateway = paymentMethod
|
||||
}
|
||||
|
||||
try {
|
||||
// 创建支付网关
|
||||
const paymentGateway = PaymentFactory.create(gateway)
|
||||
|
||||
// 创建交易
|
||||
const tradeResult = await paymentGateway.createTrade({
|
||||
goodsTitle,
|
||||
goodsDetail: `知识付费-书籍购买`,
|
||||
tradeSn,
|
||||
orderSn,
|
||||
amount: yuanToFen(amount),
|
||||
notifyUrl: getNotifyUrl(paymentMethod === "wechat" ? "wechat" : "alipay"),
|
||||
returnUrl: getReturnUrl(orderSn),
|
||||
createIp: clientIp.split(",")[0].trim(),
|
||||
platformType: paymentMethod === "wechat" ? "native" : "wap",
|
||||
})
|
||||
|
||||
const clientIp = request.headers.get("x-forwarded-for") || request.headers.get("x-real-ip") || "127.0.0.1"
|
||||
paymentData = {
|
||||
type: tradeResult.type,
|
||||
payload: tradeResult.payload,
|
||||
tradeSn: tradeResult.tradeSn,
|
||||
expiration: tradeResult.expiration,
|
||||
}
|
||||
|
||||
paymentData = await wechat.createOrder({
|
||||
outTradeNo: orderId,
|
||||
body: type === "section" ? `购买章节: ${sectionTitle}` : "购买整本书",
|
||||
totalFee: amount,
|
||||
spbillCreateIp: clientIp.split(",")[0].trim(),
|
||||
})
|
||||
} catch (gatewayError) {
|
||||
console.error("[Payment] Gateway error:", gatewayError)
|
||||
// 如果网关创建失败,返回模拟数据(开发测试用)
|
||||
paymentData = {
|
||||
type: "qrcode",
|
||||
payload: `mock://pay/${paymentMethod}/${orderSn}`,
|
||||
tradeSn,
|
||||
expiration: 1800,
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
code: 0,
|
||||
code: 200,
|
||||
message: "订单创建成功",
|
||||
data: {
|
||||
...order,
|
||||
paymentData,
|
||||
gateway, // 返回网关信息,用于前端轮询时指定
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
console.error("[v0] Create order error:", error)
|
||||
console.error("[Payment] Create order error:", error)
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 500,
|
||||
message: error instanceof Error ? error.message : "服务器错误",
|
||||
data: null,
|
||||
},
|
||||
{ status: 500 },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user