微信公众号 API 代理配置

解决本地 IP 变动及 VPN 导致的微信白名单验证失败问题。

本方案提供 Cloudflare Worker 或 PHP 服务器作为中转。请妥善保管你的代理服务地址,防止被他人滥用。

1

创建 Cloudflare Worker

  • 登录 Cloudflare Dashboard
  • 在左侧菜单选择 Workers & Pages
  • 点击 Create ApplicationCreate Worker
  • 为服务命名(例如:wechat-proxy),然后点击 Deploy
2

部署代理代码

点击 Edit code,清空原有内容,粘贴以下代码并点击 Deploy

export default {
  async fetch(request, env) {
    const MAX_UPLOAD_BYTES = 10 * 1024 * 1024;
    const ALLOWED_METHODS = new Set(['GET', 'POST', 'UPLOAD']);
    const corsHeaders = {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'POST, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type',
    };

    const jsonResponse = (payload, status = 200) =>
      new Response(JSON.stringify(payload), {
        status,
        headers: {
          ...corsHeaders,
          'Content-Type': 'application/json; charset=utf-8',
        },
      });

    const isAllowedWechatUrl = (rawUrl) => {
      try {
        const parsed = new URL(rawUrl);
        return parsed.protocol === 'https:' && parsed.hostname === 'api.weixin.qq.com';
      } catch {
        return false;
      }
    };

    const toUint8Array = (base64) => {
      const binary = atob(base64);
      const bytes = new Uint8Array(binary.length);
      for (let i = 0; i < binary.length; i++) {
        bytes[i] = binary.charCodeAt(i);
      }
      return bytes;
    };

    // 处理 CORS 预检请求
    if (request.method === 'OPTIONS') {
      return new Response(null, { headers: corsHeaders });
    }

    if (request.method !== 'POST') {
      return jsonResponse({ error: 'Method Not Allowed' }, 405);
    }

    try {
      const body = await request.json();
      const { url, method = 'GET', data, fileData, fileName, mimeType } = body;
      const normalizedMethod = String(method || 'GET').toUpperCase();
      
      // 安全校验:只允许访问微信 API
      if (typeof url !== 'string' || !isAllowedWechatUrl(url)) {
        return jsonResponse({ error: 'Invalid URL. Only https://api.weixin.qq.com/ is allowed.' }, 400);
      }

      if (!ALLOWED_METHODS.has(normalizedMethod)) {
        return jsonResponse({ error: 'Invalid method. Only GET, POST, and UPLOAD are allowed.' }, 400);
      }

      let response;
      if (normalizedMethod === 'UPLOAD') {
        if (typeof fileData !== 'string' || fileData.length === 0) {
          return jsonResponse({ error: 'Missing fileData for upload.' }, 400);
        }

        const approxBytes = Math.floor(fileData.length * 3 / 4);
        if (approxBytes > MAX_UPLOAD_BYTES) {
          return jsonResponse({ error: 'Upload too large. Maximum size is 10 MB.' }, 413);
        }

        const safeMimeType =
          typeof mimeType === 'string' && mimeType.startsWith('image/')
            ? mimeType
            : 'application/octet-stream';
        const safeFileName =
          typeof fileName === 'string' && /^[\w.\-]+$/.test(fileName)
            ? fileName
            : 'image';

        // 文件上传处理:Base64 -> Binary -> FormData
        const bytes = toUint8Array(fileData);
        const formData = new FormData();
        formData.append('media', new Blob([bytes], { type: safeMimeType }), safeFileName);
        response = await fetch(url, { method: 'POST', body: formData });
      } else {
        // 普通 JSON 请求
        const opts = { method: normalizedMethod };
        if (normalizedMethod === 'POST') {
          opts.headers = { 'Content-Type': 'application/json' };
          if (data !== undefined) opts.body = JSON.stringify(data);
        }
        response = await fetch(url, opts);
      }

      const responseText = await response.text();
      let result;
      try {
        result = responseText ? JSON.parse(responseText) : {};
      } catch {
        return jsonResponse({ error: 'Upstream returned a non-JSON response.' }, 502);
      }

      return jsonResponse(result, response.status);
    } catch (error) {
      return jsonResponse({ error: 'Proxy request failed.' }, 500);
    }
  }
};
3

配置微信白名单

登录微信公众号后台,在 基本配置 -> IP白名单 中添加 Cloudflare 的出口 IP 段。
以下是整理好的 IP 列表(每行一个,可直接复制粘贴):

提示: Cloudflare IP 偶尔会有更新。若报错建议对照 Cloudflare 官方列表 检查。

官方页面包含 IPv4 和 IPv6,请仅复制 IPv4 列表

* 数据来源:Cloudflare Official IPs

4

插件配置

回到 Obsidian 插件设置页面:

  1. 进入 高级设置
  2. 找到 API 代理地址 选项
  3. 填入你的 Worker URL,例如:
    https://wechat-proxy.your-account.workers.dev

Generated for Obsidian WeChat Plugin