H5公众号调用v2jsapi使用微信支付-PHP后端

前端示例代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>微信支付</title>
    <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
    <script src="https://s.url.cn/qqun/qun/qqweb/m/qun/confession/js/vconsole.min.js "></script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js"></script>
    <style type="text/css" media="all">
        body{
            width: 300px;
            height: 200px;
            border: 1px solid  red;
        }
        #payButton{
            width: 200px;
            height: 250px;
        }
    </style>
</head>
<body>
<button id="payButton">支付</button>

<script>
$(document).ready(function(){
    $("#payButton").click(function(){
        var openid = 'xxxxxxxxx';
        var total_fee = 1; // 金额,单位:分
        var body = '商品描述';
        // 发起统一下单请求
        $.ajax({
            type: "POST",
            url: "/api/wechat_pay.php",
            data: {openid: openid, total_fee: total_fee, body: body},
            dataType: "json",
            success: function(response){
                console.log(response);
                // 调用WeixinJSBridge拉起支付
                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": response.appId,     // 公众号ID,由商户传入
                            "timeStamp": response.timeStamp,  // 时间戳,自1970年以来的秒数
                            "nonceStr": response.nonceStr, // 随机串
                            "package": response.package,
                            "signType": "MD5",         // 微信签名方式
                            "paySign": response.paySign  // 微信签名
                        },
                        function(res) {
                            if (res.err_msg == "get_brand_wcpay_request:ok") {
                // 用户支付成功
                console.log("用户支付成功");
            } else {
                // 用户支付失败或取消支付
                console.log("用户支付失败或取消支付");
                console.log(res);
            }
                        }
                    );
                }
            }
        });
    });
});
</script>

</body>
</html>

PHP后端代码

<?php
// wechat_pay.php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $openid =  $_POST['openid'];;
    $total_fee = $_POST['total_fee']; 
    $body = $_POST['body'];
    if($openid!='' && $total_fee!=''){
       $out_trade_no = 'order' . date('Ymd') . substr(str_replace('.', '', microtime(true)), 0, 13);
        unifiedOrder($openid, $out_trade_no, $total_fee, $body);
    }
}
// 定义统一下单函数
function unifiedOrder($openid, $out_trade_no, $total_fee, $body){
    $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    $appid = '';//appid
    $mch_id = '';//商户号
    $V2apikey = '';//V2apikey
    // 构建统一下单参数
    $data = array(
        'appid' => $appid,
        'mch_id' => $mch_id,
        'nonce_str' => md5(uniqid()), // 随机字符串
        'body' => $body,
        'out_trade_no' => $out_trade_no,
        'total_fee' => $total_fee,
        'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], // 客户端IP
        'notify_url' => 'httsps://xxxxx/api/notify.php', // 支付结果回调接口地址
        'trade_type' => 'JSAPI', // 支付类型
        'openid' => $openid,
    );
    // 参数按字典序排序
    ksort($data);
    // 生成签名
     $string = '';
    foreach ($data as $key => $value) {
        if($value!=""){
            $string .= $key.'='.$value.'&';
        }        
    }
    $stringSignTemp=$string."key=".$V2apikey; 
    $sign = strtoupper(md5($stringSignTemp)); // 签名,转为大写
    $data['sign'] = $sign;
    

    // 数组转xml格式
    $xmlData = '<xml>';
    foreach ($data as $key => $value) {
        $xmlData .= '<'.$key.'>'.$value.'</'.$key.'>';
    }
    $xmlData .= '</xml>';

    // 发起请求
    $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, $xmlData);
    $output = curl_exec($ch);
    curl_close($ch);

    // 处理返回结果
    $result = simplexml_load_string($output, 'SimpleXMLElement', LIBXML_NOCDATA);
    if($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){
        $prepay_id = $result->prepay_id;
        
        $config = array(
        'appId' => $appid,
        'timeStamp' => strval(time()),
        'nonceStr' => md5(uniqid()), // 随机字符串
        'package' => 'prepay_id='.$prepay_id,
        );
        // 参数按字典序排序
        ksort($config);
            // 生成签名
        $sign = md5("appId={$config['appId']}&nonceStr={$config['nonceStr']}&package={$config['package']}&signType=MD5&timeStamp={$config['timeStamp']}&key=".$V2apikey);

        $config['paySign'] = $sign;
        $config['$stringSignTemp'] = $stringSignTemp;
        echo json_encode($config);

    } else {
       echo json_encode(array('error' => '支付失败','data'=>$result));
    }
}

?>