# How the WeChat Message Template Sending System Works in mini-shop-server

> Discover how the WeChat message template sending system in mini-shop-server works. Learn about its three-layer architecture and how it prepares data for the official WeChat API endpoint.

- Repository: [A粒麦子/mini-shop-server](https://github.com/allen7d/mini-shop-server)
- Tags: internals
- Published: 2026-02-24

---

**The WeChat message template sending system in mini-shop-server implements a three-layer architecture that retrieves an access token via `WxToken`, constructs a JSON payload using the `WxMessage` base class and its subclasses, and prepares the data for the official WeChat template message API endpoint.**

The `mini-shop-server` repository provides a lightweight Flask-based implementation for sending WeChat Mini Program template messages. The system handles authentication, payload construction, and API communication through a series of service classes located in the `app/service/` directory. While the final HTTP POST is currently stubbed in the source, the infrastructure demonstrates the complete flow required to notify users about order status changes.

## Token Retrieval with WxToken

The authentication flow begins in [`app/service/wx_token.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/service/wx_token.py) with the `WxToken` class. This service obtains a short-lived access token required for all WeChat API interactions.

The class constructs a login URL using Flask configuration values (`APP_ID`, `APP_SECRET`, and `LOGIN_URL`). It then executes an HTTP GET request via the generic helper `HTTP.get` (defined in [`app/libs/httper.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/libs/httper.py)) to fetch the token JSON. If the WeChat API returns an error code, the service raises a `WeChatException` to halt processing and prevent invalid API calls.

```python

# Conceptual flow based on wx_token.py implementation

from app.service.wx_token import WxToken

# Raises WeChatException if credentials are invalid or API returns error

token_data = WxToken.get_token(code="wechat_login_code")
access_token = token_data.get("access_token")

```

## Building the Message Payload

The message construction logic resides in [`app/service/wx_message.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/service/wx_message.py), which defines the `WxMessage` base class. This class stores the WeChat template message endpoint template: `https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=%s`.

Concrete implementations like `DeliveryMessage` in [`app/service/delivery_message.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/service/delivery_message.py) inherit from `WxMessage` and set specific fields:

- **`tlp_id`**: The WeChat template ID configured for the specific notification type
- **`form_id`**: Collected from `order.prepay_id`, this unique identifier allows the Mini Program to push messages to the user
- **`page`**: The Mini Program page path users navigate to when tapping the message
- **`emphasis_keyword`**: Specifies which keyword to highlight in the notification

The `__prepare_message_data` method constructs the `data` dictionary following WeChat's schema, mapping values to `keyword1` through `keyword4` fields with optional color specifications.

```python

# Example from delivery_message.py showing payload preparation

class DeliveryMessage(WxMessage):
    def send_delivery_message(self, order, tpl_jump_page=None):
        self.tlp_id = "your_template_id_here"
        self.form_id = order.prepay_id  # Critical: must be recent prepay_id

        self.page = tpl_jump_page       # e.g., "pages/order/detail?id=123"

        self.__prepare_message_data(order)
        # Payload now ready for transmission

```

## The Sending Flow (Current Implementation)

The final transmission step is currently stubbed in `DeliveryMessage.send_delivery_message`, which returns an empty string `''` instead of executing the HTTP request. In a complete production deployment, the method would execute the following sequence:

1. **Retrieve fresh token**: Call `WxToken` to obtain a valid `access_token`
2. **Format endpoint URL**: Insert the token into `self.__send_url % access_token`
3. **Execute POST**: Use `HTTP.post` (from [`app/libs/httper.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/libs/httper.py)) to transmit the JSON body:

```json
{
  "touser": "OPENID",
  "template_id": "TEMPLATE_ID",
  "page": "pages/index/index",
  "form_id": "PREPAY_ID",
  "data": {
    "keyword1": {"value": "Product Name"},
    "keyword2": {"value": "Shipped"},
    "keyword3": {"value": "2024-01-15"}
  },
  "emphasis_keyword": "keyword2.value"
}

```

The `HTTP` helper in [`app/libs/httper.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/libs/httper.py) provides the underlying GET and POST methods used throughout the application for external API communication.

## Integration Example: Order Delivery Notifications

In practice, the system triggers when an order status changes. The order service instantiates `DeliveryMessage` and passes the order object along with an optional navigation page.

```python
from app.service.delivery_message import DeliveryMessage
from app.models.order import Order

def notify_user_of_shipment(order_id):
    order = Order.query.get(order_id)
    
    if not order:
        raise OrderException("Order not found")
    
    messenger = DeliveryMessage()
    messenger.send_delivery_message(
        order=order,
        tpl_jump_page=f"pages/order/detail?id={order.id}"
    )
    # In current implementation, returns empty string

    # In production, would return WeChat API response

```

The method validates the order's existence and raises `OrderException` if falsy, ensuring that only valid transactions generate notification attempts.

## Summary

- **`WxToken`** manages OAuth2 authentication with WeChat, fetching access tokens using `APP_ID` and `APP_SECRET` from Flask config
- **`WxMessage`** provides the base structure for template messages, including the official WeChat API endpoint URL pattern
- **`DeliveryMessage`** demonstrates concrete implementation, mapping order data to WeChat's keyword-based template format using `prepay_id` as the `form_id`
- The architecture follows the **token → payload → POST** pattern required by WeChat's template message API, though the final HTTP transmission requires implementation in the stubbed `send_delivery_message` method
- All HTTP operations rely on the generic `HTTP` helper located in [`app/libs/httper.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/libs/httper.py)

## Frequently Asked Questions

### What is the role of the form_id in WeChat template messages?

The `form_id` is a unique identifier that authorizes the Mini Program to send a template message to a specific user. In `mini-shop-server`, this value is extracted from `order.prepay_id`, which is generated during the WeChat payment process. Each `form_id` can only be used once and expires after seven days, making it essential to send notifications promptly after payment completion.

### Why is the final HTTP POST request stubbed in the current source code?

The `send_delivery_message` method in [`app/service/delivery_message.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/service/delivery_message.py) currently ends with `return ''`, indicating the repository is either a demonstration template or awaiting completion. The stub preserves the business logic and data preparation layers while allowing developers to implement the actual HTTP call using the `HTTP.post` method from [`app/libs/httper.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/libs/httper.py) when integrating with live WeChat credentials.

### How does mini-shop-server handle WeChat API authentication errors?

The `WxToken` class in [`app/service/wx_token.py`](https://github.com/allen7d/mini-shop-server/blob/main/app/service/wx_token.py) validates the JSON response from WeChat's token endpoint. If the response contains an `errcode` field, the service raises `WeChatException` with the error details. This prevents the application from attempting to send template messages with invalid credentials and allows upstream error handling to manage retries or user notifications.

### What configuration values are required to enable WeChat template messaging?

The system requires three Flask configuration variables defined in the application config: `APP_ID` (WeChat Mini Program AppID), `APP_SECRET` (corresponding secret key), and `LOGIN_URL` (WeChat's `jscode2session` endpoint). These values are consumed by `WxToken` to authenticate with WeChat's servers and obtain the `access_token` necessary for all template message API calls.