Skip to content

New endpoint in orders/{id}/actions to send email #54597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jan 30, 2025

Conversation

coreymckrill
Copy link
Contributor

@coreymckrill coreymckrill commented Jan 17, 2025

Changes proposed in this Pull Request:

This revamps the existing OrdersActionsRestController and adds some additional endpoints:

  • A GET endpoint at orders/{id}/actions/email_templates to get a list of email templates that can be sent for this particular order.
  • A POST endpoint at orders/{id}/actions/send_email where you can trigger the sending of an email template for a particular order.

This also adds some other new things:

  • A helper method for adding or updating the billing email of the order.
  • Filter and action hooks so that extensions that register additional email templates can include them in the list of available templates for an order.

Initially this new functionality was going to be added as an entirely separate endpoint, but after reviewing the existing functionality in the send_order_details order action, we decided that this would fit better, and allow us to have less duplicated code, if we just expanded the existing endpoint.

Fixes #53810

Post-merge

  • Developer advisory about change to the send_order_details endpoint, and about embedded data in orders endpoint
  • Update REST API docs

How to test the changes in this Pull Request:

  1. Install a plugin like WP Mail Logging on your test site so you can observe outgoing email.
  2. Via the web UI, create an order with at least two products in it (or one product with at least 2 for quantity). For now you can leave the status at Pending, and don't add a billing email.
  3. Now fire up your REST API client of choice and make a request for the order you just created:
    GET wc/v3/orders/{order ID}
  4. In the response, look for the _links property, and find the new email_templates item within it.
  5. Make a request to the URL provided in the email_templates link (GET wc/v3/orders/{order ID}/actions/email_templates). You should get back an empty array, because the order doesn't have a billing email set yet, so there are no email templates available to send.
  6. Try to send an email for the order using POST wc/v3/orders/{order ID}/actions/send_email. You'll need to include a template ID in the payload:
    {"template_id": "customer_invoice"}
    You should get a message back saying "Order does not have an email address.".
  7. Ok, now make the same request to send_email, but include params for both template_id and email:
    {"template_id": "customer_invoice", "email": "someone@example.org"}
    This should update the order to have a billing address. Check the mail logger and see that an Order Details email was sent.
  8. The order has a billing email now, so make another request to get the order data, but with one extra parameter:
    GET wc/v3/orders/{order ID}?_embed=email_templates
  9. In the response, you should see a new _embedded property. Within that should be an email_templates item with an array of available template IDs. This order should currently only have one available template, customer_invoice.
  10. If you make another request to the email_templates link, you should get back a similar array as the one in the _embedded property, but each item should also include a title and description in addition to the ID.
  11. Update the order status to Processing, and then request the order data again. Now you should have two template IDs available, customer_invoice and customer_processing_order.
  12. Try to send the customer_processing_order template, but with a different email address:
    POST wc/v3/orders/{order ID}/actions/send_email
    {"template_id": "customer_processing_order", "email": "someone.else@example.org"}
  13. You should get an error, because the order already has a billing email set.
  14. Try again, but include the force param:
    {"template_id": "customer_processing_order", "email": "someone.else@example.org", "force_email_update": "true"}
  15. This time the email should send successfully, and the order should now have the new value for the billing email.
  16. Try various other order statuses and see which email templates are available. Try making a partial refund on the order, and see what other template then becomes available for it.

This revamps the existing OrdersActionsRestController and adds some
additional endpoints:
* A GET endpoint at orders/{id}/actions/email to get a list of email
  templates that can be sent for this particular order.
* A POST endpoint at orders/{id}/actions/email where you can trigger
  the sending of an email template for a particular order.

This also adds some other new things:
* A helper method for adding or updating the billing email of the order.
* Filter and action hooks so that extensions that register additional
  email templates can include them in the list of available templates
  for an order.

Initially this new functionality was going to be added as an entirely
separate endpoint, but after reviewing the existing functionality in
the `send_order_details` order action, we decided that this would fit
better, and allow us to have less duplicated code, if we just expanded
the existing endpoint.

Fixes #53810
@coreymckrill coreymckrill added Email Issues related to emails. Order Management Issues related to orders. REST/Store API/Webhooks Issues related to WooCommerce REST API. plugin: woocommerce Issues related to the WooCommerce Core plugin. labels Jan 17, 2025
@coreymckrill coreymckrill self-assigned this Jan 17, 2025
@coreymckrill coreymckrill added the stakeholder: mobile teams Task impacting the mobile apps. label Jan 17, 2025
@coreymckrill coreymckrill marked this pull request as ready for review January 24, 2025 20:44
Copy link
Contributor

Hi @albarin, @staskus,

Apart from reviewing the code changes, please make sure to review the testing instructions and verify that relevant tests (E2E, Unit, Integration, etc.) have been added or updated as needed.

You can follow this guide to find out what good testing instructions should look like:
https://github.com/woocommerce/woocommerce/wiki/Writing-high-quality-testing-instructions

Copy link
Contributor

github-actions bot commented Jan 24, 2025

Test using WordPress Playground

The changes in this pull request can be previewed and tested using a WordPress Playground instance.
WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Test this pull request with WordPress Playground.

Note that this URL is valid for 30 days from when this comment was last updated. You can update it by closing/reopening the PR or pushing a new commit.

Copy link
Contributor

@albarin albarin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @coreymckrill 👏
I've left a couple of review comments and also this small thing I found about the testing steps:

On step 6. Try sending an email for the order using POST wc/v3/orders/{order ID}/actions/send_email. You should get a message back saying "Order does not have an email address.", I'm getting:

{
  "code": "rest_missing_callback_param",
  "message": "Missing parameter(s): template_id",
  "data": {
    "status": 400,
    "params": [
      "template_id"
    ]
  }
}

I'm only getting the "Order does not have an email address." when I send the template_id in the request body, I think that's correct right? It's the test step that needs to be updated.

Copy link
Contributor

@albarin albarin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fixes, is looking good! ✅

@staskus
Copy link
Contributor

staskus commented Jan 28, 2025

👍 Thank you again! This adds comprehensive emailing capabilities that I'm excited to see!

✅ I tested all the scenarios and they work as described!

I also tried to model these new APIs within our current IPP/POS flows. This is how I imagine they could be integrated in the beginning:

🟢 Succesful payment

Merchant selects "Email Receipt", and enters an email address. We send:

PATH: wc/v3/orders/{order ID}/actions/send_email
BODY: {"template_id": "customer_completed_order", "email": "someone@example.org"}

Optionally, we would immediately pass "force_email_update": "true" with a note that this action overrides the billing email address.

It sends a “Thanks for shopping with us” email. The same one is sent if customer's email is attached to the order before the payment.

🔴 Failed payment

Same flow. Merchant selects "Email Receipt", and enters an email address. We send an email with a different template:

PATH: wc/v3/orders/{order ID}/actions/send_email
BODY: {"template_id": "customer_failed_order", "email": "someone@example.org"}

It sends "Sorry, your order was unsuccessful” email

Question

These flows would depend on hardcoded template_id to avoid making another API call to:

  • GET wc/v3/orders/{order ID}/actions/email_templates or
  • GET wc/v3/orders/{order ID}?_embed=email_templates

As a designer of this API, do you think it's reasonable to hardcode template_ids? We would like to avoid making another API call, especially if it doesn't add additional functionality.

I do imagine additional flows, that could utilize actions/email_templates. For example, having a broader email functionality within order details would allow merchants to pick from a list of available templates to send to the customer.

@coreymckrill
Copy link
Contributor Author

@albarin sorry, forgot to mention that I also updated the testing instructions from your feedback. Does it look better now?

@coreymckrill
Copy link
Contributor Author

@staskus

These flows would depend on hardcoded template_id to avoid making another API call...

I was assuming that there would be a time somewhere in the mobile app flow where you would GET the order data and could store the available template IDs for future use. 🤔 But maybe that wouldn't always be the case? One easy thing we could do here is add an enum to the schema for the template_id property so it would show what all the possible IDs are, even if they aren't all available for the current order. Then you could do an OPTIONS request to get that list and cache it for later use... would that be helpful?

do you think it's reasonable to hardcode template_ids?

I don't think hardcoding the template ID values is necessarily problematic, you're probably already doing that with other things like order statuses? But, because this new endpoint is extensible, and other extensions such as WooPayments could add their own email templates to the list, you'd probably still want to have a flow somewhere that retrieves the list just to see what's available.

@coreymckrill
Copy link
Contributor Author

Ok, I added the enum to the schema...

@staskus
Copy link
Contributor

staskus commented Jan 29, 2025

@coreymckrill

I was assuming that there would be a time somewhere in the mobile app flow where you would GET the order data and could store the available template IDs for future use. One easy thing we could do here is add an enum to the schema for the template_id property so it would show what all the possible IDs are, even if they aren't all available for the current order

Yes, it's more likely we prefer to cache available email templates rather than rely on additional calls during the payment process. Unless we update our flows to let the merchant pick a desired template, we will still need to decide within the code which templates we want to send at which moment in time. Therefore, having hardcoded template_ids within the code will be hard to avoid. The ability to fetch all available or all template IDs allows to add of an extra layer of stability to the solution.

But, because this new endpoint is extensible, and other extensions such as WooPayments could add their own email templates to the list, you'd probably still want to have a flow somewhere that retrieves the list just to see what's available.

Yes. I think what this endpoint opens up - the ability to have a more comprehensive emailing functionality from within the app. That's where the functionality to fetch templates with their titles and allow merchants to pick the desired one could be a nice addition.

@coreymckrill coreymckrill merged commit c955b15 into trunk Jan 30, 2025
28 checks passed
@coreymckrill coreymckrill deleted the fix/53810/rest-order-emails branch January 30, 2025 00:44
@github-actions github-actions bot added this to the 9.8.0 milestone Jan 30, 2025
@github-actions github-actions bot added the needs: analysis Indicates if the PR requires a PR testing scrub session. label Jan 30, 2025
@rodelgc rodelgc added needs: internal testing Indicates if the PR requires further testing conducted by Solaris status: analysis complete Indicates if a PR has been analysed by Solaris and removed needs: analysis Indicates if the PR requires a PR testing scrub session. labels Jan 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Email Issues related to emails. needs: internal testing Indicates if the PR requires further testing conducted by Solaris Order Management Issues related to orders. plugin: woocommerce Issues related to the WooCommerce Core plugin. REST/Store API/Webhooks Issues related to WooCommerce REST API. stakeholder: mobile teams Task impacting the mobile apps. status: analysis complete Indicates if a PR has been analysed by Solaris
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enable sending order-related customer emails via REST API request
5 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy