[NodeJs][TypeScript] Chain of responsibility design pattern to receive data from Stripe


This post is the example to help you understand more about Chain of responsibility design pattern in NodeJS.

In this example, i will handle the event from Stripe base on Stripe Webhook.

Step 1: Init interface


export class StripleHandler {
    private _handler: StripleHandler;
    private _eventType: string;
    constructor(eventType: string) {
        this._eventType = eventType;
    }

    public setHander(handler: StripleHandler) {
        this._handler = handler;
    }

    public getHander() {
        return this._handler;
    }

    public handleRequest(eventRequest: StripeRequest): Promise<any> {
        throw new Error("HandleRequest method is not implemented!");
    };

    public operation(eventRequest: StripeRequest): Promise<any> {
        let promise = new Promise<any>((resolve, reject) => {
            if (this._eventType === eventRequest.type) {
                this.handleRequest(eventRequest).then((httpPromise: HttpStatus<any>) => {
                    resolve(httpPromise);
                }).catch((err) => {
                    reject(err);
                });
            } else if (this._handler !== null && this._handler !== undefined) {
                this._handler.operation(eventRequest).then((httpPromise: HttpStatus<any>) => {
                    resolve(httpPromise);
                }).catch((err) => {
                    reject(err);
                });
            } else {
                let httpStatus = new HttpStatus<string>(HttpStatus.OK, 'Received data');
                resolve(httpStatus);
            }
        });
        return promise;
    }
}

Step 2: Create handle class

Process data when webhook has been receiving data from stripe and call to  subscription update

export class SubcriptionUpdated extends StripleHandler {
    constructor(stripleEvent: string) {
        super(stripleEvent);
    }
    handleRequest(eventRequest: StripeRequest): Promise&amp;lt;any&amp;gt; {
        let promise = new Promise&amp;lt;any&amp;gt;((resolve, reject) =&amp;gt; {
            let dataObject = eventRequest.data.object;
            let stripeSubcription = new StripeSubscription();
            stripeSubcription.subscriptionId = dataObject.id;
            let subscriptionManager: SubscriptionManager = new SubscriptionManager(null);
            subscriptionManager.get(stripeSubcription.subscriptionId).then((httpStatus: HttpStatus&amp;lt;Subscription&amp;gt;) =&amp;gt; {
                if (httpStatus.entity) {
                    let userId = httpStatus.entity.userIds;
                    let status = dataObject.status;
                    resolve(httpStatus);
                } else {
                    let httpStatus = new HttpStatus&amp;lt;string&amp;gt;(HttpStatus.BAD_REQUEST, '');
                    httpStatus.message = EVENT_CONSTANTS.MESSAGE.SUBCRIPTION_DOES_NOT_EXISIT;
                    reject(httpStatus);
                }
            }).catch((err) =&amp;gt; {
                reject(UtilHelper.getHttpStatus(err));
            });
        });
        return promise
    }
}

And another case for Invoice created in Stripe

export class InvoiceCreated extends StripleHandler {
    constructor(stripeEvent: string) {
        super(stripeEvent);
    }
    handleRequest(eventRequest: StripeRequest): Promise&amp;lt;any&amp;gt; {
        let promise = new Promise&amp;lt;any&amp;gt;((resolve, reject) =&amp;gt; {
            let dataObject = eventRequest.data.object;

            let stripeSubcription: StripeSubscription = new StripeSubscription();
            stripeSubcription.subscriptionId = dataObject.subscription;
            let subscriptionManager: SubscriptionManager = new SubscriptionManager(null);
            subscriptionManager.get(stripeSubcription.subscriptionId).then((httpStripeSubcription: HttpStatus&amp;lt;StripeSubscription&amp;gt;) =&amp;gt; {
                if (httpStripeSubcription.entity) {
                    let userId = httpStripeSubcription.entity.userId;
                    let userManger: UserManager = new UserManager(null);
                    ....
                        resolve(httpStatusUser);
                    }).catch((err) =&amp;gt; {
                        reject(UtilHelper.getHttpStatus(err));
                    });
                } else {
                    let httpStatus = new HttpStatus&amp;lt;string&amp;gt;(HttpStatus.BAD_REQUEST, '');
                    httpStatus.message = EVENT_CONSTANTS.MESSAGE.SUBCRIPTION_DOES_NOT_EXISIT;
                    reject(httpStatus);
                }
            }).catch((err) =&amp;gt; {
                reject(UtilHelper.getHttpStatus(err));
            });
        });
        return promise;
    }

Step 3: Register for each class handle

StripeWebHookHelper will help to init stripe event handler

&amp;nbsp;export class StripeWebHookHelper {
    private _stripeHander: StripleHandler = new StripleHandler('');
    constructor() {

    }
    /**
     * Init type of stripe
     */
    public initStripe() {
        let failPayment = new PaymentFail(EVENT_CONSTANTS.INVOICE.PAYMENT_FAILED);
        this._stripeHander.setHander(failPayment);
        let subcriptionUpdated = new SubcriptionUpdated(EVENT_CONSTANTS.CUSTOMER.SUBCRIPTION.UPDATED);
        failPayment.setHander(subcriptionUpdated);
        let chargeFail = new ChargeFail(EVENT_CONSTANTS.CHARGE.FAILED);
        subcriptionUpdated.setHander(chargeFail);
        let invoicePaymentSuccess = new InvoicePaymentSuccess(EVENT_CONSTANTS.INVOICE.PAYMENT_SUCCEEDED);
        chargeFail.setHander(invoicePaymentSuccess);
        let subcriptionDeleted = new SubcriptionDeleted(EVENT_CONSTANTS.CUSTOMER.SUBCRIPTION.DELETED);
        invoicePaymentSuccess.setHander(subcriptionDeleted);
        let subscriptionTrialWillEnd = new SubscriptionTrialWillEnd(EVENT_CONSTANTS.CUSTOMER.SUBCRIPTION.TRIAL_WILL_END);
        subcriptionDeleted.setHander(subscriptionTrialWillEnd);
    }
    /**
     * operation
     * @param eventRequest : stripe request body
     */
    public operation(eventRequest: StripeRequest): Promise&amp;lt;any&amp;gt; {
        let promise = new Promise&amp;lt;any&amp;gt;((resolve, reject) =&amp;gt; {
            this._stripeHander.operation(eventRequest).then((httpPromise: HttpStatus&amp;lt;any&amp;gt;) =&amp;gt; {
                resolve(httpPromise);
            }).catch((err) =&amp;gt; {
                reject(err);
            });
        });
        return promise;
    }
}

Final Step: Receive data from Stripe

And how to use it:

        StripeWebHookManager.operation(stripeRequest).then((httpStatus: HttpStatus<any>) => {
            response.writeHead(httpStatus.code, httpStatus.message, { 'Content-Type': 'application/json' });
            response.write(JSON.stringify(httpStatus.entity));
            response.end();
        })
            .catch((err) => {
                response.writeHead(err.code, err.message, { 'Content-Type': 'text/html' });
                response.write('Failed to retrieve list of subscriptions.');
                response.end();
            });

Hope will help a little bit for you!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s