From f4bc6b84852780daf179719ad133abe978c66efb Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Fri, 22 Apr 2022 15:54:19 +0300 Subject: [PATCH 01/12] override the default z-index --- www/docs/src/css/custom.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/www/docs/src/css/custom.css b/www/docs/src/css/custom.css index 35bdf55d98..d28024c3d6 100644 --- a/www/docs/src/css/custom.css +++ b/www/docs/src/css/custom.css @@ -265,4 +265,8 @@ details summary { .theme-doc-markdown a:hover { color: #6e3eff; text-decoration: none; +} + +.DocSearch-Container { + z-index: 1001 !important; } \ No newline at end of file From 5ef50f27141754309b51269b76a08f3f2f389d14 Mon Sep 17 00:00:00 2001 From: Shreedhar Hegde Date: Fri, 22 Apr 2022 20:21:00 +0530 Subject: [PATCH 02/12] added link to Shipping Architecture Overview --- .../advanced/backend/shipping/add-fulfillment-provider.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/advanced/backend/shipping/add-fulfillment-provider.md b/docs/content/advanced/backend/shipping/add-fulfillment-provider.md index f41e35aa7b..cee33f4cc8 100644 --- a/docs/content/advanced/backend/shipping/add-fulfillment-provider.md +++ b/docs/content/advanced/backend/shipping/add-fulfillment-provider.md @@ -1,6 +1,6 @@ # How to Add a Fulfillment Provider -In this document, you’ll learn how to add a fulfillment provider to a Medusa server. If you’re unfamiliar with the Shipping architecture in Medusa, make sure to check out the overview first. +In this document, you’ll learn how to add a fulfillment provider to a Medusa server. If you’re unfamiliar with the Shipping architecture in Medusa, make sure to [check out the overview first](https://docs.medusajs.com/advanced/backend/shipping/overview/). ## Overview From c35f01c61fb820cdd639e5dca7962d103a4873e0 Mon Sep 17 00:00:00 2001 From: Shreedhar Hegde Date: Fri, 22 Apr 2022 20:39:26 +0530 Subject: [PATCH 03/12] corrected heading level for constructor in How to Add a Fulfillment Provider --- .../advanced/backend/shipping/add-fulfillment-provider.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/advanced/backend/shipping/add-fulfillment-provider.md b/docs/content/advanced/backend/shipping/add-fulfillment-provider.md index f41e35aa7b..16f1eee458 100644 --- a/docs/content/advanced/backend/shipping/add-fulfillment-provider.md +++ b/docs/content/advanced/backend/shipping/add-fulfillment-provider.md @@ -59,7 +59,7 @@ class MyFulfillmentService extends FulfillmentService { export default MyFulfillmentService; ``` -## constructor +### constructor You can use the `constructor` of your fulfillment provider to have access to different services in Medusa through dependency injection. From 5f216a977fc5e53623a226d33280bfd628f6d833 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Sat, 23 Apr 2022 17:51:58 +0300 Subject: [PATCH 04/12] docs: added documentation for payment provider implementation (#1390) --- .../frontend-payment-flow-in-checkout.md} | 6 +- .../payment/how-to-create-payment-provider.md | 387 ++++++++++++++++++ .../advanced/backend/payment/overview.md | 2 +- www/docs/sidebars.js | 12 +- 4 files changed, 397 insertions(+), 10 deletions(-) rename docs/content/{guides/checkouts.md => advanced/backend/payment/frontend-payment-flow-in-checkout.md} (99%) create mode 100644 docs/content/advanced/backend/payment/how-to-create-payment-provider.md diff --git a/docs/content/guides/checkouts.md b/docs/content/advanced/backend/payment/frontend-payment-flow-in-checkout.md similarity index 99% rename from docs/content/guides/checkouts.md rename to docs/content/advanced/backend/payment/frontend-payment-flow-in-checkout.md index b735dd0d31..f18c3746aa 100644 --- a/docs/content/guides/checkouts.md +++ b/docs/content/advanced/backend/payment/frontend-payment-flow-in-checkout.md @@ -1,8 +1,4 @@ ---- -title: Checkouts ---- - -# Checkouts +# Frontend Payment Flow in Checkout ## Introduction The purpose of this guide is to describe a checkout flow in Medusa. It is assumed that you've completed our [Quickstart](https://docs.medusajs.com/quickstart/quick-start) or [Tutorial](https://docs.medusajs.com/tutorial/set-up-your-development-environment) and are familiar with the technologies we use in our stack. Additionally, having an understanding of the [core API](https://docs.medusajs.com/api/store/auth) would serve as a great foundation for this walkthrough. diff --git a/docs/content/advanced/backend/payment/how-to-create-payment-provider.md b/docs/content/advanced/backend/payment/how-to-create-payment-provider.md new file mode 100644 index 0000000000..53295890ce --- /dev/null +++ b/docs/content/advanced/backend/payment/how-to-create-payment-provider.md @@ -0,0 +1,387 @@ +# How to Create a Payment Provider + +In this document, you’ll learn how to add a Payment Provider to your Medusa server. If you’re unfamiliar with the Payment architecture in Medusa, make sure to check out the [overview](./overview.md) first. + +## Overview + +A Payment Provider is the payment method used to authorize, capture, and refund payment, among other actions. An example of a Payment Provider is Stripe. + +By default, Medusa has a [manual payment provider](https://github.com/medusajs/medusa/tree/2e6622ec5d0ae19d1782e583e099000f0a93b051/packages/medusa-fulfillment-manual) that has minimal implementation. It can be synonymous with a Cash on Delivery payment method. It allows store operators to manage the payment themselves but still keep track of its different stages on Medusa. + +Adding a Payment Provider is as simple as creating a [service](../services/create-service.md) file in `src/services`. A Payment Provider is essentially a service that extends `PaymentService` from `medusa-interfaces`. + +Payment Provider Services must have a static property `identifier`. It is the name that will be used to install and refer to the Payment Provider in the Medusa server. + +:::tip + +Payment Providers are loaded and installed at the server startup. + +::: + +The Payment Provider service is also required to implement the following methods: + +1. `createPayment`: Called when a Payment Session for the Payment Provider is to be created. +2. `retrievePayment`: Used to retrieve payment data from the third-party provider, if there’s any. +3. `getStatus`: Used to get the status of a Payment or Payment Session. +4. `updatePayment`: Used to update the Payment Session whenever the cart and its related data are updated. +5. `updatePaymentData`: Used to update the `data` field of Payment Sessions. Specifically called when a request is sent to the [Update Payment Session](https://docs.medusajs.com/api/store/cart/update-a-payment-session) endpoint. +6. `deletePayment`: Used to perform any action necessary before a Payment Session is deleted. +7. `authorizePayment`: Used to authorize the payment amount of the cart before the order or swap is created. +8. `getPaymentData`: Used to retrieve the data that should be stored in the `data` field of a new Payment instance after the payment amount has been authorized. +9. `capturePayment`: Used to capture the payment amount of an order or swap. +10. `refundPayment`: Used to refund a payment amount of an order or swap. +11. `cancelPayment`: Used to perform any necessary action with the third-party payment provider when an order or swap is canceled. + +:::note + +All these methods must be declared async in the Payment Provider Service. + +::: + +These methods are used at different points in the Checkout flow as well as when processing the order after it’s placed. + +![Payment Flows.jpg](https://i.imgur.com/WeDr0ph.jpg) + +## Create a Fulfillment Provider + +The first step to create a fulfillment provider is to create a file in `src/services` with the following content: + +```jsx +import { PaymentService } from "medusa-interfaces" + +class MyPaymentService extends PaymentService { + +} + +export default MyPaymentService; +``` + +Where `MyPaymentService` is the name of your Payment Provider service. For example, Stripe’s Payment Provider Service is called `StripeProviderService`. + +Payment Providers must extend `PaymentService` from `medusa-interfaces`. + +:::tip + +Following the naming convention of Services, the name of the file should be the slug name of the Payment Provider, and the name of the class should be the camel case name of the Payment Provider suffixed with “Service”. In the example above, the name of the file should be `my-payment.js`. You can learn more in the [service documentation](../services/create-service.md). + +::: + +### Identifier + +As mentioned in the overview, Payment Providers should have a static `identifier` property. + +The `PaymentProvider` model has 2 properties: `identifier` and `is_installed`. The value of the `identifier` property in the class will be used when the Payment Provider is created in the database. + +The value of this property will also be used to reference the Payment Provider throughout the Medusa server. For example, the identifier is used when a [Payment Session in a cart is selected on checkout](https://docs.medusajs.com/api/store/cart/select-a-payment-session). + +### constructor + +You can use the `constructor` of your Payment Provider to have access to different services in Medusa through dependency injection. + +You can also use the constructor to initialize your integration with the third-party provider. For example, if you use a client to connect to the third-party provider’s APIs, you can initialize it in the constructor and use it in other methods in the service. + +Additionally, if you’re creating your Payment Provider as an external plugin to be installed on any Medusa server and you want to access the options added for the plugin, you can access it in the constructor. The options are passed as a second parameter: + +```jsx +constructor({}, options) { + //you can access options here +} +``` + +### createPayment + +This method is called during checkout when [Payment Sessions are initialized](https://docs.medusajs.com/api/store/cart/initialize-payment-sessions) to present payment options to the customer. It is used to allow you to make any necessary calls to the third-party provider to initialize the payment. For example, in Stripe this method is used to initialize a Payment Intent for the customer. + +The method receives the cart as an object for its first parameter. It holds all the necessary information you need to know about the cart and the customer that owns this cart. + +This method must return an object that is going to be stored in the `data` field of the Payment Session to be created. As mentioned in the [Architecture Overview](./overview.md), the `data` field is useful to hold any data required by the third-party provider to process the payment or retrieve its details at a later point. + +An example of a minimal implementation of `createPayment` that does not interact with any third-party providers: + +```jsx +async createPayment(cart) { + return { + id: 'test-payment', + status: 'pending' + }; +} +``` + +### retrievePayment + +This method is used to provide a uniform way of retrieving the payment information from the third-party provider. For example, in Stripe’s Payment Provider Service this method is used to retrieve the payment intent details from Stripe. + +This method accepts the `data` field of a Payment Session or a Payment. So, you should make sure to store in the `data` field any necessary data that would allow you to retrieve the payment data from the third-party provider. + +This method must return an object containing the data from the third-party provider. + +An example of a minimal implementation of `retrievePayment` where you don’t need to interact with the third-party provider: + +```jsx +async retrievePayment(cart) { + return {}; +} +``` + +### getStatus + +This method is used to get the status of a Payment or a Payment Session. + +Its main usage is in the place order workflow. If the status returned is not `authorized`, then the payment is considered failed, an error will be thrown, and the order will not be placed. + +This method accepts the `data` field of the Payment or Payment Session as a parameter. You can use this data to interact with the third-party provider to check the status of the payment if necessary. + +This method returns a string that represents the status. The status must be one of the following values: + +1. `authorized`: The payment was successfully authorized. +2. `pending`: The payment is still pending. This is the default status of a Payment Session. +3. `requires_more`: The payment requires more actions from the customer. For example, if the customer must complete a 3DS check before the payment is authorized. +4. `error`: If an error occurred with the payment. +5. `canceled`: If the payment was canceled. + +An example of a minimal implementation of `getStatus` where you don’t need to interact with the third-party provider: + +```jsx +async getStatus (data) { + return data.status; +} +``` + +:::note + +This code block assumes the status is stored in the `data` field as demonstrated in the `createPayment` method. + +::: + +### updatePayment + +This method is used to perform any necessary updates on the payment. This method is called whenever the cart or any of its related data is updated. For example, when a [line item is added to the cart](https://docs.medusajs.com/api/store/cart/add-a-line-item) or when a [shipping method is selected](https://docs.medusajs.com/api/store/cart/add-a-shipping-method). + +:::tip + +A line item refers to a product in the cart. + +::: + +It accepts the `data` field of the Payment Session as the first parameter and the cart as an object for the second parameter. + +You can utilize this method to interact with the third-party provider and update any details regarding the payment if necessary. + +This method must return an object that will be stored in the `data` field of the Payment Session. + +An example of a minimal implementation of `updatePayment` that does not need to make any updates on the third-party provider or the `data` field of the Payment Session: + +```jsx +async updatePayment(sessionData, cart) { + return sessionData; +} +``` + +### updatePaymentData + +This method is used to update the `data` field of a Payment Session. Particularly, it is called when a request is sent to the [Update Payment Session](https://docs.medusajs.com/api/store/cart/update-a-payment-session) endpoint. This endpoint receives a `data` object in the body of the request that should be used to update the existing `data` field of the Payment Session. + +This method accepts the current `data` field of the Payment Session as the first parameter, and the new `data` field sent in the body request as the second parameter. + +You can utilize this method to interact with the third-party provider and make any necessary updates based on the `data` field passed in the body of the request. + +This method must return an object that will be stored in the `data` field of the Payment Session. + +An example of a minimal implementation of `updatePaymentData` that returns the `updatedData` passed in the body of the request as-is to update the `data` field of the Payment Session. + +```jsx +async updatePaymentData(sessionData, updatedData) { + return updatedData; +} +``` + +### deletePayment + +This method is used to perform any actions necessary before a Payment Session is deleted. The Payment Session is deleted in one of the following cases: + +1. When a request is sent to [delete the Payment Session](https://docs.medusajs.com/api/store/cart/delete-a-payment-session). +2. When the [Payment Session is refreshed](https://docs.medusajs.com/api/store/cart/refresh-a-payment-session). The Payment Session is deleted so that a newer one is initialized instead. +3. When the Payment Provider is no longer available. This generally happens when the store operator removes it from the available Payment Provider in the admin. +4. When the region of the store is changed based on the cart information and the Payment Provider is not available in the new region. + +It accepts the Payment Session as an object for its first parameter. + +You can use this method to interact with the third-party provider to delete data related to the Payment Session if necessary. + +An example of a minimal implementation of `deletePayment` where no interaction with a third-party provider is required: + +```jsx +async deletePayment(paymentSession) { + return; +} +``` + +### authorizePayment + +This method is used to authorize payment using the Payment Session for an order. This is called when the [cart is completed](https://docs.medusajs.com/api/store/cart/complete-a-cart) and before the order is created. + +This method is also used for authorizing payments of a swap of an order. + +The payment authorization might require additional action from the customer before it is declared authorized. Once that additional action is performed, the `authorizePayment` method will be called again to validate that the payment is now fully authorized. So, you should make sure to implement it for this case as well, if necessary. + +Once the payment is authorized successfully and the Payment Session status is set to `authorized`, the order can then be placed. + +If the payment authorization fails, then an error will be thrown and the order will not be created. + +:::note + +The payment authorization status is determined using the `getStatus` method as mentioned earlier. If the status is `requires_more` then it means additional actions are required from the customer. If the workflow process reaches the “Start Create Order” step and the status is not `authorized`, then the payment is considered failed. + +::: + +This method accepts the Payment Session as an object for its first parameter, and a `context` object as a second parameter. The `context` object contains the following properties: + +1. `ip`: The customer’s IP. +2. `idempotency_key`: The [Idempotency Key](./overview.md#idempotency-key) that is associated with the current cart. It is useful when retrying payments, retrying checkout at a failed point, or for payments that require additional actions from the customer. + +This method must return an object containing the property `status` which is a string that indicates the current status of the payment, and the property `data` which is an object containing any additional information required to perform additional payment processing such as capturing the payment. The values of both of these properties are stored in the Payment Session’s `status` and `data` fields respectively. + +You can utilize this method to interact with the third-party provider and perform any actions necessary to authorize the payment. + +An example of a minimal implementation of `authorizePayment` that doesn’t need to interact with any third-party provider: + +```jsx +async authorizePayment(paymentSession, context) { + return { + status: 'authorized', + data: { + id: 'test' + } + }; + } +``` + +### getPaymentData + +After the payment is authorized using `authorizePayment`, a Payment instance will be created. The `data` field of the Payment instance will be set to the value returned from the `getPaymentData` method in the Payment Provider. + +This method accepts the Payment Session as an object for its first parameter. + +This method must return an object to be stored in the `data` field of the Payment instance. You can either use it as-is or make any changes to it if necessary. + +An example of a minimal implementation of `getPaymentData`: + +```jsx +async getPaymentData(paymentSession) { + return paymentSession.data; +} +``` + +### capturePayment + +This method is used to capture the payment amount of an order. This is typically triggered manually by the store operator from the admin. + +This method is also used for capturing payments of a swap of an order. + +You can utilize this method to interact with the third-party provider and perform any actions necessary to capture the payment. + +This method accepts the Payment as an object for its first parameter. + +This method must return an object that will be stored in the `data` field of the Payment. + +An example of a minimal implementation of `capturePayment` that doesn’t need to interact with a third-party provider: + +```jsx +async capturePayment(payment) { + return { + status: 'captured' + }; +} +``` + +### refundPayment + +This method is used to refund an order’s payment. This is typically triggered manually by the store operator from the admin. The refund amount might be the total order amount or part of it. + +This method is also used for refunding payments of a swap of an order. + +You can utilize this method to interact with the third-party provider and perform any actions necessary to refund the payment. + +This method accepts the Payment as an object for its first parameter, and the amount to refund as a second parameter. + +This method must return an object that is stored in the `data` field of the Payment. + +An example of a minimal implementation of `refundPayment` that doesn’t need to interact with a third-party provider: + +```jsx +async refundPayment(payment, amount) { + return { + id: 'test' + } +} +``` + +### cancelPayment + +This method is used to cancel an order’s payment. This method is typically triggered by one of the following situations: + +1. Before an order is placed and after the payment is authorized, an inventory check is done on products to ensure that products are still available for purchase. If the inventory check fails for any of the products, the payment is canceled. +2. If the store operator cancels the order from the admin. + +This method is also used for canceling payments of a swap of an order. + +You can utilize this method to interact with the third-party provider and perform any actions necessary to cancel the payment. + +This method accepts the Payment as an object for its first parameter. + +This method must return an object that is stored in the `data` field of the Payment. + +An example of a minimal implementation of `cancelPayment` that doesn’t need to interact with a third-party provider: + +```jsx +async cancelPayment(payment) { + return { + id: 'test' + } +} +``` + +## Optional Methods + +### retrieveSavedMethods + +This method can be added to your Payment Provider service if your third-party provider supports saving the customer’s payment methods. Please note that in Medusa there is no way to save payment methods. + +This method is called when a request is sent to [Retrieve Saved Payment Methods](https://docs.medusajs.com/api/store/customer/retrieve-saved-payment-methods). + +This method accepts the customer as an object for its first parameter. + +This method returns an array of saved payment methods retrieved from the third-party provider. You have the freedom to shape the items in the array as you see fit since they will be returned as-is for the response to the request. + +:::note + +If you’re using Medusa’s [Next.js](../../../starters/nextjs-medusa-starter.md) or [Gatsby](../../../starters/gatsby-medusa-starter.md) storefront starters, note that the presentation of this method is not implemented. You’ll need to implement the UI and pages for this method based on your implementation and the provider you are using. + +::: + +An example of the implementation of `retrieveSavedMethods` taken from Stripe’s Payment Provider: + +```jsx +/** +* Fetches a customers saved payment methods if registered in Stripe. +* @param {object} customer - customer to fetch saved cards for +* @returns {Promise>} saved payments methods +*/ +async retrieveSavedMethods(customer) { + if (customer.metadata && customer.metadata.stripe_id) { + const methods = await this.stripe_.paymentMethods.list({ + customer: customer.metadata.stripe_id, + type: "card", + }) + + return methods.data + } + + return Promise.resolve([]) +} +``` + +## What’s Next 🚀 + +- Check out the Payment Providers for [Stripe](https://github.com/medusajs/medusa/tree/2e6622ec5d0ae19d1782e583e099000f0a93b051/packages/medusa-payment-stripe) and [PayPal](https://github.com/medusajs/medusa/tree/2e6622ec5d0ae19d1782e583e099000f0a93b051/packages/medusa-payment-paypal) for implementation examples. +- Learn more about the [frontend checkout flow](./frontend-payment-flow-in-checkout.md). diff --git a/docs/content/advanced/backend/payment/overview.md b/docs/content/advanced/backend/payment/overview.md index 03ba48fefe..c65119176a 100644 --- a/docs/content/advanced/backend/payment/overview.md +++ b/docs/content/advanced/backend/payment/overview.md @@ -126,5 +126,5 @@ This prevents any payment issues from occurring with the customers and allows fo ## What’s Next 🚀 -- [Check out how the checkout flow is implemented on the frontend.](../../../guides/checkouts.md) +- [Check out how the checkout flow is implemented on the frontend.](./frontend-payment-flow-in-checkout.md) - Check out payment plugins like [Stripe](../../../add-plugins/stripe.md), [Paypal](../../../add-plugins/paypal.md), and [Klarna](../../../add-plugins/klarna.md). diff --git a/www/docs/sidebars.js b/www/docs/sidebars.js index 52b9e82f71..4138bbe78e 100644 --- a/www/docs/sidebars.js +++ b/www/docs/sidebars.js @@ -182,6 +182,14 @@ module.exports = { id: "advanced/backend/payment/overview", label: "Architecture Overview" }, + { + type: "doc", + id: "advanced/backend/payment/how-to-create-payment-provider", + }, + { + type: "doc", + id: "advanced/backend/payment/frontend-payment-flow-in-checkout", + }, ] }, { @@ -201,10 +209,6 @@ module.exports = { type: "doc", id: "guides/plugins", }, - { - type: "doc", - id: "guides/checkouts", - }, { type: "doc", id: "guides/carts-in-medusa", From eee780f110b70fcd4e8f982684b5f4ecd4128def Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Sun, 24 Apr 2022 13:11:53 +0300 Subject: [PATCH 05/12] docs: Add Twilio SMS plugin documentation (#1405) --- docs/content/add-plugins/twilio-sms.md | 128 +++++++++++++++++++++++++ www/docs/sidebars.js | 5 + 2 files changed, 133 insertions(+) create mode 100644 docs/content/add-plugins/twilio-sms.md diff --git a/docs/content/add-plugins/twilio-sms.md b/docs/content/add-plugins/twilio-sms.md new file mode 100644 index 0000000000..af30de60f9 --- /dev/null +++ b/docs/content/add-plugins/twilio-sms.md @@ -0,0 +1,128 @@ +# Twilio SMS + +In this document, you’ll learn about the Twilio SMS Plugin, what it does, and how to use it in Medusa. + +## Overview + +[Twilio’s SMS API](https://www.twilio.com/sms) can be used to send users SMS messages instantly. It has a lot of additional features such as Whatsapp messaging and conversations. + +By integrating Twilio SMS into Medusa, you’ll have easy access to Twilio’s SMS API to send SMS messages to your users and customers. You can use it to send Order confirmations, verification codes, reset password messages, and more. + +:::note + +This plugin only gives you access to the Twilio SMS API but does not implement sending messages at any given point. You’ll have to add this yourself where you need it. You can look at the [example later in this tutorial](#example-usage-of-the-plugin) to check how you can send an SMS for a new order. + +::: + +## Prerequisites + +Before going further with this guide make sure you have a Medusa server set up. You can follow our [Quickstart guide](../quickstart/quick-start.md) if you don’t. + +You also must have a [Twilio account created](https://www.twilio.com/sms) so if you don’t already please go ahead and create one. + +## Retrieve Credentials + +For the [Twilio SMS plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-twilio-sms), you need three credentials from your Twilio account: Account SID, Auth Token, and a Twilio phone number to send from. You can find these 3 from your [Twilio Console’s homepage](https://console.twilio.com). + +## Install Plugin + +In the directory of your Medusa server, run the following command to install [Twilio SMS plugin](https://github.com/medusajs/medusa/tree/master/packages/medusa-plugin-twilio-sms): + +```bash npm2yarn +npm install medusa-plugin-twilio-sms +``` + +Then, you’ll need to add your credentials in `.env`: + +```bash +TWILIO_SMS_ACCOUNT_SID= +TWILIO_SMS_AUTH_TOKEN= +TWILIO_SMS_FROM_NUMBER= +``` + +Make sure to replace ``, ``, and `` with the credentials you obtained from your Twilio Console. + +Finally, add the plugin and its options in the `medusa-config.js` file to the `plugins` array: + +```jsx +const plugins = [ + ..., + { + resolve: `medusa-plugin-twilio-sms`, + options: { + account_sid: process.env.TWILIO_SMS_ACCOUNT_SID, + auth_token: process.env.TWILIO_SMS_AUTH_TOKEN, + from_number: process.env.TWILIO_SMS_FROM_NUMBER + } + } +]; +``` + +## Example Usage of the Plugin + +This plugin adds the service `twilioSmsService` to your Medusa server. To send SMS using it, all you have to do is resolve it in your file as explained in the [Services](../advanced/backend/services/create-service.md#using-your-custom-service) documentation. + +In this example, you’ll create a subscriber that listens to the `order.placed` event and sends an SMS to the customer to confirm their order. + +:::tip + +For this example to work, you’ll need to install and configure Redis on your server. You can refer to the [development guide](../tutorial/0-set-up-your-development-environment.md#redis) to learn how to do that. + +::: + +Create the file `src/services/sms.js` in your Medusa server with the following content: + +```jsx +class SmsSubscriber { + constructor({ twilioSmsService, orderService, eventBusService }) { + this.twilioSmsService_ = twilioSmsService; + this.orderService = orderService; + + eventBusService.subscribe("order.placed", this.sendSMS); + } + + sendSMS = async (data) => { + const order = await this.orderService.retrieve(data.id, { + relations: ['shipping_address'] + }); + + if (order.shipping_address.phone) { + this.twilioSmsService_.sendSms({ + to: order.shipping_address.phone, + body: 'We have received your order #' + data.id, + }) + } + }; +} + +export default SmsSubscriber; +``` + +In the `constructor`, you resolve the `twilioSmsService` and `orderService` using dependency injection to use it later in the `sendSMS` method. + +You also subscribe to the event `order.placed` and sets the event handler to be `sendSMS`. + +In `sendSMS`, you first retrieve the order with its relation to `shipping_address` which contains a `phone` field. If the phone is set, you send an SMS to the customer using the method `sendSms` in the `twilioSmsService`. + +This method accepts an object of parameters. These parameters are based on Twilio’s SMS APIs. You can check their [API documentation](https://www.twilio.com/docs/sms/api/message-resource#create-a-message-resource) for more fields that you can add. + +If you create an order now on your storefront, you should receive a message from Twilio on the phone number you entered in the shipping address. + +:::tip + +If you don’t have a storefront set up yet, you can install one of our [Next.js](../starters/nextjs-medusa-starter.md) or [Gatsby](../starters/gatsby-medusa-starter.md) storefronts. + +::: + +:::caution + +If you’re on a Twilio trial make sure that the phone number you entered on checkout is a [verified Twilio number on your console](https://console.twilio.com/us1/develop/phone-numbers/manage/verified). + +::: + +![Twilio Dashboard](https://i.imgur.com/MXtQMiL.png) + +## What’s Next 🚀 + +- Learn more about how [Notifications work in Medusa](../how-to/notification-api). +- Install the [Medusa admin](../admin/quickstart.md) for functionalities like Gift Cards creation, swaps, claims, order return requests, and more. diff --git a/www/docs/sidebars.js b/www/docs/sidebars.js index 4138bbe78e..e6e8c9c229 100644 --- a/www/docs/sidebars.js +++ b/www/docs/sidebars.js @@ -288,6 +288,11 @@ module.exports = { id: "add-plugins/mailchimp", label: "Mailchimp", }, + { + type: "doc", + id: "add-plugins/twilio-sms", + label: "Twilio SMS", + }, ], }, { From 01114b42a433f1b41ff436c4eed3dd32d71a8217 Mon Sep 17 00:00:00 2001 From: Shreedhar Hegde Date: Fri, 22 Apr 2022 20:01:57 +0530 Subject: [PATCH 06/12] added docusaurus admonitions to docs --- docs/content/add-plugins/minio.md | 6 +++- docs/content/add-plugins/s3.md | 6 +++- docs/content/add-plugins/segment.md | 6 +++- docs/content/add-plugins/spaces.md | 6 +++- docs/content/add-plugins/strapi.md | 26 ++++++++++++---- .../frontend-payment-flow-in-checkout.md | 14 +++++++-- .../backend/subscribers/create-subscriber.md | 6 +++- docs/content/guides/plugins.md | 18 +++++++++-- .../how-to/deploying-admin-on-netlify.md | 12 ++++++-- .../how-to/deploying-on-digital-ocean.md | 18 +++++++++-- docs/content/how-to/deploying-on-heroku.md | 29 ++++++++++++++---- docs/content/how-to/deploying-on-qovery.md | 30 ++++++++++++++----- ...rce-store-with-gatsby-contentful-medusa.md | 12 ++++++-- ...our-store-more-powerful-with-contentful.md | 18 +++++++---- docs/content/how-to/notification-api.md | 7 +++-- ...xtjs-storefront-for-your-medusa-project.md | 8 +++-- .../how-to/uploading-images-to-minio.md | 6 +++- docs/content/how-to/uploading-images-to-s3.md | 6 +++- .../how-to/uploading-images-to-spaces.md | 6 +++- docs/content/quickstart/quick-start.md | 6 +++- .../transaction-error-in-checkout.md | 6 +++- .../tutorial/1-creating-your-medusa-server.md | 6 +++- .../tutorial/2-adding-custom-functionality.md | 19 ++++++++++-- ...ng-your-local-project-with-medusa-cloud.md | 12 ++++++-- docs/services/CartService.md | 13 ++++---- 25 files changed, 242 insertions(+), 60 deletions(-) diff --git a/docs/content/add-plugins/minio.md b/docs/content/add-plugins/minio.md index 551149ae6d..f5ef62d4fe 100644 --- a/docs/content/add-plugins/minio.md +++ b/docs/content/add-plugins/minio.md @@ -46,7 +46,11 @@ Then configure your `medusa-config.js` to include the plugin alongside the requi The two access keys in the options are the ones created in the previous section. -> Make sure to use an environment variable for the secret key in a live environment. +:::note + +Make sure to use an environment variable for the secret key in a live environment. + +::: ### Try it out diff --git a/docs/content/add-plugins/s3.md b/docs/content/add-plugins/s3.md index d3059732c0..a7891fdeee 100644 --- a/docs/content/add-plugins/s3.md +++ b/docs/content/add-plugins/s3.md @@ -78,7 +78,11 @@ https://[bucket].s3.[region].amazonaws.com The two access keys in the options are the ones created in the previous section. -> Make sure to use an environment variable for the secret key in a live environment. +:::note + + Make sure to use an environment variable for the secret key in a live environment. + +::: ### Try it out diff --git a/docs/content/add-plugins/segment.md b/docs/content/add-plugins/segment.md index eccf0c414f..ebf1fbb72a 100644 --- a/docs/content/add-plugins/segment.md +++ b/docs/content/add-plugins/segment.md @@ -21,7 +21,11 @@ Common integration use cases that can be implemented with Segment include: ## Adding Segment to your Medusa store -> Note: you should create a [Node.js source in Segment](https://segment.com/docs/connections/sources/catalog/libraries/server/node/quickstart/) in order to obtain the write key that will be provided in the plugin options. +:::note + +You should create a [Node.js source in Segment](https://segment.com/docs/connections/sources/catalog/libraries/server/node/quickstart/) in order to obtain the write key that will be provided in the plugin options. + +::: Plugins in Medusa's ecosystem come as separate npm packages, that can be installed from the npm registry. diff --git a/docs/content/add-plugins/spaces.md b/docs/content/add-plugins/spaces.md index 27d856e030..cabe719814 100644 --- a/docs/content/add-plugins/spaces.md +++ b/docs/content/add-plugins/spaces.md @@ -47,7 +47,11 @@ Then configure your `medusa-config.js` to include the plugin alongside the requi In the above options, a `spaces_url` is included. This can be found in your Space overview. The `bucket` should point to the name you gave your Space. The `endpoint` identifies the region in which you created the Space. And finally the two keys are the ones created in the previous section. -> Make sure to use an environment variable for the secret key in a live environment. +:::note + +Make sure to use an environment variable for the secret key in a live environment. + +::: ### Try it out! diff --git a/docs/content/add-plugins/strapi.md b/docs/content/add-plugins/strapi.md index a9d34cd002..0071a859fa 100644 --- a/docs/content/add-plugins/strapi.md +++ b/docs/content/add-plugins/strapi.md @@ -37,7 +37,11 @@ Alternatively, using Yarn: yarn create medusa-app ``` -> When choosing `npx` you are shown different store engine options as part of the setup. For this Strapi tutorial, you should choose `medusa-starter-default`. Optionally, pick a storefront. +:::note + +When choosing `npx` you are shown different store engine options as part of the setup. For this Strapi tutorial, you should choose `medusa-starter-default`. Optionally, pick a storefront. + +::: **Use `medusa-cli`** `@medusajs/medusa-cli` is our Command Line Tool for creating the Medusa store engine (alongside many other powerful commands). First, install it: @@ -116,13 +120,19 @@ Alternatively, using Yarn: yarn global add create-strapi-app@3.6.8 create-strapi-app strapi-medusa --template https://github.com/Deathwish98/strapi-medusa-template.git ``` +:::note -> Note: The plugin expects node version to be '>= 10.16.0 and <=14.x.x', otherwise it will throw an error. +The plugin expects node version to be '>= 10.16.0 and <=14.x.x', otherwise it will throw an error. +::: After running the command, you have a full Strapi project configured to synchronize with Medusa. Upon the initial start of the Strapi server, all the required models will be created. They will correlate with models from Medusa to allow for two-way synchronization. -> Note: The Strapi template starter uses SQLite as the default database. There is a known bug related to `knex.js` that comes from multiple write connections. Restarting the Strapi server should make the error disappear. +:::note + +The Strapi template starter uses SQLite as the default database. There is a known bug related to `knex.js` that comes from multiple write connections. Restarting the Strapi server should make the error disappear. + +::: **Synchronization** @@ -134,7 +144,11 @@ When products are created in Medusa, the two-way communication ensures that data **Variants**: title **Region**: name -> Further down the road, the support for synchronizing more entities is expected to be introduced +:::note + +Further down the road, the support for synchronizing more entities is expected to be introduced + +::: **Using Postgres in Medusa (optional)** @@ -158,7 +172,9 @@ projectConfig: { }, ``` -> Note: the `DATABASE_URL` variable should use the Postgres database created in the previous step +:::note + +The `DATABASE_URL` variable should use the Postgres database created in the previous step ## Summary and next steps diff --git a/docs/content/advanced/backend/payment/frontend-payment-flow-in-checkout.md b/docs/content/advanced/backend/payment/frontend-payment-flow-in-checkout.md index f18c3746aa..9ffb6751ea 100644 --- a/docs/content/advanced/backend/payment/frontend-payment-flow-in-checkout.md +++ b/docs/content/advanced/backend/payment/frontend-payment-flow-in-checkout.md @@ -2,7 +2,12 @@ ## Introduction The purpose of this guide is to describe a checkout flow in Medusa. It is assumed that you've completed our [Quickstart](https://docs.medusajs.com/quickstart/quick-start) or [Tutorial](https://docs.medusajs.com/tutorial/set-up-your-development-environment) and are familiar with the technologies we use in our stack. Additionally, having an understanding of the [core API](https://docs.medusajs.com/api/store/auth) would serve as a great foundation for this walkthrough. -> All code snippets in the following guide, use the JS SDK distributed through **npm**. To install it, run: + +:::note + +All code snippets in the following guide, use the JS SDK distributed through **npm**. To install it, run: + +::: ```bash npm2yarn npm install @medusajs/medusa-js @@ -17,7 +22,12 @@ npm install @medusajs/medusa-js ## Checkout flow To create an order from a cart, we go through the following flow. -> At this point, it assumed that the customer has created a cart, added items and is now at the initial step of the checkout flow. + +:::note + +At this point, it assumed that the customer has created a cart, added items and is now at the initial step of the checkout flow. + +::: ### Initializing the checkout The first step in the flow is to _initialize_ the configured Payment Sessions for the Cart. If you are using the `medusa-starter-default` starter, this call will result in the `cart.payment_sessions` array being filled with one Payment Session for the manual payment provider. diff --git a/docs/content/advanced/backend/subscribers/create-subscriber.md b/docs/content/advanced/backend/subscribers/create-subscriber.md index c902ca7d0a..f8e711419d 100644 --- a/docs/content/advanced/backend/subscribers/create-subscriber.md +++ b/docs/content/advanced/backend/subscribers/create-subscriber.md @@ -69,7 +69,11 @@ export default OrderNotifierSubscriber; This subscriber will register the method `handleOrder` as one of the handlers of the `order.placed` event. The method `handleOrder` will be executed every time an order is placed, and it will receive the order ID in the `data` parameter. You can then use the order’s details to perform any kind of task you need. -> The `data` object will not contain other order data. Only the ID of the order. You can retrieve the order information using the `orderService`. +:::note + +The `data` object will not contain other order data. Only the ID of the order. You can retrieve the order information using the `orderService`. + +::: ## Using Services in Subscribers diff --git a/docs/content/guides/plugins.md b/docs/content/guides/plugins.md index 2516702c5c..07fcf5e36d 100644 --- a/docs/content/guides/plugins.md +++ b/docs/content/guides/plugins.md @@ -12,7 +12,11 @@ Plugins offer a way to extend and integrate the core functionality of Medusa. In most commerce solutions, you can extend the basic features but it often comes with the expense of having to build standalone web applications. Our architecture is built such that plugins run within the same process as the core eliminating the need for extra server capacity, infrastructure and maintenance. As a result, the plugins can use all other services as dependencies and access the database. -> You will notice that plugins vary in naming. The name should signal what functionality they provide. +:::note + +You will notice that plugins vary in naming. The name should signal what functionality they provide. + +::: In the following sections, we will go through the basics of implementing a generic plugin. And finally, how to use it as part of your commerce setup. @@ -34,7 +38,11 @@ We've already gone through the process of building custom services, endpoints, a To quickly get started with the implementation, we advise you to copy `/services/welcome.js`, `/api/index.js`, `/subscribers/welcome.js` and the config files from the tutorial and add them in `/src`. As a result, you should have the following folder structure: -> Please note: since the container resolution paths are automatically generated from the used directories and filenames you should avoid pre- or suffixing your file (e.g. `services/welcomeService.js` would result in the service being registered as `WelcomeServiceService`). +:::note + +Since the container resolution paths are automatically generated from the used directories and filenames you should avoid pre- or suffixing your file (e.g. `services/welcomeService.js` would result in the service being registered as `WelcomeServiceService`). + +::: ```js . @@ -55,7 +63,11 @@ Please note that you will need some build step before being able to properly loa It is worth mentioning the difference between building a generic and a non-generic plugin. A non-generic plugin has a specific purpose such as processing payments or creating fulfillments. Medusa core depends on a specific implementation from such plugins, which is why we've created interfaces that enforce this. These can be found in `medusa-interfaces`. -> Note: Non-generic plugins are required to extend the correct interface, otherwise they will not be loaded correctly as part of your Medusa setup. +:::note + +Non-generic plugins are required to extend the correct interface, otherwise they will not be loaded correctly as part of your Medusa setup. + +::: For a more comprehensive walkthrough of the implementation of such plugins, see our guides: diff --git a/docs/content/how-to/deploying-admin-on-netlify.md b/docs/content/how-to/deploying-admin-on-netlify.md index 018b99422b..92dc026869 100644 --- a/docs/content/how-to/deploying-admin-on-netlify.md +++ b/docs/content/how-to/deploying-admin-on-netlify.md @@ -6,7 +6,11 @@ title: "Deploying Admin on Netlify" This is a guide for deploying Medusa Admin on Netlify. Netlify is a platform that offers hosting and backend services for applications and static websites. -> At this point, you should have a running instance of Medusa Admin. If not, check out [these steps](https://github.com/medusajs/admin#-setting-up-admin) or use `npx create-medusa-app` to set up your application in a matter of minutes. For the latter, see [this guide](https://docs.medusajs.com/how-to/create-medusa-app) for a small walkthrough. +:::note + +At this point, you should have a running instance of Medusa Admin. If not, check out [these steps](https://github.com/medusajs/admin#-setting-up-admin) or use `npx create-medusa-app` to set up your application in a matter of minutes. For the latter, see [this guide](https://docs.medusajs.com/how-to/create-medusa-app) for a small walkthrough. + +::: ### 1. Install the Netlify CLI @@ -62,7 +66,11 @@ git push origin main Within a couple of minutes, your Medusa Admin is live and running on Netlify. -> If you experience CORS issues in your new setup, you might need to add your admin url as part of the ADMIN_CORS environment variable in your server setup. +:::note + +If you experience CORS issues in your new setup, you might need to add your admin url as part of the ADMIN_CORS environment variable in your server setup. + +::: ### What's next? diff --git a/docs/content/how-to/deploying-on-digital-ocean.md b/docs/content/how-to/deploying-on-digital-ocean.md index 3b6f8bded5..5cb96ac5d8 100644 --- a/docs/content/how-to/deploying-on-digital-ocean.md +++ b/docs/content/how-to/deploying-on-digital-ocean.md @@ -2,7 +2,11 @@ This is a guide for deploying a Medusa project on DigitalOcean App Platform. -> It is assumed, that you are currently running a local instance of Medusa. If not, check out our [Quickstart](https://docs.medusajs.com/quickstart/quick-start) or use `npx create-medusa-app` to set up your application in a matter of minutes. For the latter, see [this guide](https://docs.medusajs.com/how-to/create-medusa-app) for a small walkthrough. +:::note + +It is assumed, that you are currently running a local instance of Medusa. If not, check out our [Quickstart](https://docs.medusajs.com/quickstart/quick-start) or use `npx create-medusa-app` to set up your application in a matter of minutes. For the latter, see [this guide](https://docs.medusajs.com/how-to/create-medusa-app) for a small walkthrough. + +::: ### 1. Configure Medusa @@ -83,7 +87,11 @@ Navigate to the top-right dropdown **Create** and select **Apps**. Choose **GitHub** or **GitLab** and select the repository that holds your Medusa project. Check **Autodeploy code changes**, if you want DigitalOcean to deploy on every push to your repository. -> It's important, that DigitalOcean is pointing to the directory holding the Medusa store engine as it is only this which that will be deployed (If you followed the quickstart guide this will simply be the created project, and if you used the npx command this will be the backend folder inside of the newly created project). +:::note + +It's important, that DigitalOcean is pointing to the directory holding the Medusa store engine as it is only this which that will be deployed (If you followed the quickstart guide this will simply be the created project, and if you used the npx command this will be the backend folder inside of the newly created project). + +::: ### 5. Configure environment variables @@ -100,7 +108,11 @@ JWT_SECRET=your-jwt-secret COOKIE_SECRET=your-cookie-secret ``` -> Make sure to use actual secrets in a production environment +:::note + +Make sure to use actual secrets in a production environment + +::: ### 6. Set up a Database diff --git a/docs/content/how-to/deploying-on-heroku.md b/docs/content/how-to/deploying-on-heroku.md index 2d9013ae1d..778f8c2cc5 100644 --- a/docs/content/how-to/deploying-on-heroku.md +++ b/docs/content/how-to/deploying-on-heroku.md @@ -12,7 +12,11 @@ This is a guide for deploying a Medusa project on Heroku. Heroku is at PaaS that -> We assume, that you are currently running a local instance of Medusa. If not, check out our [Quickstart](https://docs.medusajs.com/quickstart/quick-start) or use `npx create-medusa-app` to set up your application in a matter of minutes. For the latter, see [this guide](https://docs.medusajs.com/how-to/create-medusa-app) for a small walkthrough. +:::note + +We assume, that you are currently running a local instance of Medusa. If not, check out our [Quickstart](https://docs.medusajs.com/quickstart/quick-start) or use `npx create-medusa-app` to set up your application in a matter of minutes. For the latter, see [this guide](https://docs.medusajs.com/how-to/create-medusa-app) for a small walkthrough. + +::: ### 1. Install the Heroku CLI @@ -45,7 +49,11 @@ Connect to your Heroku account from your terminal: heroku login ``` -> Follow the instructions on your terminal +:::note + +Follow the instructions on your terminal + +::: ### 3. Create an app on Heroku @@ -60,7 +68,11 @@ heroku git:remote -a medusa-test-app Medusa requires a Postgres database and a Redis instance to work. These are added through the Heroku CLI using the following commands. -> In this below example, we initialize the resources on free plans. This is not a valid configuration for a production environment. +:::note + +In this below example, we initialize the resources on free plans. This is not a valid configuration for a production environment. + +::: #### Postgresql @@ -76,7 +88,11 @@ You can find more informations, plans and pricing about Heroku Postgres [here](h Add a Redis instance to your Heroku app -> The addon `redistogo:nano` is free, but Heroku requires you to add a payment method to proceed. +:::note + +The addon `redistogo:nano` is free, but Heroku requires you to add a payment method to proceed. + +::: ```bash heroku addons:create redistogo:nano @@ -94,8 +110,11 @@ heroku config:set JWT_SECRET=your-super-secret heroku config:set COOKIE_SECRET=your-super-secret-pt2 heroku config:set NPM_CONFIG_PRODUCTION=false ``` +:::note -> Make sure to use actual secrets in a production environment. +Make sure to use actual secrets in a production environment. + +::: Additionally, we need to set the buildpack to Node.js diff --git a/docs/content/how-to/deploying-on-qovery.md b/docs/content/how-to/deploying-on-qovery.md index 23c221384d..a13cdd5cbc 100644 --- a/docs/content/how-to/deploying-on-qovery.md +++ b/docs/content/how-to/deploying-on-qovery.md @@ -2,7 +2,11 @@ This is a guide for deploying a Medusa project to Qovery. Qovery is a Continuous Deployment Platform, that provides you with the developer experience of Heroku on top of your cloud provider (e.g. AWS, DigitalOcean). -> We assume, that you are currently running a local instance of Medusa. If not, check out our [Quickstart](https://docs.medusajs.com/quickstart/quick-start) or use `npx create-medusa-app` to set up your application in a matter of minutes. For the latter, see [this guide](https://docs.medusajs.com/how-to/create-medusa-app) for a small walkthrough. +:::note + +We assume, that you are currently running a local instance of Medusa. If not, check out our [Quickstart](https://docs.medusajs.com/quickstart/quick-start) or use `npx create-medusa-app` to set up your application in a matter of minutes. For the latter, see [this guide](https://docs.medusajs.com/how-to/create-medusa-app) for a small walkthrough. + +::: ### 1. Qovery Console @@ -16,7 +20,11 @@ Create a project and an environment. Add a new app to your Qovery environment and connect the Git repository that holds your Medusa project. In your application settings, set the port to 9000 unless something else is specified in your setup. -> If you used our `npx` starter, your repository will most likely hold all components; storefront, admin and backend. Ensure that **Root application path** in Qovery is pointing to your Medusa project (`/backend`). +:::note + +If you used our `npx` starter, your repository will most likely hold all components; storefront, admin and backend. Ensure that **Root application path** in Qovery is pointing to your Medusa project (`/backend`). + +::: ### 4. Add a database @@ -61,10 +69,14 @@ module.exports = { }; ``` -> **IMPORTANT**: We are using the Qovery community plan, that does not allow SSL connections for the database, so this is disabled. -> -> In a production environment, you would need the following in the config: -> `database_extra: { ssl: { rejectUnauthorized: false } }` +:::caution IMPORTANT + +We are using the Qovery community plan, that does not allow SSL connections for the database, so this is disabled. + +In a production environment, you would need the following in the config: + `database_extra: { ssl: { rejectUnauthorized: false } }` + +::: #### Add some extra variables @@ -75,7 +87,11 @@ JTW_SECRET=something_secret_jwt COOKIE_SECRET=something_secret_cookie ``` -> Make sure to use actual secrets in a production environment. +:::note + +Make sure to use actual secrets in a production environment. + +::: #### Update `package.json` diff --git a/docs/content/how-to/headless-ecommerce-store-with-gatsby-contentful-medusa.md b/docs/content/how-to/headless-ecommerce-store-with-gatsby-contentful-medusa.md index adfddc1311..8a0aa4ff72 100644 --- a/docs/content/how-to/headless-ecommerce-store-with-gatsby-contentful-medusa.md +++ b/docs/content/how-to/headless-ecommerce-store-with-gatsby-contentful-medusa.md @@ -4,7 +4,11 @@ title: Create a headless ecommerce store with Gatsby, Contentful & Medusa # Creating a headless ecommerce store with Gatsby, Contentful and Medusa -> Medusa is an open source headless commerce engine that allow you to create amazing digital commerce experiences. Medusa is highly customizable, allowing you to extend the core to fit your needs. +:::note + +Medusa is an open source headless commerce engine that allow you to create amazing digital commerce experiences. Medusa is highly customizable, allowing you to extend the core to fit your needs. + +::: ## Introduction @@ -33,7 +37,11 @@ If you want to jump straight to the code for this series you can checkout: ## Prerequisites -> For a full guide to how to set up your development environment for Medusa please see [the tutorial](https://docs.medusajs.com/tutorials/set-up-your-development-environment) +:::note + +For a full guide to how to set up your development environment for Medusa please see [the tutorial](https://docs.medusajs.com/tutorials/set-up-your-development-environment) + +::: In order to get you started with your Gatsby, Contentful, Medusa store you must complete a couple of installations: diff --git a/docs/content/how-to/making-your-store-more-powerful-with-contentful.md b/docs/content/how-to/making-your-store-more-powerful-with-contentful.md index dbe0f65eb9..3a84340544 100644 --- a/docs/content/how-to/making-your-store-more-powerful-with-contentful.md +++ b/docs/content/how-to/making-your-store-more-powerful-with-contentful.md @@ -76,11 +76,13 @@ npm run migrate:contentful --file contentful-migrations/update-page-module-valid To use your new Rich Text module **Content > Page > About**, and click **Add Content > Page**. You will now make use of the new Rich Text module to add some more details about your store. You can write your own text or use the text provided below if you just want to copy/paste. -> ### About Medusa -> -> Medusa is an open-source headless commerce engine for fast-growing businesses. Getting started with Medusa is very easy and you will be able to start selling online with a basic setup in no time, however, the real power of Medusa starts showing up when you add custom functionality and extend your core to fit your needs. -> -> The core Medusa package and all the official Medusa plugins ship as individual NPM packages that you install into a Node project. You store and plugins are configured in your medusa-config.js file making it very easy to manage your store as your business grows. Custom functionality doesn't have to come from plugins, you can also add project-level functionality by simply adding files in your `src/` folder. Medusa will automatically register your custom functionalities in the bootstrap phase. +:::note About Medusa + + Medusa is an open-source headless commerce engine for fast-growing businesses. Getting started with Medusa is very easy and you will be able to start selling online with a basic setup in no time, however, the real power of Medusa starts showing up when you add custom functionality and extend your core to fit your needs. + + The core Medusa package and all the official Medusa plugins ship as individual NPM packages that you install into a Node project. You store and plugins are configured in your medusa-config.js file making it very easy to manage your store as your business grows. Custom functionality doesn't have to come from plugins, you can also add project-level functionality by simply adding files in your `src/` folder. Medusa will automatically register your custom functionalities in the bootstrap phase. + +::: ![](https://i.imgur.com/hqiaoFq.png) @@ -88,7 +90,11 @@ When you have added your text you can click **Publish changes** (make sure the A ## Updating the storefront to support the Rich Text module -> If you want to jump straight to the final frontend code visit [medusajs/medusa-contentful-storefront@part-2](https://github.com/medusajs/medusa-contentful-storefront/tree/part-2). +:::note + + If you want to jump straight to the final frontend code visit [medusajs/medusa-contentful-storefront@part-2](https://github.com/medusajs/medusa-contentful-storefront/tree/part-2). + +::: To display your newly created Rich Text module open up the storefront code and create a new file at `src/components/rich-text/rich-text.jsx`. diff --git a/docs/content/how-to/notification-api.md b/docs/content/how-to/notification-api.md index c00f1508b4..97ed5c5f8b 100644 --- a/docs/content/how-to/notification-api.md +++ b/docs/content/how-to/notification-api.md @@ -77,9 +77,12 @@ class MyService extends NotificationService { export default MyService; ``` +:::note Note -> **Note:** a notification service must have a static property called `identifier` this is used to determine which classes are called when subscribing to different events. In this case the service identifier is `my-service` so to subscribe to notifications you must use: -> `notificationService.subscribe([eventname], "my-service")` + A notification service must have a static property called `identifier` this is used to determine which classes are called when subscribing to different events. In this case the service identifier is `my-service` so to subscribe to notifications you must use: + `notificationService.subscribe([eventname], "my-service")` + +::: The above class is an example implementation of a NotificationService. It uses a fictional email service called `CoolEmailSender` to send emails to a customer whenever an order is placed. The `sendNotification` implementation gets the event name and fetches relevant data based on what event is being processed; in this case it retrieves an order, which is later used when requesting `CoolEmailSender` to dispatch an email. The address to send the email to is likewise fetched from the order. diff --git a/docs/content/how-to/setting-up-a-nextjs-storefront-for-your-medusa-project.md b/docs/content/how-to/setting-up-a-nextjs-storefront-for-your-medusa-project.md index 7b04466b0f..b9015c23c5 100644 --- a/docs/content/how-to/setting-up-a-nextjs-storefront-for-your-medusa-project.md +++ b/docs/content/how-to/setting-up-a-nextjs-storefront-for-your-medusa-project.md @@ -4,8 +4,12 @@ title: Setting up a Next.js storefront for your Medusa project # Setting up a Next.js storefront for your Medusa project -> Medusa is a headless open source commerce platform giving engineers the foundation for building unique and scalable digital commerce projects through our API-first engine. -> Being headless, our starters serve as a good foundation for you to get coupled with a frontend in a matter of minutes. +:::note + +Medusa is a headless open source commerce platform giving engineers the foundation for building unique and scalable digital commerce projects through our API-first engine. +Being headless, our starters serve as a good foundation for you to get coupled with a frontend in a matter of minutes. + +::: This article assumes you already have the Medusa project created and ready to be linked to your Next.js starter. diff --git a/docs/content/how-to/uploading-images-to-minio.md b/docs/content/how-to/uploading-images-to-minio.md index df96e1b730..99afd814f1 100644 --- a/docs/content/how-to/uploading-images-to-minio.md +++ b/docs/content/how-to/uploading-images-to-minio.md @@ -46,7 +46,11 @@ Then configure your `medusa-config.js` to include the plugin alongside the requi The two access keys in the options are the ones created in the previous section. -> Make sure to use an environment variable for the secret key in a live environment. +:::note + +Make sure to use an environment variable for the secret key in a live environment. + +::: ### Try it out diff --git a/docs/content/how-to/uploading-images-to-s3.md b/docs/content/how-to/uploading-images-to-s3.md index 12c8a36ff5..45163a0c83 100644 --- a/docs/content/how-to/uploading-images-to-s3.md +++ b/docs/content/how-to/uploading-images-to-s3.md @@ -78,7 +78,11 @@ https://[bucket].s3.[region].amazonaws.com The two access keys in the options are the ones created in the previous section. -> Make sure to use an environment variable for the secret key in a live environment. +:::note + +Make sure to use an environment variable for the secret key in a live environment. + +::: ### Try it out diff --git a/docs/content/how-to/uploading-images-to-spaces.md b/docs/content/how-to/uploading-images-to-spaces.md index 4ad47a48d6..a8416a0b57 100644 --- a/docs/content/how-to/uploading-images-to-spaces.md +++ b/docs/content/how-to/uploading-images-to-spaces.md @@ -41,7 +41,11 @@ Then configure your `medusa-config.js` to include the plugin alongside the requi In the above options, a `spaces_url` is included. This can be found in your Space overview. The `bucket` should point to the name you gave your Space. The `endpoint` identifies the region in which you created the Space. And finally the two keys are the ones created in the previous section. -> Make sure to use an environment variable for the secret key in a live environment. +:::note + +Make sure to use an environment variable for the secret key in a live environment. + +::: ### Try it out! diff --git a/docs/content/quickstart/quick-start.md b/docs/content/quickstart/quick-start.md index c41b518a41..494b36331c 100644 --- a/docs/content/quickstart/quick-start.md +++ b/docs/content/quickstart/quick-start.md @@ -50,7 +50,11 @@ We have created two starters for you that can help you lay a foundation for your - [Nextjs Starter](https://github.com/medusajs/nextjs-starter-medusa) - [Gatsby Starter](https://github.com/medusajs/gatsby-starter-medusa) -> Note: Medusa runs on port 9000 by default and the storefront starters are both configured to run on port 8000. If you wish to run your storefront starter on another port you should update your CORS settings in your project's `medusa-config.js`. +:::note + +Medusa runs on port 9000 by default and the storefront starters are both configured to run on port 8000. If you wish to run your storefront starter on another port you should update your CORS settings in your project's `medusa-config.js`. + +:::