diff --git a/README.md b/README.md index 96de996..17c8c2a 100644 --- a/README.md +++ b/README.md @@ -34,18 +34,30 @@ npm install shopify-app-koa Then, you can import the package in your app by creating an `index.js` file containing: ```javascript -const express = require('express'); -const {shopifyApp} = require('@shopify/shopify-app-express'); - -const PORT = 8080; +const Koa = require('koa'); +const Router = require('@koa/router'); +const { bodyParser } = require('@koa/bodyparser'); +const { shopifyApp } = require('@ingenierias-lentas/shopify-app-koa'); // Assuming you are using your own package version +const { DeliveryMethod } = require('@shopify/shopify-api'); +const { SHOPIFY_HOST } = require('@shopify/shopify-api/test-helpers'); + +require('dotenv').config(); + +const { + SHOPIFY_API_KEY, + SHOPIFY_API_SECRET, + SHOPIFY_HOST_SCHEME, + SHOPIFY_HOST_NAME, +} = process.env; const shopify = shopifyApp({ api: { - apiKey: 'ApiKeyFromPartnersDashboard', - apiSecretKey: 'ApiSecretKeyFromPartnersDashboard', - scopes: ['your_scopes'], - hostScheme: 'http', - hostName: `localhost:${PORT}`, + apiKey: SHOPIFY_API_KEY, + apiSecretKey: SHOPIFY_API_SECRET, + scopes: [''], + hostScheme: SHOPIFY_HOST_SCHEME, + hostName: SHOPIFY_HOST_NAME, + isEmbeddedApp: false, }, auth: { path: '/api/auth', @@ -56,24 +68,79 @@ const shopify = shopifyApp({ }, }); -const app = express(); - -app.get(shopify.config.auth.path, shopify.auth.begin()); -app.get( +function handleWebhookRequest( + topic, + shop, + webhookRequestBody, + webhookId, + apiVersion, + context +) { + const sessionId = shopify.session.getOfflineId(shop); + console.log(`Webhook received for shop ${shop} with session ID ${sessionId}`); + console.log(`Request: ${JSON.stringify(context.request)}`); + + // Run your webhook-processing code here! +} +const webhookHandlers = { + CUSTOMERS_DATA_REQUEST: [ + { + deliveryMethod: DeliveryMethod.Http, + callback: handleWebhookRequest, + callbackUrl: '/api/webhooks', + } + ], + CUSTOMERS_REDACT: [ + { + deliveryMethod: DeliveryMethod.Http, + callback: handleWebhookRequest, + callbackUrl: '/api/webhooks', + } + ], + SHOP_REDACT: [ + { + deliveryMethod: DeliveryMethod.Http, + callback: handleWebhookRequest, + callbackUrl: '/api/webhooks', + } + ], +}; + +const app = new Koa(); +const router = new Router(); + +// Add body parser for handling POST requests +app.use(bodyParser({ + enableTypes: ['json', 'text'], // Enable both JSON and text parsing + encoding: 'utf-8', + extendTypes: { + text: ['text/plain'], // Only treat text/plain as text + }, +})); + +// Shopify Auth Routes +router.get(shopify.config.auth.path, shopify.auth.begin()); +router.get( shopify.config.auth.callbackPath, shopify.auth.callback(), shopify.redirectToShopifyOrAppRoot(), ); -app.post( + +// Shopify Webhook handling route +router.post( shopify.config.webhooks.path, - shopify.processWebhooks({webhookHandlers}), + ...shopify.processWebhooks({ webhookHandlers }) ); -app.get('/', shopify.ensureInstalledOnShop(), (req, res) => { - res.send('Hello world!'); +// Root route with Shopify installation check +router.get('/', shopify.validateAuthenticatedSession(), async (ctx) => { + ctx.body = 'Hello world!'; }); -app.listen(PORT, () => console.log('Server started')); +// Apply routes and middleware +app.use(router.routes()).use(router.allowedMethods()); + +app.listen(PORT, () => console.log(`Server started on ${SHOPIFY_HOST_SCHEME}://${SHOPIFY_HOST_NAME}`)); ``` Once you set the appropriate configuration values, you can then run your Express app as usual, for instance using: @@ -90,4 +157,4 @@ To load your app within the Shopify Admin app, you need to: ## Next steps -Now that your app is up and running, you can learn more about the `shopifyApp` object in [the reference docs](./docs/reference/shopifyApp.md). +Now that your app is up and running, you can learn more about the `shopifyApp` object in [the reference docs](https://github.com/Shopify/shopify-app-js/tree/main/packages/apps/shopify-api/docs/reference). diff --git a/examples/simple-app/index.js b/examples/simple-app/index.js index 8bb45c0..9a379c8 100644 --- a/examples/simple-app/index.js +++ b/examples/simple-app/index.js @@ -3,16 +3,25 @@ const Router = require('@koa/router'); const { bodyParser } = require('@koa/bodyparser'); const { shopifyApp } = require('@ingenierias-lentas/shopify-app-koa'); // Assuming you are using your own package version const { DeliveryMethod } = require('@shopify/shopify-api'); +const { SHOPIFY_HOST } = require('@shopify/shopify-api/test-helpers'); -const PORT = 8080; +require('dotenv').config(); + +const { + SHOPIFY_API_KEY, + SHOPIFY_API_SECRET, + SHOPIFY_HOST_SCHEME, + SHOPIFY_HOST_NAME, +} = process.env; const shopify = shopifyApp({ api: { - apiKey: 'ApiKeyFromPartnersDashboard', - apiSecretKey: 'ApiSecretKeyFromPartnersDashboard', - scopes: ['your_scopes'], - hostScheme: 'http', - hostName: `localhost:${PORT}`, + apiKey: SHOPIFY_API_KEY, + apiSecretKey: SHOPIFY_API_SECRET, + scopes: [''], + hostScheme: SHOPIFY_HOST_SCHEME, + hostName: SHOPIFY_HOST_NAME, + isEmbeddedApp: false, }, auth: { path: '/api/auth', @@ -32,16 +41,32 @@ function handleWebhookRequest( context ) { const sessionId = shopify.session.getOfflineId(shop); + console.log(`Webhook received for shop ${shop} with session ID ${sessionId}`); + console.log(`Request: ${JSON.stringify(context.request)}`); // Run your webhook-processing code here! } const webhookHandlers = { - TEST_TOPIC: [ + CUSTOMERS_DATA_REQUEST: [ { deliveryMethod: DeliveryMethod.Http, + callback: handleWebhookRequest, callbackUrl: '/api/webhooks', + } + ], + CUSTOMERS_REDACT: [ + { + deliveryMethod: DeliveryMethod.Http, callback: handleWebhookRequest, - }, + callbackUrl: '/api/webhooks', + } + ], + SHOP_REDACT: [ + { + deliveryMethod: DeliveryMethod.Http, + callback: handleWebhookRequest, + callbackUrl: '/api/webhooks', + } ], }; @@ -72,11 +97,11 @@ router.post( ); // Root route with Shopify installation check -router.get('/', shopify.ensureInstalledOnShop(), async (ctx) => { +router.get('/', shopify.validateAuthenticatedSession(), async (ctx) => { ctx.body = 'Hello world!'; }); // Apply routes and middleware app.use(router.routes()).use(router.allowedMethods()); -app.listen(PORT, () => console.log(`Server started on http://localhost:${PORT}`)); +app.listen(PORT, () => console.log(`Server started on ${SHOPIFY_HOST_SCHEME}://${SHOPIFY_HOST_NAME}`)); diff --git a/examples/simple-app/package.json b/examples/simple-app/package.json index c8d7d2c..2d616ea 100644 --- a/examples/simple-app/package.json +++ b/examples/simple-app/package.json @@ -4,7 +4,8 @@ "private": true, "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "dev": "node index.js" }, "keywords": [], "author": "", @@ -14,6 +15,7 @@ "@ingenierias-lentas/shopify-app-koa": "^0.1.0", "@koa/bodyparser": "^5.1.1", "@koa/router": "^13.1.0", + "dotenv": "^16.4.5", "koa": "^2.15.3" }, "devDependencies": { diff --git a/package-lock.json b/package-lock.json index e04dbec..6529251 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@ingenierias-lentas/shopify-app-koa", - "version": "0.1.0", + "version": "0.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@ingenierias-lentas/shopify-app-koa", - "version": "0.1.0", + "version": "0.1.1", "license": "MIT", "workspaces": [ "./", @@ -64,6 +64,7 @@ "@ingenierias-lentas/shopify-app-koa": "^0.1.0", "@koa/bodyparser": "^5.1.1", "@koa/router": "^13.1.0", + "dotenv": "^16.4.5", "koa": "^2.15.3" }, "devDependencies": { @@ -4240,6 +4241,18 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",