微信掃碼支付 (Native 模式) 適用於 PC 網站、實體店面等場景,用戶掃描二維碼發起支付。本文基於 ThinkPHP 3.2 框架,梳理從官方 SDK 整理、統一下單、二維碼生成、異步通知驗證到前端展示的完整閉環代碼,並針對常見坑點給出解決方案。
Vendor/
└── Wxpay/
├── WxPay.Api.php # 核心接口調用
├── WxPay.Config.php # 配置項 (APPID, MCHID, KEY...)
├── WxPay.Data.php # 請求/響應數據對象
├── WxPay.NativePay.php # Native 支付業務邏輯
├── WxPay.Notify.php # 異步通知基類
├── log.php # 日誌處理
└── phpqrcode/ # PHP QR Code 生成庫
└── phpqrcode.php
public function native($v_oid='', $v_amount='') {
ini_set('date.timezone','Asia/Shanghai');
error_reporting(E_ERROR);
// 載入 SDK
vendor('Wxpay.WxPayApi');
vendor('Wxpay.log');
vendor('Wxpay.NativePay');
// 日誌初始化
$logHandler = new \CLogFileHandler("../logs/".date('Y-m-d').'.log');
\Log::Init($logHandler, 15);
// 參數校驗
if (empty(trim($v_oid))) {
$this->error('訂單號為空', U('User/index'));
exit;
}
$v_oid = trim($v_oid);
$v_amount = intval($v_amount * 100); // 轉分
// 調用統一下單
$notify = new \NativePay();
$input = new \WxPayUnifiedOrder();
$input->SetBody("商品描述"); // 必填
$input->SetAttach("附加數據"); // 選填,原樣返回
$input->SetOut_trade_no($v_oid); // 商戶訂單號
$input->SetTotal_fee($v_amount); // 總金額(分)
$input->SetTime_start(date("YmdHis")); // 開始時間
$input->SetTime_expire(date("YmdHis", time()+600)); // 10分鐘過期
$input->SetGoods_tag("標記"); // 訂單優惠標記
$input->SetNotify_url(U('NotifyProcess', '', '', true)); // 異步通知地址(全域名)
$input->SetTrade_type("NATIVE"); // 掃碼支付
$input->SetProduct_id("123456789"); // 商品ID
$result = $notify->GetPayUrl($input);
$url2 = $result["code_url"]; // 獲取二維碼鏈接
$this->assign('data', urlencode($url2));
$this->assign('v_oid', $v_oid);
$this->assign('v_amount', $v_amount/100);
$this->display(); // 渲染支付頁面
}
public function qrcode() {
error_reporting(E_ERROR);
vendor('Wxpay.phpqrcode.phpqrcode');
$url = $_GET["data"];
\QRcode::png($url); // 直接輸出 PNG 圖片流
}
public function NotifyProcess() {
vendor('Wxpay.WxPayApi');
vendor('Wxpay.log');
$notify = new \NativePay(); // 復用或自定義 Notify 類
$notify->Handle(false); // false: 不在頁面輸出
// 內部會調用 WxPayApi::notify() 驗證簽名、寫日誌
// 業務邏輯:查詢訂單狀態 → 更新本地訂單 → 返回 SUCCESS
}
public function Queryorder($transaction_id) {
$input = new \WxPayOrderQuery();
$input->SetTransaction_id($transaction_id);
$result = \WxPayApi::orderQuery($input);
\Log::DEBUG("query: ".json_encode($result));
return isset($result["return_code"]) && $result["return_code"]=="SUCCESS"
&& isset($result["result_code"]) && $result["result_code"]=="SUCCESS";
}
<form action="" method="post" id="myForm-table">
<h2>訂單信息</h2>
<div class="orderNumber">
<p class="a">訂單號:"{$v_oid}"</p>
<p class="b">
<span class="left">應付金額:<strong><em>{$v_amount}</em>元</strong></span>
<span class="right">付款後客服會聯系您,熱線 400-700-2016</span>
</p>
</div>
<h2>微信支付</h2>
<img src="{:U('qrcode')}?data={$data}" alt="微信掃碼">
<div class="order-submit">
<a href="javascript:history.go(-1);" class="submitOrder Order">返回其他支付方式</a>
</div>
</form>
APPID、MCHID、KEY (商戶平台設置)、APPSECRET、SSLCERT_PATH/SSLKEY_PATH (退款/紅包需雙向證書)。intval($yuan * 100),避免浮點數誤差。https://sandboxnew.weixin.qq.com/),需單獨配置沙箱 KEY。composer require wechatpay/wechatpay) 統一版本管理。transaction_id 為唯一鍵防重複處理。掌握這套流程,即可在 ThinkPHP 專案中快速接入微信掃碼支付,滿足 PC 端、展會現場、桌面應用等多樣化收款需求。