热门IT资讯网

关于微信H5支付(微信内支付 和 跳连接支付)

发表于:2024-12-04 作者:热门IT资讯网编辑
编辑最后更新 2024年12月04日,好久没有更新博客,最近做项目遇到了微信支付,整理一下需求,目的一个活动页面需要调微信支付!应用框架THINKPHP5.1注意:微信支付 需要注意 如果是h6页面调取支付的话,需要静默一个登录状态获取c

好久没有更新博客,最近做项目遇到了微信支付,整理一下需求,目的一个活动页面需要调微信支付!
应用框架THINKPHP5.1

注意:微信支付 需要注意 如果是h6页面调取支付的话,需要静默一个登录状态获取code,这样才可以保证支付调取的参数openid正常,这里的坑填了好久,微信内浏览器h6用户输入完手机号登录后,页面存cookie信息,有时候会不更新获取的openid 导致"下单账号和支付账号不一致,请核对";

微信内浏览器刷新页面用jq执行: _window.location.href = location.href+'?time='+((new Date()).getTime());

直接上代码:前端
function get_form(){
var price1 =$(".get_price1").val();
var price2 =$(".get_price2").val();
var price3 =$(".get_price3").val();
var price4 =$(".get_price4").val();
var pid =$(".pid").val();
var username =$(".username").val();
var mobile =$(".mobile").val();
var address =$(".address").val();

    if(!username && !mobile && !address){        layer.alert('收货人信息不能为空');        return false;    }    $.post("home/get_from",//get_from 是后台请求支付的逻辑            {"price1":price1,"price2":price2,"price3":price3,"price4":price4,"username":username,"mobile":mobile,"address":address,"pid":pid},function(apiConfig){           console.log(apiConfig);        var ua = navigator.userAgent.toLowerCase();//获取判断用的对象是微信内还是外部        if (ua.match(/MicroMessenger/i) == "micromessenger") {           //内部            WeixinJSBridge.invoke(                    'getBrandWCPayRequest', {                        "appId":apiConfig.appId,     //公众号名称,由商户传入                        "timeStamp":apiConfig.timeStamp,         //时间戳,自1970年以来的秒数                        "nonceStr":apiConfig.nonceStr, //随机串                        "package":apiConfig.package,                        "signType":apiConfig.signType,         //微信签名方式:                        "paySign":apiConfig.paySign //微信签名                    },                    function(res){                        if(res.err_msg == "get_brand_wcpay_request:ok" ){                            _window.location.href ="方法路径"                        }                    });            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();            }        }else{     //外部            var url="支付成功跳转";            _window.location.href =apiConfig.mweb_url+"&redirect_url="+url;        }    });}

后端代码:
静默登录 请求页面的时候通过tp5 redirect重置路由
再进入页面的方法里 查找有没有openid
$sa = Cookie::get('kj_phone');
$uid =$sa['id'];//用户id
$userAgent = $_SERVER['HTTP_USER_AGENT']; // 判断是 公众号支付还是外部网址支付
if (strpos($userAgent, 'MicroMessenger')) { // 公众号支付
$uid =$sa['id'];//用户id
$open_id= Cache::get($uid);
// print_r($open_id);
if(empty($open_id)){
$this->redirect("https://open.weixin.qq.com/connect/oauth3/authorize?appid=Appid&redirect_uri=页面进入后先通过get_open方法获得code获取openid&response_type=code&scope=snsapi_base&state=1#wechat_redirect");

          }      }

get_open方法
public function get_open(){

    $code1=empty($_GET['code']) ? '' : $_GET['code'];    $sa =Cookie::get('kj_phone');   // $appId ='appId ';    //$secret ='secret';    $get_token_url = 'https://api.weixin.qq.com/sns/oauth3/access_token?appid=Appid&secret=secre&code=' . $code1 . '&grant_type=authorization_code';    $json_obj = $this->http_request($get_token_url);    $json_obj = json_decode($json_obj,true);    $openid = empty($json_obj['openid']) ? "" : $json_obj['openid'];    $uid =$sa['id'];//用户id    Cache::set($uid,$openid,3600);    if($code1 == ''){        $this->redirect('重定向到渲染页面');    }    if(!empty($open_id)){        $this->redirect('重定向到渲染页面');    }else{        $this->redirect('重定向到渲染页面');    }}

get_from:
public function get_from(){
if(request()->isPost()){
$data =input("post.");// 前端传过来的数据 自己写逻辑吧

             $userAgent = $_SERVER['HTTP_USER_AGENT']; // 判断是 公众号支付还是外部网址支付             if (strpos($userAgent, 'MicroMessenger')) { // 公众号支付                 $sa = Cookie::get('kj_phone');                 $uid =$sa['id'];//用户id                 $open_id= Cache::get($uid);                 //print_r($open_id);exit;                 $return = $this->weixinapp($open_id,$body,$order_id,$price,$attact);                 return $return;             }else{                 $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';                 $parameters = array(                     'appid' => "小程序ID", //小程序ID                     'mch_id' => "商户号", //商户号                     'attach'=>$attact,                     'nonce_str' => $this->createNoncestr(), //随机字符串                     'body' =>$body, //商品描述                     'out_trade_no' =>$order_id,//商户订单号                     'total_fee' => $price * 100, //总金额 单位 分                     'spbill_create_ip' => '111111', //终端IP                     'notify_url' => '回调地址', //通知地址  确保外网能正常访问                     'trade_type' => 'MWEB'//交易类型                 );                 //统一下单签名                 $parameters['sign'] = $this->getSign($parameters);                 $xmlData = $this->arrayToXml($parameters);                 $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));                 return $return;             }        }    }}

//统一下单接口
private function weixinapp($openid,$body,$orderId,$price,$attact) {

    $unifiedorder = $this->unifiedorder($openid,$body,$orderId,$price,$attact);    $parameters = array(        'appId' => "appId", //小程序ID        'timeStamp' => '' . time() . '', //时间戳        'nonceStr' => $this->createNoncestr(), //随机串        'package' => 'prepay_id=' . $unifiedorder['prepay_id'], //数据包        'signType' => 'MD5'//签名方式    );    //签名    $parameters['paySign'] = $this->getSign($parameters);    return $parameters;}//作用:产生随机字符串,不长于32位private function createNoncestr($length = 32) {    $chars = "abcdefghijklmnopqrstuvwxyz0123456789";    $str = "";    for ($i = 0; $i < $length; $i++) {        $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);    }    return $str;}private function getSign($Obj) {    //halt($Obj);    foreach ($Obj as $k => $v) {        $Parameters[$k] = $v;    }    //签名步骤一:按字典序排序参数    ksort($Parameters);    $String = $this->formatBizQueryParaMap($Parameters, false);    //签名步骤二:在string后加入KEY    $String = $String . "&key=d18e10ad06222c972499296f1cefa481" ;    //签名步骤三:MD5加密    $String = md5($String);    //签名步骤四:所有字符转为大写    $result_ = strtoupper($String);    return $result_;}///作用:格式化参数,签名过程需要使用private function formatBizQueryParaMap($paraMap, $urlencode) {    $buff = "";    ksort($paraMap);    foreach ($paraMap as $k => $v) {        if ($urlencode) {            $v = urlencode($v);        }        $buff .= $k . "=" . $v . "&";    }    $reqPar="";    if (strlen($buff) > 0) {        $reqPar = substr($buff, 0, strlen($buff) - 1);    }    return $reqPar;}//数组转换成xmlprivate function arrayToXml($arr) {    $xml = "";    foreach ($arr as $key => $val) {        if (is_array($val)) {            $xml .= "<" . $key . ">" . arrayToXml($val) . "";        } else {            $xml .= "<" . $key . ">" . $val . "";        }    }    $xml .= "";    return $xml;}//xml转换成数组private function xmlToArray($xml) {    //禁止引用外部xml实体    libxml_disable_entity_loader(true);    $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);    $val = json_decode(json_encode($xmlstring), true);    return $val;}function http_curl($url){//用curl传参    $ch = curl_init();    curl_setopt($ch, CURLOPT_URL, $url);    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//关闭ssl验证    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);    curl_setopt($ch,CURLOPT_HEADER, 0);    $output = curl_exec($ch);    curl_close($ch);    return json_decode($output, true);}private static function postXmlCurl($xml, $url, $second = 30){    $ch = curl_init();    //设置超时    curl_setopt($ch, CURLOPT_TIMEOUT, $second);    curl_setopt($ch, CURLOPT_URL, $url);    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验    //设置header    curl_setopt($ch, CURLOPT_HEADER, FALSE);    //要求结果为字符串且输出到屏幕上    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);    //post提交方式    curl_setopt($ch, CURLOPT_POST, TRUE);    curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);    curl_setopt($ch, CURLOPT_TIMEOUT, 40);    set_time_limit(0);    //运行curl    $data = curl_exec($ch);    //返回结果    if ($data) {        curl_close($ch);        return $data;    } else {        $error = curl_errno($ch);        curl_close($ch);        throw new WxPayException("curl出错,错误码:$error");    }}//回调private function unifiedorder($openid,$body,$orderId,$price,$attact) {    $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';    $parameters = array(        'appid' => "appid", //小程序ID        'mch_id' =>"mch_id", //商户号        'attach'=>$attact,        'nonce_str' => $this->createNoncestr(), //随机字符串        'body' => $body,        'out_trade_no'=> $orderId,        'total_fee' => $price * 100,        'spbill_create_ip' => '11111111', //终端IP        'notify_url' => 回调, //通知地址  确保外网能正常访问        'openid' => $openid, //用户id        'trade_type' => 'JSAPI'//交易类型    );    //统一下单签名    $parameters['sign'] = $this->getSign($parameters);    $xmlData = $this->arrayToXml($parameters);    $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));    return $return;}//回调public function callback(){    $xml = file_get_contents("php://input");    // 将XML 转换为数组    $xml = json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA));    $result = json_decode($xml, true);    //如果成功返回    if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){        $where['order_id']=$result['out_trade_no'];        $data_e['states']=2;        $ud= db('hc_pr_order')->where($where)->update($data_e);    }    // 给微信的返回值    if ($ud) {        $str='';    }else{        $str='';    }    return $str;    return $result;}
0