WeChat Public Account Integration: OAuth2 Authorization and Template Messaging
Registering in the WeChat Public Platform Sandbox
To begin development, register in the WeChat public platform sandbox environment:
https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
Development Process Overview
1. Obtaining App ID and App Secret
appID: wx89085e915d351cae
appsecret: 64f87abfc664f1d4f11d0ac98b24c42d
Configure your server domain (e.g., 47.98.134.86) in the WeChat platform settings for web authorization.
2. Following the Official Account
After successful registration, you'll receive a QR code for a verified service account. Users need to scan this QR code to follow the account.
3. QR Code Generation and User Binding
Generate QR codes that users can scan. When scanned, user information is sent to WeChat, which then forwards the data to your specified redirect_uri (using MD5 hashing).
4. Callback Implementation
The callback endpoint (e.g., /callback/) should handle:
- Authorization processing
- User MD5 validation
- WeChat ID retrieval
- Database update with WeChat ID
5. Message Sending (Template Messages)
Template message functionality requires:
- WeChat ID
- Access token (valid for 2 hours)
Implementation Code
models.py
import hashlib
from django.db import models
class UserProfile(models.Model):
username = models.CharField("Username", max_length=64, unique=True)
password = models.CharField("Password", max_length=64)
uid = models.CharField(verbose_name='User Unique ID', max_length=64, unique=True)
wechat_id = models.CharField(verbose_name="WeChat ID", max_length=128, blank=True, null=True, db_index=True)
def save(self, *args, **kwargs):
# Generate unique ID when creating user
if not self.pk:
m = hashlib.md5()
m.update(self.username.encode(encoding="utf-8"))
self.uid = m.hexdigest()
super(UserProfile, self).save(*args, **kwargs)
urls.py
from django.conf.urls import url
from django.contrib import admin
from wechat_integration import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/$', views.login),
url(r'^bind/$', views.bind),
url(r'^bind_qcode/$', views.bind_qcode),
url(r'^callback/$', views.callback),
url(r'^sendmsg/$', views.sendmsg),
]
Login View
def auth_required(func):
@functools.wraps(func)
def inner(request, *args, **kwargs):
user_data = request.session.get('user_data')
if not user_data:
return redirect('/login/')
return func(request, *args, **kwargs)
return inner
def login(request):
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
user = models.UserProfile.objects.filter(username=username, password=password).first()
if user:
request.session['user_data'] = {'id': user.id, 'name': user.username, 'uid': user.uid}
return redirect('/bind/')
else:
return render(request, 'login.html')
Official Account Binding View
@auth_required
def bind(request):
return render(request, 'bind.html')
Binding Template (bind.html)
{% load staticfiles %}
WeChat Account Binding
Please follow our service account and bind your personal profile (for future notifications)
Step 1: Follow the WeChat service account
Step 2: Bind your personal account
QR Code Generation View
@auth_required
def bind_qcode(request):
response_data = {'status': 'success'}
try:
auth_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={appid}&redirect_uri={redirect_uri}&response_type=code&scope=snsapi_userinfo&state={state}#wechat_redirect"
auth_url = auth_url.format(
appid=settings.WECHAT_CONFIG["app_id"],
redirect_uri=settings.WECHAT_CONFIG["redirect_uri"],
state=request.session['user_data']['uid']
)
response_data['data'] = auth_url
except Exception as e:
response_data = {'status': 'error', 'message': str(e)}
return JsonResponse(response_data)
Callback View for Processing User Authorization
def callback(request):
authorization_code = request.GET.get("code")
user_state = request.GET.get("state")
# Retrieve user's OpenID using the authorization code
api_response = requests.get(
url="https://api.weixin.qq.com/sns/oauth2/access_token",
params={
"appid": settings.WECHAT_CONFIG["app_id"],
"secret": settings.WECHAT_CONFIG["app_secret"],
"code": authorization_code,
"grant_type": "authorization_code",
}
).()
openid = api_response.get("openid")
if openid:
models.UserProfile.objects.filter(uid=user_state).update(wechat_id=openid)
return HttpResponse("Authorization successful! Your account has been linked.
")
else:
return HttpResponse("Please complete the authorization in WeChat
")
Template Message Sending
def send_message(request):
def retrieve_access_token():
"""Obtain WeChat global interface access token (valid for 2 hours)"""
response = requests.get(
url="https://api.weixin.qq.com/cgi-bin/token",
params={
"grant_type": "client_credential",
"appid": settings.WECHAT_CONFIG['app_id'],
"secret": settings.WECHAT_CONFIG['app_secret'],
}
).()
return response.get("access_token")
access_token = retrieve_access_token()
user = models.UserProfile.objects.get(id=1)
openid = user.wechat_id
def dispatch_template_message():
"""Send template message to user"""
payload = {
"touser": openid,
"template_id": settings.WECHAT_CONFIG['template_id'],
"data": {
"first": {
"value": "Hello valued user",
"color": "#173177"
},
"keyword1": {
"value": "Important notification",
"color": "#173177"
},
}
}
response = requests.post(
url="https://api.weixin.qq.com/cgi-bin/message/template/send",
params={'access_token': access_token},
=payload
)
return response.()
result = dispatch_template_message()
return HttpResponse('Message sent successfully' if result.get('errcode') == 0 else 'Message sending failed')