import Router from 'koa-router' import fetch from 'node-fetch' import { getRepository } from 'typeorm' import { config } from '@things-factory/env' import { User, VerificationToken, VerificationTokenType } from '@things-factory/auth-base' import { MarketplaceStore } from '../entities' import { StoreAPI } from '../controllers/store-api' import { STORE_STATUS } from '../graphql/constants' const shopifyConfig = config.get('marketplaceIntegrationShopify', {}) const { apiKey, apiSecret } = shopifyConfig const debug = require('debug')('things-factory:marketplace-integration:shopify-router') export const shopifyRouter = new Router() shopifyRouter.get('/callback-shopify', async (context, next) => { try { // https://example.org/some/redirect/uri?code={authorization_code}&hmac=da9d83c171400a41f8db91a950508985×tamp=1409617544&state={nonce}&shop={hostname} const { code, hmac, timestamp, state: nonce, shop: hostname } = context.query const verificationTokenRepository = getRepository(VerificationToken) var verification: VerificationToken = await verificationTokenRepository.findOne({ where: { token: nonce, type: VerificationTokenType.REQUEST_ACCESS_TOKEN } }) const { userId, suppliment: marketplaceStoreId } = verification await verificationTokenRepository.delete({ userId, token: nonce, type: VerificationTokenType.REQUEST_ACCESS_TOKEN }) var store = await StoreAPI.getMarketplaceStore(marketplaceStoreId) const storeId = store.storeId const response = await fetch(`https://${storeId}.myshopify.com/admin/oauth/access_token`, { method: 'post', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ client_id: apiKey, client_secret: apiSecret, code }) }) if(response.ok) { var body = await response.json() var { access_token } = body if (!access_token) { const message = `failed to get access-token from shopify : ${JSON.stringify(body, null, 2)}` debug(message) throw new Error(message) } } else { const message = `failed to get access-token from shopify : ${response.status}, ${await response.text()}` debug(message) throw new Error(message) } var patch = { accessToken: access_token, refreshToken: '', accessInfo: JSON.stringify(body, null, 2), storeId: storeId, status: STORE_STATUS.ACTIVE } var user = await getRepository(User).findOne(userId) store = await getRepository(MarketplaceStore).save({ ...store, ...patch, updater: user }) var message = 'success to activate' context.redirect( `/domain/${store.domain.subdomain}/marketplace-store-shopify/${store.id}/connect-callback?status=${store.status}&message=${message}` ) } catch(err) { var message: string = err.message if(store) { context.redirect( `/domain/${store.domain.subdomain}/marketplace-store-shopify/${store.id}/connect-callback?status=${store.status}&message=${message}` ) return } throw err } }) shopifyRouter.post('/webhook-shopify/customers/redact', async (context, next) => { // When a store owner requests deletion of data on behalf of a customer, // Shopify sends a payload on the customers/redact topic to the apps installed on that store. // If the customer hasn't placed an order in the past six months, // then Shopify sends the payload 10 days after their request. // Otherwise, the the request will be withheld until 6 months have passed. // If your app has been granted access to the store's customers or orders, // then you receive a redaction request webhook with the resource IDs that you need to redact or delete. // In some cases, a customer record contains only the customer's email address. // // https://shopify.dev/tutorials/add-gdpr-webhooks-to-your-app // { // "shop_id": 954889, // "shop_domain": "snowdevil.myshopify.com", // "customer": { // "id": 191167, // "email": "john@email.com", // "phone": "555-625-1199" // }, // "orders_to_redact": [299938, 280263, 220458] // } context.status = 200 }) shopifyRouter.post('/webhook-shopify/shop/redact', async (context, next) => { // 48 hours after a store owner uninstalls your app, // Shopify sends you a shop/redact webhook. // This webhook provides the store's shop_id and shop_domain so that you can erase the customer information // for that store from your database. // // https://shopify.dev/tutorials/add-gdpr-webhooks-to-your-app // { // "shop_id": 954889, // "shop_domain": "snowdevil.myshopify.com" // } context.status = 200 }) shopifyRouter.post('/webhook-shopify/customers/data_request', async (context, next) => { // When a customer requests their data from a store owner, // Shopify sends a payload on the customers/data_request topic to the apps installed on that store. // If your app has been granted access to customers or orders, // then you receive a data request webhook with the resource IDs of the data that you need to provide to the store owner. // It's your responsibility to provide this data to the store owner directly. // In some cases, a customer record contains only the customer's email address. // // https://shopify.dev/tutorials/add-gdpr-webhooks-to-your-app // { // "shop_id": 954889, // "shop_domain": "snowdevil.myshopify.com", // "orders_requested": [299938, 280263, 220458], // "customer": { // "id": 191167, // "email": "john@email.com", // "phone": "555-625-1199" // }, // "data_request": { // "id": 9999 // } // } context.status = 200 })