博客 / WooCommerce/ 如何为WooCommerce集成微信支付(含示例代码)

如何为WooCommerce集成微信支付(含示例代码)

如何为WooCommerce集成微信支付(含示例代码)

前言

为WooCommerce商店集成微信支付,可以显著提升中国用户的购物体验和支付成功率。本教程将指导你使用微信支付官方PHP SDK,以最稳妥的方式完成集成,避免重复造轮子。

准备工作

在开始编码前,你需要完成以下配置:

  • 微信商户平台账号:申请并开通微信支付商户号。
  • API密钥:登录商户平台,在【账户中心】->【API安全】中设置API密钥(需安装操作证书)。
  • AppID与商户号:记录你的公众号AppID(或小程序AppID、移动应用AppID)和商户号(MCHID)。
  • 服务器配置:确保你的WordPress网站服务器IP已添加到商户平台的IP白名单中,并准备好一个可通过公网访问的域名(用于接收支付结果通知)。

安装微信支付官方PHP SDK

推荐使用Composer进行安装,这是最规范的方式。

composer require wechatpay/wechatpay

如果你的环境不支持Composer,也可以从GitHub下载SDK源码并手动引入。

创建WooCommerce支付网关插件

我们将创建一个简单的插件来添加微信支付网关。在WordPress的 wp-content/plugins 目录下创建一个新文件夹,例如 wechatpay-for-woocommerce,然后创建主文件。

主插件文件:wechatpay-for-woocommerce.php

<?php
/**
 * Plugin Name: WooCommerce WeChat Pay Gateway
 * Description: 集成微信支付官方SDK的WooCommerce支付网关
 * Version: 1.0.0
 */

// 防止直接访问
if (!defined('ABSPATH')) {
    exit;
}

// 确保WooCommerce激活
add_action('plugins_loaded', 'init_wechatpay_gateway');
function init_wechatpay_gateway() {
    if (!class_exists('WC_Payment_Gateway')) {
        return;
    }

    // 引入Composer自动加载(假设SDK通过Composer安装在插件目录下的vendor文件夹)
    $autoloader = plugin_dir_path(__FILE__) . 'vendor/autoload.php';
    if (file_exists($autoloader)) {
        require_once $autoloader;
    }

    // 定义支付网关类
    class WC_Gateway_WeChatPay extends WC_Payment_Gateway {
        // 类定义将在下文展开
    }

    // 将网关添加到WooCommerce
    add_filter('woocommerce_payment_gateways', 'add_wechatpay_gateway');
    function add_wechatpay_gateway($gateways) {
        $gateways[] = 'WC_Gateway_WeChatPay';
        return $gateways;
    }
}

实现支付网关类

接下来,在同一个文件内,完善 WC_Gateway_WeChatPay 类的核心方法。

1. 构造函数与基本设置

public function __construct() {
    $this->id = 'wechatpay';
    $this->icon = ''; // 可选项:支付图标URL
    $this->has_fields = false;
    $this->method_title = '微信支付';
    $this->method_description = '通过微信支付官方SDK接收付款';

    // 加载设置字段
    $this->init_form_fields();
    $this->init_settings();

    // 获取用户设置
    $this->title = $this->get_option('title');
    $this->description = $this->get_option('description');
    $this->enabled = $this->get_option('enabled');
    $this->appid = $this->get_option('appid');
    $this->mchid = $this->get_option('mchid');
    $this->api_key = $this->get_option('api_key');
    $this->notify_url = home_url('/wc-api/wc_gateway_wechatpay/'); // 通知端点

    // 保存设置
    add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options'));
    // 注册支付结果回调处理
    add_action('woocommerce_api_wc_gateway_wechatpay', array($this, 'handle_notify'));
}

2. 管理后台设置字段

public function init_form_fields() {
    $this->form_fields = array(
        'enabled' => array(
            'title' => '启用/禁用',
            'type' => 'checkbox',
            'label' => '启用微信支付',
            'default' => 'no'
        ),
        'title' => array(
            'title' => '标题',
            'type' => 'text',
            'description' => '客户在结账时看到的支付方式标题。',
            'default' => '微信支付',
            'desc_tip' => true
        ),
        'description' => array(
            'title' => '描述',
            'type' => 'textarea',
            'description' => '支付方式的描述信息。',
            'default' => '使用微信扫码支付。'
        ),
        'appid' => array(
            'title' => 'AppID',
            'type' => 'text',
            'description' => '微信公众号或小程序的AppID。',
            'default' => ''
        ),
        'mchid' => array(
            'title' => '商户号 (MCHID)',
            'type' => 'text',
            'description' => '微信支付商户号。',
            'default' => ''
        ),
        'api_key' => array(
            'title' => 'API密钥',
            'type' => 'password',
            'description' => '商户平台设置的API密钥。',
            'default' => ''
        )
    );
}

3. 处理支付请求(核心)

当用户下单并选择微信支付后,此方法被调用,用于创建微信支付订单并返回支付参数(如二维码链接)。

public function process_payment($order_id) {
    $order = wc_get_order($order_id);

    // 1. 初始化微信支付客户端
    $wechatpay = $this->init_wechatpay_client();

    // 2. 构建请求参数(以Native支付为例,生成二维码)
    $requestData = [
        'mchid' => $this->mchid,
        'out_trade_no' => $order->get_order_number(),
        'appid' => $this->appid,
        'description' => '订单:' . $order->get_order_number(),
        'notify_url' => $this->notify_url,
        'amount' => [
            'total' => intval($order->get_total() * 100), // 转换为分
            'currency' => 'CNY'
        ]
    ];

    try {
        // 3. 调用SDK创建订单
        $resp = $wechatpay->chain('v3/pay/transactions/native')->post(['json' => $requestData]);
        $result = json_decode($resp->getBody(), true);

        // 4. 获取二维码链接(code_url)
        $code_url = $result['code_url'];

        // 5. 将订单状态设为“等待支付”并存储二维码URL(临时方案)
        $order->update_status('pending', '等待客户微信扫码支付。');
        // 实际应用中,应将code_url与订单关联存储,例如使用订单元数据
        update_post_meta($order_id, '_wechatpay_qrcode_url', $code_url);

        // 6. 重定向到自定义的“展示二维码”页面
        return array(
            'result' => 'success',
            'redirect' => $order->get_checkout_payment_url(true) // 将触发支付页面
        );

    } catch (Exception $e) {
        wc_add_notice('支付请求创建失败:' . $e->getMessage(), 'error');
        return array('result' => 'failure');
    }
}

// 辅助函数:初始化SDK客户端
private function init_wechatpay_client() {
    // 商户API私钥(此处假设你已下载并妥善保存私钥文件,例如apiclient_key.pem)
    $merchantPrivateKeyFilePath = plugin_dir_path(__FILE__) . 'cert/apiclient_key.pem';
    $merchantPrivateKey = file_get_contents($merchantPrivateKeyFilePath);

    // 微信支付平台证书(SDK支持自动下载和缓存,此处简化处理)
    // 强烈建议在生产环境中实现平台证书的自动更新机制

    $merchantId = $this->mchid;
    $merchantSerialNumber = '你的商户证书序列号'; // 从商户平台获取

    $wechatpay = WeChatPayBuilder::factory([
        'mchid' => $merchantId,
        'serial' => $merchantSerialNumber,
        'privateKey' => $merchantPrivateKey,
        'certs' => [
            // 此处应放置平台证书,示例中省略了自动获取逻辑
        ],
        'secret' => $this->api_key, // API v3密钥
        'merchantCerts' => [$merchantPrivateKey],
    ]);

    return $wechatpay;
}

4. 处理支付结果异步通知

微信支付服务器会向你的通知地址发送POST请求,告知支付结果。你必须正确验证并处理。

public function handle_notify() {
    $body = file_get_contents('php://input');
    $headers = getallheaders();
    // 注意:getallheaders()可能在某些环境下不可用,需调整

    try {
        $wechatpay = $this->init_wechatpay_client();
        // SDK内置了通知验签和解密工具,此处为简化示例逻辑
        // 实际应使用 $inWechatpay->decrypt($headers, $body) 进行验证和解密

        $data = json_decode($body, true);
        $out_trade_no = $data['out_trade_no'];
        $order = wc_get_order(wc_get_order_id_by_order_key($out_trade_no)); // 需根据你的订单号匹配逻辑调整

        if ($order && $data['trade_state'] === 'SUCCESS') {
            // 支付成功
            $order->payment_complete();
            $order->add_order_note('微信支付成功。交易单号:' . $data['transaction_id']);
            // 返回成功响应给微信支付
            header('HTTP/1.1 200 OK');
            echo json_encode(['code' => 'SUCCESS', 'message' => '成功']);
        } else {
            // 支付失败或其他状态
            header('HTTP/1.1 500 Internal Server Error');
        }
    } catch (Exception $e) {
        header('HTTP/1.1 500 Internal Server Error');
        error_log('微信支付通知处理错误:' . $e->getMessage());
    }
    exit;
}

前端展示支付二维码

你需要在主题中创建一个页面模板或使用钩子,在订单支付页面展示从 process_payment 步骤获取的二维码。一个简单的示例:

// 在支付页面(例如 checkout/payment 页面)添加短代码或自定义模板
// 从订单元数据获取二维码URL并生成img标签
$qrcode_url = get_post_meta($order_id, '_wechatpay_qrcode_url', true);
echo '<div class="wechatpay-qrcode"><img src="' . esc_url($qrcode_url) . '" alt="微信支付二维码" /></div>';

重要注意事项与安全建议

  • 证书管理:商户私钥必须妥善保管,严禁提交到代码仓库。平台证书应实现自动更新。
  • 通知验证:必须验证微信支付通知的签名,确保请求来源合法,防止伪造支付成功。
  • 订单状态:仅以异步通知(handle_notify)的结果为准来更新订单状态,不要依赖前端回调。
  • 错误处理:在生产环境中,应完善所有异常捕获,并记录日志以便排查。
  • 测试:务必在微信支付沙箱环境或使用真实小额交易进行充分测试。

总结

通过以上步骤,你已成功为WooCommerce集成了微信支付官方SDK。本教程提供了从插件创建、SDK初始化、支付下单到结果通知处理的完整流程和示例代码。请根据你的具体业务场景(如公众号支付、小程序支付)调整接口和参数,并严格遵守微信支付的官方文档和安全规范。

发表评论

您的邮箱不会公开。必填项已用 * 标注。