├── .commitlintrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.back.js ├── .eslintrc.front.js ├── .eslintrc.js ├── .gitattributes ├── .github └── workflows │ └── npm-publish.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .prettierignore ├── .prettierrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── admin ├── api │ ├── plans.js │ └── settings.js ├── components │ ├── Initializer │ │ └── index.js │ ├── Modal │ │ ├── index.js │ │ └── modal.min.css │ ├── PlanCard │ │ ├── index.js │ │ └── stylePlanCard.min.css │ └── PluginIcon │ │ └── index.js ├── index.js ├── pages │ ├── App │ │ ├── app.min.css │ │ └── index.js │ └── Settings │ │ └── index.js ├── pluginId.js ├── translations │ ├── en.json │ └── fr.json └── utils │ ├── axiosInstance.js │ └── getTrad.js ├── assets └── screenshot-create-shopify-app.jpg ├── package-lock.json ├── package.json ├── server ├── bootstrap │ ├── actions.js │ └── index.js ├── config │ └── index.js ├── content-types │ ├── Billing │ │ ├── Plan │ │ │ ├── index.js │ │ │ ├── lifecycle.js │ │ │ └── schema.json │ │ ├── Subscription │ │ │ ├── index.js │ │ │ ├── lifecycle.js │ │ │ └── schema.json │ │ ├── UsageRecord │ │ │ ├── index.js │ │ │ ├── lifecycle.js │ │ │ └── schema.json │ │ └── index.js │ ├── Session │ │ ├── index.js │ │ ├── lifecycle.js │ │ └── schema.json │ ├── Shop │ │ ├── index.js │ │ ├── lifecycle.js │ │ └── schema.json │ └── index.js ├── controllers │ ├── auth.js │ ├── billing │ │ ├── index.js │ │ ├── plan.js │ │ └── subscription.js │ ├── index.js │ ├── install.js │ ├── settings.js │ ├── shop.js │ └── shopify.js ├── index.js ├── policies │ ├── index.js │ ├── is-authenticated.js │ ├── valid-body-hmac.js │ ├── valid-entry-point.js │ ├── valid-header-hmac.js │ └── valid-query-hmac.js ├── register.js ├── routes │ ├── auth.js │ ├── billing │ │ ├── index.js │ │ ├── plan.js │ │ └── subscription.js │ ├── index.js │ ├── install.js │ ├── settings.js │ ├── shop.js │ └── shopify.js ├── services │ ├── billing │ │ ├── graphql │ │ │ ├── index.js │ │ │ ├── mutations │ │ │ │ ├── appSubscriptionCreate.js │ │ │ │ ├── appUsageRecordCreate.js │ │ │ │ └── index.js │ │ │ └── queries │ │ │ │ ├── appSubscriptionFind.js │ │ │ │ ├── appSubscriptionUsageRecords.js │ │ │ │ ├── appUsageRecordFind.js │ │ │ │ └── index.js │ │ ├── index.js │ │ ├── initialize.js │ │ ├── plan.js │ │ ├── subscription.js │ │ ├── usage-record.js │ │ ├── utils.js │ │ └── webhooks.js │ ├── index.js │ ├── lifecycles.js │ ├── session.js │ ├── shop.js │ ├── shopify.js │ ├── utils.js │ └── webhooks.js ├── strategies │ └── shopify-auth.js └── validation │ ├── config.js │ └── index.js ├── strapi-admin.js └── strapi-server.js /.commitlintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@commitlint/config-conventional" 4 | ] 5 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = false 6 | indent_style = space 7 | indent_size = 2 8 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.eslintrc.back.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": [ 3 | "eslint:recommended", 4 | "prettier", 5 | "plugin:import/errors", 6 | "plugin:import/warnings", 7 | "plugin:node/recommended" 8 | ], 9 | "plugins": ["prettier"], 10 | "env": { 11 | "es6": true, 12 | "node": true, 13 | "jest": true, 14 | "browser": false 15 | }, 16 | "globals": { 17 | "strapi": false 18 | }, 19 | "rules": { 20 | "prettier/prettier": "error", 21 | "indent": ["error", 2, { "SwitchCase": 1 }], 22 | "linebreak-style": ["error", "unix"], 23 | "no-console": "error", 24 | "quotes": ["error", "single", { "avoidEscape": true }], 25 | "semi": ["error", "always"], 26 | "strict": ["error", "global"], 27 | "no-unused-vars": ["warn", { "ignoreRestSiblings": true }], 28 | "no-return-await": "error", 29 | "import/order": "error", 30 | "import/no-cycle": "error", 31 | "import/no-useless-path-segments": "error", 32 | "import/first": "error", 33 | "import/extensions": ["error", "never"], 34 | "import/newline-after-import": "error", 35 | "import/no-extraneous-dependencies": "off", 36 | "node/exports-style": ["error", "module.exports"], 37 | "node/no-new-require": "error", 38 | "node/no-path-concat": "error", 39 | "node/no-callback-literal": "error", 40 | "node/handle-callback-err": "error", 41 | "node/no-extraneous-require": "off", 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.eslintrc.front.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "parser": "@babel/eslint-parser", 3 | "extends": [ 4 | "eslint:recommended", 5 | "prettier", 6 | "plugin:import/errors", 7 | "plugin:import/warnings", 8 | "plugin:react/recommended" 9 | ], 10 | "plugins": ["react", "import", "prettier"], 11 | "env": { 12 | "browser": true, 13 | "commonjs": true, 14 | "es6": true, 15 | "jest": true 16 | }, 17 | "parserOptions": { 18 | "requireConfigFile": false, 19 | "sourceType": "module", 20 | "babelOptions": { 21 | "presets": ["@babel/preset-react"] 22 | } 23 | }, 24 | "settings": { 25 | "react": { 26 | "version": "detect" 27 | } 28 | }, 29 | "globals": { 30 | "process": true 31 | }, 32 | "rules": { 33 | "prettier/prettier": "error", 34 | "indent": ["error", 2, { "SwitchCase": 1 }], 35 | "linebreak-style": ["error", "unix"], 36 | "no-console": "error", 37 | "quotes": ["error", "single", { "avoidEscape": true }], 38 | "semi": ["error", "always"], 39 | "no-unused-vars": ["warn", { "ignoreRestSiblings": true }], 40 | "no-return-await": "error", 41 | "import/order": "error", 42 | "import/no-cycle": "error", 43 | "import/no-useless-path-segments": "error", 44 | "import/first": "error", 45 | "import/extensions": ["error", "never", { "json": "always" }], 46 | "import/newline-after-import": "error", 47 | "import/no-extraneous-dependencies": "off" 48 | } 49 | } -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "parserOptions": { 3 | "ecmaVersion": 2018, 4 | }, 5 | "overrides": [ 6 | { 7 | "files": ["server/**/*.js"], 8 | ...require("./.eslintrc.back.js"), 9 | }, 10 | { 11 | "files": ["admin/**/*.js"], 12 | ...require("./.eslintrc.front.js"), 13 | }, 14 | ], 15 | }; -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # From https://github.com/Danimoth/gitattributes/blob/master/Web.gitattributes 2 | 3 | # Handle line endings automatically for files detected as text 4 | # and leave all files detected as binary untouched. 5 | * text=auto 6 | 7 | # 8 | # The above will handle all files NOT found below 9 | # 10 | 11 | # 12 | ## These files are text and should be normalized (Convert crlf => lf) 13 | # 14 | 15 | # source code 16 | *.php text 17 | *.css text 18 | *.sass text 19 | *.scss text 20 | *.less text 21 | *.styl text 22 | *.js text eol=lf 23 | *.coffee text 24 | *.json text 25 | *.htm text 26 | *.html text 27 | *.xml text 28 | *.svg text 29 | *.txt text 30 | *.ini text 31 | *.inc text 32 | *.pl text 33 | *.rb text 34 | *.py text 35 | *.scm text 36 | *.sql text 37 | *.sh text 38 | *.bat text 39 | 40 | # templates 41 | *.ejs text 42 | *.hbt text 43 | *.jade text 44 | *.haml text 45 | *.hbs text 46 | *.dot text 47 | *.tmpl text 48 | *.phtml text 49 | 50 | # git config 51 | .gitattributes text 52 | .gitignore text 53 | .gitconfig text 54 | 55 | # code analysis config 56 | .jshintrc text 57 | .jscsrc text 58 | .jshintignore text 59 | .csslintrc text 60 | 61 | # misc config 62 | *.yaml text 63 | *.yml text 64 | .editorconfig text 65 | 66 | # build config 67 | *.npmignore text 68 | *.bowerrc text 69 | 70 | # Heroku 71 | Procfile text 72 | .slugignore text 73 | 74 | # Documentation 75 | *.md text 76 | LICENSE text 77 | AUTHORS text 78 | 79 | 80 | # 81 | ## These files are binary and should be left untouched 82 | # 83 | 84 | # (binary is a macro for -text -diff) 85 | *.png binary 86 | *.jpg binary 87 | *.jpeg binary 88 | *.gif binary 89 | *.ico binary 90 | *.mov binary 91 | *.mp4 binary 92 | *.mp3 binary 93 | *.flv binary 94 | *.fla binary 95 | *.swf binary 96 | *.gz binary 97 | *.zip binary 98 | *.7z binary 99 | *.ttf binary 100 | *.eot binary 101 | *.woff binary 102 | *.pyc binary 103 | *.pdf binary 104 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | name: publish-npm-package 2 | on: 3 | release: 4 | types: [created] 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | permissions: 9 | contents: read 10 | packages: write 11 | steps: 12 | - uses: actions/checkout@v3 13 | - uses: actions/setup-node@v3 14 | with: 15 | node-version: '16.x' 16 | registry-url: 'https://registry.npmjs.org' 17 | - run: npm ci 18 | - run: npm publish 19 | env: 20 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Don't check auto-generated stuff into git 2 | coverage 3 | node_modules 4 | stats.json 5 | 6 | # Cruft 7 | .DS_Store 8 | npm-debug.log 9 | .idea 10 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run commit-msg -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run pre-commit -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .eslintrc.back.js 3 | .eslintrc.front.js 4 | .eslintrc.js 5 | README.md 6 | package-lock.json -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 120 7 | } 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ## [0.3.0](https://github.com/shop3/strapi-plugin-shopify/compare/v0.2.1...v0.3.0) (2023-03-15) 6 | 7 | 8 | ### ⚠ BREAKING CHANGES 9 | 10 | * added shopify_id to shop 11 | 12 | ### Features 13 | 14 | * added plan admin routes permissions ([ca194f6](https://github.com/shop3/strapi-plugin-shopify/commit/ca194f64b5d279ffe526d6a8a7044bd3a52be9ed)) 15 | * added plan API for admin panel ([3886177](https://github.com/shop3/strapi-plugin-shopify/commit/3886177ba6f8af2dc7d763a9753c7a3fc3c82b07)) 16 | * added shopify_id to shop ([fb6293d](https://github.com/shop3/strapi-plugin-shopify/commit/fb6293d2919ad245c459eebdc8a67677a2606537)) 17 | * Admin panel Plan UI ([587169a](https://github.com/shop3/strapi-plugin-shopify/commit/587169ac95b44b5a8d04af2f22fddb180bddbad4)) 18 | * error handling for install and auth callbacks ([4655053](https://github.com/shop3/strapi-plugin-shopify/commit/4655053edc49c648c97b63d294a780d2f9799bb9)) 19 | * refactored admin panel plan with native design components ([5e6df58](https://github.com/shop3/strapi-plugin-shopify/commit/5e6df58c54fe96323b1c0e769f6bdd60776716bf)) 20 | * shop redact endpoint ([3974544](https://github.com/shop3/strapi-plugin-shopify/commit/39745442e3980c04ddbcd7730c45e9078170bea7)) 21 | * shopify_id in subscription and usage record ([57da423](https://github.com/shop3/strapi-plugin-shopify/commit/57da423b32ee8c33bf8688991fbc13cf2677f109)) 22 | 23 | ### [0.2.1](https://github.com/shop3/strapi-plugin-shopify/compare/v0.2.0...v0.2.1) (2023-01-04) 24 | 25 | 26 | ### Bug Fixes 27 | 28 | * shop update works with big integers ([d49d40c](https://github.com/shop3/strapi-plugin-shopify/commit/d49d40cd857e5c421c91d5d381655bb572806cc4)) 29 | 30 | ## [0.2.0](https://github.com/shop3/strapi-plugin-shopify/compare/v0.1.3...v0.2.0) (2022-12-11) 31 | 32 | 33 | ### ⚠ BREAKING CHANGES 34 | 35 | * set api version by config or use latest release 36 | 37 | ### Features 38 | 39 | * set api version by config or use latest release ([f2bb131](https://github.com/shop3/strapi-plugin-shopify/commit/f2bb13189f032f8a1396561fb4a2e851e496905e)) 40 | 41 | ### [0.1.3](https://github.com/shop3/strapi-plugin-shopify/compare/v0.1.2...v0.1.3) (2022-12-11) 42 | 43 | 44 | ### Features 45 | 46 | * added subscribe lifecycles ([41641ab](https://github.com/shop3/strapi-plugin-shopify/commit/41641abaf4f0f2f161d59144daf896d83099a9c9)) 47 | 48 | ### [0.1.2](https://github.com/shop3/strapi-plugin-shopify/compare/v0.1.1...v0.1.2) (2022-11-18) 49 | 50 | 51 | ### Bug Fixes 52 | 53 | * fixed find subscription by shop ([8f758cd](https://github.com/shop3/strapi-plugin-shopify/commit/8f758cd08bcb806c03ec0f2912376bca11f2a569)) 54 | 55 | ### [0.1.1](https://github.com/shop3/strapi-plugin-shopify/compare/v0.1.0...v0.1.1) (2022-11-07) 56 | 57 | 58 | ### Features 59 | 60 | * added plan routes and controller ([b7f98b6](https://github.com/shop3/strapi-plugin-shopify/commit/b7f98b60db03ce0537d7ac3a517ba7a9057f1470)) 61 | * handle redirect on the entrypoint ([9c73e25](https://github.com/shop3/strapi-plugin-shopify/commit/9c73e2513f82fdb1e089878ac20230295c7a720c)) 62 | 63 | 64 | ### Bug Fixes 65 | 66 | * fixed plan not found ([e288ace](https://github.com/shop3/strapi-plugin-shopify/commit/e288ace5c7d1a529583b944d27dab3e7c508955c)) 67 | 68 | ## [0.1.0](https://github.com/shop3/strapi-plugin-shopify/compare/v0.0.6...v0.1.0) (2022-11-03) 69 | 70 | 71 | ### ⚠ BREAKING CHANGES 72 | 73 | * added shop and session to ctx.state.shopify to reduce database calls 74 | 75 | ### Features 76 | 77 | * added shop and session to ctx.state.shopify to reduce database calls ([e0a5e6a](https://github.com/shop3/strapi-plugin-shopify/commit/e0a5e6a43f46febaf69f5ea31573c05574bdd586)) 78 | * cancel subscription after shop is uninstalled ([8d9e450](https://github.com/shop3/strapi-plugin-shopify/commit/8d9e4509ddfa039fa0ebe7e4a9238aa650b909f0)) 79 | 80 | ### [0.0.6](https://github.com/shop3/strapi-plugin-shopify/compare/v0.0.5...v0.0.6) (2022-11-02) 81 | 82 | 83 | ### Features 84 | 85 | * added usage record price on db ([0b7f582](https://github.com/shop3/strapi-plugin-shopify/commit/0b7f5824481e2ef6937ae62de4ef9da43b912b43)) 86 | 87 | ### [0.0.5](https://github.com/shop3/strapi-plugin-shopify/compare/v0.0.4...v0.0.5) (2022-11-01) 88 | 89 | 90 | ### Features 91 | 92 | * added shopify lifecycles ([3198df3](https://github.com/shop3/strapi-plugin-shopify/commit/3198df37ca2c218dba8bc780eedf18ad9936537c)) 93 | * added valid-header-hmac policy ([1ab02a4](https://github.com/shop3/strapi-plugin-shopify/commit/1ab02a43b4b80e8056b552134686877b06283376)) 94 | * initial version of billing feature ([d077154](https://github.com/shop3/strapi-plugin-shopify/commit/d07715408a495d2c5263d65d6ef97109caf8fbcf)) 95 | * return shopify-api from shopify service ([abe20e0](https://github.com/shop3/strapi-plugin-shopify/commit/abe20e0088c0ddd3f2eab1bb04adb516a3b64108)) 96 | 97 | ### [0.0.4](https://github.com/shop3/strapi-plugin-shopify/compare/v0.0.3...v0.0.4) (2022-07-06) 98 | 99 | ### [0.0.3](https://github.com/shop3/strapi-plugin-shopify/compare/v0.0.2...v0.0.3) (2022-06-27) 100 | 101 | 102 | ### Bug Fixes 103 | 104 | * **release:** added missing files in npm package ([3e19737](https://github.com/shop3/strapi-plugin-shopify/commit/3e197370cd515c9724d54ab54cea505818064e09)) 105 | 106 | ### [0.0.2](https://github.com/shop3/strapi-plugin-shopify/compare/v0.0.1...v0.0.2) (2022-06-21) 107 | 108 | 109 | ### Features 110 | 111 | * added current user endpoint ([af76cf6](https://github.com/shop3/strapi-plugin-shopify/commit/af76cf61d39f6fc3939f433a7d1eabdbc58e21fa)) 112 | * added logout endpoint ([af5b752](https://github.com/shop3/strapi-plugin-shopify/commit/af5b75272901c164a6a0f236f55250ccd8e5e1b0)) 113 | * **settings:** created admin settings page and api endpoint ([8b26e27](https://github.com/shop3/strapi-plugin-shopify/commit/8b26e27ad131fc8fe427cf7c4e940de161e91fd8)) 114 | 115 | ### 0.0.1 (2022-05-27) 116 | 117 | 118 | ### Features 119 | 120 | * initial commit of strapi-plugin-shopify ([2e4715d](https://github.com/shop3/strapi-plugin-shopify/commit/2e4715d2670fdf1c394adfe2bf1928c90f7a04e6)) 121 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Giacomo Minighin 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Strapi Plugin Shopify 2 | 3 | Build a Shopify application with Strapi. 4 | 5 | ## Table Of Content 6 | 7 | - [Requirements](#requirements) 8 | - [Installation](#installation) 9 | - [Middlewares Configuration](#middlewares-configuration) 10 | - [Shopify Configuration](#shopify-configuration) 11 | - [Environment Variables](#environment-variables) 12 | - [Endpoints](#endpoints) 13 | 14 | ## Requirements 15 | 16 | Strapi v4 is required. 17 | 18 | ## Installation 19 | 20 | ```bash 21 | npm install --save strapi-plugin-shopify 22 | ``` 23 | 24 | ## Middlewares configuration 25 | 26 | Webhooks are authenticated with **HMAC** calculated on the raw body, `strapi::body` middleware should be configured to pass the unparsed body as following: 27 | 28 | ```js 29 | { 30 | name: 'strapi::body', 31 | config: { 32 | includeUnparsed: true, 33 | }, 34 | }, 35 | ``` 36 | 37 | If you want to serve an embedded app directly from Strapi you will find that default **CSP policies** will not allow to do that, `strapi::security` middleware should be configured as following *(this configuration should be used only if you have problem with the embedded app iframe)*: 38 | 39 | ```js 40 | { 41 | name: 'strapi::security', 42 | config: { 43 | contentSecurityPolicy: { 44 | useDefaults: true, 45 | directives: { 46 | 'frame-ancestors': null, 47 | }, 48 | }, 49 | frameguard: false, 50 | }, 51 | }, 52 | ``` 53 | 54 | ## Shopify Configuration 55 | 56 | The Shopify application should be configured as follow: 57 | - App URL should be set as `https://your-domain.com/api/shopify` 58 | - Allowed redirection URL(s) should have both 59 | - `https://your-domain.com/api/shopify/install/callback` 60 | - `https://your-domain.com/api/shopify/auth/callback` 61 | 62 | ![Screenshot illustrating how to configure the Shopify application](https://github.com/shop3/strapi-plugin-shopify/blob/main/assets/screenshot-create-shopify-app.jpg) 63 | 64 | ## Environment Variables 65 | 66 | This plugin needs the following environment variables to work: 67 | 68 | | Variable | Example | Description | 69 | | -------- | ------- | ----------- | 70 | | HOST_NAME | `shop3.app` | the host name of your app without the protocol (http or https) | 71 | | SHOPIFY_API_KEY | `553536bf79ee112525f63aaf25df59f8` | the API key generated by Shopify | 72 | | SHOPIFY_API_SECRET | `687b73300b570bdbe53220d84a18e23d` | the API secret generated by Shopify | 73 | | SHOPIFY_SCOPES | `read_locales,read_products` | the API scopes used by the application | 74 | | SHOPIFY_APP_EMBEDDED | `true` | whether the app is an embedded app or not | 75 | | SHOPIFY_REDIRECT_URL | `https://shop3.app/home` | the url where the user is redirect after authentication | 76 | 77 | ## Endpoints 78 | 79 | This are the endpoints exposed by this plugin: 80 | 81 | | Method | Path | Description | 82 | | ------ | ---- | ----------- | 83 | | GET | /api/shopify | the entry point of the application, it handles installation and authentication | 84 | | POST | /api/shopify/webhooks | the default webhooks endpoint called by Shopify | 85 | | GET | /api/shopify/install | the installation endpoint, should not be called directly, use /api/shopify instead | 86 | | GET | /api/shopify/install/callback | the installation callback endpoint, should be called only by Shopify | 87 | | GET | /api/shopify/auth | the authentication endpoint, should not be called directly, use /api/shopify instead | 88 | | GET | /api/shopify/auth/callback | the authentication callback endpoint, should be called only by Shopify | 89 | | POST | /api/shopify/auth/logout | the logout endpoint, should be called to delete the Shopify session | 90 | | GET | /api/shopify/shop | this endpoint should be called to get the authenticated shop data | 91 | | GET | /api/shopify/plans | this endpoint should be called to get available subscription plans | 92 | | GET | /api/shopify/subscription | this endpoint should be called to get the shop subscription | 93 | | POST | /api/shopify/subscription | this endpoint should be called to create a shop subscription | 94 | -------------------------------------------------------------------------------- /admin/api/plans.js: -------------------------------------------------------------------------------- 1 | import axiosInstance from '../utils/axiosInstance'; 2 | 3 | const plansRequests = { 4 | getPlans: async () => { 5 | const data = await axiosInstance.get('/shopify/plans'); 6 | return data; 7 | }, 8 | createPlans: async ( data ) => { 9 | const plans = await axiosInstance.post(`/shopify/plans/create`, JSON.stringify(data)); 10 | return plans; 11 | }, 12 | editPlans: async ( data, id ) => { 13 | const plans = await axiosInstance.put(`/shopify/plans/edit`, JSON.stringify({ 14 | "id": id, 15 | "data": data, 16 | })); 17 | return plans; 18 | }, 19 | deletePlans: async ( id ) => { 20 | const plans = await axiosInstance.post(`/shopify/plans/delete`, JSON.stringify({ "id": id })); 21 | return plans; 22 | } 23 | }; 24 | export default plansRequests; 25 | -------------------------------------------------------------------------------- /admin/api/settings.js: -------------------------------------------------------------------------------- 1 | import axiosInstance from '../utils/axiosInstance'; 2 | 3 | const taskRequests = { 4 | getSettings: async () => { 5 | const data = await axiosInstance.get('/shopify/settings'); 6 | return data; 7 | }, 8 | }; 9 | export default taskRequests; 10 | -------------------------------------------------------------------------------- /admin/components/Initializer/index.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import pluginId from '../../pluginId'; 4 | 5 | const Initializer = ({ setPlugin }) => { 6 | const ref = useRef(); 7 | ref.current = setPlugin; 8 | 9 | useEffect(() => { 10 | ref.current(pluginId); 11 | }, []); 12 | 13 | return null; 14 | }; 15 | 16 | Initializer.propTypes = { 17 | setPlugin: PropTypes.func.isRequired, 18 | }; 19 | 20 | export default Initializer; 21 | -------------------------------------------------------------------------------- /admin/components/Modal/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { Typography, Grid, GridItem, Flex, Button, Select, Option, Textarea, TextInput, NumberInput, Box, ToggleInput } from '@strapi/design-system'; 3 | import plansApi from '../../api/plans'; 4 | 5 | const Modal = ({ setIsOpen, setStatus, setItem, item }) => { 6 | 7 | const [name, setName] = useState(item.name); 8 | const [recurringPrice, setRecurringPrice] = useState(item.recurringPrice); 9 | const [recurringInterval, setRecurringInterval] = useState(item.recurringInterval); 10 | const [usageTerms, setUsageTerms] = useState(item.usageTerms); 11 | const [usageCappedAmount, setUsageCappedAmount] = useState(item.usageCappedAmount); 12 | const [currencyCode, setCurrencyCode] = useState(item.currencyCode); 13 | const [trialDays, setTrialDays] = useState(item.trialDays); 14 | const [test, setTest] = useState(item.test); 15 | 16 | const handleSave = async () => { 17 | const id = item.id 18 | const data = { 19 | "name" : name, 20 | "recurringPrice" : recurringPrice, 21 | "recurringInterval" : recurringInterval, 22 | "usageTerms" : usageTerms, 23 | "usageCappedAmount" : usageCappedAmount, 24 | "currencyCode" : currencyCode, 25 | "trialDays" : trialDays, 26 | "test" : test 27 | } 28 | 29 | if(id==='') { 30 | await plansApi.createPlans( data ).then((res) => { 31 | setItem(res.data.plan); 32 | }); 33 | } 34 | else { 35 | await plansApi.editPlans( data, id ).then((res) => { 36 | setItem(res.data.plan); 37 | }); 38 | } 39 | 40 | setIsOpen(false) 41 | } 42 | 43 | return ( 44 | <> 45 | setIsOpen(false)} /> 46 | 47 | 48 | 49 | {item.id==='' ? (Create Plan) : (Edit Plan)} 50 | 51 | 52 | 53 | 54 | 55 | setName(e.target.value)} value={name} required /> 56 | 57 | 58 | setRecurringPrice(value)} value={recurringPrice} required /> 59 | 60 | 61 | 62 | 63 | 64 | 65 | 69 | 70 | 71 |