Cómo cargar una tarjeta de crédito con Stripe en Node.js

Cómo usar el paquete Stripe NPM para comunicarse con la API de Stripe y cargar una tarjeta de crédito en Node.js.

Primeros pasos

Para este tutorial, vamos a utilizar CheatCode Node.js Boilerplate como punto de partida para nuestro trabajo. Para empezar, clonemos una copia de Github:

Terminal

git clone https://github.com/cheatcode/nodejs-server-boilerplate

A continuación, cd en el proyecto e instalar sus dependencias:

Terminal

cd nodejs-server-boilerplate && npm install

A continuación, necesitamos instalar una dependencia adicional, stripe :

Terminal

npm i stripe

Finalmente, continúe e inicie el servidor de desarrollo:

Terminal

npm run dev

Con eso, estamos listos para comenzar.

Obtener un token de tarjeta

Para procesar un cargo a través de la API de Stripe, necesitaremos obtener acceso a un token de Stripe. Para este tutorial, solo nos centraremos en el back-end, pero se recomienda que consulte nuestro tutorial sobre Cómo crear un formulario de tarjeta de crédito con Stripe.js para aprender a crear una interfaz de usuario para recuperar una tarjeta Stripe. ficha.

Una vez que tenga un medio para obtener un token de tarjeta, podemos profundizar en el procesamiento de un cargo.

Accediendo a nuestras claves API de Stripe

Antes de profundizar en el código, para este tutorial, vamos a necesitar acceso a una cuenta de Stripe. Dirígete a la página de registro en su sitio y crea una cuenta si aún no lo has hecho.

Una vez que tenga una cuenta, inicie sesión en el tablero. Debería ser algo como esto:

Donde queremos navegar es la página que se muestra arriba. Para llegar:

  1. En la esquina superior derecha, asegúrese de haber activado el botón "Modo de prueba" para que se ilumine (en el momento de escribir esto, se volverá naranja cuando esté activado).
  2. A la izquierda de ese interruptor, haga clic en el botón "Desarrolladores".
  3. En la página siguiente, en el menú de navegación de la izquierda, seleccione la pestaña "Claves API".
  4. Bajo el bloque "Claves estándar" en esta página, busque su "Clave secreta" y haga clic en el botón "Revelar clave de prueba".
  5. Copie esta clave (guárdela en un lugar seguro ya que se usa para realizar transacciones con su cuenta de Stripe).

Luego, una vez que tengamos nuestra clave secreta, debemos abrir el proyecto que acabamos de clonar y navegar hasta el /settings-development.json archivo:

/configuración-desarrollo.json

const settings = {
  "authentication": { ... },
  "databases": { ... },
  "smtp": { ... },
  "stripe": {
    "secretKey": "<Paste your secret key here>"
  },
  "support": { ... },
  "urls": { ... }
};

export default settings;

En este archivo, alfabéticamente cerca de la parte inferior del settings exportado objeto, queremos agregar una nueva propiedad stripe y configúrelo en un objeto con una sola propiedad:secretKey . Para el valor de esta propiedad, queremos pegar la clave secreta que copió del panel de Stripe anterior. Péguelo y luego guarde este archivo.

A continuación, para acceder a la API de Stripe, debemos configurar una instancia de Stripe a través de stripe Paquete NPM.

Conexión de acceso a Stripe

Con nuestra clave secreta configurada, ahora necesitamos obtener acceso a la API de Stripe. Afortunadamente, la gente de Stripe ofrece un paquete Node.js para su API (lo instalamos antes), por lo que todo lo que tenemos que hacer es configurar una conexión.

/lib/stripe.js

import Stripe from 'stripe';
import settings from "./settings";

const stripe = Stripe(settings.stripe.secretKey);

export default stripe;

Dentro de nuestro /lib carpeta, queremos crear un archivo stripe.js donde cargaremos en el stripe paquete de NPM e inicialícelo con nuestro secretKey de Stripe que acabamos de agregar a nuestro archivo de configuración.

Aquí, importamos la configuración adecuada en función de nuestro entorno. Suponemos que el entorno actual es development , entonces settings aquí contendrá el contenido de nuestro settings-development.json archivo.

En ese objeto, esperamos una propiedad stripe para ser definido como un objeto con su propia propiedad secretKey . Arriba, primero importamos Stripe del stripe paquete NPM que instalamos anteriormente y luego llamamos a ese valor importado como una función, pasando nuestro secretKey de nuestro archivo de configuración.

A cambio, esperamos recuperar una instancia de la API de Stripe, que almacenamos en una variable stripe y luego exporte como el valor predeterminado de este archivo.

Con esto, ahora, siempre que queramos comunicarnos con Stripe, solo necesitamos importar este archivo en lugar de escribir todo este código en todos los archivos donde queremos llamar a Stripe.

Cableado de un terminal para cargos

A continuación, vamos a conectar un punto final HTTP POST usando Express.js (integrado y preconfigurado en el modelo que estamos usando). Usaremos este punto final para demostrar cómo crear el cargo a través de Stripe. Es importante tener en cuenta:puede llamar al código Stripe que veremos a continuación desde cualquier lugar dentro de Node.js . Solo estamos usando una ruta Express como ejemplo.

/api/index.js

import graphql from "./graphql/server";
import stripe from "../lib/stripe";

export default (app) => {
  graphql(app);
  app.post("/checkout", (req, res) => {
    // We'll wire up the charge here...
  });
};

Dentro del /api/index.js archivo ya incluido en nuestro repetitivo, añadimos una nueva ruta /checkout llamando al .post() método en el app argumento pasado a la función exportada desde este archivo. Aquí, app representa Express.js app que recibimos a cambio al llamar a express() (puedes ver la configuración para esto en el /index.js archivo en la raíz del repetitivo:el api() la función que llamamos allí es la que vemos que se exporta arriba).

Aquí, usamos el .post() método para crear una ruta Express que solo acepte solicitudes HTTP POST. Como veremos, enviaremos una solicitud HTTP POST más tarde para probar esto.

/api/index.js

import graphql from "./graphql/server";
import stripe from "../lib/stripe";

export default (app) => {
  graphql(app);
  app.post("/checkout", (req, res) => {
    const items = [
      { _id: "water-jug", amount: 9999, name: "Water Jug" },
      { _id: "coffee-cup", amount: 2999, name: "Coffee Cup" },
      { _id: "ham-sandwich", amount: 2999, name: "Ham Sandwich" },
    ];

    const item = items.find(({ _id }) => _id === req?.body?.itemId);
    const source = req?.body?.source;

    if (item && source) {
      // We'll process the charge here...
    }

    res
      .status(400)
      .send(
        "Must pass an itemId and source in the request body in order to process a charge."
      );
  });
};

Dentro de la devolución de llamada de nuestra ruta, antes de manejar el req Por ejemplo, configuramos una serie de artículos para que actúen como una base de datos simulada para artículos reales que un cliente podría comprarnos.

Esto es importante. La razón por la que mostramos esto aquí en lugar de pasar una cantidad del cliente es que nunca debemos confiar en el cliente . Por ejemplo, si un usuario descubre que simplemente pasamos el monto del cliente al servidor, podría cambiar un pedido de $1000 a $0,01 y el cargo se procesaría.

Para mitigar esto, hacemos un seguimiento de los precios que vamos a cobrar en el servidor y use una identificación única para decirnos qué artículo obtener el precio cuando recibamos una solicitud de cargo.

Aquí, lo hacemos diciendo "esta matriz de items están a la venta con estos precios". Esperamos que el req.body objeto que recibimos tendrá dos propiedades:un itemId y un source . Aquí, itemId debería coincide con uno de los _id campos en un artículo si la compra es válida (en la práctica, cargaríamos la misma lista de artículos en nuestra interfaz de usuario desde la base de datos para que las ID fueran consistentes).

Para verificar, usamos items.find() , buscando un artículo con un _id propiedad—dentro de nuestro .find() devolución de llamada usamos la desestructuración de objetos de JavaScript para "arrancar" esta propiedad de cada elemento que recorremos, eso es igual a req.body.itemId recibimos del cliente.

Si hacemos encuentra un artículo coincidente, sabemos que la compra es válida. A continuación, también obtenemos el source —este es el término que usa Stripe para referirse al pago fuente:del req.body .

Suponiendo que ambos item y source están definidos, queremos intentar una carga. Si son no definido, queremos responder con un código de estado HTTP 400 que significa "Solicitud incorrecta" y enviar un mensaje con instrucciones sobre cómo resolver el problema.

/api/index.js

import graphql from "./graphql/server";
import stripe from "../lib/stripe";

export default (app) => {
  graphql(app);
  app.post("/checkout", (req, res) => {
    const items = [
      { _id: "water-jug", amount: 9999, name: "Water Jug" },
      { _id: "coffee-cup", amount: 2999, name: "Coffee Cup" },
      { _id: "ham-sandwich", amount: 2999, name: "Ham Sandwich" },
    ];

    const item = items.find(({ _id }) => _id === req?.body?.itemId);
    const source = req?.body?.source;

    if (item && source) {
      return stripe.charges
        .create({
          amount: item.amount,
          currency: "usd",
          source,
          description: item.name,
          metadata: {
            ...item,
          },
        })
        .then((charge) => {
          res.status(200).send(charge);
        })
        .catch((error) => {
          res.status(402).send(error);
        });
    }

    res
      .status(400)
      .send(
        "Must pass an itemId and source in the request body in order to process a charge."
      );
  });
};

Ahora estamos listos para enviar nuestra solicitud de cargo a Stripe. Para hacerlo, vamos a llamar al stripe.charges.create() método del stripe Instancia de API que configuramos en el archivo que importamos anteriormente. Al llamar a esa función, pasamos un objeto con las opciones apropiadas para nuestro cargo (ver lo que está disponible en la documentación de Stripe aquí).

Para nuestras necesidades, queremos pasar los dos campos obligatorios amount (un número entero que representa el cargo en centavos; por ejemplo, $5,00 sería 500) y currency . También aprobamos nuestro source (este será el token de Stripe que recuperamos en el cliente), el nombre de nuestro elemento como description , y también incluir todos los datos sobre nuestro cargo en el metadata campo como ejemplo de pasar datos misceláneos junto con nuestro cargo (una opción conveniente para los desarrolladores que necesitan almacenar datos adicionales, personalizados y relacionados con el cargo, como una ID de usuario interna).

Finalmente, como esperamos que todos los métodos en el stripe Instancia de API para devolver una promesa de JavaScript, encadenamos en un .then() función de devolución de llamada para manejar nuestro estado de éxito y un .catch() función de devolución de llamada para manejar un estado de error.

Si el cargo es exitoso, respondemos al req original con un código de estado de 200 (el código de estado HTTP para señalar una solicitud exitosa) y pasar la respuesta que recibimos de Stripe (un objeto que contiene los detalles del cargo procesado).

Si el cargo falla, enviamos un código de estado HTTP 402 (que significa "Pago requerido") y devuelva el error objeto recibido de Stripe.

¡Eso es todo! Iniciemos el cliente para obtener nuestro token de Stripe y luego procesemos la solicitud a través de una aplicación HTTP (estoy usando la aplicación Paw de MacOS para probar nuestro punto final).

Terminando

En este tutorial, aprendimos cómo cargar una tarjeta de crédito usando el stripe API en Node.js. Aprendimos cómo crear una instancia de Stripe API a través de su stripe paquete de nodo, creando un módulo reutilizable para comunicarse con stripe, y luego aprendimos cómo configurar una ruta HTTP POST a través de Express.js donde podíamos enviar una solicitud de cargo a Stripe.