Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

WeChat Public Account Integration: OAuth2 Authorization and Template Messaging

Tech 1

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')

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.