Skip to content

Commit

Permalink
docs(payments-plugin): Add inline documentation for Braintree plugin
Browse files Browse the repository at this point in the history
Relates to #1087
  • Loading branch information
michaelbromley committed Nov 30, 2021
1 parent 42c0be4 commit 8f218da
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 74 deletions.
46 changes: 3 additions & 43 deletions packages/payments-plugin/src/braintree/README.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,6 @@
# Braintree plugin
# Braintree payment plugin

This plugin enables payments to be processed by [Braintree](https://www.braintreepayments.com/), a popular payment provider.
This plugin enables payments to be processed by [Braintree](https://www.braintreepayments.com/).

## Requirements
For documentation, see https://www.vendure.io/docs/typescript-api/payments-plugin/braintree-plugin

1. You will need to create a Braintree sandbox account as outlined in https://developers.braintreepayments.com/start/overview.
2. Then install `braintree` and `@types/braintree` from npm. This plugin was written with `v3.0.0` of the Braintree lib.

## Setup

1. Add the plugin to your VendureConfig `plugins` array.
2. In the admin UI, fill in the `merchantId`, `publicKey` & `privateKey` from your Braintree sandbox account.

## Usage

The plugin is designed to work with the [Braintree drop-in UI](https://developers.braintreepayments.com/guides/drop-in/overview/javascript/v3).

In your storefront, you'll have some code like this to submit the payment:

```TypeScript
async function submitPayment() {
const paymentResult = await this.dropin.requestPaymentMethod();
myGraphQlClient.mutation(gql`
mutation {
addPaymentToOrder(input: $input) {
id
state
payments {
id
amount
errorMessage
method
state
transactionId
createdAt
}
}
}`, {
input: {
method: 'braintree',
metadata: paymentResult,
},
});
}
```
26 changes: 0 additions & 26 deletions packages/payments-plugin/src/braintree/braintree-plugin.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { loggerCtx } from './constants';
*/
export const braintreePaymentMethodHandler = new PaymentMethodHandler({
code: 'braintree',
description: [{ languageCode: LanguageCode.en, value: 'Braintree' }],
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' }] },
Expand Down
193 changes: 193 additions & 0 deletions packages/payments-plugin/src/braintree/braintree.plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import { PluginCommonModule, VendurePlugin } from '@vendure/core';
import { gql } from 'apollo-server-core';

import { braintreePaymentMethodHandler } from './braintree.handler';
import { BraintreeResolver } from './braintree.resolver';

/**
* @description
* This plugin enables payments to be processed by [Braintree](https://www.braintreepayments.com/), a popular payment provider.
*
* ## Requirements
*
* 1. You will need to create a Braintree sandbox account as outlined in https://developers.braintreepayments.com/start/overview.
* 2. Then install `braintree` and `@types/braintree` from npm. This plugin was written with `v3.x` of the Braintree lib.
* ```shell
* yarn add \@vendure/payments-plugin braintree
* yarn add -D \@types/braintree
* ```
* or
* ```shell
* npm install \@vendure/payments-plugin braintree
* npm install -D \@types/braintree
* ```
*
* ## Setup
*
* 1. Add the plugin to your VendureConfig `plugins` array:
* ```TypeScript
* import { BraintreePlugin } from '\@vendure/payments-plugin/package/braintree';
*
* // ...
*
* plugins: [
* BraintreePlugin,
* ]
* ```
* 2. Create a new PaymentMethod in the Admin UI, and select "Braintree payments" as the handler.
* 2. Fill in the `Merchant ID`, `Public Key` & `Private Key` from your Braintree sandbox account.
*
* ## Storefront usage
*
* The plugin is designed to work with the [Braintree drop-in UI](https://developers.braintreepayments.com/guides/drop-in/overview/javascript/v3).
* This is a library provided by Braintree which will handle the payment UI for you. You can install it in your storefront project
* with:
*
* ```shell
* yarn add braintree-web-drop-in
* # or
* npm install braintree-web-drop-in
* ```
*
* The high-level workflow is:
* 1. Generate a "client token" on the server by executing the `generateBraintreeClientToken` mutation which is exposed by this plugin.
* 2. Use this client token to instantiate the Braintree Dropin UI.
* 3. Listen for the `"paymentMethodRequestable"` event which emitted by the Dropin.
* 4. Use the Dropin's `requestPaymentMethod()` method to get the required payment metadata.
* 5. Pass that metadata to the `addPaymentToOrder` mutation.
*
* Here is an example of how your storefront code will look. Note that this example is attempting to
* be framework-agnostic, so you'll need to adapt it to fit to your framework of choice.
*
* ```TypeScript
* // The Braintree Dropin instance
* let dropin: import('braintree-web-drop-in').Dropin;
*
* // Used to show/hide a "submit" button, which would be bound to the
* // `submitPayment()` method below.
* let showSubmitButton = false;
*
* // Used to display a "processing..." spinner
* let processing = false;
*
* //
* // This method would be invoked when the payment screen is mounted/created.
* //
* async function renderDropin(order: Order, clientToken: string) {
* // Lazy load braintree dropin because it has a reference
* // to `window` which breaks SSR
* dropin = await import('braintree-web-drop-in').then((module) =>
* module.default.create({
* authorization: clientToken,
* // This assumes a div in your view with the corresponding ID
* container: '#dropin-container',
* card: {
* cardholderName: {
* required: true,
* },
* overrides: {},
* },
* // Additional config is passed here depending on
* // which payment methods you have enabled in your
* // Braintree account.
* paypal: {
* flow: 'checkout',
* amount: order.totalWithTax,
* currency: 'GBP',
* },
* }),
* );
*
* dropin.on('paymentMethodRequestable', (payload) => {
* if (payload.type === 'CreditCard') {
* showSubmitButton = true;
* }
* if (payload.type === 'PayPalAccount') {
* this.submitPayment();
* }
* });
*
* dropin.on('noPaymentMethodRequestable', () => {
* // Display an error
* });
* }
*
* async function generateClientToken(orderId: string) {
* const { generateBraintreeClientToken } = await graphQlClient.query(gql`
* query GenerateBraintreeClientToken($orderId: ID!) {
* generateBraintreeClientToken(orderId: $orderId)
* }
* `, { orderId });
* return generateBraintreeClientToken;
* }
*
* async submitPayment() {
* if (!dropin.isPaymentMethodRequestable()) {
* return;
* }
* showSubmitButton = false;
* processing = true;
*
* const paymentResult = await dropin.requestPaymentMethod();
*
* const { addPaymentToOrder } = await graphQlClient.query(gql`
* mutation AddPayment($input: PaymentInput!) {
* addPaymentToOrder(input: $input) {
* ... on Order {
* id
* payments {
* id
* amount
* errorMessage
* method
* state
* transactionId
* createdAt
* }
* }
* ... on ErrorResult {
* errorCode
* message
* }
* }
* }`, {
* input: {
* method: 'braintree', // The code of you Braintree PaymentMethod
* metadata: paymentResult,
* },
* },
* );
*
* switch (addPaymentToOrder?.__typename) {
* case 'Order':
* // Adding payment succeeded!
* break;
* case 'OrderStateTransitionError':
* case 'OrderPaymentStateError':
* case 'PaymentDeclinedError':
* case 'PaymentFailedError':
* // Display an error to the customer
* dropin.clearSelectedPaymentMethod();
* }
* }
* ```
* @docsCategory payments-plugin
* @docsPage BraintreePlugin
*/
@VendurePlugin({
imports: [PluginCommonModule],
providers: [],
configuration: config => {
config.paymentOptions.paymentMethodHandlers.push(braintreePaymentMethodHandler);
return config;
},
shopApiExtensions: {
schema: gql`
extend type Query {
generateBraintreeClientToken(orderId: ID!): String!
}
`,
resolvers: [BraintreeResolver],
},
})
export class BraintreePlugin {}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from '@vendure/core';

import { getGateway } from './braintree-common';
import { braintreePaymentMethodHandler } from './braintree-payment-method';
import { braintreePaymentMethodHandler } from './braintree.handler';
import { loggerCtx } from './constants';
import { PaymentMethodArgsHash } from './types';

Expand Down
4 changes: 2 additions & 2 deletions packages/payments-plugin/src/braintree/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from './braintree-plugin';
export * from './braintree-payment-method';
export * from './braintree.plugin';
export * from './braintree.handler';
export * from './braintree.resolver';
export * from './braintree-common';
2 changes: 1 addition & 1 deletion packages/payments-plugin/src/braintree/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ConfigArgValues } from '@vendure/core/dist/common/configurable-operation';

import { braintreePaymentMethodHandler } from './braintree-payment-method';
import { braintreePaymentMethodHandler } from './braintree.handler';

export type PaymentMethodArgsHash = ConfigArgValues<typeof braintreePaymentMethodHandler['args']>;

0 comments on commit 8f218da

Please sign in to comment.