diff --git a/docs/content/advanced/backend/subscribers/create-subscriber.md b/docs/content/advanced/backend/subscribers/create-subscriber.md index 5dcb25fa17..7a63a2151d 100644 --- a/docs/content/advanced/backend/subscribers/create-subscriber.md +++ b/docs/content/advanced/backend/subscribers/create-subscriber.md @@ -54,7 +54,20 @@ constructor({ productService, eventBusService }) { } ``` -You can then use `this.productService` anywhere in your subscriber’s methods. +You can then use `this.productService` anywhere in your subscriber’s methods. For example: + +```ts +handleOrder = async (data) => { + //... + const product = this.productService.list() +} +``` + +:::note + +When using attributes defined in the subscriber, such as the `productService` in the example above, you must use an arrow function to declare the method. Otherwise, the attribute will be undefined when used. + +::: ## What’s Next diff --git a/docs/content/advanced/backend/subscribers/events-list.md b/docs/content/advanced/backend/subscribers/events-list.md index 883fc0d91f..02953731bc 100644 --- a/docs/content/advanced/backend/subscribers/events-list.md +++ b/docs/content/advanced/backend/subscribers/events-list.md @@ -2681,6 +2681,55 @@ Object of the following format: +## Token Events + +This section holds all events related to tokens. + + + + + + + + + + + + + + + + + +
+Event Name + +Description + +Event Data Payload +
+ +`order-update-token.created` + + + +Triggered when a customer requests to claim an order and a token is created. + + + +Object of the following format: + +```js noReport noCopy +{ + old_email, //string email of order + new_customer_id, //string ID of customer + orders, //array of string IDs of orders + token, //string token used for verification +} +``` + +
+ ## User Events This section holds all events related to users. diff --git a/docs/content/advanced/ecommerce/handle-order-claim-event.md b/docs/content/advanced/ecommerce/handle-order-claim-event.md new file mode 100644 index 0000000000..5b5d08a750 --- /dev/null +++ b/docs/content/advanced/ecommerce/handle-order-claim-event.md @@ -0,0 +1,149 @@ +# How to Handle Order Claim Event + +In this document, you’ll learn how to handle the order claim event and send a confirmation email when the event is triggered. + +## Overview + +When a guest customer places an order, the order is not associated with a customer. It is associated with an email address. + +After the customer registers, later on, they can claim that order by providing the order’s ID. + +When the customer requests to claim the order, the event `order-update-token.created` is triggered on the Medusa server. This event should be used to send the customer a confirmation email. + +### What You’ll Learn + +In this document, you’ll learn how to handle the `order-update-token.created` event on the server to send the customer a confirmation email. + +## Prerequisites + +### Medusa Components + +It's assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.md) to get started. + +### Redis + +Redis is required for batch jobs to work. Make sure you [install Redis](../../tutorial/0-set-up-your-development-environment.mdx#redis) and [configure it with your Medusa server](../../usage/configurations.md#redis). + +### Notification Provider + +To send an email or another type of notification method, you must have a notification provider installed or configured. + +This document has an example using the [SendGrid](../../add-plugins/sendgrid.mdx) plugin. + +## Step 1: Create a Subscriber + +To subscribe to and handle an event, you must create a subscriber. + +:::tip + +You can learn more about subscribers in the [Subscribers](../backend/subscribers/overview.md) documentation. + +::: + +Create the file `src/subscribers/claim-order.ts` with the following content: + +```ts title=src/subscribers/claim-order.ts +import { EventBusService } from "@medusajs/medusa"; + +type InjectedDependencies = { + eventBusService: EventBusService, +} + +class ClaimOrderSubscriber { + constructor({ eventBusService }: InjectedDependencies) { + + } +} + +export default ClaimOrderSubscriber; +``` + +If you want to add any other dependencies, you can add them to the `InjectedDependencies` type. + +:::tip + +You can learn more about dependency injection in [this documentation](../backend/dependency-container/index.md). + +::: + +## Step 2: Subscribe to the Event + +In the subscriber you created, add the following in the `constructor`: + +```ts title=src/subscribers/claim-order.ts +constructor({ eventBusService }: InjectedDependencies) { + eventBusService.subscribe("order-update-token.created", this.handleRequestClaimOrder); +} +``` + +You use the `eventBusService` to subscribe to the `order-update-token.created` event. You pass the method `handleRequestClaimOrder` as a handler to that event. You’ll create this method in the next step. + +## Step 3: Create Event Handler + +In the subscriber, add a new method `handleRequestClaimOrder`: + +```ts title=src/subscribers/claim-order.ts +class ClaimOrderSubscriber { + //... + + handleRequestClaimOrder = async (data) { + //TODO: handle event + } +} + +export default ClaimOrderSubscriber; +``` + +The `handleRequestClaimOrder` event receives a `data` object as a parameter. This object holds the following properties: + +1. `old_email`: The email associated with the orders. +2. `new_customer_id`: The ID of the customer claiming the orders. +3. `orders`: An array of the order IDs that the customer is requesting to claim. +4. `token`: A verification token. This token is used to later verify the claim request and associate the order with the customer. + +In this method, you should typically send an email to the customer’s old email. In the email, you should link to a page in your storefront and pass the `token` as a parameter. + +The page would then send a request to the server to verify that the `token` is valid and associate the order with the customer. You can read more about how to implement this in your storefront in [this documentation](../storefront/implement-claim-order.mdx). + +## Example: Using SendGrid + +For example, you can implement this subscriber to send emails using SendGrid: + +```ts title=src/subscribers/claim-order.ts +import { EventBusService } from "@medusajs/medusa"; + +type InjectedDependencies = { + eventBusService: EventBusService, + sendgridService: any +} + +class ClaimOrderSubscriber { + protected sendGridService: any; + + constructor({ eventBusService, sendgridService }: InjectedDependencies) { + this.sendGridService = sendgridService; + eventBusService.subscribe("order-update-token.created", this.handleRequestClaimOrder); + } + + + handleRequestClaimOrder = async (data) => { + this.sendGridService.sendEmail({ + templateId: 'order-claim-confirmation', + from: 'hello@medusajs.com', + to: data.old_email, + data: { + link: `http://example-storefront.com/confirm-order-claim/${data.token}`, + //other data... + } + }) + } +} + +export default ClaimOrderSubscriber; +``` + +Notice how the `token` is passed to the storefront link as a parameter. + +## See Also + +- Learn [how to implement claim-order flow in your storefront](../storefront/implement-claim-order.mdx). \ No newline at end of file diff --git a/docs/content/advanced/storefront/implement-claim-order.mdx b/docs/content/advanced/storefront/implement-claim-order.mdx new file mode 100644 index 0000000000..0c223d556c --- /dev/null +++ b/docs/content/advanced/storefront/implement-claim-order.mdx @@ -0,0 +1,163 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# How to Implement Claim Order Flow + +In this document, you’ll learn how to implement the claim order flow in a storefront to allow customers to claim their orders. + +## Flow Overview + +When a guest customer places an order, their order is not associated with any customer. The order is only associated with an email that the guest customer provides during checkout. + +This email must be an email that isn’t used with an existing account. Also, this email cannot be used later on to create a new account. It can, however, be used to create another order as a guest customer. + +After this customer registers with a different email and logs in, they can claim their order by providing the order’s ID. An email will then be sent to the email address associated with the order. + +The email should contain a link to a page in the storefront, and the link should have a token as a parameter. This token will be used for verification. + +The customer must then click the link in the email they received. If the token is valid, the order will be associated with the customer. + +![Claim Order Flow](https://res.cloudinary.com/dza7lstvk/image/upload/v1671040165/Medusa%20Docs/Diagrams/Claim_Order_Flow_ybf2ok.jpg) + +### What You’ll Learn + +In this document, you’ll learn how to implement two parts of this flow: + +1. Allow customers to claim their orders. +2. Verify a claim to an order. + +## Prerequisites + +### Medusa Components + +It's assumed that you already have a Medusa server installed and set up. If not, you can follow the [quickstart guide](../../quickstart/quick-start.md) to get started. + +It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../../starters/nextjs-medusa-starter.md) or [Gatsby](../../starters/gatsby-medusa-starter.md) storefronts. + +### JS Client + +This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client and JavaScript’s Fetch API. + +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../js-client/overview.md) and have [created an instance of the client](../../js-client/overview.md#configuration). + +### Handle Order Claim Request Event + +When the customer requests to claim the order, an event will be triggered. You should subscribe to this event to send a confirmation email to the customer when the event is triggered. + +You can learn how to implement this flow in [this documentation](../ecommerce/handle-order-claim-event.md). + +### Previous Steps + +It is assumed you already have an order placed by a guest customer. You can refer to the [Cart](../../guides/carts-in-medusa.mdx) and [Checkout](./how-to-implement-checkout-flow.mdx) implementation documentation to learn how to implement them in your storefront. + +In addition, it is assumed you already have a logged-in customer before performing the steps in this document. You can refer to the [API reference](/api/store/#tag/Auth/operation/PostAuth) for more details on that. + +## Request to Claim an Order + +When the customer wants to claim an order, they must supply its ID. + +To allow the customer to claim an order, send a request to the Claim an Order endpoint: + + + + +```tsx +medusa.orders.claimOrders({ + order_ids: [ + order_id, + ], +}) +.then(() => { + // successful +}) +.catch(() => { + // an error occurred +}); +``` + + + + +```tsx +fetch(`/store/orders/batch/customer/token`, { + method: 'POST', + credentials: 'include', + body: JSON.stringify({ + order_ids: [ + order_id, + ], + }), + headers: { + 'Content-Type': 'application/json' + } +}) +.then(() => { + //successful +}) +.catch(() => { + //display an error to the customer +}); +``` + + + + +This request accepts as a body parameter the array `order_ids`. Each item in the array is the ID of an order that the customer wants to claim. You can pass more than one ID. + +If the customer’s request has been processed successfully, the request returns a response with a `200` status code. + +The customer at this point will receive an email with a link to verify their claim on the order. + +## Manually Verify a Claim to an Order + +The link in the email that the customer receives should be a page in your storefront that accepts a `token` query parameter. + +Then, you send a request to the Verify Claim Order endpoint: + + + + +```tsx +medusa.orders.confirmRequest({ + token +}) +.then(() => { + // successful +}) +.catch(() => { + // an error occurred +}); +``` + + + + +```tsx +fetch(`/store/orders/customer/confirm`, { + method: 'POST', + credentials: 'include', + body: JSON.stringify({ + token + }), + headers: { + 'Content-Type': 'application/json' + } +}) +.then(() => { + //successful +}) +.catch(() => { + //display an error to the customer +}); +``` + + + + +This request accepts as a body parameter the string `token`. This would be the token passed as a parameter to your storefront page through the link in the email. + +If the verification is successful, the order will now be associated with the customer and the customer will be able to see it among their orders. + +## See Also + +- Learn [how to send a confirmation email to claim an order](../ecommerce/handle-order-claim-event.md). diff --git a/www/docs/sidebars.js b/www/docs/sidebars.js index 24f20876c9..317114cc31 100644 --- a/www/docs/sidebars.js +++ b/www/docs/sidebars.js @@ -225,6 +225,11 @@ module.exports = { id: "advanced/storefront/use-discounts-in-checkout", label: "Use Discounts in Checkout" }, + { + type: "doc", + id: "advanced/backend/taxes/manual-calculation", + label: "Calculate Taxes Manually" + }, { type: "doc", id: "advanced/storefront/how-to-implement-checkout-flow", @@ -232,8 +237,8 @@ module.exports = { }, { type: "doc", - id: "advanced/backend/taxes/manual-calculation", - label: "Calculate Taxes Manually" + id: "advanced/storefront/implement-claim-order", + label: "Implement Claim Order" }, { type: "doc", @@ -347,6 +352,11 @@ module.exports = { id: "advanced/backend/price-selection-strategy/override", label: "Override Price Selection" }, + { + type: "doc", + id: "advanced/ecommerce/handle-order-claim-event", + label: "Handle Order Claim Event" + }, ] }, {