import { Injectable } from '@nestjs/common'; import { PrismaService } from '../../prisma/prisma.service'; import { PaymentService } from '../payment/payment.service'; @Injectable() export class OrdersService { constructor( private prisma: PrismaService, private paymentService: PaymentService, ) {} async create(userId: number, data: { amount: number; planType: string; payChannel?: string; tradeType?: string; openid?: string }) { const orderNo = `YZR${Date.now()}${Math.random().toString(36).slice(2, 8).toUpperCase()}`; const order = await this.prisma.order.create({ data: { orderNo, userId, amount: data.amount, planType: data.planType, payChannel: data.payChannel || 'wxpay', }, }); // If paying via WeChat, create unified order if (data.payChannel === 'wxpay' || !data.payChannel) { try { const planLabels: Record = { MONTHLY: '宇之然AI月卡会员', YEARLY: '宇之然AI年卡会员', }; const payResult = await this.paymentService.createUnifiedOrder({ description: planLabels[data.planType] || '宇之然AI会员充值', outTradeNo: orderNo, amount: data.amount, tradeType: (data.tradeType as 'JSAPI' | 'NATIVE' | 'MWEB') || 'NATIVE', openid: data.openid, }); // Mock 模式下自动完成支付闭环(NATIVE mock 无需扫码) if (payResult?.codeUrl === 'mock://pay') { await this.paymentService.completeMockPayment(orderNo); } return { order, payResult }; } catch { return { order, payResult: null }; } } return { order }; } async findByUser(userId: number, params: { page?: number; pageSize?: number }) { const page = Number(params.page ?? 1); const pageSize = Number(params.pageSize ?? 20); const [items, total] = await Promise.all([ this.prisma.order.findMany({ where: { userId }, skip: (page - 1) * pageSize, take: pageSize, orderBy: { createdAt: 'desc' }, }), this.prisma.order.count({ where: { userId } }), ]); return { items, total, page, pageSize }; } async findByOrderNo(orderNo: string) { return this.prisma.order.findUnique({ where: { orderNo } }); } async getCurrentSubscription(userId: number) { const now = new Date(); return this.prisma.subscription.findFirst({ where: { userId, status: 'ACTIVE', endDate: { gt: now }, }, orderBy: { endDate: 'desc' }, }); } async getSubscriptions(userId: number) { return this.prisma.subscription.findMany({ where: { userId }, orderBy: { createdAt: 'desc' }, }); } }