@sgftech/medusa-payment-stripe-subscription 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/.babelrc.js +12 -0
  2. package/.eslintrc.js +112 -0
  3. package/.github/dependabot.yml +21 -0
  4. package/.github/scripts/wait-for-server-live.sh +29 -0
  5. package/.github/workflows/test-cli.yml +149 -0
  6. package/.github/workflows/update-preview-deps-ci.yml +70 -0
  7. package/.github/workflows/update-preview-deps.yml +70 -0
  8. package/.vscode/settings.json +2 -0
  9. package/.yarnrc.yml +1 -0
  10. package/README.md +79 -0
  11. package/data/seed-onboarding.json +141 -0
  12. package/data/seed.json +1006 -0
  13. package/index.js +50 -0
  14. package/medusa-config.js +88 -0
  15. package/package.json +109 -0
  16. package/src/__fixtures__/data.ts +30 -0
  17. package/src/__mocks__/stripe.ts +104 -0
  18. package/src/api/README.md +179 -0
  19. package/src/core/__fixtures__/data.ts +225 -0
  20. package/src/core/__fixtures__/stripe-test.ts +12 -0
  21. package/src/core/__tests__/stripe-base.spec.ts +640 -0
  22. package/src/core/stripe-subscription.ts +523 -0
  23. package/src/index.ts +0 -0
  24. package/src/jobs/README.md +32 -0
  25. package/src/loaders/README.md +19 -0
  26. package/src/migrations/README.md +29 -0
  27. package/src/models/README.md +46 -0
  28. package/src/services/README.md +49 -0
  29. package/src/services/stripe-subscription-provider.ts +83 -0
  30. package/src/subscribers/README.md +44 -0
  31. package/src/subscribers/create-product-stripe.ts +23 -0
  32. package/src/subscribers/delete-product-stripe.ts +24 -0
  33. package/src/subscribers/stripe-event.ts +24 -0
  34. package/src/subscribers/update-product-stripe.ts +23 -0
  35. package/src/types/index.ts +9 -0
  36. package/src/utils/handle-customer-subscription.ts +36 -0
  37. package/src/utils/handle-invoice-subscription.ts +54 -0
  38. package/src/utils/handle-subscription.ts +64 -0
  39. package/src/utils/index.ts +143 -0
  40. package/tsconfig.admin.json +8 -0
  41. package/tsconfig.json +30 -0
  42. package/tsconfig.server.json +8 -0
  43. package/tsconfig.spec.json +5 -0
package/.babelrc.js ADDED
@@ -0,0 +1,12 @@
1
+ let ignore = [`**/dist`]
2
+
3
+ // Jest needs to compile this code, but generally we don't want this copied
4
+ // to output folders
5
+ if (process.env.NODE_ENV !== `test`) {
6
+ ignore.push(`**/__tests__`)
7
+ }
8
+
9
+ module.exports = {
10
+ presets: [["babel-preset-medusa-package"], ["@babel/preset-typescript"]],
11
+ ignore,
12
+ }
package/.eslintrc.js ADDED
@@ -0,0 +1,112 @@
1
+ module.exports = {
2
+ // parser: `@babel/eslint-parser`,
3
+ parserOptions: {
4
+ requireConfigFile: false,
5
+ ecmaFeatures: {
6
+ experimentalDecorators: true
7
+ },
8
+ ecmaVersion: "latest",
9
+ sourceType: "module"
10
+ },
11
+ plugins: ["file-progress", "prettier"],
12
+ extends: [
13
+ "eslint:recommended",
14
+ "eslint-config-prettier",
15
+ "google",
16
+ "prettier"
17
+ ],
18
+ rules: {
19
+ "no-use-before-define": "off",
20
+ "@typescript-eslint/no-use-before-define": ["error"],
21
+ // "react/jsx-filename-extension": ["warn", { extensions: [".tsx"] }],
22
+ "file-progress/activate": 1,
23
+ "prettier/prettier": [
24
+ "error",
25
+ {
26
+ "endOfLine": "auto",
27
+ "quoteProps": "consistent",
28
+ "printWidth": 80,
29
+ "editor.formatOnSave": true,
30
+ "proseWrap": "always",
31
+ "tabSize": 4,
32
+ "tabWidth": 4,
33
+ "requireConfig": false,
34
+ "useTabs": false,
35
+ "trailingComma": "none",
36
+ "bracketSpacing": true,
37
+ "jsxBracketSameLine": false,
38
+ "semi": true
39
+ },
40
+ {
41
+ usePrettierrc: true
42
+ }
43
+ ],
44
+ "object-curly-spacing": [2, "always"],
45
+ "quotes": [2, "double", { avoidEscape: true }],
46
+ "curly": [2, "all"],
47
+ "new-cap": "off",
48
+ "require-jsdoc": "off",
49
+ "semi": "error",
50
+ "no-unused-expressions": "off",
51
+ "camelcase": "off",
52
+ "no-invalid-this": "off"
53
+ },
54
+ env: {
55
+ es6: true,
56
+ node: true,
57
+ jest: true
58
+ },
59
+ ignorePatterns: ["**/reports", "**/dist", "**/coverage","**/node_modules"],
60
+ overrides: [
61
+ {
62
+ files: ["*.ts", "*.tsx"],
63
+ parser: "@typescript-eslint/parser",
64
+ plugins: ["@typescript-eslint/eslint-plugin"],
65
+ extends: ["plugin:@typescript-eslint/recommended"],
66
+ rules: {
67
+ "valid-jsdoc": [
68
+ "error",
69
+ {
70
+ requireParamType: false,
71
+ requireReturnType: false,
72
+ prefer: {
73
+ arg: "param",
74
+ argument: "param",
75
+ class: "constructor",
76
+ return: "return",
77
+ virtual: "abstract"
78
+ }
79
+ }
80
+ ],
81
+ "@typescript-eslint/explicit-function-return-type": ["error"],
82
+ "@typescript-eslint/no-non-null-assertion": ["off"]
83
+ }
84
+ },
85
+ {
86
+ files: [
87
+ "**/common/**/*.ts",
88
+ "**/bin/**/*.ts",
89
+ "**/api/**/*.ts",
90
+ "**/medusa-js/**/resources/**/*.ts"
91
+ ],
92
+ rules: {
93
+ "valid-jsdoc": ["off"]
94
+ }
95
+ },
96
+ {
97
+ // Medusa JS client
98
+ files: ["**/medusa-js/**/resources/**/*.ts"],
99
+ rules: {
100
+ "valid-jsdoc": ["off"]
101
+ }
102
+ },
103
+ {
104
+ files: ["**/api/**/*.ts"],
105
+ rules: {
106
+ "valid-jsdoc": ["off"],
107
+ "@typescript-eslint/explicit-function-return-type": ["off"],
108
+ "@typescript-eslint/no-var-requires": ["off"]
109
+ }
110
+ }
111
+ ]
112
+ };
@@ -0,0 +1,21 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "npm"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "daily"
7
+ allow:
8
+ - dependency-type: production
9
+ groups:
10
+ medusa:
11
+ patterns:
12
+ - "@medusajs*"
13
+ - "medusa*"
14
+ update-types:
15
+ - "minor"
16
+ - "patch"
17
+ ignore:
18
+ - dependency-name: "@medusajs*"
19
+ update-types: ["version-update:semver-major"]
20
+ - dependency-name: "medusa*"
21
+ update-types: ["version-update:semver-major"]
@@ -0,0 +1,29 @@
1
+ #!/bin/bash
2
+
3
+ for i in {1..6}
4
+ do
5
+ echo $i
6
+ status_code=$(curl \
7
+ -X GET \
8
+ --write-out %{http_code} \
9
+ --silent\
10
+ --output /dev/null\
11
+ http://localhost:9000/store/products)
12
+
13
+ echo $status_code
14
+ if [[ "$status_code" -ne 000 ]] ; then
15
+ echo "exiting"
16
+ exit 0
17
+ else
18
+ sleep 5
19
+ fi
20
+ done
21
+
22
+ echo $status_code
23
+
24
+ if [[ "$status_code" = 000 ]] ; then
25
+ echo "Site status changed to $status_code"
26
+ exit 1
27
+ else
28
+ exit 0
29
+ fi
@@ -0,0 +1,149 @@
1
+ name: Test CLI
2
+ on:
3
+ pull_request:
4
+ branches:
5
+ - 'feat/v2'
6
+ - 'feat/v2-ci'
7
+
8
+ jobs:
9
+ test-cli-yarn:
10
+ name: "Test CLI (Yarn)"
11
+ env:
12
+ NODE_ENV: CI
13
+ REDIS_URL: redis://localhost:6379
14
+ DATABASE_URL: "postgres://postgres:postgres@localhost/cli-test"
15
+ POSTGRES_URL: "postgres://postgres:postgres@localhost/cli-test"
16
+ services:
17
+ redis:
18
+ image: redis
19
+ options: >-
20
+ --health-cmd "redis-cli ping"
21
+ --health-interval 10s
22
+ --health-timeout 5s
23
+ --health-retries 5
24
+ ports:
25
+ - 6379:6379
26
+
27
+ postgres:
28
+ image: postgres
29
+ env:
30
+ POSTGRES_PASSWORD: postgres
31
+ POSTGRES_USER: postgres
32
+ POSTGRES_DB: cli-test
33
+ options: >-
34
+ --health-cmd pg_isready
35
+ --health-interval 10s
36
+ --health-timeout 5s
37
+ --health-retries 5
38
+ ports:
39
+ - 5432:5432
40
+
41
+ runs-on: ubuntu-latest
42
+ steps:
43
+ - name: Checkout
44
+ uses: actions/checkout@v3
45
+ with:
46
+ fetch-depth: 0
47
+
48
+ - name: Cancel Previous Runs
49
+ uses: styfle/cancel-workflow-action@0.11.0
50
+ with:
51
+ access_token: ${{ github.token }}
52
+
53
+ - name: Setup Node.js environment
54
+ uses: actions/setup-node@v3
55
+ with:
56
+ node-version: 20
57
+
58
+ - name: Install Dependencies
59
+ run: yarn install
60
+
61
+ - name: Check CLI tool is installed
62
+ run: ./node_modules/.bin/medusa -v
63
+
64
+ - name: run build
65
+ run: yarn build
66
+
67
+ - name: Run migrations
68
+ run: npx medusa migrations run
69
+
70
+ - name: Run seed
71
+ run: yarn seed
72
+
73
+ - name: Run development server
74
+ run: yarn dev &
75
+
76
+ - name: Wait for live server response
77
+ shell: "bash"
78
+ run: ./.github/scripts/wait-for-server-live.sh
79
+
80
+ - name: Kill server
81
+ shell: "bash"
82
+ run: kill -9 $(lsof -t -i :9000)
83
+
84
+ test-cli-npm:
85
+ name: "Test CLI (npm)"
86
+ env:
87
+ NODE_ENV: CI
88
+ REDIS_URL: redis://localhost:6379
89
+ DATABASE_URL: "postgres://postgres:postgres@localhost/cli-test"
90
+ POSTGRES_URL: "postgres://postgres:postgres@localhost/cli-test"
91
+ services:
92
+ postgres:
93
+ image: postgres
94
+ env:
95
+ POSTGRES_PASSWORD: postgres
96
+ POSTGRES_USER: postgres
97
+ POSTGRES_DB: cli-test
98
+ options: >-
99
+ --health-cmd pg_isready
100
+ --health-interval 10s
101
+ --health-timeout 5s
102
+ --health-retries 5
103
+ ports:
104
+ - 5432:5432
105
+
106
+ runs-on: ubuntu-latest
107
+ steps:
108
+ - name: Checkout
109
+ uses: actions/checkout@v3
110
+ with:
111
+ fetch-depth: 0
112
+
113
+ - name: Cancel Previous Runs
114
+ uses: styfle/cancel-workflow-action@0.11.0
115
+ with:
116
+ access_token: ${{ github.token }}
117
+
118
+ - name: Setup Node.js environment
119
+ uses: actions/setup-node@v3
120
+ with:
121
+ node-version: 20
122
+ cache: "npm"
123
+
124
+ - name: Install Dependencies
125
+ run: npm install
126
+
127
+ - name: Check CLI tool is installed
128
+ run: ./node_modules/.bin/medusa -v
129
+
130
+ - name: run medusa build
131
+ run: npm run build
132
+
133
+ - name: Run migrations
134
+ run: npx medusa migrations run
135
+
136
+ - name: Run seed
137
+ run: npm run seed
138
+
139
+ - name: Run development server
140
+ run: npm run dev -- &
141
+
142
+ - name: Wait for live server response
143
+ shell: "bash"
144
+ run: ./.github/scripts/wait-for-server-live.sh
145
+
146
+ - name: Kill server
147
+ shell: "bash"
148
+ run: kill -9 $(lsof -t -i :9000)
149
+
@@ -0,0 +1,70 @@
1
+ name: "Update Preview Dependencies (feat/v2-ci)"
2
+ on:
3
+ schedule:
4
+ - cron: "0 */3 * * *" # every three hours
5
+ workflow_dispatch:
6
+
7
+ jobs:
8
+ update:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Cancel Previous Runs
12
+ uses: styfle/cancel-workflow-action@0.9.1
13
+ with:
14
+ access_token: ${{ github.token }}
15
+
16
+ - name: Checkout
17
+ uses: actions/checkout@v2.3.5
18
+ with:
19
+ ref: 'feat/v2-ci'
20
+
21
+ - name: Setup Node.js 18.x
22
+ uses: actions/setup-node@v2
23
+ with:
24
+ node-version: 18.x
25
+
26
+ - name: Remove yarn.lock
27
+ run: rm yarn.lock
28
+
29
+ - name: Install Dependencies
30
+ run: yarn
31
+
32
+ - name: Close Previous PRs
33
+ shell: "bash"
34
+ run: |
35
+ TITLE="chore(feat/v2-ci): updated preview dependencies [automated]"
36
+
37
+ # Get the list of pull requests with the specified title
38
+ PR_LIST=$(gh pr list --search "$TITLE in:title" --json number)
39
+
40
+ echo "$PR_LIST"
41
+
42
+ # Check if any pull requests were found
43
+ if [ -z "$PR_LIST" ]; then
44
+ echo "No pull requests found with the title: $TITLE"
45
+ exit 0
46
+ fi
47
+
48
+ # Close each pull request
49
+ echo "$PR_LIST" | jq -r '.[].number' | while read -r PR_NUMBER; do
50
+ echo "Closing pull request #$PR_NUMBER"
51
+ gh pr close "$PR_NUMBER" -d
52
+ done
53
+ env:
54
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55
+ OWNER: ${{ github.repository_owner }}
56
+ REPO: ${{ github.event.repository.name }}
57
+
58
+ - name: Open PR with changes
59
+ uses: peter-evans/create-pull-request@v5
60
+ with:
61
+ title: "chore(feat/v2-ci): updated preview dependencies [automated]"
62
+ commit-message: "chore(feat/v2-ci): updated preview dependencies [automated]"
63
+ body: "This PR updates preview dependencies to the latest versions."
64
+ branch: "chore/update-preview"
65
+ branch-suffix: "timestamp"
66
+ token: ${{ secrets.PAT_TOKEN }}
67
+ base: "feat/v2-ci"
68
+ add-paths: yarn.lock
69
+ committer: "GitHub <noreply@github.com>"
70
+ author: "GitHub <github-actions[bot]@users.noreply.github.com>"
@@ -0,0 +1,70 @@
1
+ name: "Update Preview Dependencies (feat/v2)"
2
+ on:
3
+ schedule:
4
+ - cron: "0 */3 * * *" # every three hours
5
+ workflow_dispatch:
6
+
7
+ jobs:
8
+ update:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Cancel Previous Runs
12
+ uses: styfle/cancel-workflow-action@0.9.1
13
+ with:
14
+ access_token: ${{ github.token }}
15
+
16
+ - name: Checkout
17
+ uses: actions/checkout@v2.3.5
18
+ with:
19
+ ref: 'feat/v2'
20
+
21
+ - name: Setup Node.js 18.x
22
+ uses: actions/setup-node@v2
23
+ with:
24
+ node-version: 18.x
25
+
26
+ - name: Remove yarn.lock
27
+ run: rm yarn.lock
28
+
29
+ - name: Install Dependencies
30
+ run: yarn
31
+
32
+ - name: Close Previous PRs
33
+ shell: "bash"
34
+ run: |
35
+ TITLE="chore(feat/v2): updated preview dependencies [automated]"
36
+
37
+ # Get the list of pull requests with the specified title
38
+ PR_LIST=$(gh pr list --search "$TITLE in:title" --json number)
39
+
40
+ echo "$PR_LIST"
41
+
42
+ # Check if any pull requests were found
43
+ if [ -z "$PR_LIST" ]; then
44
+ echo "No pull requests found with the title: $TITLE"
45
+ exit 0
46
+ fi
47
+
48
+ # Close each pull request
49
+ echo "$PR_LIST" | jq -r '.[].number' | while read -r PR_NUMBER; do
50
+ echo "Closing pull request #$PR_NUMBER"
51
+ gh pr close "$PR_NUMBER" -d
52
+ done
53
+ env:
54
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55
+ OWNER: ${{ github.repository_owner }}
56
+ REPO: ${{ github.event.repository.name }}
57
+
58
+ - name: Open PR with changes
59
+ uses: peter-evans/create-pull-request@v5
60
+ with:
61
+ title: "chore(feat/v2): updated preview dependencies [automated]"
62
+ body: "This PR updates preview dependencies to the latest versions."
63
+ commit-message: "chore(feat/v2): updated preview dependencies [automated]"
64
+ branch: "chore/update-preview"
65
+ branch-suffix: "timestamp"
66
+ token: ${{ secrets.PAT_TOKEN }}
67
+ base: "feat/v2"
68
+ add-paths: yarn.lock
69
+ committer: "GitHub <noreply@github.com>"
70
+ author: "GitHub <github-actions[bot]@users.noreply.github.com>"
@@ -0,0 +1,2 @@
1
+ {
2
+ }
package/.yarnrc.yml ADDED
@@ -0,0 +1 @@
1
+ nodeLinker: node-modules
package/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # Medusa Payment Stripe Subscription Plugin
2
+
3
+ The Medusa Payment Stripe Subscription plugin provides seamless integration with the Stripe payment gateway for managing subscription-based payments in your Medusa e-commerce store.
4
+
5
+ ## Installation
6
+
7
+ To install the Medusa Payment Stripe Subscription plugin, follow these steps:
8
+
9
+ 1. Ensure that you have Medusa installed and set up in your project.
10
+ 2. Run the following command to install the plugin:
11
+
12
+ ```bash
13
+ npm install medusa-payment-stripe-subscription
14
+ ```
15
+
16
+ 3. Configure the plugin by adding the following environment variables to your project:
17
+
18
+ ```bash
19
+ STRIPE_API_KEY=your_stripe_api_key
20
+ ```
21
+
22
+ 4. Add the plugin to your Medusa configuration file (`medusa-config.js`):
23
+
24
+ ```javascript
25
+
26
+ const stripeSubscriptionConfig = {
27
+ api_key: process.env.STRIPE_API_TEST_KEY,
28
+ webhook_secret: process.env.STRIPE_API_WEBHOOK_TEST_SECRET,
29
+ /**
30
+ * Use this flag to capture payment immediately (default is false)
31
+ */
32
+ capture: true,
33
+ /**
34
+ * set `automatic_payment_methods` to `{ enabled: true }`
35
+ */
36
+ automatic_payment_methods: { enabled: true },
37
+ /**
38
+ * Set a default description on the intent if the context does not provide one
39
+ */
40
+ payment_description: "Payment for order",
41
+ /**
42
+ * The delay in milliseconds before processing the webhook event.
43
+ * @defaultValue 5000
44
+ */
45
+ webhook_delay: 5000,
46
+ /**
47
+ * The number of times to retry the webhook event processing in case of an error.
48
+ * @defaultValue 3
49
+ */
50
+ webhook_retries: 3,
51
+
52
+ product_url_prefix: process.env.PRODUCT_URL_PREFIX ?? "/products",
53
+ shop_base_url: process.env.SHOP_DOMAIN ?? "http://localhost:8000",
54
+ subscription_interval_period:
55
+ parseInt(process.env.SUBSCRIPTION_PERIOD) ?? 30,
56
+ cancel_at_period_end: true
57
+ };
58
+ plugins:[
59
+ ...
60
+ {
61
+ resolve: "medusa-payment-stripe-subscription",
62
+ options: stripeSubscriptionConfig
63
+ },
64
+ ...]
65
+
66
+ ```
67
+
68
+ ## Usage
69
+
70
+ Once the Medusa Payment Stripe Subscription plugin is installed and configured, you can start using it to handle subscription payments in your Medusa store. Here are some examples of how to use the plugin:
71
+
72
+
73
+ ## Contributing
74
+
75
+ Contributions to the Medusa Payment Stripe Subscription plugin are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request on the [GitHub repository](https://github.com/medusajs/medusa-payment-stripe-subscription).
76
+
77
+ ## License
78
+
79
+ This plugin is licensed under the [MIT License](LICENSE).
@@ -0,0 +1,141 @@
1
+ {
2
+ "store": {
3
+ "currencies": [
4
+ "eur",
5
+ "usd"
6
+ ]
7
+ },
8
+ "users": [],
9
+ "regions": [
10
+ {
11
+ "id": "test-region-eu",
12
+ "name": "EU",
13
+ "currency_code": "eur",
14
+ "tax_rate": 0,
15
+ "payment_providers": [
16
+ "manual"
17
+ ],
18
+ "fulfillment_providers": [
19
+ "manual"
20
+ ],
21
+ "countries": [
22
+ "gb",
23
+ "de",
24
+ "dk",
25
+ "se",
26
+ "fr",
27
+ "es",
28
+ "it"
29
+ ]
30
+ },
31
+ {
32
+ "id": "test-region-na",
33
+ "name": "NA",
34
+ "currency_code": "usd",
35
+ "tax_rate": 0,
36
+ "payment_providers": [
37
+ "manual"
38
+ ],
39
+ "fulfillment_providers": [
40
+ "manual"
41
+ ],
42
+ "countries": [
43
+ "us",
44
+ "ca"
45
+ ]
46
+ }
47
+ ],
48
+ "shipping_options": [
49
+ {
50
+ "name": "PostFake Standard",
51
+ "region_id": "test-region-eu",
52
+ "provider_id": "manual",
53
+ "data": {
54
+ "id": "manual-fulfillment"
55
+ },
56
+ "price_type": "flat_rate",
57
+ "amount": 1000
58
+ },
59
+ {
60
+ "name": "PostFake Express",
61
+ "region_id": "test-region-eu",
62
+ "provider_id": "manual",
63
+ "data": {
64
+ "id": "manual-fulfillment"
65
+ },
66
+ "price_type": "flat_rate",
67
+ "amount": 1500
68
+ },
69
+ {
70
+ "name": "PostFake Return",
71
+ "region_id": "test-region-eu",
72
+ "provider_id": "manual",
73
+ "data": {
74
+ "id": "manual-fulfillment"
75
+ },
76
+ "price_type": "flat_rate",
77
+ "is_return": true,
78
+ "amount": 1000
79
+ },
80
+ {
81
+ "name": "I want to return it myself",
82
+ "region_id": "test-region-eu",
83
+ "provider_id": "manual",
84
+ "data": {
85
+ "id": "manual-fulfillment"
86
+ },
87
+ "price_type": "flat_rate",
88
+ "is_return": true,
89
+ "amount": 0
90
+ },
91
+ {
92
+ "name": "FakeEx Standard",
93
+ "region_id": "test-region-na",
94
+ "provider_id": "manual",
95
+ "data": {
96
+ "id": "manual-fulfillment"
97
+ },
98
+ "price_type": "flat_rate",
99
+ "amount": 800
100
+ },
101
+ {
102
+ "name": "FakeEx Express",
103
+ "region_id": "test-region-na",
104
+ "provider_id": "manual",
105
+ "data": {
106
+ "id": "manual-fulfillment"
107
+ },
108
+ "price_type": "flat_rate",
109
+ "amount": 1200
110
+ },
111
+ {
112
+ "name": "FakeEx Return",
113
+ "region_id": "test-region-na",
114
+ "provider_id": "manual",
115
+ "data": {
116
+ "id": "manual-fulfillment"
117
+ },
118
+ "price_type": "flat_rate",
119
+ "is_return": true,
120
+ "amount": 800
121
+ },
122
+ {
123
+ "name": "I want to return it myself",
124
+ "region_id": "test-region-na",
125
+ "provider_id": "manual",
126
+ "data": {
127
+ "id": "manual-fulfillment"
128
+ },
129
+ "price_type": "flat_rate",
130
+ "is_return": true,
131
+ "amount": 0
132
+ }
133
+ ],
134
+ "products": [],
135
+ "categories": [],
136
+ "publishable_api_keys": [
137
+ {
138
+ "title": "Development"
139
+ }
140
+ ]
141
+ }