微信支付:自动识别切换H5和公众号支付

| 阅读:41 发表时间:2019-09-10 16:29:15 微信

1、下载微信支付SDK包

2、引用,并按下面的代码进行配置


require_once("wxlib/WxPay.Api.php");        
require_once("wxlib/WxPay.NativePay.php");
require_once("wxlib/WxPay.JsApiPay.php");

header('Content-type:text/html; Charset=utf-8');
/*** 请填写以下配置信息 ***/

if($_POST){
    
    $amount = $_POST['amount'];
  
    $if_wap = $_POST['wap'];    

    $outTradeNo = date("ymdhis").rand(10000, 999999); 
    $time = date("Y-m-d H:i:s");
  
    $order['order_amount'] = $amount;
    $order['order_sn'] = $outTradeNo;
    
    mysql_query("INSERT INTO wxpay(PayID,PayPrice,PayName,PayResult,time,PayType) VALUES ({$outTradeNo},'{$amount}','{$ir['username']}','0','{$time}',1)")or die("INSERT INTO alipay(PayID,PayPrice,PayName,PayResult,time,PayType) VALUES ({$outTradeNo},'{$amount}','{$ir['username']}','0','{$time}',1)");

    WxPayConfig::$appid = ""; // * APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
    WxPayConfig::$mchid = ""; // * MCHID:商户号(必须配置,开户邮件中可查看)
    WxPayConfig::$key = ""; // KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
    WxPayConfig::$appsecret = ""; // 公众帐号secert(仅JSAPI支付的时候需要配置)
    
    if($if_wap){
       //启用h5支付
       if(strstr($_SERVER['HTTP_USER_AGENT'],'MicroMessenger')){
           $code_str = getJSAPI($order);
           exit($code_str);
       }else{
           payh5($order);
       }
    }else{
       //使用native支付
       $ret =  get_code($order);
       echo $ret;
    }
}

function get_code($order){
  $notify = 'http://'.$_SERVER['HTTP_HOST'].'/native_notify.php';
  $input = new WxPayUnifiedOrder();
  $input->SetBody("会员充值"); // 商品描述
  $input->SetAttach("weixin"); // 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
  $input->SetOut_trade_no($order['order_sn']); // 商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
  $input->SetTotal_fee($order['order_amount']*100); // 订单总金额,单位为分,详见支付金额
  $input->SetNotify_url($notify); // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
  $input->SetTrade_type("NATIVE"); // 交易类型   取值如下:JSAPI,NATIVE,APP,详细说明见参数规定    NATIVE--原生扫码支付
  $input->SetProduct_id("123456789"); // 商品ID trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。
  $notify = new NativePay();
  $result = $notify->GetPayUrl($input); // 获取生成二维码的地址
  $url2 = $result["code_url"];
  return $url2;
} 


 function getJSAPI($order){
        $go_url = 'http://'.$_SERVER['HTTP_HOST'].'/cashto.php';
        $back_url =  'http://'.$_SERVER['HTTP_HOST'].'/cashto.php';
        
        WxPayConfig::$appid = '';
        WxPayConfig::$mchid = ""; // * MCHID:商户号(必须配置,开户邮件中可查看)
        WxPayConfig::$key = ""; // KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
        WxPayConfig::$appsecret = ""; // 公众帐号secert(仅JSAPI支付的时候需要配置)
       
        //①、获取用户openid
        $tools = new JsApiPay();
        $openId = $_SESSION['openid'];
        //②、统一下单
        $input = new WxPayUnifiedOrder();
        $input->SetBody("会员充值:".$order['order_sn']);
        $input->SetAttach("weixin");
        $input->SetOut_trade_no($order['order_sn']);
        $input->SetTotal_fee($order['order_amount']*100);
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        $input->SetGoods_tag("tp_wx_pay");
        $input->SetNotify_url('http://'.$_SERVER['HTTP_HOST'].'/native_notify.php');
        $input->SetTrade_type("JSAPI");
        $input->SetOpenid($openId);
        //var_dump($input);die;
        $order2 = WxPayApi::unifiedOrder($input);
        //echo '<font color="#f00"><b>统一下单支付单信息</b></font><br/>';
        //var_dump($order2);exit;  
        $jsApiParameters = $tools->GetJsApiParameters($order2);
        $html = <<<EOF
	<script type="text/javascript">
	//调用微信JS api 支付
	function jsApiCall()
	{
		WeixinJSBridge.invoke(
			'getBrandWCPayRequest',$jsApiParameters,
			function(res){
				//WeixinJSBridge.log(res.err_msg);
				 if(res.err_msg == "get_brand_wcpay_request:ok") {
				    location.href='$go_url';
				 }else{
				 	alert(res.err_code+res.err_desc+res.err_msg);
				    location.href='$back_url';
				 }
			}
		);
	}

	function callpay()
	{
		if (typeof WeixinJSBridge == "undefined"){
		    if( document.addEventListener ){
		        document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
		    }else if (document.attachEvent){
		        document.attachEvent('WeixinJSBridgeReady', jsApiCall);
		        document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
		    }
		}else{
		    jsApiCall();
		}
	}
	callpay();
	</script>
EOF;
        
    return $html;

    }

function payh5($order){
         $ip = get_client_ip();
         $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
         $notify = 'http://'.$_SERVER['HTTP_HOST'].'/native_notify.php';
         $nonce_str = createNoncestr();
         
         $appid = '';
         $key  = '';
         $body = "会员充值";
         $mch_id = '';
         $notify_url = $notify;
         $spbill_create_ip = $ip;
         $total_fee = $order['order_amount']*100;
         $trade_type = 'MWEB';
         $out_trade_no = $order['order_sn'];
         
         $scene_info = '{"h5_info": {"type":"Android","app_name": "CCGG","package_name": "com.ccgg2019"}}';
         $signA = "appid=$appid&body=$body&mch_id=$mch_id&nonce_str=$nonce_str&notify_url=$notify_url&out_trade_no=$out_trade_no&scene_info=$scene_info&spbill_create_ip=$spbill_create_ip&total_fee=$total_fee&trade_type=$trade_type";
         $strSignTmp = $signA."&key=".$key;
         $sign = strtoupper(MD5($strSignTmp));
         $data['sign'] = $sign;
         
         $post_data = "<xml> 
                <appid>$appid</appid> 
                <body>$body</body> 
                <mch_id>$mch_id</mch_id> 
                <nonce_str>$nonce_str</nonce_str> 
                <notify_url>$notify_url</notify_url> 
                <out_trade_no>$out_trade_no</out_trade_no> 
                <spbill_create_ip>$spbill_create_ip</spbill_create_ip> 
                <total_fee>$total_fee</total_fee> 
                <trade_type>$trade_type</trade_type> 
                <scene_info>$scene_info</scene_info> 
                <sign>$sign</sign> 
                </xml>";
        
        $dataxml = http_post($url, $post_data);
        $objectxml = XmlToArr($dataxml);
       
        if( $objectxml['return_code'] == 'SUCCESS' && $objectxml['result_code'] == 'SUCCESS' ){
             $url = $objectxml['mweb_url'];
             exit("<script>location.href='".$url."'</script>");
        }
 }

function createNoncestr(){
  $num = rand(10,20);
  $times = rand(1,9);
  $str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  for ($i=0; $i < $times ; $i++) {
    for ($j=0; $j < $num; $j++) {
      $b = rand(0,61);
      $code .= $str[$b];
    }
  }
  return md5($code);
}

function get_client_ip($type = 0) {
    $type       =  $type ? 1 : 0;
    static $ip  =   NULL;
    if ($ip !== NULL) return $ip[$type];
    if($_SERVER['HTTP_X_REAL_IP']){//nginx 代理模式下,获取客户端真实IP
        $ip=$_SERVER['HTTP_X_REAL_IP'];     
    }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {//客户端的ip
        $ip     =   $_SERVER['HTTP_CLIENT_IP'];
    }elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {//浏览当前页面的用户计算机的网关
        $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        $pos    =   array_search('unknown',$arr);
        if(false !== $pos) unset($arr[$pos]);
        $ip     =   trim($arr[0]);
    }elseif (isset($_SERVER['REMOTE_ADDR'])) {
        $ip     =   $_SERVER['REMOTE_ADDR'];//浏览当前页面的用户计算机的ip地址
    }else{
        $ip=$_SERVER['REMOTE_ADDR'];
    }
    // IP地址合法验证
    $long = sprintf("%u",ip2long($ip));
    $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
    return $ip[$type];
}

function XmlToArr($xml)
{	
  if($xml == '') return '';
  libxml_disable_entity_loader(true);
  $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);		
  return $arr;
}

function http_post($url='',$post_data=array(),$header=array(),$timeout=30) {
  $ch = curl_init();  
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查  
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);  // 从证书中检查SSL加密算法是否存在  
  curl_setopt($ch, CURLOPT_URL, $url);  
  curl_setopt($ch, CURLOPT_HTTPHEADER, $header);  
  curl_setopt($ch, CURLOPT_POST, true);  
  curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);  
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);   
  curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);  
  $response = curl_exec($ch);
  curl_close($ch);
  return $response;
}

3、注意里面的逻辑部分代码,按自己的编码框架进行修改

*文章为作者独立观点,不代表【uuuho有乎】的立场
本文由【uuuho有乎】发表并编辑,转载此文章须经作者同意,并请附上出处及本页链接。如有侵权,请联系本站删除。