php如何实现微信支付

发布时间:2021-09-13 09:33:37 作者:小新
来源:亿速云 阅读:154
# PHP如何实现微信支付

微信支付作为国内主流的移动支付方式,其API接入是Web开发中的常见需求。本文将全面讲解PHP环境下微信支付的完整实现流程,涵盖从前期准备到代码实现的各个环节。

## 一、微信支付接入前准备

### 1.1 申请微信支付商户号

在开始开发前,您需要:

1. 注册微信支付商户平台账号
2. 提交企业资质材料(营业执照、法人身份证等)
3. 完成账户验证(对公账户打款验证)
4. 获取以下关键信息:
   - 商户号(MCHID)
   - API密钥(32位随机字符串)
   - 申请对应的支付产品(如Native支付、JSAPI支付等)

### 1.2 配置服务器环境

PHP环境要求:
- PHP 5.6+(推荐7.0以上版本)
- 开启cURL扩展
- 服务器需要支持HTTPS(微信支付要求全站HTTPS)
- 设置好服务器IP白名单(在商户平台配置)

```php
// 检查PHP环境
if (version_compare(PHP_VERSION, '5.6.0', '<')) {
    die("需要PHP 5.6.0或更高版本");
}

if (!function_exists('curl_init')) {
    die("需要启用cURL扩展");
}

二、微信支付核心配置

2.1 配置参数设置

创建配置文件wxpay_config.php

<?php
// 微信支付配置
define('WXPAY_APPID', '您的公众号APPID');
define('WXPAY_MCHID', '商户号');
define('WXPAY_KEY', '商户支付密钥');
define('WXPAY_APPSECRET', '公众号APPSECRET'); // JSAPI支付需要
define('WXPAY_NOTIFY_URL', 'https://您的域名.com/notify.php'); // 支付结果通知地址
define('WXPAY_CERT_PATH', __DIR__.'/cert/apiclient_cert.pem'); // 证书路径
define('WXPAY_KEY_PATH', __DIR__.'/cert/apiclient_key.pem');  // 密钥路径

2.2 获取微信支付证书

  1. 登录商户平台 → API安全 → 下载证书
  2. 将下载的压缩包中的以下文件放到项目cert目录:
    • apiclient_cert.pem
    • apiclient_key.pem
  3. 设置正确的文件权限(建议600)

三、Native支付实现(扫码支付)

3.1 生成支付二维码

require_once 'wxpay_config.php';
require_once 'WxPay.Api.php';
require_once 'WxPay.NativePay.php';

$notify = new NativePay();
$input = new WxPayUnifiedOrder();
$input->SetBody("测试商品");          // 商品描述
$input->SetAttach("附加数据");        // 附加数据
$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis")); // 商户订单号
$input->SetTotal_fee("1");           // 支付金额(单位:分)
$input->SetTime_start(date("YmdHis")); // 交易起始时间
$input->SetTime_expire(date("YmdHis", time() + 600)); // 交易结束时间
$input->SetGoods_tag("测试");         // 商品标记
$input->SetNotify_url(WxPayConfig::NOTIFY_URL); // 通知地址
$input->SetTrade_type("NATIVE");     // 交易类型
$input->SetProduct_id("123456789");  // 商品ID

$result = $notify->GetPayUrl($input);
$url2 = $result["code_url"]; // 获取支付二维码链接

3.2 生成二维码图片

使用PHP QR Code库生成二维码:

include 'phpqrcode/phpqrcode.php';
QRcode::png($url2, false, QR_ECLEVEL_L, 10); // 输出二维码图片

四、JSAPI支付实现(公众号支付)

4.1 获取用户OpenID

// 在微信授权回调页面获取openid
if (!isset($_GET['code'])) {
    $redirectUrl = urlencode('https://您的域名.com/getOpenid.php');
    $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".WXPAY_APPID."&redirect_uri={$redirectUrl}&response_type=code&scope=snsapi_base&state=123#wechat_redirect";
    header("Location: $url");
    exit();
} else {
    $code = $_GET['code'];
    $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".WXPAY_APPID."&secret=".WXPAY_APPSECRET."&code={$code}&grant_type=authorization_code";
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $response = curl_exec($ch);
    curl_close($ch);
    
    $data = json_decode($response, true);
    $openid = $data['openid']; // 获取到的用户openid
}

4.2 发起JSAPI支付

$input = new WxPayUnifiedOrder();
$input->SetBody("测试商品");
$input->SetAttach("附加数据");
$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
$input->SetTotal_fee("1");
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("测试");
$input->SetNotify_url(WxPayConfig::NOTIFY_URL);
$input->SetTrade_type("JSAPI");
$input->SetOpenid($openid); // 设置用户openid

$order = WxPayApi::unifiedOrder($input);
$jsApiParameters = $tools->GetJsApiParameters($order);

4.3 前端调用支付

<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
    // 注入配置
    wx.config({
        debug: false, // 开启调试模式
        appId: '<?php echo WXPAY_APPID; ?>',
        timestamp: <?php echo time(); ?>,
        nonceStr: '随机字符串',
        signature: '签名',
        jsApiList: ['chooseWXPay']
    });
    
    // 调用支付
    wx.chooseWXPay({
        timestamp: <?php echo $order['timestamp']; ?>,
        nonceStr: '<?php echo $order['nonce_str']; ?>',
        package: '<?php echo $order['prepay_id']; ?>',
        signType: 'MD5',
        paySign: '<?php echo $order['sign']; ?>',
        success: function(res) {
            alert('支付成功');
        },
        fail: function(res) {
            alert('支付失败: ' + JSON.stringify(res));
        }
    });
});
</script>

五、支付结果通知处理

5.1 创建通知处理文件

require_once "wxpay_config.php";
require_once "WxPay.Api.php";
require_once "WxPay.Notify.php";

class PayNotifyCallBack extends WxPayNotify
{
    // 重写回调处理函数
    public function NotifyProcess($data, &$msg)
    {
        // 1. 验证签名
        if(!array_key_exists("transaction_id", $data)){
            $msg = "输入参数不正确";
            return false;
        }
        
        // 2. 查询订单,判断订单真实性
        $query = new WxPayOrderQuery();
        $query->SetTransaction_id($data["transaction_id"]);
        $result = WxPayApi::orderQuery($query);
        
        if(array_key_exists("return_code", $result)
            && array_key_exists("result_code", $result)
            && $result["return_code"] == "SUCCESS"
            && $result["result_code"] == "SUCCESS")
        {
            // 3. 处理业务逻辑
            $out_trade_no = $data['out_trade_no'];
            $total_fee = $data['total_fee'] / 100; // 转换为元
            
            // TODO: 更新订单状态、发货等业务逻辑
            
            return true;
        }
        return false;
    }
}

// 处理通知
$notify = new PayNotifyCallBack();
$notify->Handle(false);

六、订单查询与退款处理

6.1 订单查询实现

function queryOrder($transaction_id)
{
    $input = new WxPayOrderQuery();
    $input->SetTransaction_id($transaction_id);
    
    try {
        $result = WxPayApi::orderQuery($input);
        if($result["return_code"] == "SUCCESS" 
           && $result["result_code"] == "SUCCESS")
        {
            // 支付成功
            return [
                'status' => true,
                'data' => $result
            ];
        } else {
            return [
                'status' => false,
                'msg' => $result["return_msg"]
            ];
        }
    } catch(Exception $e) {
        return [
            'status' => false,
            'msg' => $e->getMessage()
        ];
    }
}

6.2 退款申请实现

function applyRefund($transaction_id, $total_fee, $refund_fee)
{
    $input = new WxPayRefund();
    $input->SetTransaction_id($transaction_id);
    $input->SetTotal_fee($total_fee);
    $input->SetRefund_fee($refund_fee);
    $input->SetOut_refund_no(WxPayConfig::MCHID.date("YmdHis"));
    $input->SetOp_user_id(WxPayConfig::MCHID);
    
    try {
        $result = WxPayApi::refund($input);
        if($result["return_code"] == "SUCCESS" 
           && $result["result_code"] == "SUCCESS")
        {
            return [
                'status' => true,
                'data' => $result
            ];
        } else {
            return [
                'status' => false,
                'msg' => $result["err_code_des"] ?? $result["return_msg"]
            ];
        }
    } catch(Exception $e) {
        return [
            'status' => false,
            'msg' => $e->getMessage()
        ];
    }
}

七、安全优化与异常处理

7.1 支付安全措施

  1. 签名验证:所有接口调用必须验证签名
  2. 金额校验:后端校验支付金额与订单金额一致
  3. 防重处理:使用唯一订单号,防止重复支付
  4. IP白名单:限制API调用IP
  5. 频率限制:防止恶意调用

7.2 常见异常处理

try {
    // 微信支付API调用
    $result = WxPayApi::unifiedOrder($input);
} catch (WxPayException $e) {
    // 捕获微信支付异常
    error_log("微信支付异常: ".$e->getMessage());
    return [
        'status' => false,
        'msg' => '支付系统繁忙,请稍后再试'
    ];
} catch (Exception $e) {
    // 其他异常
    error_log("系统异常: ".$e->getMessage());
    return [
        'status' => false,
        'msg' => '系统错误,请联系客服'
    ];
}

八、实际项目中的最佳实践

8.1 支付流程设计建议

  1. 订单状态管理
    • 创建订单 → 待支付 → 支付成功/失败 → 发货 → 完成
  2. 超时处理
    • 设置订单有效时间(通常30分钟)
    • 定时任务检查超时未支付订单
  3. 对账机制
    • 每日定时与微信支付对账
    • 处理异常订单(已支付未回调等)

8.2 日志记录策略

class WxPayLogger
{
    public static function write($content, $type = 'INFO')
    {
        $logFile = __DIR__.'/logs/'.date('Y-m-d').'.log';
        $content = "[".date('Y-m-d H:i:s')."] [$type] ".$content.PHP_EOL;
        file_put_contents($logFile, $content, FILE_APPEND);
    }
}

// 使用示例
WxPayLogger::write("创建支付订单,订单号:".$outTradeNo);

九、微信支付常见问题解答

9.1 常见错误代码

错误代码 说明 解决方案
NOAUTH 商户无此接口权限 检查商户号配置和支付产品权限
NOTENOUGH 用户账户余额不足 提示用户充值或更换支付方式
ORDERPD 订单已支付 检查订单状态,避免重复支付
ORDERCLOSED 订单已关闭 重新创建订单
SYSTEMERROR 系统错误 重试或联系微信支付客服

9.2 调试技巧

  1. 沙箱环境:使用微信支付沙箱测试
  2. 日志分析:详细记录请求和响应数据
  3. 工具推荐
    • Postman:模拟API调用
    • Wireshark:网络请求分析
    • 微信支付调试工具:官方提供的调试工具

十、总结

本文详细介绍了PHP环境下微信支付的完整实现流程,包括:

  1. 前期准备和配置
  2. Native支付和JSAPI支付的实现
  3. 支付结果通知处理
  4. 订单查询和退款功能
  5. 安全措施和异常处理
  6. 实际项目中的最佳实践

通过以上步骤,开发者可以构建一个安全、稳定的微信支付系统。在实际开发中,还需要根据具体业务需求进行调整和优化,特别是要做好异常处理和日志记录,确保支付系统的可靠性。

扩展阅读: - 微信支付官方文档 - PHP cURL高级用法 - 支付系统设计原则

附录:示例代码下载 点击下载完整示例项目 “`

推荐阅读:
  1. PHP 唤起微信支付
  2. php实现微信支付功能的操作步骤

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

php

上一篇:iis7如何设置php最大执行时间

下一篇:Html5怎么实现无刷新修改browser Url

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》