- Notifications
You must be signed in to change notification settings - Fork8
A module for braintree reoccurring payments and transactions 💳
License
nestjsx/nestjs-braintree
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A module forBraintree reoccurring payments and transactions built for theNestjs framework.
Using theBraintree node SDK.
NOTE! Currently building
$ yarn add nestjs-braintree
import{Module}from'@nestjs/common';import{BraintreeModule}from'nestjs-braintree';import*asbraintreefrom'braintree';@Module({imports:[BraintreeModule.forRoot({environment:braintree.Environment.Sandbox,merchantId:'',publicKey:'',privateKey:'',}),],})exportdefaultclassAppModule{}
import{Module}from'@nestjs/common';import{BraintreeModule}from'nestjs-braintree';@Module({imports:[BraintreeModule.forFeature(),],})exportdefaultclassSubModule{}
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],}),],})exportdefaultclassAppModule{}//config/braintree.tsimport*asbraintreefrom'braintree';exportdefault{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,};
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';classTransactionProvider{constructor( @InjectBraintreeProvider()privatereadonlybraintreeProvider: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],})exportdefaultclassAppModule{}
Available methods relating to transactions are
braintreeProvider.sale(transaction: BraintreeTransactionInterface): Promise<BraintreeTransactionResultInterface>
braintreeProvider.refund(transactionId: string, amount?: string, orderId?: string): Promise<BraintreeTransactionResultInterface>
braintreeProvider.find(transactionId: string): Promise<BraintreeTransactionResultInterface>
The braintree SDK does offer additional methods. I will implement them soon hopefully
When using subscriptions with braintree, braintree will issue webhooks to yourendpoint 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()classSubscriptionProvider{ @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],})exportdefaultclassAppModule{}
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()exportclassSubscriptionProvider{constructor(@InjectRepository(Subscription)privatereadonlysubscriptionRepository:Repository<Subscription>){}asyncfindByBraintreeId(braintreeId:string):Promise<Subscription|null>{returnawaitthis.subscriptionRepository.find({where:{ braintreeId,},});}asyncupdate(subscription:Subscription):Promise<boolean>{returnawaitthis.subscriptionRepository.update(subscription);} @BraintreeSubscriptionCanceled()asynccanceled(webhook:BraintreeWebhook){constsubscription=awaitthis.findByBraintreeId(webhook.subscription.id);if(!subscription){return;}subscription.active=false;awaitthis.update(subscription);}}
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 webhookshere.
You may want to divert from the default routing of{your_domain}/braintree/webhook
for whatever reason. You can do so using theforRoot
method on theBraintreeWebhookModule
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],})exportdefaultclassAppModule{}
The above will result in your route for your braintree webhooks being{your_domain}/replace-braintree/replace-webhook
About
A module for braintree reoccurring payments and transactions 💳