尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

微信9.9付费进群网站搭建:微信支付v3与分销返佣实战

微信9.9付费进群网站搭建:微信支付v3与分销返佣实战 简介一套可用于社群付费变现的微信付费进群网站源码与搭建教程面向具备基础建站技能、希望独立运营付费群或分销业务的站长。程序采用单页设计默认展示9.9元进群入口支持自定义价格与场景可灵活用于相亲、表情包、资源分享、社群付费等同时带分销功能便于设置推广角色并追踪订单效果但需配合认证微信服务号、营业执照和自有服务器使用。压缩包共136个文件约1.08MB包含62个HTML页面、15个PHP后台逻辑文件、多张JPG/PNG图片素材以及JS、CSS、GIF、XML等辅助文件覆盖首页、群展示、订单、支付成功页、页面设置、管理员/用户模板消息等模块目录结构清晰便于按需求定位和修改。附带搭建教程可帮助用户完成部署与参数配置降低踩坑成本目前已有987人学习下载适合想以低成本搭建付费进群及分销体系的小白或站长参考使用。1. 微信9.9付费进群网站做了什么这套系统到底要解决什么微信9.9付费进群带分销网站搭建表面看是卖群名额的小业务实际要做的是“支付、进群、分销返佣”三条链路的闭环。用户扫码进入 H5 支付页微信支付 9.9 元后拿到群入口每个用户又有一条专属邀请链接别人通过链接成交后邀请人能拿到一笔佣金。这类网站在知识付费、副业群、同城交流群里很常见不涉及库存物流核心就两件事订单与资金。很多人直接拿现成源码改改就上线结果被支付回调不通知、佣金重复入账、群二维码过期、刷单薅羊毛几件事卡住。这篇不写源码故事就按微信支付 v3 接口、MySQL 事务和 phpStudy 部署把一套能用的骨架搭出来适合懂点 PHP 基础、想自己控制业务逻辑的读者。2. 微信9.9付费进群网站的核心链路账号准备、数据库与支付回调2.1 先确定账号组合认证服务号与微信支付商户号微信9.9付费进群走的是 JSAPI 支付只能在微信内置浏览器里拉起收银台。这意味着你必须有一个已经认证的服务号订阅号没有网页授权和 JSAPI 支付能力。微信支付商户号只能挂在企业或个体工商户主体下不能直接挂在个人主体下这是第一个准入门槛。我一般会先把服务号、微信支付商户号、一台轻量云服务器和一个备案过的域名准备好再动手。小程序也能做进群业务但标题既然是“网站”就把服务号的网页授权和 JSAPI 支付权限做满。开放平台暂时不绑除非后面还要做 App 扫码登录。2.2 数据库表设计三张表撑起进群和分销业务流是“用户进页面 → 下订单 → 微信付 9.9 → 回调改单 → 给上级记佣金”所以数据库一开始不用搞复杂模型。建用户表、订单表、佣金表、提现表四张就够用下面是精简版建表 SQLCREATE TABLE user ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, openid VARCHAR(64) NOT NULL, nickname VARCHAR(100) DEFAULT , invite_code VARCHAR(16) NOT NULL UNIQUE, invite_by INT UNSIGNED NOT NULL DEFAULT 0, created_at INT UNSIGNED NOT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE pay_order ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, out_trade_no VARCHAR(32) NOT NULL UNIQUE, openid VARCHAR(64) NOT NULL, amount INT UNSIGNED NOT NULL COMMENT 金额单位分, invite_by INT UNSIGNED NOT NULL DEFAULT 0, status TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 0待支付 1已支付 2退款, transaction_id VARCHAR(64) DEFAULT , pay_time INT UNSIGNED DEFAULT 0 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE commission ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, order_id INT UNSIGNED NOT NULL UNIQUE, user_id INT UNSIGNED NOT NULL, amount INT UNSIGNED NOT NULL, status TINYINT UNSIGNED NOT NULL DEFAULT 0, created_at INT UNSIGNED NOT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE withdraw ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id INT UNSIGNED NOT NULL, amount INT UNSIGNED NOT NULL, status TINYINT UNSIGNED NOT NULL DEFAULT 0, created_at INT UNSIGNED NOT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;参数说明金额全部用“分”存储9.9 元记作 990后面所有计算都用整数避免浮点误差。pay_order.out_trade_no设置唯一约束防止同一笔支付单被重复落库commission.order_id也设唯一约束防止回调重试时给上级加两次佣金。invite_by存上级用户 id不存邀请码本身方便 SQL 里直接 join 用户表。2.3 JSAPI 下单从 openid 到微信收银台用户进入支付页后先用服务号 OAuth2 网页授权换到 openid这一步在第 4 章专门讲。拿到 openid 后创建预支付订单调用微信支付 API v3 的/v3/pay/transactions/jsapi。这是服务端下单函数function createJsapiOrder($openid, $outTradeNo, $amountFen) { $config loadWxpayConfig(); $url https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi; $data [ appid $config[appid], mchid $config[mchid], description 9.9元付费进群, out_trade_no $outTradeNo, notify_url https://yourdomain.com/wxpay/notify, amount [total $amountFen, currency CNY], payer [openid $openid] ]; $body json_encode($data, JSON_UNESCAPED_UNICODE); $timestamp time(); $nonce bin2hex(random_bytes(16)); $message POST\n{$url}\n{$timestamp}\n{$nonce}\n{$body}\n; openssl_sign($message, $sign, $config[privateKey], sha256WithRSAEncryption); $auth sprintf( WECHATPAY2-SHA256-RSA2048 mchid%s,nonce_str%s,timestamp%s,serial_no%s,signature%s, $config[mchid], $nonce, $timestamp, $config[serialNo], base64_encode($sign) ); $ch curl_init($url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $body); curl_setopt($ch, CURLOPT_HTTPHEADER, [ Content-Type: application/json, Accept: application/json, Authorization: . $auth, User-Agent: wx-pay-demo/1.0 ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $result curl_exec($ch); curl_close($ch); return json_decode($result, true); }这段代码里最容易写错的是签名字符串它是POST 换行 带路径的完整请求 URL 换行 Unix 时间戳 换行 随机串 换行 请求体 换行末尾那个换行不能丢。openssl_sign用的是商户 API 证书里的私钥不是公众平台后台的 API 密钥。返回结果里有prepay_id之后前端再用wx.requestPayment拉起收银台。2.4 支付回调先验签解密再幂等记账支付回调最容易踩坑。微信会把回调推送到notify_url请求体里的resource字段用 AES-256-GCM 加密。回调地址里要用 API v3 密钥解密然后做业务更新$plaintext decryptResource($wechatCallback[resource]); $data json_decode($plaintext, true); if (($data[trade_state] ?? ) ! SUCCESS) { return response(FAIL); } $order queryOrderByOutTradeNo($data[out_trade_no]); if (!$order || $order[status] 1) { return response(SUCCESS); } if ((int)$data[amount][total] ! (int)$order[amount]) { writeNotifyLog(amount mismatch: . $order[out_trade_no]); return response(FAIL); } markOrderPaid($order[id], $data[transaction_id], time()); if ((int)$order[invite_by] 0) { grantCommission($order[id], $order[invite_by], (int)round($order[amount] * 0.5)); } return response(SUCCESS);注意这里的SUCCESS是微信支付协议要求返回的固定报文不是用户看到的文案。业务代码一旦抛异常或者返回其它字符串微信会按间隔重试。所以在markOrderPaid和grantCommission之间断库、超时微信重试时幂等逻辑能把问题兜住。2.5 回调日志必须记我习惯在回调入口把原始报文、解密结果、订单号、返回文本按时间写进notify.log。线上丢单时这份日志比数据库更管用能看到微信到底有没有来请求、请求体是否完整、哪一步抛了异常。日志按天切割文件名带日期比如notify-2025-07-24.log后面写对账脚本也要用。3. 分销机制落地推荐码、佣金结算与提现审核3.1 分销层级怎么定单级还是二级9.9 元客单价不高如果做三级分销平台利润会被佣金层层吃干法律和平台规则风险也很大。我通常只做一级分销逻辑很清晰A 推荐 BB 支付后 A 拿佣金B 再推荐 CC 支付后 B 拿佣金A 不再拿钱。这样做一条 SQL 就能完成入账不用跑无限层级后台对账时也能说清每一笔佣金来自哪笔订单。3.2 推荐码绑定把邀请关系落到订单上用户访问分享链接时URL 带?invite推荐码服务端把推荐码解析成上级用户 id写到 session 里。用户支付下单时把该 id 写入pay_order.invite_by。这里有个细节用户如果先被别人邀请一次又点了别人的链接以最后一次点进页面的链接为准。session_start(); if (!empty($_GET[invite])) { $inviteCode preg_replace(/[^A-Za-z0-9]/, , $_GET[invite]); $parent getUserByInviteCode($inviteCode); if ($parent) { $_SESSION[invite_by] (int)$parent[id]; setcookie(invite_by, $_SESSION[invite_by], time() 86400, /); } } $inviteBy isset($_SESSION[invite_by]) ? (int)$_SESSION[invite_by] : 0;微信 OAuth2 跳转时会刷新一次页面有些 WebView 对 session 的支持不稳定所以我除了写 session 还会写一个invite_bycookie生命周期设置成 1 天能覆盖同一用户短时间重复被邀请的场景。3.3 佣金状态机与发放口径佣金不能在支付回调成功时立刻变成可提现。用户付 9.9 元后可能申请退款退款一旦发生已发出去的佣金就追不回来。我把commission.status做成三态0 冻结、1 可提现、2 已打款。支付成功后先写 0用户申请提现时再把满足售后期限比如 7 天的佣金置为 1UPDATE commission SET status 1 WHERE user_id :userId AND status 0 AND created_at :deadline;这里:deadline用当前时间减 7 天计算。订单退款时在退款回调里把对应commission.status改回 0并从可提现余额中扣除。每笔佣金必须关联order_id否则退款时找不到需要回冲的是哪一笔。3.4 提现申请与防超提用户端提现页面只展示状态为 1 的佣金合计申请后写入withdraw表状态为 0。真正打钱的操作我会放后台人工执行导出当天通过审核的提现单用微信支付“商家转账到零钱”批量打款成功后把withdraw.status改成 1同时把对应佣金改成 2。防超提不要靠前端计算后端在用户点“申请提现”时先取佣金总额再判断是否有金额相同的未完成提现记录。给withdraw表加一个UNIQUE(user_id, amount, status)约束同一金额的未处理提现只能存在一条这样能挡掉用户连续点击两次按钮造成的重复申请。4. 微信9.9付费进群网站部署到 phpStudy 与微信后台配置4.1 用 phpStudy 建站并跑通 PHP 环境phpStudy 的优势是 Apache/Nginx、MySQL、PHP 一键启动适合本地开发也能装在小服务器上。我常用的路径是安装后在“网站”里新增站点域名填wxpay.test或真实域名目录指向代码目录PHP 版本选 7.4 或 8.0。如果只是本地联调还要改 host但微信支付回调必须公网可达所以建议直接把代码放在云服务器上用真实域名解析绑定。Apache 版本下站点根目录放一个.htaccessRewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?/$1 [QSA,L]规则作用是把不存在的路由交给index.php处理。微信支付回调notify_url必须写完整 URL比如https://wx.yourdomain.com/wxpay/notify。回调地址里不要带index.phpURL 解析稍有偏差回调就会 404。4.2 微信公众平台需要配齐的四个位置服务号登录后台后下面几项要逐个配好缺一个支付环境就起不来。配置项位置填写内容网页授权域名公众号后台-接口权限-网页授权你的域名不带 httpJS 接口安全域名公众号后台-JS 接口安全域名你的域名支付授权目录商户平台-产品中心-开发配置支付页面的目录精确到路径回调域名商户平台-开发配置notify_url 的域名支付授权目录最常见的问题是把根目录写成/。微信要求填具体路径并且以/结束。JSAPI 支付页在/pay/目录这里就填https://wx.yourdomain.com/pay/否则前端wx.requestPayment会报“当前页面的 URL 未在商户号配置的支付授权目录下”。4.3 OAuth2 拉取 openid 的最小示例进入支付页之前先执行网页授权$appid wx12345; $secret your_app_secret; if (empty($_GET[code])) { $redirect https://wx.yourdomain.com/pay/start.php; $authUrl https://open.weixin.qq.com/connect/oauth2/authorize?appid{$appid}redirect_uri . urlencode($redirect) . response_typecodescopesnsapi_basestatepay#wechat_redirect; header(Location: . $authUrl); exit; } $code $_GET[code]; $tokenUrl https://api.weixin.qq.com/sns/oauth2/access_token?appid{$appid}secret{$secret}code{$code}grant_typeauthorization_code; $json json_decode(file_get_contents($tokenUrl), true); $openid $json[openid] ?? ;scopesnsapi_base是静默授权用户无感知能直接拿到 openid不需要snsapi_userinfo。这里的access_token和公众号普通 access_token 是两套体系不要混在同一个缓存 key 里。4.4 HTTPS 证书与服务器时间微信支付接口对时间戳敏感本地或云服务器时间慢 5 分钟接口就会报签名相关问题。启动 phpStudy 前先执行date或ntpdate校对时间。HTTPS 证书用云厂商的免费证书即可配置时填完整证书链不要只放证书公钥。回调地址必须已经生效最好在浏览器里直接访问一次https://wx.yourdomain.com/wxpay/notify确认没有跳转、证书没有过期。5. 微信9.9付费进群网站的反刷单与对账技巧5.1 用两把“唯一键”兜住回调重试回调网络抖动很常见。我会在pay_order.out_trade_no和commission.order_id上都建唯一索引先 insert 后 update让 MySQL 的唯一约束挡住重复单。如果微信重试时订单已经status1直接返回 SUCCESS不再执行后续佣金逻辑。日志里出现“order already paid”这类记录不代表出错是微信发了两次回执。5.2 佣金四舍五入与最小单位防御9.9 元分佣 50%正好是 495 分没有除不尽的问题。但如果把比例改成 35%就会出现小数分。PHP 里不要在浮点上做round()全部用整数计算intdiv($orderAmount * 35, 100)得到分。写进数据库前再校验一次佣金必须小于订单金额否则一定是逻辑 bug。5.3 进群二维码活码化付费成功后的进群页面不能放一张长期不变的群二维码。微信群二维码 7 天过期人工频繁换图很痛苦。我会建一张group_qrcode配置表后台维护多张二维码图片用户支付成功后读取当前有效的一张展示。管理员只需要定期替换新二维码。如果担心用户把二维码转发给未付费的人可以限制截图并在页面上加水印这些属于运营手段技术上不做强校验。5.4 全链路对账脚本最后一定要有一个对账脚本每天比对微信账单和本地pay_orderphp cli.php reconcile --date2025-07-24同一out_trade_no在微信侧已 SUCCESS、本地仍是待支付时标为异常并触发一次佣金补发。这一步能兜住回调漏单、WebHook 程序被防火墙杀掉等极端情况。脚本只输出差异记录不直接改库第一次跑出来的差异一定最多后续会越来越少。5.5 别把打款权限开给非管理员分销页面要展示佣金和邀请关系但“提现审核”和“二维码替换”一定要分开授权。用最简单的 role 字段1 是管理员2 是运营3 是只读。运营能替换二维码不代表能提现确认。9.9 元的单价看起来低一旦打款权限暴露在运营手里要刷走几千几百元比刷订单容易得多。本文还有配套的精品资源点击获取
返回列表