forked from yoone/API
1
0
Fork 0

refactor(webhook): 重构webhook控制器逻辑,使用siteApiService适配器

- 移除对UnifiedOrderDTO的直接使用,改为通过适配器转换订单数据
- 统一处理woocommerce和shoppy的webhook验证逻辑
- 清理冗余代码和注释
This commit is contained in:
tikkhun 2026-01-08 20:54:45 +08:00
parent 3f5fb6adba
commit 2888d62037
1 changed files with 43 additions and 54 deletions

View File

@ -12,10 +12,7 @@ import * as crypto from 'crypto';
import { SiteService } from '../service/site.service'; import { SiteService } from '../service/site.service';
import { OrderService } from '../service/order.service'; import { OrderService } from '../service/order.service';
import { SiteApiService } from '../service/site-api.service';
import {
UnifiedOrderDTO,
} from '../dto/site-api.dto';
@Controller('/webhook') @Controller('/webhook')
export class WebhookController { export class WebhookController {
@ -34,6 +31,8 @@ export class WebhookController {
@Inject() @Inject()
private readonly siteService: SiteService; private readonly siteService: SiteService;
@Inject()
private readonly siteApiService: SiteApiService;
// 移除配置中的站点数组,来源统一改为数据库 // 移除配置中的站点数组,来源统一改为数据库
@ -49,7 +48,7 @@ export class WebhookController {
@Query('siteId') siteIdStr: string, @Query('siteId') siteIdStr: string,
@Headers() header: any @Headers() header: any
) { ) {
console.log(`webhook woocommerce`, siteIdStr, body,header) console.log(`webhook woocommerce`, siteIdStr, body, header)
const signature = header['x-wc-webhook-signature']; const signature = header['x-wc-webhook-signature'];
const topic = header['x-wc-webhook-topic']; const topic = header['x-wc-webhook-topic'];
const source = header['x-wc-webhook-source']; const source = header['x-wc-webhook-source'];
@ -79,7 +78,14 @@ export class WebhookController {
.update(rawBody) .update(rawBody)
.digest('base64'); .digest('base64');
try { try {
if (hash === signature) { if (hash !== signature) {
return {
code: 403,
success: false,
message: 'Webhook verification failed',
};
}
const adapter = await this.siteApiService.getAdapter(siteId);
switch (topic) { switch (topic) {
case 'product.created': case 'product.created':
case 'product.updated': case 'product.updated':
@ -90,7 +96,8 @@ export class WebhookController {
break; break;
case 'order.created': case 'order.created':
case 'order.updated': case 'order.updated':
await this.orderService.syncSingleOrder(siteId, body); const order = adapter.mapPlatformToUnifiedOrder(body)
await this.orderService.syncSingleOrder(siteId, order);
break; break;
case 'order.deleted': case 'order.deleted':
break; break;
@ -102,19 +109,12 @@ export class WebhookController {
break; break;
default: default:
console.log('Unhandled event:', body.event); console.log('Unhandled event:', body.event);
}
return { return {
code: 200, code: 200,
success: true, success: true,
message: 'Webhook processed successfully', message: 'Webhook processed successfully',
}; };
} else {
return {
code: 403,
success: false,
message: 'Webhook verification failed',
};
} }
} catch (error) { } catch (error) {
console.log(error); console.log(error);
@ -130,23 +130,10 @@ export class WebhookController {
@Query('signature') signature: string, @Query('signature') signature: string,
@Headers() header: any @Headers() header: any
) { ) {
console.log(`webhook shoppy`, siteIdStr, body, header)
const topic = header['x-oemsaas-event-type']; const topic = header['x-oemsaas-event-type'];
// const source = header['x-oemsaas-shop-domain']; // const source = header['x-oemsaas-shop-domain'];
const siteId = Number(siteIdStr); const siteId = Number(siteIdStr);
const bodys = new UnifiedOrderDTO();
Object.assign(bodys, body);
// 从数据库获取站点配置
const site = await this.siteService.get(siteId, true);
// if (!site || !source?.includes(site.websiteUrl)) {
if (!site) {
console.log('domain not match');
return {
code: HttpStatus.BAD_REQUEST,
success: false,
message: 'domain not match',
};
}
if (!signature) { if (!signature) {
return { return {
@ -162,6 +149,7 @@ export class WebhookController {
// .createHmac('sha256', this.secret) // .createHmac('sha256', this.secret)
// .update(rawBody) // .update(rawBody)
// .digest('base64'); // .digest('base64');
const adapter = await this.siteApiService.getAdapter(siteId);
try { try {
if (this.secret === signature) { if (this.secret === signature) {
switch (topic) { switch (topic) {
@ -174,7 +162,8 @@ export class WebhookController {
break; break;
case 'orders/create': case 'orders/create':
case 'orders/update': case 'orders/update':
await this.orderService.syncSingleOrder(siteId, bodys); const order = adapter.mapPlatformToUnifiedOrder(body)
await this.orderService.syncSingleOrder(siteId, order);
break; break;
case 'orders/delete': case 'orders/delete':
break; break;