After a payment, the customer expects an email: "we got your money". A shop doesn't run its own mail server. It calls a mail service through its API, like the supplier and the payment provider. Ours lives at http://127.0.0.1:8003: you POST JSON with "to", "subject" and "body" to /send, and it answers 202 Accepted, which means "I have it, I'll deliver it".
The email's text is built from pieces joined with +. When one side of + is a String, Java turns a number on the other side into text by itself:
int count = 3;
String text = "You have " + count + " new messages";
System.out.println(text); // You have 3 new messages
Put the email in a helper method, so it has its own place and other code can send it too. Call it from payOrder only once the order is saved as paid: a declined card returns earlier, and so does a retry with the same idempotency key, so neither sends an email. The checker adds GET /check/sent, the list of emails the mail service received:
POST /orders/8/pay (Idempotency-Key: 5f1d7c9e-…) → 201 {"amount": 80, "order_id": 8, "payment_id": "pay_1"}
GET /check/sent → 200 [{"body": "Hello Eva Rossi, we received your payment of 80. Thank you!", "id": 1, "subject": "Your order 8 is paid", "to": "eva@example.com"}]
POST /orders/8/pay (the same key) → 201 {"amount": 80, "order_id": 8, "payment_id": "pay_1"}
POST /orders/9/pay → 402 {"error": "Payment declined", "reason": "card_declined"}
POST /orders/10/pay → 201 {"amount": 21, "order_id": 10, "payment_id": "pay_2"}
GET /check/sent → 200 [Eva's email, {"body": "Hello Chloe Ng, we received your payment of 21. Thank you!", "id": 2, "subject": "Your order 10 is paid", "to": "chloe@example.com"}]
Your task: add the constant MAIL, then write HttpResponse<String> sendReceipt(int orderId): it finds the order and its customer, builds the subject and the body, and POSTs them as JSON to MAIL + "/send", returning the mail service's answer. Call it in payOrder right after the UPDATE.
Assignment
Follow the Coding Tutorial to write the sendReceipt helper and send a receipt after each successful payment.
Hint
The order has a customer_id; the name and the email are in the customers table, and db.queryForMap gives that one row as a map. The method won't compile until its return is written. A method runs only when it's called: until payOrder calls the helper, GET /check/sent stays empty.
Free plan: 30 tutor messages. PRO is unlimited.
