From 55d67d93763a4147c7c768831994596dae304bfa Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Mon, 6 Dec 2021 14:17:28 +0100 Subject: [PATCH] feat(payments-plugin): Allow Braintree environment to be set --- .../src/braintree/braintree-common.ts | 6 ++--- .../src/braintree/braintree.handler.ts | 18 +++++++++------ .../src/braintree/braintree.plugin.ts | 20 +++++++++++++--- .../src/braintree/braintree.resolver.ts | 23 ++++++++++++------- .../src/braintree/constants.ts | 1 + .../payments-plugin/src/braintree/index.ts | 1 + .../payments-plugin/src/braintree/types.ts | 16 +++++++++++++ scripts/publish-to-verdaccio.sh | 1 + 8 files changed, 65 insertions(+), 21 deletions(-) diff --git a/packages/payments-plugin/src/braintree/braintree-common.ts b/packages/payments-plugin/src/braintree/braintree-common.ts index cc1aa4bd0d..6b7cdd8d1c 100644 --- a/packages/payments-plugin/src/braintree/braintree-common.ts +++ b/packages/payments-plugin/src/braintree/braintree-common.ts @@ -1,10 +1,10 @@ import { BraintreeGateway, Environment, Transaction } from 'braintree'; -import { PaymentMethodArgsHash } from './types'; +import { BraintreePluginOptions, PaymentMethodArgsHash } from './types'; -export function getGateway(args: PaymentMethodArgsHash): BraintreeGateway { +export function getGateway(args: PaymentMethodArgsHash, options: BraintreePluginOptions): BraintreeGateway { return new BraintreeGateway({ - environment: Environment.Sandbox, + environment: options.environment || Environment.Sandbox, merchantId: args.merchantId, privateKey: args.privateKey, publicKey: args.publicKey, diff --git a/packages/payments-plugin/src/braintree/braintree.handler.ts b/packages/payments-plugin/src/braintree/braintree.handler.ts index 6eea5148b7..42f98f0ef5 100644 --- a/packages/payments-plugin/src/braintree/braintree.handler.ts +++ b/packages/payments-plugin/src/braintree/braintree.handler.ts @@ -1,9 +1,11 @@ import { LanguageCode } from '@vendure/common/lib/generated-types'; -import { Logger, PaymentMethodHandler } from '@vendure/core'; +import { Injector, Logger, PaymentMethodHandler } from '@vendure/core'; import { extractMetadataFromTransaction, getGateway } from './braintree-common'; -import { loggerCtx } from './constants'; +import { BRAINTREE_PLUGIN_OPTIONS, loggerCtx } from './constants'; +import { BraintreePluginOptions } from './types'; +let options: BraintreePluginOptions; /** * The handler for Braintree payments. */ @@ -12,12 +14,14 @@ export const braintreePaymentMethodHandler = new PaymentMethodHandler({ description: [{ languageCode: LanguageCode.en, value: 'Braintree payments' }], args: { merchantId: { type: 'string', label: [{ languageCode: LanguageCode.en, value: 'Merchant ID' }] }, - publicKey: { type: 'string', label: [{ languageCode: LanguageCode.en, value: 'Private Key' }] }, - privateKey: { type: 'string', label: [{ languageCode: LanguageCode.en, value: 'Public Key' }] }, + publicKey: { type: 'string', label: [{ languageCode: LanguageCode.en, value: 'Public Key' }] }, + privateKey: { type: 'string', label: [{ languageCode: LanguageCode.en, value: 'Private Key' }] }, + }, + init(injector: Injector) { + options = injector.get(BRAINTREE_PLUGIN_OPTIONS); }, - async createPayment(ctx, order, amount, args, metadata) { - const gateway = getGateway(args); + const gateway = getGateway(args, options); try { const response = await gateway.transaction.sale({ amount: (amount / 100).toString(10), @@ -61,7 +65,7 @@ export const braintreePaymentMethodHandler = new PaymentMethodHandler({ }, async createRefund(ctx, input, total, order, payment, args) { - const gateway = getGateway(args); + const gateway = getGateway(args, options); const response = await gateway.transaction.refund(payment.transactionId, (total / 100).toString(10)); if (!response.success) { return { diff --git a/packages/payments-plugin/src/braintree/braintree.plugin.ts b/packages/payments-plugin/src/braintree/braintree.plugin.ts index 124cac5f02..2be2205320 100644 --- a/packages/payments-plugin/src/braintree/braintree.plugin.ts +++ b/packages/payments-plugin/src/braintree/braintree.plugin.ts @@ -3,6 +3,8 @@ import { gql } from 'apollo-server-core'; import { braintreePaymentMethodHandler } from './braintree.handler'; import { BraintreeResolver } from './braintree.resolver'; +import { BRAINTREE_PLUGIN_OPTIONS } from './constants'; +import { BraintreePluginOptions } from './types'; /** * @description @@ -27,11 +29,12 @@ import { BraintreeResolver } from './braintree.resolver'; * 1. Add the plugin to your VendureConfig `plugins` array: * ```TypeScript * import { BraintreePlugin } from '\@vendure/payments-plugin/package/braintree'; + * import { Environment } from 'braintree'; * * // ... * * plugins: [ - * BraintreePlugin, + * BraintreePlugin.init({ environment: Environment.Sandbox }), * ] * ``` * 2. Create a new PaymentMethod in the Admin UI, and select "Braintree payments" as the handler. @@ -176,7 +179,12 @@ import { BraintreeResolver } from './braintree.resolver'; */ @VendurePlugin({ imports: [PluginCommonModule], - providers: [], + providers: [ + { + provide: BRAINTREE_PLUGIN_OPTIONS, + useFactory: () => BraintreePlugin.options, + }, + ], configuration: config => { config.paymentOptions.paymentMethodHandlers.push(braintreePaymentMethodHandler); return config; @@ -190,4 +198,10 @@ import { BraintreeResolver } from './braintree.resolver'; resolvers: [BraintreeResolver], }, }) -export class BraintreePlugin {} +export class BraintreePlugin { + static options: BraintreePluginOptions = {}; + static init(options: BraintreePluginOptions): BraintreePlugin { + this.options = options; + return BraintreePlugin; + } +} diff --git a/packages/payments-plugin/src/braintree/braintree.resolver.ts b/packages/payments-plugin/src/braintree/braintree.resolver.ts index 4fa6ec875e..4bc405465c 100644 --- a/packages/payments-plugin/src/braintree/braintree.resolver.ts +++ b/packages/payments-plugin/src/braintree/braintree.resolver.ts @@ -1,3 +1,4 @@ +import { Inject } from '@nestjs/common'; import { Args, Query, Resolver } from '@nestjs/graphql'; import { Ctx, @@ -12,12 +13,16 @@ import { import { getGateway } from './braintree-common'; import { braintreePaymentMethodHandler } from './braintree.handler'; -import { loggerCtx } from './constants'; -import { PaymentMethodArgsHash } from './types'; +import { BRAINTREE_PLUGIN_OPTIONS, loggerCtx } from './constants'; +import { BraintreePluginOptions, PaymentMethodArgsHash } from './types'; @Resolver() export class BraintreeResolver { - constructor(private connection: TransactionalConnection, private orderService: OrderService) {} + constructor( + private connection: TransactionalConnection, + private orderService: OrderService, + @Inject(BRAINTREE_PLUGIN_OPTIONS) private options: BraintreePluginOptions, + ) {} @Query() async generateBraintreeClientToken(@Ctx() ctx: RequestContext, @Args() { orderId }: { orderId: ID }) { @@ -25,14 +30,16 @@ export class BraintreeResolver { if (order && order.customer) { const customerId = order.customer.id.toString(); const args = await this.getPaymentMethodArgs(ctx); - const gateway = getGateway(args); + const gateway = getGateway(args, this.options); try { - const result = await gateway.clientToken.generate({ - customerId, - }); + const result = await gateway.clientToken.generate({}); return result.clientToken; } catch (e) { - Logger.error(e); + Logger.error( + `Could not generate Braintree clientToken. Check the configured credentials.`, + loggerCtx, + ); + throw e; } } else { throw new InternalServerError(`[${loggerCtx}] Could not find a Customer for the given Order`); diff --git a/packages/payments-plugin/src/braintree/constants.ts b/packages/payments-plugin/src/braintree/constants.ts index 6dbeb428fd..092590f648 100644 --- a/packages/payments-plugin/src/braintree/constants.ts +++ b/packages/payments-plugin/src/braintree/constants.ts @@ -1 +1,2 @@ export const loggerCtx = 'BraintreePlugin'; +export const BRAINTREE_PLUGIN_OPTIONS = Symbol('BRAINTREE_PLUGIN_OPTIONS'); diff --git a/packages/payments-plugin/src/braintree/index.ts b/packages/payments-plugin/src/braintree/index.ts index de7d5b7d56..36d656878d 100644 --- a/packages/payments-plugin/src/braintree/index.ts +++ b/packages/payments-plugin/src/braintree/index.ts @@ -2,3 +2,4 @@ export * from './braintree.plugin'; export * from './braintree.handler'; export * from './braintree.resolver'; export * from './braintree-common'; +export * from './types'; diff --git a/packages/payments-plugin/src/braintree/types.ts b/packages/payments-plugin/src/braintree/types.ts index 16ccb2d03b..1a53309b3f 100644 --- a/packages/payments-plugin/src/braintree/types.ts +++ b/packages/payments-plugin/src/braintree/types.ts @@ -1,5 +1,21 @@ import { ConfigArgValues } from '@vendure/core/dist/common/configurable-operation'; +import { Environment } from 'braintree'; import { braintreePaymentMethodHandler } from './braintree.handler'; export type PaymentMethodArgsHash = ConfigArgValues; + +/** + * @description + * Options for the Braintree plugin. + * + * @docsCategory payments-plugin + * @docsPage BraintreePlugin + */ +export interface BraintreePluginOptions { + /** + * @description + * The Braintree environment being targeted, e.g. sandbox or production. + */ + environment?: Environment; +} diff --git a/scripts/publish-to-verdaccio.sh b/scripts/publish-to-verdaccio.sh index b74198dcdf..0796c1880d 100755 --- a/scripts/publish-to-verdaccio.sh +++ b/scripts/publish-to-verdaccio.sh @@ -21,6 +21,7 @@ cd ../core && npm publish -reg $VERDACCIO &&\ cd ../create && npm publish -reg $VERDACCIO &&\ cd ../elasticsearch-plugin && npm publish -reg $VERDACCIO &&\ cd ../email-plugin && npm publish -reg $VERDACCIO &&\ +cd ../payments-plugin && npm publish -reg $VERDACCIO &&\ cd ../testing && npm publish -reg $VERDACCIO &&\ cd ../ui-devkit && npm publish -reg $VERDACCIO &&\ cd ../job-queue-plugin && npm publish -reg $VERDACCIO &&\