下面我将提供一个详细、完整、可操作的教程,涵盖从准备工作到代码实现,再到前后端联调的全过程。

核心思想
织梦本身不包含微信支付功能,所以我们需要通过开发一个自定义模块或自定义表单处理函数来集成,我们将采用一种更灵活和强大的方式:创建一个自定义模块,这样做的好处是代码结构清晰,易于维护和升级。
我们将实现一个“在线充值”功能作为示例,用户点击充值按钮后,跳转到微信支付扫码页面,支付成功后自动更新用户的余额。
第一步:准备工作(非常重要)
在开始写代码之前,你必须先完成以下准备工作,否则后续代码将无法运行。
-
拥有一个微信支付商户号:
(图片来源网络,侵删)- 访问 微信支付商户平台。
- 完成企业/个体工商户认证,并开通了“Native支付”(扫码支付)产品。
- 获取以下关键信息:
- API密钥:在“账户中心 > API安全 > API密钥(32位)”中设置并获取,这个密钥用于生成和验证签名,请务必妥善保管,不要泄露。
- 商户号 (MCH_ID):如
1234567890。 - APPID / 公众号ID:如
wx1234567890abcdef。
-
下载微信支付PHP SDK:
- 官方提供了PHP版本的SDK,可以大大简化开发。
- 下载地址:微信支付PHP SDK
- 下载后,解压,你会看到一个名为
lib的文件夹。我们只需要这个文件夹里的内容。
-
准备服务器环境:
- 确保你的服务器支持 PHP 7.0+ 和 cURL 扩展。
- 你的网站必须能通过 HTTPS 访问,微信支付的所有通信都要求使用SSL加密。
第二步:目录结构与文件准备
为了不破坏织梦的核心文件,我们将创建一个自定义模块。
-
在织梦根目录下创建以下文件夹结构:
(图片来源网络,侵删)/dede/ <-- 织梦后台目录 /plus/ <-- 织梦前台功能目录 └── my_wechatpay/ <-- 我们自定义的微信支付模块目录 ├── index.php <-- 前台入口,显示充值页面 ├── notify.php <-- 异步通知处理页面(核心!) ├── return.php <-- 同步跳转处理页面(可选,用于用户支付后返回) ├── config.php <-- 配置文件,存放你的微信支付信息 └── lib/ <-- 存放微信支付SDK └── (将下载的SDK中的lib文件夹内容复制到这里) -
配置文件 (
config.php): 在/my_wechatpay/config.php中填入你的微信支付信息。<?php // my_wechatpay/config.php return [ 'appid' => '你的公众号APPID', // 如 'wx1234567890abcdef' 'mch_id' => '你的商户号', // 如 '1234567890' 'key' => '你的API密钥', // 如 'abcdefghijklmnopqrstuvwxyz0123456789' 'notify_url' => 'https://你的网站域名/plus/my_wechatpay/notify.php', // 异步通知地址,必须是公网可访问的URL 'return_url' => 'https://你的网站域名/plus/my_wechatpay/return.php', // 同步跳转地址 ];
第三步:创建后台充值管理功能
为了能让用户充值,我们需要在后台添加一个功能来管理用户的余额。
-
进入织梦后台 -> 核心 -> 内容模型管理 -> 添加新表。
- 表前缀:保持默认
dede_ - 表名:
member_account - 表类型:主表
- 数据表字段:
mid(int, 11, 主键, 默认值0)money(decimal, 10,2, 默认值0.00) - 用户余额
- 表前缀:保持默认
-
修改会员模型:
- 进入 会员 -> 会员模型管理 -> 修改会员模型。
- 在“会员字段列表”中,添加一个自定义字段:
- 字段名:
money - 字段标识:
余额 - 字段类型:
数字 - 默认值:
0 - 其他选项根据需要填写。
- 字段名:
-
生成SQL:
- 在第一步添加的
member_account表管理页面,点击“生成SQL”,然后执行它,确保表被创建。
- 在第一步添加的
-
在后台添加充值操作:
- 进入 会员 -> 会员管理,点击任意一个会员进入编辑页面。
- 你会看到刚才添加的“余额”字段,现在你可以直接在这里手动修改会员余额,完成充值操作,虽然原始,但简单有效。
第四步:编写前端充值页面 (index.php)
这个页面将展示给用户,让他们选择充值金额并发起支付。
<?php
// /plus/my_wechatpay/index.php
require_once(dirname(__FILE__) . "/../include/common.inc.php");
require_once(DEDEINC . "/userlogin.class.php");
require_once "config.php";
// 检查用户是否登录
if ($cfg_ml->IsLogin()) {
$uid = $cfg_ml->M_ID;
$username = $cfg_ml->M_UserName;
} else {
ShowMsg('请先登录!', '/member/login.php');
exit();
}
// 获取用户当前余额
$dsql->SetQuery("SELECT money FROM `#@__member_account` WHERE mid = {$uid}");
$row = $dsql->GetOne();
$current_money = $row['money'];
// 处理充值请求
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['amount'])) {
$amount = floatval($_POST['amount']);
if ($amount > 0) {
// 调用统一下单API,生成支付二维码
$order_no = 'DZ' . date('YmdHis') . rand(1000, 9999); // 生成唯一订单号
$jsApiParameters = createJsApiUrl($config, $order_no, $amount * 100); // 金额单位为分
// 在这里可以将订单信息存入数据库,方便后续查询
// $dsql->ExecuteNoneQuery("INSERT INTO `#@__recharge_orders` (uid, order_no, amount, status) VALUES ({$uid}, '{$order_no}', {$amount}, 'pending');");
// 显示支付二维码
include 'pay_qrcode.php';
exit;
} else {
ShowMsg('充值金额必须大于0!', '-1');
exit();
}
}
// 显示充值表单
$amount_options = [10, 50, 100, 200, 500];
include 'pay_form.php';
exit;
/**
* 创建微信支付JSAPI下单URL
*/
function createJsApiUrl($config, $out_trade_no, $total_fee)
{
// 引入SDK
require_once "lib/WxPay.Api.php";
require_once "lib/WxPay.Notify.php";
require_once "lib/WxPay.Config.php";
// 设置配置
$configObj = new WxPayConfig();
$configObj->SetAppid($config['appid']);
$configObj->SetMchId($config['mch_id']);
$configObj->SetKey($config['key']);
$configObj->SetNotifyUrl($config['notify_url']);
// 创建UnifiedOrder对象
$input = new WxPayUnifiedOrder();
$input->SetBody("网站在线充值");
$input->SetAttach($out_trade_no); // 订单号作为附加数据
$input->SetOut_trade_no($out_trade_no);
$input->SetTotal_fee($total_fee);
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 7200));
$input->SetNotify_url($config['notify_url']);
$input->SetTrade_type("NATIVE"); // 扫码支付
$input->SetProduct_id($out_trade_no);
// 统一下单
$order = WxPayApi::unifiedOrder($configObj, $input);
// 返回支付二维码URL
if ($order['return_code'] == 'SUCCESS' && $order['result_code'] == 'SUCCESS') {
return $order['code_url'];
} else {
// 记录错误日志
$logFile = dirname(__FILE__) . '/error.log';
file_put_contents($logFile, date('Y-m-d H:i:s') . " - " . $order['return_msg'] . "\n", FILE_APPEND);
ShowMsg('创建支付订单失败,请联系管理员!', '-1');
exit();
}
}
第五步:创建支付表单和二维码显示页面
-
支付表单 (
pay_form.php):<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>账户充值</title> <style> body { font-family: Arial, sans-serif; text-align: center; padding: 50px; } .money-display { font-size: 24px; margin-bottom: 20px; } .amount-options button { margin: 5px; padding: 10px 20px; } .amount-options button.active { background-color: #007bff; color: white; } </style> </head> <body> <h1>账户充值</h1> <p class="money-display">当前余额: <strong>¥ <?php echo number_format($current_money, 2); ?></strong></p> <form method="post" action=""> <div class="amount-options"> <?php foreach ($amount_options as $opt): ?> <button type="button" onclick="setAmount(<?php echo $opt; ?>)"><?php echo $opt; ?>元</button> <?php endforeach; ?> </div> <br> <input type="hidden" name="amount" id="amount" value=""> <input type="submit" value="确认支付" style="padding: 10px 30px; font-size: 16px;"> </form> <script> function setAmount(value) { document.getElementById('amount').value = value; // 移除所有按钮的active类 document.querySelectorAll('.amount-options button').forEach(btn => { btn.classList.remove('active'); }); // 给当前点击的按钮添加active类 event.target.classList.add('active'); } </script> </body> </html> -
二维码显示页面 (
pay_qrcode.php):<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>扫码支付</title> <script src="https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.min.js"></script> <style> body { font-family: Arial, sans-serif; text-align: center; padding: 50px; } #qrcode { margin: 20px auto; } .order-info { font-size: 18px; } </style> </head> <body> <h1>扫码支付</h1> <p class="order-info">订单号:<?php echo $order_no; ?></p> <p class="order-info">支付金额:¥ <?php echo number_format($amount, 2); ?></p> <div id="qrcode"></div> <p>请使用微信扫描上方二维码完成支付</p> <script> new QRCode(document.getElementById("qrcode"), { text: "<?php echo $jsApiParameters; ?>", width: 200, height: 200, colorDark : "#000000", colorLight : "#ffffff", correctLevel : QRCode.CorrectLevel.H }); </script> </body> </html>
第六步:创建核心的异步通知处理页面 (notify.php)
这是整个流程最关键的一步,用户支付成功后,微信服务器会主动访问这个页面,告诉你的网站“钱收到了”,你的网站必须根据这个通知来更新用户余额。
<?php
// /plus/my_wechatpay/notify.php
// 1. 引入必要的文件
require_once "lib/WxPay.Api.php";
require_once "lib/WxPay.Notify.php";
require_once "lib/WxPay.Config.php";
require_once(dirname(__FILE__) . "/../include/common.inc.php");
require_once "config.php";
// 2. 继承Notify类,并重写处理方法
class PayNotifyCallBack extends WxPayNotify
{
// 查询订单
public function Queryorder($transaction_id, $config)
{
$input = new WxPayOrderQuery();
$input->SetTransaction_id($transaction_id);
$result = WxPayApi::orderQuery($config, $input);
if (array_key_exists("return_code", $result) && array_key_exists("result_code", $result) && $result["return_code"] == "SUCCESS" && $result["result_code"] == "SUCCESS") {
return true;
}
return false;
}
// 重写处理回调的方法
public function NotifyProcess($data, $config)
{
// 1. 验证签名
if (!array_key_exists("transaction_id", $data)) {
$this->SetReturn_code("FAIL");
$this->SetReturn_msg("输入参数不正确");
return false;
}
// 2. 查询订单,确认交易状态
if (!$this->Queryorder($data["transaction_id"], $config)) {
$this->SetReturn_code("FAIL");
$this->SetReturn_msg("订单查询失败");
return false;
}
// 3. 业务逻辑处理:更新用户余额
// $data['out_trade_no'] 是我们下单时传入的订单号
$order_no = $data['out_trade_no'];
$uid = intval(substr($order_no, 2, 10)); // 假设订单号是DZ+时间戳+随机数,这里需要根据你的实际订单号规则解析出uid
$amount = floatval($data['total_fee']) / 100; // 金额从分转成元
// 从数据库中获取该订单信息,确认是否已经处理过
$dsql->SetQuery("SELECT * FROM `#@__recharge_orders` WHERE order_no = '{$order_no}' AND status = 'pending'");
$order = $dsql->GetOne();
if ($order) {
// 更新订单状态为已支付
$dsql->ExecuteNoneQuery("UPDATE `#@__recharge_orders` SET status = 'paid', transaction_id = '{$data['transaction_id']}' WHERE order_no = '{$order_no}'");
// 更新用户余额
$dsql->ExecuteNoneQuery("UPDATE `#@__member_account` SET money = money + {$amount} WHERE mid = {$uid}");
// 记录日志
$logFile = dirname(__FILE__) . '/success.log';
file_put_contents($logFile, date('Y-m-d H:i:s') . " - Order: {$order_no}, User: {$uid}, Amount: {$amount}\n", FILE_APPEND);
}
// 4. 告诉微信服务器,我已成功处理通知
$this->SetReturn_code("SUCCESS");
$this->SetReturn_msg("OK");
return true;
}
}
// 3. 初始化配置
$configObj = new WxPayConfig();
$configObj->SetAppid($config['appid']);
$configObj->SetMchId($config['mch_id']);
$configObj->SetKey($config['key']);
// 4. 调用NotifyCallBack处理
$logHandler = new CLogFileHandler(dirname(__FILE__) . '/notify.log');
$log = Log::Init($logHandler, 15);
$notify = new PayNotifyCallBack();
$notify->Handle($configObj);
第七步:创建同步跳转页面 (return.php)
用户支付成功后,可能会被微信跳转回这个页面,这个页面主要用于给用户一个友好的提示,但不要在这里做核心业务逻辑(比如加余额),因为用户可能中途关闭了页面,或者网络问题导致微信没有调用你的异步通知页面。
<?php
// /plus/my_wechatpay/return.php
require_once(dirname(__FILE__) . "/../include/common.inc.php");
require_once "config.php";
// 显示支付成功页面
// 实际业务逻辑应该由异步通知完成,这里仅做提示
ShowMsg('支付成功!正在返回首页...', '/');
exit();
第八步:测试与上线
-
配置测试环境:
- 在微信支付商户平台,将“产品中心 > 支付配置”中的“支付测试目录”设置为你的网站域名。
- 开启“测试授权”功能,这样可以使用测试账号进行支付。
-
使用测试账号支付:
- 在手机上关注你的测试公众号,使用测试账号扫码支付,微信支付会提示这是“测试环境”。
- 观察你的
notify.php是否被调用,检查success.log文件。 - 登录织梦后台,查看对应会员的余额是否增加。
-
关闭测试,正式上线:
- 确认所有功能正常后,回到微信支付商户平台,关闭“测试授权”和“支付测试目录”。
- 正常用户现在就可以使用微信支付进行充值了。
总结与注意事项
- 安全第一:API密钥、服务器权限等都要做好安全防护。
- 日志记录:无论是成功还是失败,都要做好日志记录,这是排查问题的关键。
- 幂等性:在
notify.php中处理业务逻辑时,一定要判断该订单是否已经处理过,防止重复添加余额。 - 错误处理:代码中加入了大量的
ShowMsg和日志记录,这是为了在开发阶段能快速定位问题。 - 订单表:为了更严谨,强烈建议你创建一个
recharge_orders表来记录所有充值订单,包括订单号、用户ID、金额、状态、支付时间等,便于对账和查询。
这个教程涵盖了从零开始集成微信支付的全过程,虽然步骤较多,但每一步都很关键,请耐心操作,祝你成功!
