iconsulting/packages/services/payment-service/src/adapters/outbound/payment-methods/stripe.adapter.ts

89 lines
2.8 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { OrderEntity } from '../../../domain/entities/order.entity';
export interface StripePaymentResult {
paymentUrl: string;
sessionId: string;
}
export interface StripeCallbackResult {
orderId: string;
transactionId: string;
success: boolean;
}
@Injectable()
export class StripeAdapter {
constructor(private configService: ConfigService) {}
/**
* Create Stripe checkout session
*/
async createPayment(order: OrderEntity): Promise<StripePaymentResult> {
// In production, use Stripe SDK
// const stripe = new Stripe(this.configService.get('STRIPE_SECRET_KEY'));
//
// const session = await stripe.checkout.sessions.create({
// payment_method_types: ['card'],
// line_items: [
// {
// price_data: {
// currency: 'cny',
// product_data: {
// name: `iConsulting - ${order.serviceType}`,
// description: `${order.serviceCategory} 移民评估服务`,
// },
// unit_amount: Math.round(order.amount * 100),
// },
// quantity: 1,
// },
// ],
// mode: 'payment',
// success_url: `${this.configService.get('WEB_CLIENT_URL')}/payment/success?order=${order.id}`,
// cancel_url: `${this.configService.get('WEB_CLIENT_URL')}/payment/cancel?order=${order.id}`,
// metadata: {
// orderId: order.id,
// },
// });
// For development, return mock URL
const mockSessionId = `cs_mock_${Date.now()}`;
const webClientUrl = this.configService.get('WEB_CLIENT_URL') || 'http://localhost:5173';
const mockPaymentUrl = `${webClientUrl}/payment/mock?session=${mockSessionId}&order=${order.id}`;
console.log(`[Stripe] Created checkout session for order ${order.id}, amount: ${order.amount}`);
return {
paymentUrl: mockPaymentUrl,
sessionId: mockSessionId,
};
}
/**
* Handle Stripe webhook
*/
async handleCallback(payload: Record<string, unknown>): Promise<StripeCallbackResult> {
// In production:
// 1. Verify webhook signature using STRIPE_WEBHOOK_SECRET
// 2. Parse the event
// 3. Handle checkout.session.completed event
const eventType = payload.type as string;
const data = payload.data as Record<string, unknown> | undefined;
const object = data?.object as Record<string, unknown> | undefined;
const metadata = object?.metadata as Record<string, string> | undefined;
const orderId = metadata?.orderId || (payload.orderId as string);
const transactionId = (object?.payment_intent as string) || `pi_${Date.now()}`;
console.log(`[Stripe] Webhook received: ${eventType} for order ${orderId}`);
return {
orderId,
transactionId,
success: eventType === 'checkout.session.completed',
};
}
}