微信支付二维码PHP实现指南:从零开始搭建扫码支付功能
在移动互联网时代,微信支付已成为国内主流的支付方式之一,对于PHP开发者而言,将微信支付二维码集成到网站或应用中,是提升用户体验、实现商业化的重要环节,本文将详细介绍如何使用PHP生成微信支付二维码,涵盖准备工作、核心代码实现、常见问题及注意事项,帮助开发者快速上手。
准备工作:接入微信支付前的必要条件
在开始编写PHP代码前,需完成以下准备工作,确保后续流程顺畅:
注册微信支付商户号
- 访问微信支付官网,注册并完成企业认证(个人用户无法开通微信支付)。
- 完成商户资质审核,获取商户号(mchid)、API密钥(key)(在“账户中心 > API安全”中设置,需妥善保管)。
- 开通“Native扫码支付”产品权限(在“产品中心 > 产品”中配置)。
安装必要依赖
PHP本身无需额外安装库,但建议使用cURL
扩展(用于发送HTTP请求)和OpenSSL
扩展(用于签名加密),这两个扩展在PHP默认环境中已包含,可通过phpinfo()
检查是否启用。
理解微信支付Native支付流程
Native扫码支付的流程如下:
- 商户服务器生成支付参数(如订单号、金额、商品描述等)。
- 通过微信支付统一下单接口,生成预支付交易会话标识(
prepay_id
)。 - 使用
prepay_id
调用“Native支付下单接口”,获取二维码链接(包含code_url
)。 - 将
code_url
生成二维码,用户微信扫码后完成支付。
PHP生成微信支付二维码的完整步骤
步骤1:配置商户信息
在PHP项目中创建一个配置文件(如config.php
),存储商户号、API密钥等敏感信息:
<?php // config.php return [ 'mchid' => '你的商户号', // 商户号 'appid' => '你的应用APPID', // 微信支付分配的公众账号ID 'api_key' => '你的API密钥', // API密钥 'notify_url' => 'https://你的域名/notify.php', // 支付结果通知地址 ];
注意:
appid
需在微信公众平台(公众号或小程序)中获取,且与商户号关联。
步骤2:生成统一下单参数
微信支付需要先通过“统一下单接口”生成prepay_id
,再获取二维码链接,创建UnifiedOrder.php
文件,实现统一下单逻辑:
<?php require_once 'config.php'; class UnifiedOrder { private $config; public function __construct() { $this->config = include('config.php'); } /** * 统一下单 * @param array $orderData 订单数据(out_trade_no, body, total_fee, spbill_create_ip等) * @return array|string 成功返回预支付ID,失败返回错误信息 */ public function createOrder($orderData) { // 1. 构造请求数据 $params = [ 'appid' => $this->config['appid'], 'mch_id' => $this->config['mchid'], 'nonce_str' => $this->->createNonceStr(), // 随机字符串 'body' => $orderData['body'], 'out_trade_no' => $orderData['out_trade_no'], // 商户订单号 'total_fee' => $orderData['total_fee'], // 金额(单位:分) 'spbill_create_ip' => $orderData['spbill_create_ip'], // 客户端IP 'notify_url' => $this->config['notify_url'], 'trade_type' => 'NATIVE', // Native扫码支付 ]; // 2. 生成签名 $params['sign'] = $this->generateSign($params); // 3. 发送请求到微信统一下单接口 $xmlData = $this->arrayToXml($params); $response = $this->postXmlCurl($xmlData, 'https://api.mch.weixin.qq.com/pay/unifiedorder'); // 4. 解析响应结果 $result = $this->xmlToArray($response); if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') { return $result['prepay_id']; // 返回预支付ID } else { return $result['return_msg'] ?? '统一下单失败'; } } /** * 生成随机字符串 */ private function createNonceStr($length = 32) { $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $str = ''; for ($i = 0; $i < $length; $i++) { $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $str; } /** * 生成签名 */ private function generateSign($params) { // 1. 过滤空值,按ASCII码排序 $filteredParams = array_filter($params, function($value) { return $value !== '' && $value !== null; }); ksort($filteredParams); // 2. 拼接键值对(格式:key=value&) $stringToSign = ''; foreach ($filteredParams as $key => $value) { $stringToSign .= $key . '=' . $value . '&'; } $stringToSign .= 'key=' . $this->config['api_key']; // 添加API密钥 // 3. MD5加密并转为大写 return strtoupper(md5($stringToSign)); } /** * 数组转XML */ private function arrayToXml($array) { $xml = '<xml>'; foreach ($array as $key => $value) { $xml .= '<' . $key . '><![CDATA[' . $value . ']]></' . $key . '>'; } $xml .= '</xml>'; return $xml; } /** * XML转数组 */ private function xmlToArray($xml) { $libxmlDisableEntityLoader = libxml_disable_entity_loader(true); $result = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); libxml_disable_entity_loader($libxmlDisableEntityLoader); return $result; } /** * 发送POST请求(XML格式) */ private function postXmlCurl($xml, $url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 测试环境可关闭,生产环境需开启 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $response = curl_exec($ch); curl_close($ch); return $response; } }
步骤3:获取二维码链接
创建GetQrCode.php
文件,调用统一下单接口并生成二维码链接:
<?php require_once 'UnifiedOrder.php'; $orderData = [ 'out_trade_no' => 'ORDER_' . time(), // 商户订单号(需唯一) 'body' => '测试商品', 'total_fee' => 100, // 金额(单位:分,1元=100分) 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], // 客户端IP ]; $unifiedOrder = new UnifiedOrder(); $prepayId = $unifiedOrder->createOrder($orderData); if (is_string($prepayId)) { // 统一下单失败,返回错误信息 echo '错误:' . $prepayId; } else { // 使用prepay_id获取二维码链接 $qrCodeUrl = 'weixin://wxpay/bizpayurl?pr=' . urlencode($prepayId); echo '二维码链接:' . $qrCodeUrl; // 如果需要直接生成二维码图片,可以使用第三方库(如endroid/qr-code) // 示例: // require_once 'vendor/autoload.php'; // use Endroid\QrCode\QrCode; // $qrCode = new QrCode($qrCodeUrl); // header('Content-Type: '.$qrCode->getContentType()); // echo $qrCode->writeString(); }
步骤4:生成二维码并展示
上述代码已输出二维码链接,实际开发中
还没有评论,来说两句吧...