首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

微信公眾號 Access Token 獲取、儲存與自動刷新完整方案

     編輯:關於C語言

核心痛點

  • access_token 為全域唯一憑證,有效期 **7200 秒 (2 小時)**。
  • 重複獲取會使上一個失效,且 **API 每日調用上限極低**。
  • 必須**全域單例儲存**,並在過期前主動刷新,避免業務中斷。

資料庫設計

表 SWX_Config 記錄每個公眾號的 Token 與時間戳:

CREATE TABLE SWX_Config (
    UserName      NVARCHAR(50) PRIMARY KEY,  -- 管理員帳號
    AppID         NVARCHAR(50) NOT NULL,
    APPSecret     NVARCHAR(100) NOT NULL,
    AccessToken   NVARCHAR(500),
    TokenExpires  DATETIME       -- 可選:記錄過期時間,減少探測請求
);

架構分層

  1. HttpRequestUtil:封裝 HttpWebRequest GET/POST、檔案上傳。
  2. Tools:輕量 JSON 節點擷取(避免引入完整 Json.NET 依賴)。
  3. WXApi:微信介面封裝(獲取 Token、驗證過期)。
  4. AdminUtil:業務協調,決定「讀取緩存」或「重新獲取並持久化」。

關鍵程式碼實作

1. HTTP 請求基礎類

public static class HttpRequestUtil
{
    public static string RequestUrl(string url, string method = "POST")
    {
        var req = (HttpWebRequest)WebRequest.Create(url);
        req.Method = method;
        req.ContentType = "text/html";
        req.Headers.Add("charset", "utf-8");
        req.CookieContainer = new CookieContainer();
        req.AllowAutoRedirect = true;

        using (var resp = (HttpWebResponse)req.GetResponse())
        using (var stream = resp.GetResponseStream())
        using (var reader = new StreamReader(stream, Encoding.UTF8))
            return reader.ReadToEnd();
    }

    public static string PostUrl(string url, string postData)
    {
        byte[] data = Encoding.UTF8.GetBytes(postData);
        var req = (HttpWebRequest)WebRequest.Create(url);
        req.Method = "POST";
        req.ContentType = "application/x-www-form-urlencoded";
        req.ContentLength = data.Length;
        req.CookieContainer = new CookieContainer();

        using (var outStream = req.GetRequestStream())
            outStream.Write(data, 0, data.Length);

        using (var resp = (HttpWebResponse)req.GetResponse())
        using (var stream = resp.GetResponseStream())
        using (var reader = new StreamReader(stream, Encoding.UTF8))
            return reader.ReadToEnd();
    }
}

2. 輕量 JSON 值擷取

public static class Tools
{
    public static string GetJsonValue(string json, string key)
    {
        if (string.IsNullOrEmpty(json)) return string.Empty;
        key = $"\"{key.Trim('\"')}\"";
        int idx = json.IndexOf(key);
        if (idx < 0) return string.Empty;
        idx += key.Length + 1; // skip colon and space
        int end = json.IndexOf(',', idx);
        if (end < 0) end = json.IndexOf('}', idx);
        if (end < 0) return string.Empty;
        return json.Substring(idx, end - idx).Trim('"', ' ', '\'');
    }
}

3. Token 過期檢測(呼叫自定義菜單介面,errcode=42001 表過期)

public static class WXApi
{
    public static bool TokenExpired(string accessToken)
    {
        string url = $"https://api.weixin.qq.com/cgi-bin/menu/get?access_token={accessToken}";
        string json = HttpRequestUtil.RequestUrl(url);
        return Tools.GetJsonValue(json, "errcode") == "42001";
    }

    public static string GetToken(string appId, string secret)
    {
        string url = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appId}&secret={secret}";
        string json = HttpRequestUtil.RequestUrl(url);
        return Tools.GetJsonValue(json, "access_token");
    }
}

4. 統一入口:獲取可用 Token(含自動刷新與資料庫落地)

public static class AdminUtil
{
    public static string GetAccessToken(PageBase page)
    {
        var user = GetLoginUser(page);
        if (user == null) return string.Empty;

        string token = user.AccessToken;

        if (string.IsNullOrWhiteSpace(token) || WXApi.TokenExpired(token))
        {
            token = WXApi.GetToken(user.AppID, user.APPSecret);
            // 持久化到資料庫
            string sql = $"UPDATE SWX_Config SET AccessToken='{token}' WHERE UserName='{user.UserName}'";
            MSSQLHelper.ExecuteSql(sql);
        }
        return token;
    }
}

進階優化建議

  • 雙緩存策略:記憶體 static ConcurrentDictionary + 資料庫,減少 DB 讀寫。
  • 背景定時刷新:啟動 Timer 或 HostedService,在過期前 5 分鐘主動刷新,完全避免請求阻塞。
  • 分散式鎖:多實例部署時,用 Redis SETNX 確保同一時間只有一個節點呼叫微信 API。
  • 記錄 TokenExpires:資料庫存入過期時間,啟動時直接判斷是否過期,省去一次 HTTP 探測。

結語

本方案以「檢測過期 → 重新獲取 → 持久化」為核心邏輯,配合輕量 HTTP/JSON 工具,零第三方依賴即可穩定支撐微信公眾號高頻介面調用。實際上線後建議加入上述進階優化,進一步提升可用性與擴展性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved