WeChat Mini Program Login Flow (code2Session) Implementation in Mini-Shop Server
The Mini-Shop Server implements WeChat Mini Program authentication through a three-layer architecture that exchanges JavaScript login codes for session keys via the WeChat code2session API, creates user identities, and issues JWT tokens.
The allen7d/mini-shop-server repository provides a complete Python-based backend for e-commerce applications, including robust support for WeChat Mini Program authentication. This server-side implementation handles the OAuth-style code2session flow, transforming temporary login codes from the Mini Program into persistent user sessions without exposing sensitive credentials to the client.
Configuration and Credentials
Secure Storage of WeChat App Settings
All WeChat Mini Program credentials are centralized in app/config/secure.py (lines 18-22). This file stores the App ID, App Secret, and the official WeChat code2session endpoint URL.
# app/config/secure.py
WECHAT = {
'APP_ID': 'wx551ff8259cd7339b',
'APP_SECRET': '7773e41929841faf6aa9e68807f6e2cb',
'LOGIN_URL': 'https://api.weixin.qq.com/sns/jscode2session'
}
Keeping these values in a dedicated secure module ensures that sensitive authentication parameters remain isolated from the main application configuration and can be easily rotated without affecting business logic.
Token Service Layer
Building the WeChat API Request
The app/service/wx_token.py file contains the WxToken class, which serves as the primary interface to the WeChat authentication servers. When instantiated, this class receives the JavaScript code obtained by the Mini Program via wx.login.
The class implements three key behaviors:
wx_login_urlproperty – Dynamically formats the complete request URL by interpolatingAPP_ID,APP_SECRET, and the providedcodeinto the WeChat API template.get()method – Executes an HTTP GET request using the internalHTTPutility (fromapp/libs/httper.py) to the formatted URL and parses the JSON response.- Error normalization – Any
errcodeorerrmsgreturned by WeChat triggers aWeChatException, halting the authentication process immediately (lines 21-42).
# app/service/wx_token.py (simplified logic)
class WxToken:
def __init__(self, code):
self.code = code
self.app_id = current_app.config['WECHAT']['APP_ID']
self.app_secret = current_app.config['WECHAT']['APP_SECRET']
self.login_url = current_app.config['WECHAT']['LOGIN_URL']
@property
def wx_login_url(self):
return f"{self.login_url}?appid={self.app_id}&secret={self.app_secret}&js_code={self.code}&grant_type=authorization_code"
def get(self):
result = HTTP.get(self.wx_login_url)
if 'errcode' in result:
raise WeChatException(msg=result['errmsg'])
return result # Contains openid, session_key, expires_in
User Verification and Identity Management
Client Type Routing
When the /login endpoint receives a request, app/service/login_verify.py inspects the type parameter to determine which authentication routine to execute. For WeChat Mini Programs, the client sends type=4 (corresponding to ClientTypeEnum.WX_MINA), which triggers the verify_by_wx_mina method.
Account Creation and Lookup Logic
The verification flow follows this exact sequence as implemented in the source code:
- Instantiate
WxTokenwith the providedcode - Call
.get()to exchange the code for WeChat's response containingopenid - Query the Identity table for an existing record matching that
openidand typeWX_MINA - If no identity exists, invoke
UserDao.register_by_wx_mina(defined inapp/dao/user.py, lines 68-77) to atomically create a newUserrecord and a correspondingIdentityentry linking the WeChat OpenID to the local user ID. - If an identity exists, fetch the associated
Userrecord byuser_id.
# app/service/login_verify.py (verify_by_wx_mina logic)
ut = WxToken(code) # ← receive the Mini-Program code
wx_result = ut.get() # ← call WeChat code2session
openid = wx_result['openid'] # ← unique identifier
identity = Identity.get(identifier=openid,
type=ClientTypeEnum.WX_MINA.value)
if not identity: # first-time login → register
user = UserDao.register_by_wx_mina(openid=openid)
else:
user = User.get(id=identity.user_id)
return {'uid': user.id, 'scope': user.auth_scope}
After resolving the user record, the service generates a JWT-style authentication token via generate_auth_token, which the Mini Program stores for subsequent API requests.
End-to-End Authentication Flow
The complete interaction between client, server, and WeChat follows this path:
Mini-Program (wx.login) → client sends `code` → POST /v1/login
↓
LoginVerifyService.verify_by_wx_mina (type=4)
↓
WxToken builds https://api.weixin.qq.com/sns/jscode2session?... & GETs it
↓
WeChat returns {openid, session_key, expires_in}
↓
Server looks up Identity → creates User via UserDao.register_by_wx_mina if needed
↓
generate_auth_token → token returned to Mini-Program
Client Integration Examples
Mini Program JavaScript Implementation
To initiate the flow from the client, call wx.login to obtain a temporary code, then POST it to the server with type: 4:
wx.login({
success(res) {
if (res.code) {
wx.request({
url: 'https://your.api/v1/login',
method: 'POST',
data: {
account: res.code, // The code from wx.login
secret: '',
type: 4 // 4 == WX_MINA
},
success(r) {
console.log('auth token:', r.data.token);
wx.setStorageSync('token', r.data.token);
}
});
}
}
});
Testing with cURL
For backend debugging or automated testing, simulate the Mini Program request:
curl -X POST https://your.api/v1/login \
-H "Content-Type: application/json" \
-d '{"account":"<CODE_FROM_WX_LOGIN>","secret":"","type":4}'
Server-Side Debugging Script
To verify WeChat API connectivity independently of the application logic, reproduce the token exchange in Python:
import requests
APP_ID = 'wx551ff8259cd7339b'
APP_SECRET = '7773e41929841faf6aa9e68807f6e2cb'
code = '<CODE_FROM_CLIENT>'
login_url = (
f'https://api.weixin.qq.com/sns/jscode2session?'
f'appid={APP_ID}&secret={APP_SECRET}&js_code={code}&grant_type=authorization_code'
)
result = requests.get(login_url).json()
print(result) # {'openid': '...', 'session_key': '...', 'expires_in': 7200}
Summary
- Configuration isolation: WeChat credentials live in
app/config/secure.py, keeping secrets separate from business logic. - Service encapsulation:
app/service/wx_token.pyhandles all direct communication with WeChat'scode2sessionendpoint, normalizing errors intoWeChatException. - Identity bridging:
app/service/login_verify.pyandapp/dao/user.pymap WeChat OpenIDs to internalUserrecords, automatically registering new users throughUserDao.register_by_wx_mina. - Type dispatch: The system uses
ClientTypeEnum.WX_MINA(value4) to route Mini Program login requests to the appropriate verification handler.
Frequently Asked Questions
How does the server handle expired or invalid WeChat login codes?
The WxToken.get() method in app/service/wx_token.py inspects the JSON response from WeChat for errcode or errmsg fields. If present, it immediately raises a WeChatException, which propagates to the client as an authentication failure, preventing invalid codes from proceeding to the user lookup stage.
What happens when a user logs in for the first time versus returning?
For first-time users, the verify_by_wx_mina function detects that no Identity record exists for the provided openid and type=WX_MINA. It then calls UserDao.register_by_wx_mina (lines 68-77 in app/dao/user.py) to create both a new User entity and a linked Identity entry. Returning users simply have their existing record fetched by Identity.get, bypassing the registration logic.
Is the session_key returned by WeChat stored or used by the server?
While the WeChat API returns session_key, openid, and expires_in, the current implementation in app/service/login_verify.py primarily utilizes the openid as the unique user identifier. The session_key is available in the raw response from WxToken.get() but is not persisted in the provided code snippets, suggesting the server relies on its own JWT token mechanism rather than WeChat's session key for ongoing session management.
How does the client specify it wants WeChat Mini Program authentication?
The client must send type: 4 in the JSON payload to the /v1/login endpoint, which corresponds to ClientTypeEnum.WX_MINA.value. This numeric discriminator allows LoginVerifyService in app/service/login_verify.py to route the request to verify_by_wx_mina rather than handling it as a standard username/password or mobile login.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →