Giter VIP home page Giter VIP logo

nestjs-braintree's Introduction

Coverage Status

Nestjs Braintree

A module for Braintree reoccurring payments and transactions built for the Nestjs framework.


Using the Braintree node SDK.

NOTE! Currently building

Install

$ yarn add nestjs-braintree

Use

Basic use

import { Module } from '@nestjs/common';
import { BraintreeModule } from 'nestjs-braintree';
import * as braintree from 'braintree';

@Module({
  imports: [
    BraintreeModule.forRoot({
      environment: braintree.Environment.Sandbox,
      merchantId: '',
      publicKey: '',
      privateKey: '',
    }),
  ],
})
export default class AppModule {}

In a subModule

import { Module } from '@nestjs/common';
import { BraintreeModule } from 'nestjs-braintree';

@Module({
  imports: [
    BraintreeModule.forFeature(),
  ],
})
export default class SubModule {}

Use with nestjs-config

import { Module } from '@nestjs/common';
import { BraintreeModule } from 'nestjs-braintree';
import { ConfigModule, ConfigService } from 'nestjs-config';

@Module({
  imports: [
    ConfigModule.load('root/to/config/*/**.{ts,js}'),
    BraintreeModule.forRootAsync({
      useFactory: async (config: ConfigService) => config.get('braintree'),
      inject: [ConfigService],
    }),
  ],
})
export default class AppModule {}

//config/braintree.ts
import * as braintree from 'braintree';

export default {
  environment:
    process.env.NODE_ENV == 'development'
      ? braintree.Environment.Sandbox
      : braintree.Environment.Live,
  merchantId: process.env.BRAINTREE_MERCHANT_ID,
  publicKey: process.env.BRAINTREE_PUBLIC_KEY,
  privateKey: process.env.BRAINTREE_PRIVATE_KEY,
};

Transactions

Braintree is capable of making one off transactions

import { Module } from '@nestjs/common';
import { BraintreeModule, InjectBraintreeProvider } from 'nestjs-braintree';
import { ConfigModule, ConfigService } from 'nestjs-config';

class TransactionProvider {
  constructor(
    @InjectBraintreeProvider()
    private readonly braintreeProvider: BraintreeProvider,
  ) {}

  takePayment(amount: string, nonce: string) {
    this.braintreeProvider.sale({
      payment_method_nonce: nonce,
      amount,
    });
  }
}

@Module({
  imports: [
    ConfigModule.load('root/to/config/*/**.{ts,js}'),
    BraintreeModule.forRoot({
      useFactory: async (config: ConfigService) => config.get('braintree'),
      inject: [ConfigService],
    }),
  ],
  providers: [TransactionProvider],
})
export default class AppModule {}

Available methods relating to transactions are

Sale

braintreeProvider.sale(transaction: BraintreeTransactionInterface): Promise<BraintreeTransactionResultInterface>

Refund

braintreeProvider.refund(transactionId: string, amount?: string, orderId?: string): Promise<BraintreeTransactionResultInterface>

Find

braintreeProvider.find(transactionId: string): Promise<BraintreeTransactionResultInterface>

The braintree SDK does offer additional methods. I will implement them soon hopefully

Webhooks

When using subscriptions with braintree, braintree will issue webhooks to your endpoint which you can use the decorators to handle those actions.

import { Module } from '@nestjs/common';
import {
  BraintreeModule,
  BraintreeWebhookModule,
  BraintreeSubscriptionCanceled,
  BraintreeSubscriptionExpired,
  BraintreeWebhookHandler,
} from 'nestjs-braintree';
import { ConfigModule, ConfigService } from 'nestjs-config';

@BraintreeWebhookHandler()
class SubscriptionProvider {
  @BraintreeSubscriptionCanceled()
  canceled() {
    console.log('subscription canceled');
  }

  @BraintreeSubscriptionExpired()
  expired() {
    console.log('subscription expired');
  }
}

@Module({
  imports: [
    ConfigModule.load('root/to/config/*/**.{ts,js}'),
    BraintreeModule.forRootAsync({
      useFactory: async (config: ConfigService) => config.get('braintree'),
      inject: [ConfigService],
    }),
    BraintreeWebhookModule,
  ],
  providers: [SubscriptionProvider],
})
export default class AppModule {}

Use Example

The idea of the Braintree Webhook Module is to make implementation of actions a lot easier. For example we can build a provider like this one to cancel canceled subscriptions.

@BraintreeWebhookHandler()
export class SubscriptionProvider {
  constructor(@InjectRepository(Subscription) private readonly subscriptionRepository: Repository<Subscription>) {}

  async findByBraintreeId(braintreeId: string): Promise<Subscription|null> {
    return await this.subscriptionRepository.find({
      where: {
        braintreeId,
      },
    });
  }

  async update(subscription: Subscription): Promise<boolean> {
    return await this.subscriptionRepository.update(subscription);
  }

  @BraintreeSubscriptionCanceled()
  async canceled(webhook: BraintreeWebhook) {
    const subscription = await this.findByBraintreeId(webhook.subscription.id);
    if (!subscription) {
      return;
    }
    subscription.active = false;
    await this.update(subscription);
  }
}

Available webhooks

Shortname Braintree webhook name/const/key NestJS decorator
Subscription Canceled subscription_canceled @BraintreeSubscriptionCanceled()
Subscription Expired subscription_expired @BraintreeSubscriptionExpired()
Subscription Charged Successfully subscription_charged_successfully @BraintreeSubscriptionChargedSuccessfully()
Subscription Charged Unsuccessfully subscription_charged_unsuccessfully @BraintreeSubscriptionChargedUnsuccessfully()
Subscription Went Active subscription_went_active @BraintreeSubscriptionWentActive()
Subscription Went Past Due subscription_went_past_due @BraintreeSubscriptionWentPastDue()
Subscription Trial Ended subscription_trial_ended @BraintreeSubscriptionTrialEnded()

You can find out more about the webhooks here.

Custom routing for webhooks

You may want to divert from the default routing of {your_domain}/braintree/webhook for whatever reason. You can do so using the forRoot method on the BraintreeWebhookModule like so

@Module({
  imports: [
    ConfigModule.load('root/to/config/*/**.{ts,js}'),
    BraintreeModule.forRootAsync({
      useFactory: async (config: ConfigService) => config.get('braintree'),
      inject: [ConfigService],
    }),
    BraintreeWebhookModule.forRoot({
      root: 'replace-braintree',
      handle: 'replace-webhook',
    }),
  ],
  providers: [SubscriptionProvider],
})
export default class AppModule {}

The above will result in your route for your braintree webhooks being {your_domain}/replace-braintree/replace-webhook

nestjs-braintree's People

Contributors

0xflotus avatar bashleigh avatar dependabot-preview[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

nestjs-braintree's Issues

Add webhook type

Add a webhook type interface with subscription and transaction type interfaces

Create in depth description on transactions and subscriptions

Add additional MD files in the wiki for how tos on how to create payments and subscriptions from start to finish. Including nonces etc. Reference these how to docs to the readme.

This will also include refunds, cancelations etc

Must also include all options in BraintreeTransactionInterface like how to add a customer, address etc. Maybe also validation?

Add typeorm test

Add a test with typeorm to check that the example in the read me works

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.