這里開發時使用的是thinkphp5.1
1.直接喚起微信支付
<?php namespace app\index\controller; use wechatpay\lib\WxPayApi; use wechatpay\lib\WxPayUnifiedOrder; use wechatpay\example\JsApiPay; use wechatpay\example\WxPayConfig; use think\facade\Env; class Pay { /* 1、交易金額 交易金額默認為人民幣交易,接口中參數支付金額單位為【分】,參數值不能帶小數。對賬單中的交易金額單位為【元】。 外幣交易的支付金額精確到幣種的最小單位,參數值不能帶小數點。 2、交易類型 JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付,統一下單接口trade_type的傳參可參考這里 MICROPAY--刷卡支付,刷卡支付有單獨的支付接口,不調用統一下單接口 3、貨幣類型 貨幣類型的取值列表: CNY:人民幣 4、時間 標准北京時間,時區為東八區;如果商戶的系統時間為非標准北京時間。參數值必須根據商戶系統所在時區先換算成標准北京時間, 例如商戶所在地為0時區的倫敦,當地時間為2014年11月11日0時0分0秒,換算成北京時間為2014年11月11日8時0分0秒。 5、時間戳 標准北京時間,時區為東八區,自1970年1月1日 0點0分0秒以來的秒數。注意:部分系統取到的值為毫秒級,需要轉換成秒(10位數字)。 6、商戶訂單號 商戶支付的訂單號由商戶自定義生成,僅支持使用字母、數字、中划線-、下划線_、豎線|、星號*這些英文半角字符的組合,請勿使用漢字或全角等特殊字符。微信支付要求商戶訂單號保持唯一性(建議根據當前系統時間加隨機序列來生成訂單號)。重新發起一筆支付要使用原訂單號,避免重復支付;已支付過或已調用關單、撤銷(請見后文的API列表)的訂單號不能重新發起支付。 */ /** * 微信支付調用 * @author ffx * @param int $userId 用戶id * @param float $money 金額 * @param int $type 支付類型(1充值,2訂單支付) * @param string $body 顯示title,提示頭信息 * @param string $backUrl 回調地址(/index/pay/wxPayBack) * @param string $addition 附加參數(微信回調時原樣返回) * @return bool|mixed */ public function wxPay($userId,$money,$type,$body,$backUrl,$addition = '') { $out_trade_no = self::getOrderNo(); $wxchid = config('wechat.wxmchid'); $wxAppId = config('wechat.paywxAppId'); //微信支付sdk中的文件 include_once EXTEND_PATH."wechatpay/lib/WxPay.Api.php"; include_once EXTEND_PATH."wechatpay/example/WxPay.JsApiPay.php"; $total_money = floor(sprintf("%0.3f",$money)*100); if(!$total_money || $total_money <= 0){ return ['code'=>100001,'message'=>"支付金額小於0"]; } if($_SERVER["REQUEST_SCHEME"] == "http"){ $notify_url = 'http://'.$_SERVER['HTTP_HOST'].$backUrl; }else{ $notify_url = 'https://'.$_SERVER['HTTP_HOST'].$backUrl; } //此處查詢的是登錄時存起來的openid $openid = Db::name('member')->where('id',$userId)->value('openid'); $input = new \WxPayUnifiedOrder(); $input->SetAppid($wxAppId); $input->SetMch_id($wxchid); //商戶號 $input->SetAttach($addition); //附加參數 $nonceStr = self::createNonceStr(); $input->SetNonce_str($nonceStr);//自定義隨機字符串 $input->SetBody($body);// $input->SetOut_trade_no($out_trade_no);//訂單號,自己建 $input->SetTotal_fee($total_money);//金錢 $input->SetSpbill_create_ip($this->getIP());//客戶端ip $input->SetTime_start(date("YmdHis")); $input->SetTime_expire(date("YmdHis", time() + 600));//過期時間 $input->SetNotify_url($notify_url);//回調的接口地址 $input->SetTrade_type("JSAPI");//支付類型 $input->SetOpenid($openid); //此處兩個是微信支付的sdk的類 $WxPayApi = new WxPayApi(); $config = new WxPayConfig(); $response = $WxPayApi->unifiedOrder($config,$input);//預創建訂單 //寫入支付記錄表(業務邏輯處理) $res = $this->insertWxPayLog($userId,$out_trade_no,$money,$type,0); if(!$res){ return false; } if($response['result_code']=='SUCCESS' && $response['return_code']=='SUCCESS' && $response['return_msg']=='OK') { $tools = new JsApiPay(); $response['nonce_str'] = $nonceStr; $jsApiParameters = $tools->GetJsApiParameters($response); return json_decode($jsApiParameters); //$jsApiParameters示例 //{"appId":"wx194a1075c8bca3d9","nonceStr":"4tmc7nttscu5w6u6cqbxlgvum4qs6p8y","package":"prepay_id=wx05155440194924091e0efc912670185750","signType":"MD5","timeStamp":"1541404480","paySign":"CD4DE57A6B5B2B5418B5F07536C4DF10"} //輸出直接喚起支付 // $str = "<html><body></body></html>"; // // $str .='<html><head><meta http-equiv="content-type" content="text/html;charset=utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>微信支付</title></head><body>'; // // $str .= "<script>function onBridgeReady(){WeixinJSBridge.invoke('getBrandWCPayRequest',$jsApiParameters)}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()}</script></body></html>"; // // echo $str;exit; }else{ return false; } } /** * 余額支付回調 * @author ffx * */ function amountPayBack() { $xml = file_get_contents('php://input'); $xmlJson = json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)); $arr = json_decode($xmlJson, true); //此處注釋暫未用到 /* //用戶http_build_query()將數據轉成URL鍵值對形式 $sign = http_build_query($arr); //md5處理 $sign = md5($sign); //轉大寫 $sign = strtoupper($sign); //驗簽名。默認支持MD5 if($sign === $arr['sign']) { // 校驗返回的訂單金額是否與商戶側的訂單金額一致。修改訂單表中的支付狀態。 } $return = ['return_code'=>'SUCCESS','return_msg'=>'OK']; $xml = '<xml>'; foreach($return as $k=>$v){ $xml.='<'.$k.'><![CDATA['.$v.']]></'.$k.'>'; } $xml.='</xml>';*/ $out_trade_no=$arr['out_trade_no']; //訂單號 //判斷金額 $total_fee=$arr['total_fee']/100*10000; //回調回來的xml文件中金額是以分為單位的 $money = Db::name('recharge_log')->where('out_trade_no',$out_trade_no)->value('money'); if($money != $total_fee){ return; } $result_code=$arr['result_code']; //狀態 if($result_code=='SUCCESS'){ //處理數據庫操作 $post = [ 'out_trade_no'=>$out_trade_no, 'total_fee'=>$arr['total_fee'] //微信實際收到金額(分為單位) ]; //處理業務邏輯 $res = $this->amountPayBackLogic($xmlJson,$post,1,$money); if($res['code'] == 0){ echo 'SUCCESS'; //返回成功給微信端 一定要帶上不然微信會一直回調8次 exit; } }else{ //失敗 return; } } /** * 獲取隨機字符串 * @author ffx * @param int $length 長度 * @return string */ 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; } /** * 獲取訂單號 * @author ffx * @return string */ public static function getOrderNo() { $outTradeNo = time() . rand(1000, 9999); return $outTradeNo; } /** * @purpose 獲取請求來源的ip * @author ffx * @return mixed */ function getIp() { if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; } else { $ip = $_SERVER['REMOTE_ADDR']; } $ip_arr = explode(',', $ip); return $ip_arr[0]; } }
2.生成二維碼支付
回調和喚起支付一樣
/** * 微信支付調用 * @author ffx * @param int $userId 用戶id * @param float $money 金額 * @param string $body 顯示title,提示頭信息 * @param string $backUrl 回調地址(/v1/pay/wxPayBack) * @param string $addition 附加參數(微信回調時原樣返回) * @return bool */ public function wxPayErWeiMa($userId,$money,$body,$backUrl,$addition = '') { $out_trade_no = self::getOrderNo(); $total_money = $money; include_once EXTEND_PATH."wxpay/lib/WxPay.Api.php"; include_once EXTEND_PATH."wxpay/example/WxPay.JsApiPay.php"; include_once EXTEND_PATH."wxpay/example/WxPay.NativePay.php"; $total_money = floor(sprintf("%0.3f",$total_money)*100); if(!$total_money || $total_money <= 0){ return ['code'=>100001,'message'=>"支付金額小於0"]; } $notify_url = 'http://'.$_SERVER['HTTP_HOST'].$backUrl; $wxPayConfig = Db::name('user_wxpay_config') ->alias('c') ->join('member m','m.admin_user=c.admin_user') ->where('m.id', $userId) ->where('c.status', 1) ->field('c.*') ->order('update_time','desc') ->find(); if(empty($wxPayConfig)){ return false; } if(empty($body)){ $body = $wxPayConfig['body']; } $wxchid = $wxPayConfig['mac_id']; $wxAppId = $wxPayConfig['appid']; $wxAppSecret = $wxPayConfig['app_secret']; $wxKey = $wxPayConfig['key']; $config = new WxPayConfig(); $config->SetAppSecret($wxAppSecret); $config->SetKey($wxKey); $config->SetAppId1($wxAppId); $config->SetMerchantId1($wxchid); $input = new WxPayUnifiedOrder(); $input->SetBody($body); $input->SetAttach($addition); //附加參數 $input->SetOut_trade_no($out_trade_no); //訂單號,自己建 $input->SetTotal_fee($total_money);//金錢 $input->SetTime_start(date("YmdHis")); $input->SetTime_expire(date("YmdHis", time() + 600)); //過期時間 $input->SetGoods_tag("test"); $input->SetNotify_url($notify_url); //回調的接口地址 $input->SetTrade_type("NATIVE"); //支付類型(二維碼) $input->SetProduct_id("123456789"); //寫入支付記錄表 $res = $this->insertRechargeLog($userId,$out_trade_no,$money,0,'wxpay'); if(!$res){ return false; } $notify = new \NativePay(); $result = $notify->GetPayUrl($input); if(isset($result["code_url"]) && !empty($result["code_url"])){ require_once './../extend/wxpay/example/phpqrcode/phpqrcode.php'; $url = urldecode($result['code_url']); if(substr($url, 0, 6) == "weixin"){ QRcode::png($url); }else{ header('HTTP/1.1 404 Not Found'); } }else{ return false; } }
