本文目录导读:

我来详细介绍PHP项目对接微信支付功能的完整步骤和核心代码实现。
前期准备
申请商户号
- 在微信商户平台(pay.weixin.qq.com)注册商户号
- 获取商户号(MCHID)
- 设置API密钥(Key)
- 下载商户证书
开通产品权限
- 在商户平台开通JSAPI支付、Native支付等
- 配置支付回调域名
核心配置
创建配置文件
<?php
// config/wechat.php
return [
'appid' => '你的公众号APPID', // 公众号APPID
'mch_id' => '你的商户号', // 商户号
'key' => '你的API密钥', // API密钥
'notify_url' => 'https://yourdomain.com/notify', // 回调地址
'cert_path' => __DIR__ . '/cert/apiclient_cert.pem', // 证书路径
'key_path' => __DIR__ . '/cert/apiclient_key.pem', // 密钥路径
];
支付SDK封装
基础工具类
<?php
// lib/WechatPay.php
class WechatPay {
private $config;
public function __construct($config) {
$this->config = $config;
}
/**
* 生成签名
*/
public function makeSign($params) {
// 1. 排序
ksort($params);
// 2. 拼接字符串
$string = '';
foreach ($params as $key => $value) {
if ($value !== '' && $key !== 'sign') {
$string .= $key . '=' . $value . '&';
}
}
$string .= 'key=' . $this->config['key'];
// 3. MD5加密并转大写
return strtoupper(md5($string));
}
/**
* 发送POST请求
*/
public function postXml($url, $xml) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
/**
* 数组转XML
*/
public function arrayToXml($params) {
$xml = '<xml>';
foreach ($params as $key => $value) {
if (is_numeric($value)) {
$xml .= "<{$key}>{$value}</{$key}>";
} else {
$xml .= "<{$key}><![CDATA[{$value}]]></{$key}>";
}
}
$xml .= '</xml>';
return $xml;
}
/**
* XML转数组
*/
public function xmlToArray($xml) {
libxml_disable_entity_loader(true);
$result = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $result;
}
}
支付接口实现
JSAPI支付(公众号支付)
<?php
// controller/PaymentController.php
class PaymentController {
/**
* 创建JSAPI支付订单
*/
public function jsapiPay($openId, $totalFee, $orderNo, $body) {
$config = require 'config/wechat.php';
$wechatPay = new WechatPay($config);
// 构建请求参数
$params = [
'appid' => $config['appid'],
'mch_id' => $config['mch_id'],
'nonce_str' => $this->createNonceStr(),
'body' => $body,
'out_trade_no' => $orderNo,
'total_fee' => $totalFee, // 单位:分
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
'notify_url' => $config['notify_url'],
'trade_type' => 'JSAPI',
'openid' => $openId,
];
// 生成签名
$params['sign'] = $wechatPay->makeSign($params);
// 发送请求
$xml = $wechatPay->arrayToXml($params);
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$result = $wechatPay->postXml($url, $xml);
$response = $wechatPay->xmlToArray($result);
// 处理返回结果
if ($response['return_code'] == 'SUCCESS' && $response['result_code'] == 'SUCCESS') {
// 生成JSAPI调起支付参数
$jsapiParams = [
'appId' => $config['appid'],
'timeStamp' => (string)time(),
'nonceStr' => $this->createNonceStr(),
'package' => 'prepay_id=' . $response['prepay_id'],
'signType' => 'MD5',
];
$jsapiParams['paySign'] = $wechatPay->makeSign($jsapiParams);
return [
'success' => true,
'data' => $jsapiParams
];
}
return [
'success' => false,
'message' => $response['return_msg']
];
}
/**
* 生成随机字符串
*/
private function createNonceStr($length = 32) {
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$str = '';
for ($i = 0; $i < $length; $i++) {
$str .= $chars[mt_rand(0, strlen($chars) - 1)];
}
return $str;
}
}
Native支付(扫码支付)
/**
* 创建Native支付订单
*/
public function nativePay($totalFee, $orderNo, $body) {
$config = require 'config/wechat.php';
$wechatPay = new WechatPay($config);
$params = [
'appid' => $config['appid'],
'mch_id' => $config['mch_id'],
'nonce_str' => $this->createNonceStr(),
'body' => $body,
'out_trade_no' => $orderNo,
'total_fee' => $totalFee,
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
'notify_url' => $config['notify_url'],
'trade_type' => 'NATIVE',
];
$params['sign'] = $wechatPay->makeSign($params);
$xml = $wechatPay->arrayToXml($params);
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$result = $wechatPay->postXml($url, $xml);
$response = $wechatPay->xmlToArray($result);
if ($response['return_code'] == 'SUCCESS' && $response['result_code'] == 'SUCCESS') {
return [
'success' => true,
'code_url' => $response['code_url'], // 二维码链接
'prepay_id' => $response['prepay_id']
];
}
return [
'success' => false,
'message' => $response['return_msg']
];
}
支付回调处理
<?php
// notify/NotifyController.php
class NotifyController {
/**
* 支付回调处理
*/
public function handleNotify() {
$config = require 'config/wechat.php';
$wechatPay = new WechatPay($config);
// 获取回调数据
$xml = file_get_contents('php://input');
$data = $wechatPay->xmlToArray($xml);
// 验证签名
if ($data['sign'] != $wechatPay->makeSign($data)) {
// 签名验证失败
$this->returnFail('签名验证失败');
return;
}
// 验证订单金额
$orderNo = $data['out_trade_no'];
$totalFee = $data['total_fee'];
// 1. 查询本地订单
$order = $this->getOrderByNo($orderNo);
if (!$order) {
$this->returnFail('订单不存在');
return;
}
// 2. 验证金额
if ($order['total_fee'] != $totalFee) {
$this->returnFail('金额不匹配');
return;
}
// 3. 更新订单状态
$this->updateOrderStatus($orderNo, 'paid', $data['transaction_id']);
// 4. 返回成功
$this->returnSuccess();
}
/**
* 返回处理成功
*/
private function returnSuccess() {
$xml = '<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>';
header('Content-Type: text/xml');
echo $xml;
}
/**
* 返回处理失败
*/
private function returnFail($message) {
$xml = '<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[' . $message . ']]></return_msg>
</xml>';
header('Content-Type: text/xml');
echo $xml;
}
/**
* 查询订单信息
*/
private function getOrderByNo($orderNo) {
// 从数据库查询订单
// return $orderInfo;
}
/**
* 更新订单状态
*/
private function updateOrderStatus($orderNo, $status, $transactionId) {
// 更新数据库订单状态
}
}
前端调用示例
JSAPI支付前端
// 获取支付参数后调起支付
function onBridgePay(jsapiParams) {
if (typeof WeixinJSBridge === "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady();
}
function onBridgeReady() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": jsapiParams.appId,
"timeStamp": jsapiParams.timeStamp,
"nonceStr": jsapiParams.nonceStr,
"package": jsapiParams.package,
"signType": jsapiParams.signType,
"paySign": jsapiParams.paySign
},
function(res) {
if (res.err_msg === "get_brand_wcpay_request:ok") {
// 支付成功
alert('支付成功');
} else if (res.err_msg === "get_brand_wcpay_request:cancel") {
// 支付取消
alert('支付已取消');
} else {
// 支付失败
alert('支付失败:' + res.err_msg);
}
}
);
}
}
生成二维码(Native支付)
// 控制器
public function showQrCode($orderNo) {
$result = $this->nativePay($totalFee, $orderNo, '商品描述');
if ($result['success']) {
// 生成二维码图片
$qrCode = new \Endroid\QrCode\QrCode($result['code_url']);
header('Content-Type: ' . $qrCode->getContentType());
echo $qrCode->writeString();
}
}
完整流程示例
// 支付控制器完整示例
class PaymentDemo {
/**
* 支付流程入口
*/
public function index() {
// 1. 获取用户openid(需有微信网页授权)
$openId = $_SESSION['openid'];
// 2. 生成订单
$orderInfo = $this->createOrder($openId);
// 3. 调用支付接口
$payment = new PaymentController();
$result = $payment->jsapiPay(
$openId,
$orderInfo['total_fee'],
$orderInfo['order_no'],
'测试商品'
);
if ($result['success']) {
// 4. 返回JSON给前端
echo json_encode([
'code' => 200,
'data' => $result['data']
]);
} else {
echo json_encode([
'code' => 400,
'message' => $result['message']
]);
}
}
}
注意事项
-
安全性:
- 不要在前端暴露API密钥
- 验证回调签名
- 使用HTTPS传输
-
错误处理:
- 记录支付日志
- 设置合理的超时时间
- 处理重复通知
-
性能优化:
- 使用Redis缓存access_token
- 异步处理订单状态
-
建议使用现成SDK:
- wechatpay-php(官方)
- EasyWeChat(第三方)
这样,你的PHP项目就可以成功对接微信支付功能了,记得在生产环境中做好充分的测试和错误处理。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播