Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

nestjs-braintree

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nestjs-braintree - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

.editorconfig

2

package.json
{
"name": "nestjs-braintree",
"version": "0.0.1",
"version": "0.0.2",
"description": "Nestjs braintree module",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

<p align="center"><img src="https://avatars1.githubusercontent.com/u/41109786?s=200&v=4"/></p>
<p align="center">
<a href="https://travis-ci.org/nestjs-community/nestjs-braintree"><img src="https://travis-ci.org/nestjs-community/nestjs-braintree.svg?branch=master"/></a>
<a href="https://www.npmjs.com/package/nestjs-braintree"><img src="https://img.shields.io/npm/v/nestjs-braintree.svg"/></a>
<a href="https://github.com/nestjs-community/nestjs-braintree/blob/master/LICENSE"><img src="https://img.shields.io/github/license/nestjs-community/nestjs-braintree.svg"/></a>

@@ -18,3 +19,3 @@ <a href='https://coveralls.io/github/nestjs-community/nestjs-braintree?branch=master'><img src='https://coveralls.io/repos/github/nestjs-community/nestjs-braintree/badge.svg?branch=master' alt='Coverage Status' /></a>

```bash
$ yarn add nestjs-braintree //not currently published
$ yarn add nestjs-braintree
```

@@ -89,2 +90,51 @@

## Transactions
Braintree is capable of making one off transactions
```typescript
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 {}
```
Avaliable 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

@@ -141,5 +191,7 @@

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

@@ -153,3 +205,3 @@ }

@BraintreeSubscriptionCanceled()
async canceled(webhook) {
async canceled(webhook: BraintreeWebhook) {
const subscription = await this.findByBraintreeId(webhook.subscription.id);

@@ -179,34 +231,23 @@ if (!subscription) {

## Transactions
#### 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
Braintree is also capable of making one off transactions
```typescript
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: number) {
//Will probably be similar to sale https://developers.braintreepayments.com/guides/transactions/node#settlement
this.braintreeProvider.notImplementedYet(amount);
}
}
```ts
@Module({
imports: [
ConfigModule.load('root/to/config/*/**.{ts,js}'),
BraintreeModule.forRoot({
BraintreeModule.forRootAsync({
useFactory: async (config: ConfigService) => config.get('braintree'),
inject: [ConfigService],
}),
BraintreeWebhookModule.forRoot({
root: 'replace-braintree',
handle: 'replace-webhook',
}),
],
providers: [TransactionProvider],
providers: [SubscriptionProvider],
})
export default class AppModule {}
```
The above will result in your route for your braintree webhooks being `{your_domain}/replace-braintree/replace-webhook`

@@ -5,5 +5,5 @@ import * as braintree from 'braintree';

environment: braintree.Environment.Sandbox,
merchantId: 'merchantId',
publicKey: 'publicKey',
privateKey: 'privateKey',
merchantId: process.env.BRAINTREE_MERCHANT_ID,
publicKey: process.env.BRAINTREE_PUBLIC_KEY,
privateKey: process.env.BRAINTREE_PRIVATE_KEY,
}

@@ -53,5 +53,5 @@ import { Test, TestingModule } from '@nestjs/testing';

expect(options.environment).toBe(braintree.Environment.Sandbox);
expect(options.merchantId).toBe('merchantId');
expect(options.publicKey).toBe('publicKey');
expect(options.privateKey).toBe('privateKey');
expect(typeof options.merchantId).toBe('string');
expect(typeof options.publicKey).toBe('string');
expect(typeof options.privateKey).toBe('string');
expect(provider).toBeInstanceOf(BraintreeProvider);

@@ -58,0 +58,0 @@ });

import { Test, TestingModule } from '@nestjs/testing';
import * as path from 'path';
import { ConfigModule, ConfigService } from 'nestjs-config';
import {

@@ -36,8 +34,7 @@ BraintreeModule,

imports: [
ConfigModule.load(
path.resolve(__dirname, '__stubs__', 'config', '*.ts'),
),
BraintreeModule.forRootAsync({
useFactory: async config => config.get('braintree'),
inject: [ConfigService],
BraintreeModule.forRoot({
environment: braintree.Environment.Sandbox,
merchantId: 'merchantId',
publicKey: 'publicKey',
privateKey: 'privateKey',
}),

@@ -44,0 +41,0 @@ BraintreeWebhookModule,

@@ -42,5 +42,7 @@ import { INestApplication } from "@nestjs/common";

),
BraintreeModule.forRootAsync({
useFactory: async config => config.get('braintree'),
inject: [ConfigService],
BraintreeModule.forRoot({
environment: braintree.Environment.Sandbox,
merchantId: 'merchantId',
publicKey: 'publicKey',
privateKey: 'privateKey',
}),

@@ -47,0 +49,0 @@ BraintreeWebhookModule,

import {Injectable, Inject} from '@nestjs/common';
import { BraintreeOptions, BraintreeWebhookPayloadInterface, BraintreeWebhookNotificationInterface } from './interfaces';
import {
BraintreeOptions,
BraintreeWebhookPayloadInterface,
BraintreeWebhookNotificationInterface,
BraintreeTransactionInterface,
BraintreeTransactionResultInterface,
BraintreeSubscriptionInterface,
BraintreeSubscriptionResultInterface,
} from './interfaces';
import * as braintree from 'braintree';

@@ -19,5 +27,33 @@ import { BRAINTREE_OPTIONS_PROVIDER } from './braintree.constants';

//TODO add methods to handle creating a subscription
//TODO add methods to handle transactions
//TODO add methods for refunds
async sale(transaction: BraintreeTransactionInterface): Promise<BraintreeTransactionResultInterface> {
return await this.gateway.transaction.sale(transaction);
}
async refund(transactionId: string, amount?: string, orderId?: string): Promise<BraintreeTransactionResultInterface> {
return await this.gateway.transaction.refund(transactionId, amount, orderId);
}
async find(transactionId: string): Promise<BraintreeTransactionResultInterface> {
return await this.gateway.transaction.find(transactionId);
}
async createSubscription(subscription: BraintreeSubscriptionInterface): Promise<BraintreeSubscriptionResultInterface> {
return await this.gateway.subscription.create(subscription);
}
async cancelSubscription(subscriptionId: string): Promise<BraintreeSubscriptionResultInterface> {
return await this.gateway.subscription.cancel(subscriptionId);
}
async findSubscription(subscriptionId: string): Promise<BraintreeSubscriptionResultInterface> {
return await this.gateway.subscription.find(subscriptionId);
}
async updateSubscription(subscriptionId: string, subscription: BraintreeSubscriptionInterface): Promise<BraintreeSubscriptionResultInterface> {
return await this.gateway.subscription.update(subscriptionId, subscription);
}
// TODO implement confusing looking search plans
// https://developers.braintreepayments.com/reference/request/subscription/search/node#search-results
}

@@ -1,19 +0,35 @@

import {Controller, Req, Logger, Post, HttpException} from '@nestjs/common';
import {Controller, Req, Logger, HttpException, RequestMethod} from '@nestjs/common';
import BraintreeProvider from './braintree.provider';
import BraintreeWebhookProvider from './braintree.webhook.provider';
import { BraintreeWebhookNotificationInterface } from './interfaces';
import { PATH_METADATA, METHOD_METADATA } from '@nestjs/common/constants';
//TODO make path configurable
@Controller('braintree')
@Controller()
export default class BraintreeWebhookController {
constructor(private readonly braintree: BraintreeProvider, private readonly webhookProvider: BraintreeWebhookProvider) {}
constructor(
private readonly braintree: BraintreeProvider,
private readonly webhookProvider: BraintreeWebhookProvider,
) {}
@Post('webhook')
public static forRoot(root: string = 'braintree', handle: string = 'webhook') {
Reflect.defineMetadata(PATH_METADATA, root, BraintreeWebhookController);
Reflect.defineMetadata(
METHOD_METADATA,
RequestMethod.POST,
Object.getOwnPropertyDescriptor(BraintreeWebhookController.prototype, 'handle').value,
);
Reflect.defineMetadata(
PATH_METADATA,
handle,
Object.getOwnPropertyDescriptor(BraintreeWebhookController.prototype, 'handle').value,
);
return BraintreeWebhookController;
}
async handle(@Req() request) {
let webhook: BraintreeWebhookNotificationInterface;
try {
webhook = await this.braintree.parseWebhook({
bt_signature: request.body.bt_signature,
webhook = await this.braintree.parseWebhook({
bt_signature: request.body.bt_signature,
bt_payload: request.body.bt_payload,

@@ -20,0 +36,0 @@ });

@@ -10,3 +10,4 @@ import {Module, OnModuleInit,} from '@nestjs/common';

import { MetadataScanner } from '@nestjs/core/metadata-scanner';
import { Injectable } from '@nestjs/common/interfaces';
import { Injectable, DynamicModule } from '@nestjs/common/interfaces';
import { BraintreeWebhookOptionsInterface } from './interfaces';

@@ -16,3 +17,3 @@ @Module({

providers: [BraintreeWebhookProvider],
controllers: [BraintreeWebhookController],
controllers: [BraintreeWebhookController.forRoot('braintree', 'webhook')],
})

@@ -59,2 +60,11 @@ export default class BraintreeWebhookModule implements OnModuleInit {

}
public static forRoot(webhookOptions: BraintreeWebhookOptionsInterface): DynamicModule {
return {
module: BraintreeWebhookModule,
imports: [BraintreeModule],
providers: [BraintreeWebhookProvider],
controllers: [BraintreeWebhookController.forRoot(webhookOptions.root, webhookOptions.handle)],
};
}
}

@@ -32,3 +32,2 @@ import {Injectable, Provider, Logger, HttpException} from '@nestjs/common';

async handle(webhook: BraintreeWebhookNotificationInterface): Promise<void> {
if (Object.keys(this.methods).includes(webhook.kind)) {

@@ -35,0 +34,0 @@ this.methods[webhook.kind].forEach(async (methodProto: BraintreeWebhookMethodInterface) => {

@@ -5,1 +5,3 @@ export * from './braintree.options.interface';

export * from './braintree.webhook.methods.interface';
export * from './braintree.webhook.options.interface';
export * from './braintree.transaction.interface';
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc