✅微信支付 & 支付宝支付 IP 校验机制与socket代理支付解决方案总结日志

社区话题 wordpress开发 ✅微信支付 & 支付宝支付 IP 校验机制与socket代理支付解决方案总结日志

正在查看 1 条回复
  • 作者
    帖子
    • #1172

      追光
      管理员

      ✅ 微信支付 & 支付宝支付 IP 校验机制与解决方案总结日志

      ? 一、IP 校验机制对比

      | 项目 | 微信支付 | 支付宝支付 |
      |——|———-|————|
      | 核心校验IP | ✅ 请求入口IP(服务器公网IP) | ✅ 请求入口IP(服务器公网IP) |
      | 辅助参数 | `spbill_create_ip`(用户终端IP) | 无类似参数 |
      | 白名单作用 | 强制校验,必须配置 | 强制校验,必须配置 |
      | 风控策略 | 较宽松,重白名单 | 极其严格,重IP历史、归属、行为 |
      | 云服务器IP | ✅ 接受(如腾讯云、阿里云国内IP) | ❌ 可能拒绝(标记为高风险) |
      | 动态IP | ❌ 拒绝 | ❌ 拒绝 |

      ?️ 二、解决方案代码

      #1. 集中管理代理配置(mu-plugin)

      创建文件:`wp-content/mu-plugins/proxy-config.php`

      php

      <?php
      /
       * 支付代理配置(集中管理)
       * 修改代理只需改这里,无需动支付文件
       */
      if (!function_exists('get_payment_proxy_config')) {
          function get_payment_proxy_config() {
              return [
                  'enabled'  => true,  // true=走代理,false=不走代理
                  'host'     => '公网socket代理ip',
                  'port'     => 'socket代理ip端口',
                  'username' => '用户名',
                  'password' => '密码'
              ];
          }
      }

      #2. 微信支付:`WxPay.Api.php`

      修改 `postXmlCurl` 函数:

      php

      private static function postXmlCurl($xml, $url, $useCert = false, $second =)
      {
          $ch = curl_init();
      
          // ??? 智能代理判断 ???
          if (function_exists('get_payment_proxy_config')) {
              $proxy = get_payment_proxy_config();
              if (!empty($proxy['enabled']) && $proxy['enabled'] === true) {
                  if (!empty($proxy['host']) && !empty($proxy['port'])) {
                      curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
                      curl_setopt($ch, CURLOPT_PROXY, $proxy['host'] . ':' . $proxy['port']);
                      curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
                      if (!empty($proxy['username']) && !empty($proxy['password'])) {
                          curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy['username'] . ':' . $proxy['password']);
                      }
                  }
              }
          }
          // ??? 智能代理判断 ???

      // … 后面代码保持不变 …
      }

      #3. 支付宝支付:`AopClient.php`

      修改 `curl` 函数:

      php

      public function curl($url, $postFields = null)
      {
          $ch = curl_init();
      
          // ??? 智能代理判断 ???
          if (function_exists('get_payment_proxy_config')) {
              $proxy = get_payment_proxy_config();
              if (strpos($url, 'alipay') !== false && !empty($proxy['enabled']) && $proxy['enabled'] === true) {
                  if (!empty($proxy['host']) && !empty($proxy['port'])) {
                      curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
                      curl_setopt($ch, CURLOPT_PROXY, $proxy['host'] . ':' . $proxy['port']);
                      curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
                      if (!empty($proxy['username']) && !empty($proxy['password'])) {
                          curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy['username'] . ':' . $proxy['password']);
                      }
                  }
              }
          }
          // ??? 智能代理判断 ???

      // … 后面代码保持不变 …
      }

      #4. 终端IP设置(可选,推荐)

      在 `WxPay.Api.php` 的 `unifiedOrder` 函数中,替换:

      php

      // 获取真实客户端 IP,确保格式正确
      function get_real_client_ip() {
          if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && filter_var($_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
              return $_SERVER['HTTP_X_FORWARDED_FOR'];
          }
          if (isset($_SERVER['HTTP_CLIENT_IP']) && filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
              return $_SERVER['HTTP_CLIENT_IP'];
          }
          if (isset($_SERVER['REMOTE_ADDR']) && filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
              return $_SERVER['REMOTE_ADDR'];
          }
          return '1.1.1.1'; // 默认 fallback
      }
      
      $inputObj->SetSpbill_create_ip(get_real_client_ip());//终端ip

      ✅ 三、最终效果

      – 微信支付:
      – 请求入口IP = `公网socket代理ip`(白名单IP)
      – `spbill_create_ip` = 真实用户IP(通过 Nginx `X-Forwarded-For` 获取)
      – ✅ 100% 合规,无需代理(但保留代理开关,兼容未来)

      – 支付宝支付:
      – 请求入口IP = `公网socket代理ip`(通过 SOCKS5 代理)
      – ✅ 绕过支付宝严格风控,100% 稳定

      – 一键切换:
      – 修改 `proxy-config.php` 中的 `’enabled’ => true/false`,秒切换代理状态
      – 插件升级无忧,配置集中管理

      ✅ 此方案为生产环境最佳实践,稳定、合规、易维护。

    • #1178

      追光
      管理员

      微信支付的ip校验是提交客户端来源的真实ip。而支付宝校验的是请求的出口ip,所以支付宝必须在请求的时候使用代理或者使用公网服务器,而微信只需要传入的时候在整个链路上都传递了真实ip,提交时候直接使用这个ip。上方的配置中,为了更加严谨和应对未来的合规性检测,我们将微信支付的出口也标准化,让微信支付和支付宝支付都使用了相同的服务器出口代理IP。

      所以:支付宝支付,必须走代理。而微信支付不强制需要走代理。

      针对微信的ip获取机制,我这里做一个进一步的补充
      ✅ 是的,这段代码在真实公网服务器上部署时,依然能获取到真实客户端 IP 但前提是:你的 Nginx/Apache 没有做反向代理或 CDN。

      ✅ 三种部署场景分析

      场景一:纯公网服务器(无反向代理、无 CDN)
      $SERVER[\’REMOTEADDR\’] = 真实用户IP ✅
      $SERVER[\’HTTPXFORWARDEDFOR\’] = 不存在或为空
      你的代码会返回 REMOTEADDR → 真实IP

      → 完美工作,100% 获取真实IP

      场景二:公网服务器 + Nginx 反向代理(如负载均衡、WAF)
      $SERVER[\’REMOTEADDR\’] = 反向代理服务器IP ❌
      $SERVER[\’HTTPXFORWARDEDFOR\’] = 真实用户IP(如果 Nginx 配置了 proxysetheader X-Forwarded-For $proxyaddxforwardedfor;)✅

      → 你的代码会返回 HTTPXFORWARDEDFOR → 真实IP

      → 依然完美工作

      场景三:公网服务器 + CDN(如 Cloudflare、阿里云CDN)
      $SERVER[\’REMOTEADDR\’] = CDN 节点IP ❌
      $SERVER[\’HTTPXFORWARDEDFOR\’] = 真实用户IP(如果 CDN 传递了)✅
      有些 CDN 用 $SERVER[\’HTTPCFCONNECTINGIP\’](Cloudflare)或自定义 Header

      → 你的代码会返回 HTTPXFORWARDEDFOR → 真实IP

      → 依然工作,但依赖 CDN 配置

      ✅ 代码为什么健壮?

      php

      function getrealclientip() {
      // 1. 优先取 X-Forwarded-For(反向代理/CDN 场景)
      if (isset($SERVER[\'HTTPXFORWARDEDFOR\']) && filtervar($SERVER[\'HTTPXFORWARDEDFOR\'], FILTERVALIDATEIP, FILTERFLAGIPV4)) {
      return $SERVER[\'HTTPXFORWARDEDFOR\'];
      }
      // 2. 其次取 HTTPCLIENTIP(某些代理)
      if (isset($SERVER[\'HTTPCLIENTIP\']) && filtervar($SERVER[\'HTTPCLIENTIP\'], FILTERVALIDATEIP, FILTERFLAGIPV4)) {
      return $SERVER[\'HTTPCLIENTIP\'];
      }
      // 3. 最后取 REMOTEADDR(直连场景)
      if (isset($SERVER[\'REMOTEADDR\']) && filtervar($SERVER[\'REMOTEADDR\'], FILTERVALIDATEIP, FILTERFLAGIPV4)) {
      return $SERVER[\'REMOTEADDR\'];
      }
      return \'1.1.1.1\'; // 兜底
      }

      兼容所有场景:直连、反向代理、CDN
      优先级合理:先取代理传递的IP,再取直连IP
      格式校验:确保返回的是合法 IPv4
      兜底机制:避免返回空值导致微信支付报错

      ✅ 最佳实践建议:

      如果你使用 Nginx 反向代理服务器,在 nginx.conf 中确保:

      nginx

      location / {
      proxysetheader X-Forwarded-For $proxyaddxforwardedfor;
      proxysetheader X-Real-IP $remoteaddr;
      proxysetheader Host $host;
      proxypass http://your-backend;
      }

      在反向代理的后端服务器需要解析真实ip:

      # 反代的真实客户端 IP
          set_real_ip_from 0.0.0.0/0;
          real_ip_header X-Forwarded-For;
          real_ip_recursive on;

      如果你使用 Cloudflare,在代码中可加:

      php

      if (isset($SERVER[\'HTTPCFCONNECTINGIP\']) && filtervar($SERVER[\'HTTPCFCONNECTINGIP\'], FILTERVALIDATEIP, FILTERFLAGIPV4)) {
      return $SERVER[\'HTTPCFCONNECTINGIP\'];
      }

      ✅ 结论:

      无论你的服务器是“后端”还是“真实公网服务器”,这段代码都能正确获取真实客户端 IP 只要你的网络架构(Nginx/CDN)正确传递了 IP 头。

正在查看 1 条回复
  • 在下方一键注册,登录后就可以回复啦。