织梦如何对接微信支付接口?

99ANYc3cd6
预计阅读时长 48 分钟
位置: 首页 织梦建站 正文

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

给织梦增加微信支付接口
(图片来源网络,侵删)

核心思想

织梦本身不包含微信支付功能,所以我们需要通过开发一个自定义模块自定义表单处理函数来集成,我们将采用一种更灵活和强大的方式:创建一个自定义模块,这样做的好处是代码结构清晰,易于维护和升级。

我们将实现一个“在线充值”功能作为示例,用户点击充值按钮后,跳转到微信支付扫码页面,支付成功后自动更新用户的余额。


第一步:准备工作(非常重要)

在开始写代码之前,你必须先完成以下准备工作,否则后续代码将无法运行。

  1. 拥有一个微信支付商户号

    给织梦增加微信支付接口
    (图片来源网络,侵删)
    • 访问 微信支付商户平台
    • 完成企业/个体工商户认证,并开通了“Native支付”(扫码支付)产品。
    • 获取以下关键信息:
      • API密钥:在“账户中心 > API安全 > API密钥(32位)”中设置并获取,这个密钥用于生成和验证签名,请务必妥善保管,不要泄露
      • 商户号 (MCH_ID):如 1234567890
      • APPID / 公众号ID:如 wx1234567890abcdef
  2. 下载微信支付PHP SDK

    • 官方提供了PHP版本的SDK,可以大大简化开发。
    • 下载地址:微信支付PHP SDK
    • 下载后,解压,你会看到一个名为 lib 的文件夹。我们只需要这个文件夹里的内容
  3. 准备服务器环境

    • 确保你的服务器支持 PHP 7.0+cURL 扩展。
    • 你的网站必须能通过 HTTPS 访问,微信支付的所有通信都要求使用SSL加密。

第二步:目录结构与文件准备

为了不破坏织梦的核心文件,我们将创建一个自定义模块。

  1. 在织梦根目录下创建以下文件夹结构

    给织梦增加微信支付接口
    (图片来源网络,侵删)
    /dede/  <-- 织梦后台目录
    /plus/  <-- 织梦前台功能目录
    └── my_wechatpay/  <-- 我们自定义的微信支付模块目录
        ├── index.php      <-- 前台入口,显示充值页面
        ├── notify.php     <-- 异步通知处理页面(核心!)
        ├── return.php     <-- 同步跳转处理页面(可选,用于用户支付后返回)
        ├── config.php     <-- 配置文件,存放你的微信支付信息
        └── lib/           <-- 存放微信支付SDK
            └── (将下载的SDK中的lib文件夹内容复制到这里)
  2. 配置文件 (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', // 同步跳转地址
    ];

第三步:创建后台充值管理功能

为了能让用户充值,我们需要在后台添加一个功能来管理用户的余额。

  1. 进入织梦后台 -> 核心 -> 内容模型管理 -> 添加新表

    • 表前缀:保持默认 dede_
    • 表名member_account
    • 表类型:主表
    • 数据表字段
      • mid (int, 11, 主键, 默认值0)
      • money (decimal, 10,2, 默认值0.00) - 用户余额
  2. 修改会员模型

    • 进入 会员 -> 会员模型管理 -> 修改会员模型
    • 在“会员字段列表”中,添加一个自定义字段:
      • 字段名money
      • 字段标识余额
      • 字段类型数字
      • 默认值0
      • 其他选项根据需要填写。
  3. 生成SQL

    • 在第一步添加的 member_account 表管理页面,点击“生成SQL”,然后执行它,确保表被创建。
  4. 在后台添加充值操作

    • 进入 会员 -> 会员管理,点击任意一个会员进入编辑页面。
    • 你会看到刚才添加的“余额”字段,现在你可以直接在这里手动修改会员余额,完成充值操作,虽然原始,但简单有效。

第四步:编写前端充值页面 (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();
    }
}

第五步:创建支付表单和二维码显示页面

  1. 支付表单 (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>
  2. 二维码显示页面 (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();

第八步:测试与上线

  1. 配置测试环境

    • 在微信支付商户平台,将“产品中心 > 支付配置”中的“支付测试目录”设置为你的网站域名。
    • 开启“测试授权”功能,这样可以使用测试账号进行支付。
  2. 使用测试账号支付

    • 在手机上关注你的测试公众号,使用测试账号扫码支付,微信支付会提示这是“测试环境”。
    • 观察你的 notify.php 是否被调用,检查 success.log 文件。
    • 登录织梦后台,查看对应会员的余额是否增加。
  3. 关闭测试,正式上线

    • 确认所有功能正常后,回到微信支付商户平台,关闭“测试授权”和“支付测试目录”。
    • 正常用户现在就可以使用微信支付进行充值了。

总结与注意事项

  • 安全第一:API密钥、服务器权限等都要做好安全防护。
  • 日志记录:无论是成功还是失败,都要做好日志记录,这是排查问题的关键。
  • 幂等性:在 notify.php 中处理业务逻辑时,一定要判断该订单是否已经处理过,防止重复添加余额。
  • 错误处理:代码中加入了大量的 ShowMsg 和日志记录,这是为了在开发阶段能快速定位问题。
  • 订单表:为了更严谨,强烈建议你创建一个 recharge_orders 表来记录所有充值订单,包括订单号、用户ID、金额、状态、支付时间等,便于对账和查询。

这个教程涵盖了从零开始集成微信支付的全过程,虽然步骤较多,但每一步都很关键,请耐心操作,祝你成功!

-- 展开阅读全文 --
头像
Linux C如何连接操作MySQL数据库?
« 上一篇 01-13
织梦CMS模板带数据库,如何安装使用?
下一篇 » 01-13

相关文章

取消
微信二维码
支付宝二维码

目录[+]