付费内容 微信支付-H5 PHP

微信支付-H5 PHP

时间:2025-08-02 12:26:55 分类:其他

config.php

<?php
// 微信支付配置
$wechatConfig = [
    'mchid' => '商户号',// 商户号
    'appid' => '公众号appid',// 公众号appid
    'appKey' => '公众号APPSECRET',// 公众号APPSECRET
    'apiKey' => '商户API密钥'// 商户API密钥
];

// 自动获取当前域名
$domain = ($_SERVER['SERVER_PORT'] == 443 ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'];
$alipayConfig['returnUrl'] = $domain . '/return.php';
$alipayConfig['notifyUrl'] = $domain . '/notify.php';
$wechatConfig['notifyUrl'] = $domain . '/wx_notify.php';

// 开启错误报告
error_reporting(E_ALL);
ini_set('display_errors', 1);
?>

index.php

<?php
require_once 'config.php';
require_once 'functions.php';

$amount = isset($_GET['amount']) ? floatval($_GET['amount']) : 0.01;

class WxpayService {
    protected $mchid;
    protected $appid;
    protected $apiKey;
    
    public function __construct($mchid, $appid, $key) {
        $this->mchid = $mchid;
        $this->appid = $appid;
        $this->apiKey = $key;
    }
    
    public function createH5BizPackage($totalFee, $outTradeNo, $orderName, $notifyUrl, $timestamp, $sceneInfo = []) {
        // 金额验证
        if ($totalFee <= 0) {
            die('支付金额必须大于0');
        }
        
        // 金额转换为分(微信支付单位为分)
        $totalFeeInCent = intval(floatval($totalFee) * 100);
        if ($totalFeeInCent <= 0) {
            die('支付金额转换错误');
        }

        $config = [
            'mch_id' => $this->mchid,
            'appid' => $this->appid,
            'key' => $this->apiKey,
        ];
        
        $unified = [
            'appid' => $config['appid'],
            'attach' => 'pay',
            'body' => $orderName,
            'mch_id' => $config['mch_id'],
            'nonce_str' => self::createNonceStr(),
            'notify_url' => $notifyUrl,
            'out_trade_no' => $outTradeNo,
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
            'total_fee' => $totalFeeInCent, // 使用整数分
            'trade_type' => 'MWEB',
        ];
        
        // 添加H5支付场景信息
        if (!empty($sceneInfo)) {
            $unified['scene_info'] = json_encode($sceneInfo);
        }
        
        $unified['sign'] = self::getSign($unified, $config['key']);
        $responseXml = self::curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', self::arrayToXml($unified));
        
        $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
        
        if ($unifiedOrder === false) {
            die('parse xml error');
        }
        if ($unifiedOrder->return_code != 'SUCCESS') {
            die($unifiedOrder->return_msg);
        }
        if ($unifiedOrder->result_code != 'SUCCESS') {
            die($unifiedOrder->err_code);
        }
        
        return [
            'mweb_url' => (string)$unifiedOrder->mweb_url,
            'prepay_id' => (string)$unifiedOrder->prepay_id
        ];
    }
    
    public static function curlGet($url = '', $options = []) {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($options)) curl_setopt_array($ch, $options);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
    
    public static function curlPost($url = '', $postData = '', $options = []) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($options)) curl_setopt_array($ch, $options);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
    
    public static function createNonceStr($length = 16) {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $str = '';
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
    
    public static function arrayToXml($arr) {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }
    
    public static function getSign($params, $key) {
        ksort($params, SORT_STRING);
        $unSignParaString = self::formatQueryParaMap($params, false);
        return strtoupper(md5($unSignParaString . "&key=" . $key));
    }
    
    protected static function formatQueryParaMap($paraMap, $urlEncode = false) {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v) {
                if ($urlEncode) $v = urlencode($v);
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = '';
        if (strlen($buff) > 0) $reqPar = substr($buff, 0, strlen($buff) - 1);
        return $reqPar;
    }
}

// 初始化微信支付服务
$wxPay = new WxpayService($wechatConfig['mchid'], $wechatConfig['appid'], $wechatConfig['apiKey']);

// 生成订单号
$outTradeNo = uniqid();
$orderName = '商品支付';
$payTime = time();

// H5支付场景信息(可选)
$sceneInfo = [
    'h5_info' => [
        'type' => 'Wap',
        'wap_url' => 'https://你的网站域名.com', // 替换为您的网站URL
        'wap_name' => '你的网站名称' // 替换为您的网站名称
    ]
];

// 创建H5支付请求
$h5PayResult = $wxPay->createH5BizPackage($amount, $outTradeNo, $orderName, $wechatConfig['notifyUrl'], $payTime, $sceneInfo);

// 获取H5支付链接
$mwebUrl = $h5PayResult['mweb_url'];

// 如果需要添加回调页面参数
$redirectUrl = urlencode('https://您的网站域名.com/pay_result.php?out_trade_no='.$outTradeNo);
$mwebUrl .= '&redirect_url='.$redirectUrl;
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>微信支付</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            padding: 20px;
        }
        .pay-container {
            max-width: 400px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f9f9f9;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        .amount {
            font-size: 24px;
            color: #f56c6c;
            margin: 20px 0;
        }
        .order-info {
            margin: 20px 0;
            text-align: left;
            padding: 15px;
            background-color: #fff;
            border-radius: 5px;
        }
        #payButton {
            width: 200px;
            height: 40px;
            background-color: #07C160;
            color: white;
            border: none;
            border-radius: 4px;
            font-size: 16px;
            margin: 20px auto;
            cursor: pointer;
        }
        .loading {
            margin: 30px 0;
            color: #888;
        }
    </style>
    <script type="text/javascript">
        function startPayment() {
            // 跳转到微信H5支付页面
            window.location.href = "<?php echo $mwebUrl; ?>";
        }
        
        // 页面加载后自动跳转支付
        window.onload = function() {
            // 可以设置延迟跳转,让用户看到订单信息
            setTimeout(startPayment, 1000);
            
            // 也可以不自动跳转,让用户点击按钮
            // document.getElementById('payButton').style.display = 'block';
        };
    </script>
</head>
<body>
    <div class="pay-container">
        <h2>微信支付</h2>
        <div class="amount">¥<?php echo number_format($amount, 2); ?></div>
        
        <div class="order-info">
            <p><strong>订单号:</strong><?php echo $outTradeNo; ?></p>
            <p><strong>商品名称:</strong><?php echo $orderName; ?></p>
        </div>
        
        <div class="loading">正在跳转到微信支付...</div>
        <button id="payButton" onclick="startPayment()" style="display:none;">立即支付</button>
    </div>
</body>
</html>


QQ
微信
扫一扫
客服