Cómo crear una app de shopify – Paso a paso

Hola, voy a crear una app de shopify para suscripciones y sobre todo para cancelarlas según la nueva ley
Por lo tanto he creado un plan personal paso a paso para crear una app de shopify.
Sólo he copiado la mayoría de las cosas de diferentes fuentes, espero que ayude 🙂



Vocabulario:

Hay tres áreas clave donde las apps interactúan con la plataforma de Shopify: Administración de Shopify, tienda online, y compras.



Shopify admin

Después de iniciar sesión en Shopify, los comerciantes establecen su tienda, configuran los ajustes y gestionan su negocio utilizando el Administrador de Shopify.

El administrador de Shopify incluye los aspectos principales del negocio de Shopify del comerciante, incluyendo pedidos, productos y clientes. Los comerciantes también instalan aplicaciones en el admin de Shopify.



Tienda-online

La tienda online es un hogar online para el negocio de un comerciante. Los comerciantes utilizan la tienda online para crear páginas web, publicar un blog y vender sus productos.

Como desarrollador de aplicaciones, puedes construir integraciones en todos los lugares donde los comerciantes quieren vender, y donde sus clientes quieren comprar.



Checkout

Los comerciantes utilizan la caja segura Shopify checkout para aceptar los pedidos y tomar los pagos dondequiera que vendan en línea. Después de que un cliente añada productos a un carrito, utiliza el checkout de Shopify para introducir su información de envío y los detalles de pago antes de realizar el pedido.

Las aplicaciones pueden integrarse con Shopify checkout para ofrecer funcionalidades adicionales a comerciantes y clientes. Por ejemplo, los comerciantes pueden utilizar apps que soporten ofertas posteriores a la compra para mostrar una oferta de venta cruzada o de venta adicional a los clientes en el momento de la compra.



Crea tu primera aplicación de shopify



Paso 1: Registrar cuenta de socio de Shopify

Crea primero una cuenta de socio aquí:
https://partners.shopify.com/signup



Paso 2: Crear una tienda de prueba

Una tienda de desarrollo es una cuenta gratuita de Shopify que viene con algunas limitaciones. Como Socio de Shopify, puedes crear un número ilimitado de tiendas de desarrollo.

Puedes utilizar una tienda de desarrollo para probar cualquier tema o aplicación que crees, o para montar una tienda Shopify para un cliente. Montar una tienda de desarrollo y transferirla a un cliente te da una comisión recurrente.
2.1. Inicie sesión en su Panel de socio.
2.2. Haga clic en Tiendas.
2.3. Haz clic en Añadir tienda.
2.4. En la sección Tipo de tienda, seleccione Tienda de desarrollo.
2.5. En la sección Información de inicio de sesión, introduzca un nombre para su tienda y una contraseña que pueda utilizar para iniciar sesión. Por defecto, se utiliza como nombre de usuario el correo electrónico asociado a su Tablero de Socios, pero puede cambiarlo si lo desea.
2.6. Opcional: Habilite una vista previa para desarrolladores marcando Crear una tienda no transferible que utilice una vista previa para desarrolladores. Seleccione una versión de vista previa para desarrolladores en la lista desplegable.
2.7. En la sección Dirección de la tienda, introduzca su dirección.
2.8. Opcional: En la sección Propósito de la tienda, seleccione la razón por la que está creando esta tienda de desarrollo.
2.9. Haz clic en Guardar.



Paso 3: Instalar el último Node.js

https://nodejs.org/en/download/



Paso 4: Instalar Shopify CLI

Si quieres usar Shopify CLI de forma nativa en Windows 10, entonces primero asegúrate de haber instalado Ruby+Devkit usando RubyInstaller para Windows (versión 2.7 o superior).
Alternativamente, puedes usar Shopify CLI usando Windows Subsystem para Linux, en cuyo caso necesitas instalar lo siguiente:

Después de instalar los requisitos previos, puedes instalar Shopify CLI como una gema de Ruby utilizando el gestor de paquetes RubyGems.org. En una nueva ventana de terminal, navega a tu directorio principal y ejecuta el siguiente comando:

gem install shopify-cli

Para verificar que Shopify CLI está instalado correctamente, ejecuta el siguiente comando:

shopify version



Paso 5: Iniciar sesión en Shopify con la CLI

Antes de crear el proyecto con la ayuda de la CLI necesitamos iniciar sesión en shopify. Por lo tanto escribimos en la terminal:

shopify login

Se abrirá una pestaña del navegador, inicie sesión en su cuenta de socio. Debería ver un mensaje en su terminal, después de haber iniciado la sesión con éxito

Ha iniciado sesión en la tienda xxxxxx.myshopify.com en la organización asociada xxxx



Paso 6: Crear un nuevo proyecto

Después de haber instalado Shopify CLI, estás listo para crear un nuevo proyecto.

Navega hasta el directorio donde quieres crear tu proyecto y ejecuta shopify node create. Este comando andamiaje una nueva app Node.js en un subdirectorio y crea tu app en el Partner Dashboard.



Paso 7: Iniciar un servidor de desarrollo local

Una vez creada tu app, puedes trabajar con ella navegando al directorio de tu proyecto y ejecutando shopify node serve para iniciar un servidor de desarrollo local.

Shopify CLI utiliza ngrok para crear un túnel que permita acceder a tu app utilizando una única URL HTTPS, lo cual es obligatorio al crear una app.



Paso 8: Instalar su aplicación en su tienda de desarrollo

Con el servidor en marcha, abre la URL que tu terminal imprimió en el paso anterior. Cuando abra la URL, se le pedirá que instale la aplicación en su tienda de desarrollo.

Si sigues este enlace, deberías ver un mensaje con tu aplicación y los alcances de la misma. Presione instalar y su bueno para ir más allá.



Paso 9: Comienza a construir la aplicación

Previamente, has creado una nueva app con Shopify CLI. Ahora estás listo para empezar a construir tu app.

En este tutorial, realizarás una serie de tareas para añadir alguna funcionalidad específica a tu app. Tu app final será sencilla, pero aprenderás dónde encontrar recursos para construir características más complejas por tu cuenta.
Después de terminar este tutorial, habrás logrado lo siguiente:

    • haber poblado productos en tu tienda de desarrollo para probar tu app
    • Construir los inicios de tu interfaz de usuario con Polaris
    • configurar una consulta GraphQL para recuperar productos
    • configurar una mutación GraphQL para actualizar los precios de los productos



Paso 10 : Poblar productos

Shopify CLI ayuda con el proceso de añadir datos de ejemplo para probar el comportamiento de tu app. Puedes usar Shopify CLI para crear registros para productos, clientes y borradores de pedidos.

Debido a que tu app necesita interactuar con los datos de los productos, comienza por poblar los productos en tu tienda de desarrollo:

Abra una nueva ventana de terminal.

Navega hasta el directorio de tu proyecto.

  1. Ejecuta <código>shopify populate products</código>



Paso 11: Añadir un estado vacío

Ahora que puedes ejecutar tu app en Shopify, puedes ver y probar tus componentes del frontend mientras los construyes. Puedes utilizar Polaris, la biblioteca de componentes React de Shopify y el sistema de diseño, para construir tu interfaz de usuario.

Usa Polaris para añadir un estado vacío a tu app. El componente Estado vacío de Polaris ayuda a comunicar el valor de tu app y su acción principal cuando los comerciantes la añaden por primera vez a su admin de Shopify.

En su editor de código, navegue hasta su archivo pages/index.js.

Reemplace el contenido del archivo con un componente EmptyState:

import { Heading, Page, TextStyle, Layout, EmptyState} from "@shopify/polaris";
const img = 'https://cdn.shopify.com/s/files/1/0757/9955/files/empty-state.svg';
const Index = () => (
  <Page>
    <Layout>
      <EmptyState // Empty state component
        heading="Discount your products temporarily"
        action={{
          content: 'Select products',
          onAction: () => this.setState({ open: true }),
        }}
        image={img}
      >
        <p>Select products to change their price temporarily.</p>
      </EmptyState>
    </Layout>
  </Page>
);
export default Index;

Cuando previsualizas tu aplicación incrustada, muestra el estado vacío.



Paso 12: Añadir un selector de recursos

A continuación, añade un selector de recursos para que puedas seleccionar los productos de tu app. Puedes utilizar App Bridge, la biblioteca JavaScript independiente de Shopify, para añadir un selector de recursos a tu app.

El conjunto de acciones de App Bridge <código>ResourcePicker</código> proporciona una interfaz basada en la búsqueda para ayudarte a encontrar y seleccionar uno o más productos y, a continuación, devuelve los recursos seleccionados a tu app.

En tu archivo pages/index.js, añade una clase que establezca un estado para el selector de recursos. A continuación, añade el componente ResourcePicker al botón de acción principal del componente EmptyState:

import React from 'react';
import { Heading, Page, TextStyle, Layout, EmptyState} from "@shopify/polaris";
import { ResourcePicker, TitleBar } from '@shopify/app-bridge-react';
const img = 'https://cdn.shopify.com/s/files/1/0757/9955/files/empty-state.svg';
// Sets the state for the resource picker
class Index extends React.Component {
  state = { open: false };
  render() {
    return (
      <Page>
        <TitleBar
          primaryAction={{
            content: 'Select products',
            onAction: () => this.setState({ open: true }),
          }}
        />
        <ResourcePicker // Resource picker component
          resourceType="Product"
          showVariants={false}
          open={this.state.open}
          onSelection={(resources) => this.handleSelection(resources)}
          onCancel={() => this.setState({ open: false })}
        />
        <Layout>
          <EmptyState
            heading="Discount your products temporarily"
            action={{
              content: 'Select products',
              onAction: () => this.setState({ open: true }),
            }}
            image={img}
          >
            <p>Select products to change their price temporarily.</p>
          </EmptyState>
        </Layout>
      </Page>
    );
  }
  handleSelection = (resources) => {
    this.setState({ open: false });
    console.log(resources);
  };
}
export default Index;
 

En tu app incrustada, al hacer clic en Seleccionar productos, se abre el modal Añadir productos.



Paso 13: Añadir una lista de recursos

Ahora que has configurado tu selector de recursos, necesitas una forma de recuperar productos. Puedes recuperar los productos utilizando la Apriencia de administración GraphQL. En última instancia, desea mostrar estos productos en una lista de recursos.

Para que tu app pueda consultar datos con GraphQL, crea un nuevo archivo ResourceList.js e incluye las importaciones graphql-tag y react-apollo en el archivo.

A continuación, configura una consulta GraphQL llamada getProducts para recuperar una lista de productos y sus precios.

  1. Ejecuta npm install store-js
  2. Crea una nueva carpeta componentes en la carpeta páginas de tu proyecto, y crea un nuevo archivo ResourceList.js en la carpeta.
  3. Añade importaciones a tu archivo ResourceList.js y configura tu consulta GraphQL para recuperar los productos y sus precios:
import React from 'react';
import gql from 'graphql-tag';
import { Query } from 'react-apollo';
import {
  Card,
  ResourceList,
  Stack,
  TextStyle,
  Thumbnail,
} from '@shopify/polaris';
import store from 'store-js';
import { Redirect } from '@shopify/app-bridge/actions';
import { Context } from '@shopify/app-bridge-react';
// GraphQL query to retrieve products by IDs.
// The price field belongs to the variants object because
// variations of a product can have different prices.
const GET_PRODUCTS_BY_ID = gql`
  query getProducts($ids: [ID!]!) {
    nodes(ids: $ids) {
      ... on Product {
        title
        handle
        descriptionHtml
        id
        images(first: 1) {
          edges {
            node {
              originalSrc
              altText
            }
          }
        }
        variants(first: 1) {
          edges {
            node {
              price
              id
            }
          }
        }
      }
    }
  }
`;

En tu archivo ResourceList.js, después de tu consulta GraphQL, configura una clase llamada ResourceListWithProducts que extienda el componente ResourceList y devuelva productos y precios. A continuación, defina su componente ResourceList:

class ResourceListWithProducts extends React.Component {
  static contextType = Context;

  render() {
    const app = this.context;

    return (
      // GraphQL query to retrieve products and their prices
      <Query query={GET_PRODUCTS_BY_ID} variables={{ ids: store.get('ids') }}>
        {({ data, loading, error }) => {
          if (loading) return <div>Loading</div>;
          if (error) return <div>{error.message}</div>;

          return (
            <Card>
              <ResourceList // Defines your resource list component
                showHeader
                resourceName={{ singular: 'Product', plural: 'Products' }}
                items={data.nodes}
                renderItem={item => {
                  const media = (
                    <Thumbnail
                      source={
                        item.images.edges[0]
                          ? item.images.edges[0].node.originalSrc
                          : ''
                      }
                      alt={
                        item.images.edges[0]
                          ? item.images.edges[0].node.altText
                          : ''
                      }
                    />
                  );
                  const price = item.variants.edges[0].node.price;
                  return (
                    <ResourceList.Item
                      id={item.id}
                      media={media}
                      accessibilityLabel={`View details for ${item.title}`}
                      onClick={() => {
                        store.set('item', item);
                      }}
                    >
                      <Stack>
                        <Stack.Item fill>
                          <h3>
                            <TextStyle variation="strong">
                              {item.title}
                            </TextStyle>
                          </h3>
                        </Stack.Item>
                        <Stack.Item>
                          <p>${price}</p>
                        </Stack.Item>
                      </Stack>
                    </ResourceList.Item>
                    );
                  }}
                />
              </Card>
            );
          }}
        </Query>
      );
    }
  }
export default ResourceListWithProducts;

En el archivo pages/index.js, añade tus importaciones y define una constante para
el estado vacío de tu aplicación. Luego, actualiza el código que controla el
disposición de tu estado vacío, y especifica el uso de tu nueva lista de recursos
con productos:

import React from 'react';
import { Page, Layout, EmptyState} from "@shopify/polaris";
import { ResourcePicker, TitleBar } from '@shopify/app-bridge-react';
import store from 'store-js';
import ResourceListWithProducts from './components/ResourceList';
const img = 'https://cdn.shopify.com/s/files/1/0757/9955/files/empty-state.svg';
class Index extends React.Component {
  state = { open: false };
  render() {
    // A constant that defines your app's empty state
    const emptyState = !store.get('ids');
    return (
      <Page>
        <TitleBar
          primaryAction={{
            content: 'Select products',
            onAction: () => this.setState({ open: true }),
          }}
        />
        <ResourcePicker
          resourceType="Product"
          showVariants={false}
          open={this.state.open}
          onSelection={(resources) => this.handleSelection(resources)}
          onCancel={() => this.setState({ open: false })}
        />
        {emptyState ? ( // Controls the layout of your app's empty state
          <Layout>
            <EmptyState
              heading="Discount your products temporarily"
              action={{
                content: 'Select products',
                onAction: () => this.setState({ open: true }),
              }}
              image={img}
            >
              <p>Select products to change their price temporarily.</p>
            </EmptyState>
          </Layout>
        ) : (
          // Uses the new resource list that retrieves products by IDs
          <ResourceListWithProducts />
        )}
      </Page>
    );
  }
  handleSelection = (resources) => {
    const idsFromResources = resources.selection.map((product) => product.id);
    this.setState({ open: false });
    store.set('ids', idsFromResources);
  };
}
export default Index;

Ahora, al hacer clic en Seleccionar productos, y añadir productos desde el modal Añadir productos, se muestra una lista de productos.



Paso 14: Actualizar los precios de los productos

Has implementado una consulta GraphQL para leer los datos de los productos, y has añadido la funcionalidad para mostrar los productos recuperados en una lista de recursos. A continuación, utilizarás GraphQL para modificar los datos de los productos.

Configura una mutación de GraphQL llamada <código>ProductVariantUpdate</código> para actualizar los precios de los productos en tu app.

    1. Crea un nuevo archivo ApplyRandomPrices.js en tu carpeta de componentes.

.

    1. Añade importaciones a tu archivo ApplyRandomPrices.js y configura una mutación GraphQL que permita a tu app actualizar los precios de los productos:

.

páginas/componentes/ApplyRandomPrices.js

import React, { useState } from 'react';
import gql from 'graphql-tag';
import { Mutation } from 'react-apollo';
import { Layout, Button, Banner, Toast, Stack, Frame } from '@shopify/polaris';
import { Context } from '@shopify/app-bridge-react';
// GraphQL mutation that updates the prices of products
const UPDATE_PRICE = gql`
  mutation productVariantUpdate($input: ProductVariantInput!) {
    productVariantUpdate(input: $input) {
      product {
        title
      }
      productVariant {
        id
        price
      }
    }
  }
`;
  1. Después de tu mutación en ApplyRandomPrices.js, configura una clase llamada ApplyRandomPrices que toma la entrada de tu mutación y aplica un precio aleatorio al producto seleccionado:páginas/componentes/AplicarPreciosAleatorios.js
 
  class ApplyRandomPrices extends React.Component {
  static contextType = Context;

  render() {
    return ( // Uses mutation's input to update product prices
      <Mutation mutation={UPDATE_PRICE}>
        {(handleSubmit, {error, data}) => {
          const [hasResults, setHasResults] = useState(false);

          const showError = error && (
            <Banner status="critical">{error.message}</Banner>
          );

          const showToast = hasResults && (
            <Toast
              content="Successfully updated"
              onDismiss={() => setHasResults(false)}
            />
          );

          return (
            <Frame>
              {showToast}
              <Layout.Section>
                {showError}
              </Layout.Section>

              <Layout.Section>
                <Stack distribution={"center"}>
                  <Button
                    primary
                    textAlign={"center"}
                    onClick={() => {
                      let promise = new Promise((resolve) => resolve());
                      for (const variantId in this.props.selectedItems) {
                        const price = Math.random().toPrecision(3) * 10;
                        const productVariableInput = {
                          id: this.props.selectedItems[variantId].variants.edges[0].node.id,
                          price: price,
                        };

                        promise = promise.then(() => handleSubmit({ variables: { input: productVariableInput }}));
                      }

                      if (promise) {
                        promise.then(() => this.props.onUpdate().then(() => setHasResults(true)));
                    }}
                  }
                  >
                    Randomize prices
                  </Button>
                </Stack>
              </Layout.Section>
            </Frame>
          );
        }}
      </Mutation>
    );
  }
}
export default ApplyRandomPrices;
 
  1. Actualiza tu archivo pages/index.js para incluir las siguientes importaciones:
    import React from 'react';
    import gql from 'graphql-tag';
    import { Mutation } from 'react-apollo';
    import { Page, Layout, EmptyState, Button, Card } from "@shopify/polaris";
    import { ResourcePicker, TitleBar } from '@shopify/app-bridge-react';
    import store from 'store-js';
    import ResourceListWithProducts from './components/ResourceList';
  2. En ResourceList.js, añade la importación ApplyRandomPrices. Implementa un constructor en tu clase ResourceListWithProducts y actualiza tu consulta GraphQL para habilitar la obtención de productos por ID. Por último, actualice su componente ResourceList:páginas/componentes/ResourceList.js
    import React from 'react';
    import gql from 'graphql-tag';
    import { Query } from 'react-apollo';
    import {
    Card,
    ResourceList,
    Stack,
    TextStyle,
    Thumbnail,
    } from '@shopify/polaris';
    import store from 'store-js';
    import { Redirect } from '@shopify/app-bridge/actions';
    import { Context } from '@shopify/app-bridge-react';
    import ApplyRandomPrices from './ApplyRandomPrices';
    // GraphQL query that retrieves products by ID
    const GET_PRODUCTS_BY_ID = gql`
    query getProducts($ids: [ID!]!) {
    nodes(ids: $ids) {
      ... on Product {
        title
        handle
        descriptionHtml
        id
        images(first: 1) {
          edges {
            node {
              originalSrc
              altText
            }
          }
        }
        variants(first: 1) {
          edges {
            node {
              price
              id
            }
          }
        }
      }
    }
    }
    `;
    class ResourceListWithProducts extends React.Component {
    static contextType = Context;
    

// A constructor that defines selected items and nodes
constructor(props) {
super(props);
this.state = {
selectedItems: [],
selectedNodes: {},
};
}

render() {
const app = this.context;

// Returns products by ID
return (
    <Query query={GET_PRODUCTS_BY_ID} variables={{ ids: store.get('ids') }}>
      {({ data, loading, error, refetch }) => { // Refetches products by ID
        if (loading) return <div>Loading…</div>;
        if (error) return <div>{error.message}</div>;

        const nodesById = {};
        data.nodes.forEach(node => nodesById[node.id] = node);

        return (
          <>
            <Card>
              <ResourceList
                showHeader
                resourceName={{ singular: 'Product', plural: 'Products' }}
                items={data.nodes}
                selectable
                selectedItems={this.state.selectedItems}
                onSelectionChange={selectedItems => {
                  const selectedNodes = {};
                  selectedItems.forEach(item => selectedNodes[item] = nodesById[item]);

                  return this.setState({
                    selectedItems: selectedItems,
                    selectedNodes: selectedNodes,
                  });
                }}
                renderItem={item => {
                  const media = (
                    <Thumbnail
                      source={
                        item.images.edges[0]
                          ? item.images.edges[0].node.originalSrc
                          : ''
                      }
                      alt={
                        item.images.edges[0]
                          ? item.images.edges[0].node.altText
                          : ''
                      }
                    />
                  );
                  const price = item.variants.edges[0].node.price;
                  return (
                    <ResourceList.Item
                      id={item.id}
                      media={media}
                      accessibilityLabel={`View details for ${item.title}`}
                      verticalAlignment="center"
                      onClick={() => {
                        let index = this.state.selectedItems.indexOf(item.id);
                        const node = nodesById[item.id];
                        if (index === -1) {
                            this.state.selectedItems.push(item.id);
                            this.state.selectedNodes[item.id] = node;
                        } else {
                          this.state.selectedItems.splice(index, 1);
                            delete this.state.selectedNodes[item.id];
                        }

                        this.setState({
                          selectedItems: this.state.selectedItems,
                          selectedNodes: this.state.selectedNodes,
                          });
                      }}
                    >
                      <Stack alignment="center">
                        <Stack.Item fill>
                          <h3>
                            <TextStyle variation="strong">
                              {item.title}
                            </TextStyle>
                          </h3>
                        </Stack.Item>
                        <Stack.Item>
                          <p>${price}</p>
                        </Stack.Item>
                      </Stack>
                    </ResourceList.Item>
                  );
                }}
              />
            </Card>

          <ApplyRandomPrices selectedItems={this.state.selectedNodes} onUpdate={refetch} />
        </>
      );
    }}
  </Query>
);
 

exportar por defecto ResourceListWithProducts;



En tu app, ahora puedes actualizar los precios de los productos.

![GIF mostrando cómo rellenar los datos en una tienda de desarrollo](https://shopify.dev/assets/apps/randomize-prices-a8c49c220e447a3b5ac233f582eddd2a9bc81050c32c601b5de6ae99001e8ae8.gif)


## Próximos pasos[](https://shopify.dev/apps/getting-started/add-functionality#next-steps)

- Utiliza [webhooks](https://shopify.dev/apps/webhooks) para estar sincronizado con Shopify o ejecutar código después de que ocurra un evento específico en una tienda.
- Identifica tu [modelo de negocio de la app](https://shopify.dev/apps/billing/models) y aprende a utilizar la [API de facturación](https://shopify.dev/apps/billing) para facturar a los clientes con cargos mensuales recurrentes o compras únicas.
- Aprende a utilizar las [extensiones de la aplicación](https://shopify.dev/apps/app-extensions) para añadir funciones al administrador de Shopify o al TPV.
- Explora las referencias [GraphQL Admin API](https://shopify.dev/api/admin/graphql/reference) y [REST Admin API](https://shopify.dev/api/admin/rest/reference).
Categorías : Sin categoría

Deja una respuesta

Tu dirección de correo electrónico no será publicada.