当前位置: 首页 > 后端技术 > Node.js

在NestJS中为Stripe添加WebHook身份验证

时间:2023-04-03 21:25:11 Node.js

在NestJS中为Stripe添加WebHook身份验证背景简介Nest是一个用于构建高效且可扩展的NodeJS服务器端应用程序的框架。它使用渐进式JavaScript,内置并完全支持TypeScript,但仍允许开发人员使用纯JavaScript编写代码。并结合了OOP(面向对象编程)、FP(函数式编程)和FRP(函数式反应式编程)的元素。Stripe是一家美国金融服务和软件即服务公司,总部位于美国加利福尼亚州旧金山。它主要为电子商务网站和移动应用程序提供支付处理软件和应用程序编程接口。《苏州高新区 · 2020胡润全球独角兽榜》发布于2020年8月4日,Stripe排名第5。注意:以下内容需要有NodeJS和NestJS的使用经验。如果没有,您需要学习如何使用它。代码实现1.去掉内置的HttpBodyParser。因为Nest内部默认会直接将所有请求的结果转成JavaScript对象,一般情况下是很方便的,但是如果我们要自定义响应的内容,验证就会有问题,所以我们要替换掉首先是自定义的。首先在根入口启动应用时传入参数禁用内置Parser.import{NestFactory}from'@nestjs/core';import{ExpressAdapter,NestExpressApplication}from'@nestjs/platform-express';//Applicationrootimport{AppModule}from'@app/app/app.module';//disablebodyParserconstapp=awaitNestFactory.create(AppModule,newExpressAdapter(),{cors:true,bodyParser:false},);2.Parser中间件定义了三个不同的中间件:ParserforStripe//raw-body.middleware.tsimport{Injectable,NestMiddleware}from'@nestjs/common';import{Request,Response}from'express';import*asbodyParserfrom'body-parser';@Injectable()exportclassRawBodyMiddlewareimplementsNestMiddleware{use(req:Request,res:Response,next:()=>任何){bodyParser.raw({type:'*/*'})(req,res,next);}}//raw-body-parser.middleware.tsimport{Injectable,NestMiddleware}from'@nestjs/common';import{Request,Response}from'express';@Injectable()导出类RawBodyParserMiddleware实现NestMiddleware{使用(req:Request,res:Response,next:()=>any){req['rawBody']=req.body;req.body=JSON.parse(req.body.toString());下一个();}}对于在其他地方使用的普通解析器;@Injectable()exportclassJsonBodyMiddlewareimplementsNestMiddleware{use(req:Request,res:Response,next:()=>any){bodyParser.json()(req,res,next);}}基于以上两种不同的场景注入根App:import{Module,NestModule,MiddlewareConsumer}from'@nestjs/common';从“@app/core/middlewares/json-body.middleware”导入{JsonBodyMiddleware};从“@app/core/middlewares/raw-body.middleware”导入{RawBodyMiddleware};从“@app/core/middlewares/raw-body-parser.middleware”导入{RawBodyParserMiddleware};从“@app”导入{StripeController}/events/stripe/stripe.controller';@Module()导出类AppModule实现NestModule{publicconfigure(consumer:MiddlewareConsumer):void{consumer.apply(RawBodyMiddleware,RawBodyParserMiddleware).forRoutes(StripeController).apply(JsonBodyMiddleware).forRoutes('*');}}这里我们应用了实际处理WebHook的相关ControllerRawBodyMiddleware,RawBodyParserMiddleware这两个中间件会在原始转换结果的基础上添加一个未转换的key,返回RawResponse给程序进一步处理;其他地方都使用默认的JsonParser,效果和内置的一样。3.Interceptorvalidator接下来我们写一个Interceptor来进行验证。它用于处理验证。如果是正常的,它会通过。如果验证不通过,则直接拦截返回从'@nestjs/common'导入{BadRequestException,CallHandler,ExecutionContext,Injectable,Logger,NestInterceptor,};从'stripe'导入Stripe;从'rxjs'导入{Observable};从'@app/shared/导入{ConfigService}config/config.service';import{StripeService}from'@app/shared/services/stripe.service';@Injectable()exportclassStripeInterceptorimplementsNestInterceptor{privatereadonlystripe:Stripe;私人只读记录器=新记录器(StripeInterceptor.name);constructor(privatereadonlyconfigService:ConfigService,privatereadonlystripeService:StripeService,){//等同于//this.stripe=newStripe(secret,{}asStripe.StripeConfig);this.stripe=stripeService.getClient();}intercept(context:ExecutionContext,next:CallHandler):Observable{constrequest=context.switchToHttp().getRequest();constsignature=request.headers['stripe-signature'];//因为Stripe的验证是不同的WebHook有不同的Key//这里只需要根据业务的需要添加对应的key即可constCHARGE_SUCCEEDED=this.configService.get('STRIPE_SECRET_CHARGE_SUCCEEDED',);constsecrets={'charge.succeed':CHARGE_SUCCEEDED,};constsecret=secrets[request.body['type']];if(!secret){thrownewBadRequestException({status:'哎呀,不错的尝试',message:'WebHookError:Functionnotsupported',});}try{this.logger.log(signature,'StripeWebHookSignature');this.logger.log(request.body,'StripeWebHookBody');constevent=this.stripe.webhooks.constructEvent(request.rawBody,signature,secret,);this.logger.log(event,'StripeWebHookEvent');}catch(e){this.logger.error(e.message,'StripeWebHookValidation');thrownewBadRequestException({status:'Oops,NiceTry',message:`WebHookError:${e.messageasstring}`,});}接下来返回。处理();}}4。最后,我们将这个拦截器添加到我们的WebHook控制器中UseInterceptors(StripeInterceptor)exportclassStripeController{}就大功告成了!