laravel下微信支付接入,三種支付模式
(掃碼模式二,微信瀏覽器內部支付(jsapi模式),手機端瀏覽器支付 (H5支付或者wap支付)
先進微信https://pay.weixin.qq.com/index.php作參數配置工做
A 支付受權目錄(支付發起的頁面url 必須精確到最後一個目錄/下 必須有 / 不然不行)
B 回調地址 就是付款完成了微信會回調你的url告訴你處理結果(我這裏沒用上,微信死活不回調我,我就js輪詢主動去查詢微信那邊的訂單狀態作處理)
$order_info['body']='畫品購買';
$order_info['order_number']=$order_id;
if($_SERVER['HTTP_HOST']=='www.qq.cn'){
$order_info['money']=$money;//畫品總價
$order_info['money']='1';
$order_info['id']=$order_id;
$result=$wxpay->do_nativepay($order_info);
//這個if裏面的就是本身定義的內容,好比生成二維碼以後你要插入一條數據進入數據庫之類 上面
$data['order_id']=$order_id;
if($_SERVER['HTTP_HOST']=='www.qq.cn'){
$data['money']=$money;//畫品總價
return ajax_success($data); 這裏包含微信返回的支付信息
getoneorder(data.info.order_id);
function getoneorder(pr){
url: '/wechat/checkwxorderstatus', //這個方法是查詢微信那邊的訂單處理狀結果 由於的回調微信沒有觸發.
success: function (msg) {
window.location.href='/member';
}else if (msg.status==2 ) {
//查詢微信的訂單狀態並處理訂單業務邏輯返回處理結果
public function checkWxOrderStatus(Request $request){
$order_id=$data['order_id'];
$result=$wxpay->query_order($order_id);
if(!empty($result['trade_state'])&&$result['trade_state']=='SUCCESS'){//去微信查詢訂單狀態是ok
$doorder=Order::doOrder($order_id,2); //傳訂單id處理訂單
'trade_state'=>'SUCCESS',
'order_status'=>'SUCCESS',
'trade_state'=>'SUCCESS',
'status'=>'2' //付款成功可是沒改訂單狀態
'status'=>'3' //付款不成功訂單也沒修改
2.微信內部瀏覽器支付(jsapi模式)和手機瀏覽器模式參見下面合併在一塊兒判斷處理的,我這裏是是根據UA進行判斷用戶進入哪一種支付模式,若是是微信打開的進入第一個不然進入第二個H5支付
if($this->isWeixin()){ //微信內部瀏覽器,這個方法網上不少本身搜索
$wxpay = new Mobilewxpay();
$order_info['uatype']='2';
$order_info['body']='畫品購買';
$order_info['opend_id']=Auth::user()->openid;
$order_info['order_number']=$parent_order_id;
if($_SERVER['HTTP_HOST']=='www.qq.cn'){
$order_info['money']=$total_money;
$order_info['money']='1';
$order_info['id']=$parent_order_id;
$order_info['pay_type']=2;
$wxpay->unifiedOrder($order_info);
$resulturl = $wxpay->GetJsApiParameters($order_info);
//這一步是把微信返回的json格式的數據轉換成數組
$resulturl = json_decode($resulturl,true);
$order_info['resulturl']= $resulturl;
$wxpay = new Mobilewxpay();
$order_info['uatype']='1';
$order_info['body']='畫品購買';
$order_info['order_number']=$parent_order_id;
if($_SERVER['HTTP_HOST']=='www.qq.cn'){
$order_info['money']=$total_money;
$order_info['money']='1';
$order_info['id']=$parent_order_id;
$h5result= $wxpay->MobileH5Pay($order_info);
$order_info['pay_type']=2;
$order_info['h5resulturl']=!empty($h5result['mweb_url'])?$h5result['mweb_url']:'';
return ajax_success($order_info);
if(data.info.pay_type==2){//微信支付
if(data.info.uatype == 1){//手機自帶瀏覽器H5支付走這裏
var h5resulturlss=data.info.h5resulturl.replace(/amp;/, "");//這裏進入了一個坑IOS手機上url會被轉義這裏是處理這個狀況的,請注意支付跳轉的url裏面的&是否被轉義成& 切記大坑. 若是是賦值在a連接的一個連接的話不會有這種狀況發生.若是變量賦值給js的話會有這種狀況.
var h5resulturl12=decodeURI(h5resulturlss);
window.open(h5resulturl12);//這裏是走微信支付協議調用微信彈框
}else{//微信內部瀏覽器jsapi支付走這裏
callpay(data.info.resulturl);//這裏是呼喚微信支付彈框
getoneorder(data.info.id);
WeixinJSBridge.log(res.err_msg);
// alert(res.err_code+res.err_desc+res.err_msg);
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
function getoneorder(pr){
url: '/wechat/checkwxorderstatus',//這裏仍是查詢微信那邊的訂單狀態作判斷處理
success: function (msg) {
content: '<div class="demo-tip-box"><div class="tip-text">支付成功</div></div>'
// window.setTimeout('window.location.href="/buy/paysuccess?type=1&oid='+pr+'"',2000);
window.setTimeout('window.location.href="/member/myorder"',2000);
}else if (msg.status==2 ) {
content: '<div class="demo-tip-box"><div class="tip-text">支付失敗</div></div>'
$(document).ready(function(){
namespace App\Tools\weixin;
public function do_nativepay1($productId){
include_once '../app/Tools/weixin/lib/WxPay.NativePay.php';
$notify = new NativePay();
$url1 = $notify->GetPrePayUrl($productId);
public function do_nativepay($order_info) {
include_once '../app/Tools/weixin/lib/WxPay.NativePay.php';
$notify = new \NativePay();
$input = new \WxPayUnifiedOrder();
$input->SetBody($order_info['body']);
$input->SetAttach("畫品購買");
$input->SetOut_trade_no($order_info['id']);
//$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
if($_SERVER['HTTP_HOST']=='www.qq.cn'){
$input->SetTotal_fee($order_info['money']*100);
$input->SetTotal_fee($order_info['money']);
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("test");
$input->SetTrade_type("NATIVE");
$input->SetProduct_id($order_info['id']);
$result = $notify->GetPayUrl($input);
$url2 = $result["code_url"];
public function do_wxpay($order_info) {
ini_set('date.timezone', 'Asia/Shanghai');
include_once '../app/Tools/weixin/lib/WxPay.JsApiPay.php';
$tools = new \JsApiPay();
$openId = $tools->GetOpenid();
$input = new \WxPayUnifiedOrder();
$input->SetBody($order_info['goods_name']);
$input->SetOut_trade_no($order_info['order_sn']);
$input->SetTotal_fee($order_info['order_amount']);
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag('');
// $input->SetNotify_url(WxPayConfig::NOTIFY_URL);
$input->SetTrade_type("JSAPI");
$input->SetOpenid($openId);
$order = \WxPayApi::unifiedOrder($input);
$jsApiParameters = $tools->GetJsApiParameters($order);
include_once('../app/Tools/weixin/lib/WxPay.Api.php');
$url_arr = json_decode($jsApiParameters, TRUE);
unset($url_arr['signType']);
unset($url_arr['paySign']);
$url_arr['order_sn'] = $order_info['order_sn'];
$notify = new \WxPayResults();
$notify->FromArray($url_arr);
$sign = $notify->SetSign();
$url_arr['sign'] = $sign;
$return_url = \WxPayConfig::RETURN_URL . '?' . http_build_query($url_arr);
$pay_url = \WxPayConfig::PAY_URL . '?order_sn=' . $order_info['order_sn'];
include_once 'weixin.html';
public function do_return($arr = array()) {
include_once('../app/Tools/weixin/lib/WxPay.Api.php');
$notify = new \WxPayResults();
$notify->FromArray($arr);
if ($notify->CheckSign() == true) {
public function do_notify($xml) {
include_once('../app/Tools/weixin/lib/WxPay.Api.php');
$notify = new WxPayResults();
if ($notify->CheckSign() == true) {
public function FromXml($xml) {
include_once('../app/Tools/weixin/lib/notify.php');
$notify = new PayNotifyCallBack();
return $notify->FromXml($xml);
@param string $order_sn 07073訂單號
public function query_order($order_sn) {
include_once '../app/Tools/weixin/lib/WxPay.Api.php';
if (isset($order_sn) && $order_sn != "") {
$input = new \WxPayOrderQuery();
$input->SetOut_trade_no($order_sn);
$result_arr = \WxPayApi::orderQuery($input);
public function wx_refund($order_info) {
require_once "../app/Tools/weixin/lib/WxPay.Api.php";
$input = new WxPayRefund();
$input->SetTransaction_id($order_info['transaction_id']);
$input->SetTotal_fee($order_info['total_fee']);
$input->SetRefund_fee($order_info['refund_fee']);
$input->SetOut_refund_no($order_info['batch_no']);
$input->SetOp_user_id(WxPayConfig::MCHID);
$res = WxPayApi::refund($input);
public function wx_refund_query($order_info) {
require_once '../app/Tools/weixin/lib/WxPay.Api.php';
$input = new WxPayRefundQuery();
$input->SetTransaction_id($order_info['transaction_id']);
$res = WxPayApi::refundQuery($input);
public function do_wappay($order_info) {
include_once '../app/Tools/weixin/lib/WxPay.WapPay.php';
$input = new \WxPayUnifiedOrder();
$input->SetBody($order_info['goods_name']);
$input->SetOut_trade_no($order_info['order_sn']);
$input->SetTotal_fee($order_info['order_amount']);
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("");
$input->SetNotify_url(\WxPayConfig::NOTIFY_URL);
$input->SetTrade_type("WAP");
$input->SetProduct_id($order_info['id']);
$prepay_res = $wxpay->GetPrepayInfo($input);
$wxpay->GetWapPayUrl($prepay_res['prepayid']);
public function wxlogin() {
include_once '../app/Tools/weixin/lib/WxPay.JsApiPay.php';
$data = $tools->GetOpenData();
public function wxuser($access_token, $openid) {
include_once '../app/Tools/weixin/lib/WxPay.JsApiPay.php';
$data = $tools->getUserInfo($access_token, $openid);
public function xmlToArray($xml){
$array_data = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
function arrayToXml($arr)
foreach ($arr as $key=>$val)
$xml.="<".$key.">".$val."</".$key.">";
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
public function mobile_h5pay(){
include_once '../app/Tools/weixin/lib/WxPay.JsApiPay.php';
$tools = new \JsApiPay();
$openId = $tools->GetOpenid();
$input = new \WxPayUnifiedOrder();
$input->SetAttach("test");
$input->SetOut_trade_no(\WxPayConfig::MCHID.date("YmdHis"));
$input->SetTotal_fee("1");
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("test");
$input->SetTrade_type("MWEB"); //H5支付的交易類型爲MWEB
// $input->SetOpenid($openId); //這裏要註釋掉
$order = \WxPayApi::unifiedOrder($input);
下面這個是H5支付和微信內部瀏覽器支付使用的類文件
namespace App\Tools\weixin;
header('Content-type:text/html;charset=utf-8');
@package App\Tools\weixin
public $APPID = 'wx811a9fc';
public $KEY = '68e4b3eae5b171f17fc5';
public $APPSECRET = '6bce72a750664d61a3b47c';
function ToUrlParams($urlObj)
foreach ($urlObj as $k => $v)
$buff .= $k . "=" . $v . "&";
$buff = trim($buff, "&");
統一下單,WxPayUnifiedOrder中out_trade_no、body、total_fee、trade_type必填
appid、mchid、spbill_create_ip、nonce_str不須要填入
@param WxPayUnifiedOrder $inputObj
function unifiedOrder($order_info,$timeOut = 6)
$datas['out_trade_no'] = $order_info['id'];//訂單號
$datas['total_fee'] = $order_info['money'];
$datas['time_start'] = date("YmdHis");
$datas['time_expire'] = date("YmdHis", time() + 600);
$datas['trade_type'] = 'JSAPI';//微信內部瀏覽器支付
// $datas['openid'] = $order_info['opend_id'];
$datas['openid'] = 'o_rTz0bCFLXRx5XSmE_ijh9xaC3U';
$datas['appid'] = $this->APPID;//公衆帳號ID
$datas['mch_id'] = $this->MCHID;//商戶號
$datas['spbill_create_ip'] = $_SERVER['REMOTE_ADDR'];//ip
$datas['nonce_str'] = $this->getNonceStr();//隨機字符串
$string = $this->ToUrlParamss($datas);
$string = $string . "&key=".$this->KEY;
$result = strtoupper($string);
$datas['sign'] = $result;//簽名
$xml = $this->ToXml($datas);
$response = $this->postXmlCurl($xml, $url, false, $timeOut);
$data = $this->FromXml($response);
function getNonceStr($length = 32)
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
for ( $i = 0; $i < $length; $i++ ) {
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
foreach ($datas as $key=>$val)
$xml.="<".$key.">".$val."</".$key.">";
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
function ToUrlParamss($datas)
foreach ($datas as $k => $v)
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
$buff = trim($buff, "&");
@param string $xml 須要post的xml數據
@param bool $useCert 是否須要證書,默認不須要
@param int $second url執行超時時間,默認30s
function postXmlCurl($xml, $url, $useCert = false, $second = 30)
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);//嚴格校驗
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
public function FromXml($xml) {
return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
@param array $UnifiedOrderResult 統一支付接口返回的數據
@return json數據,可直接填入js函數做爲參數
function GetJsApiParameters($order_info,$timeOut = 6){
$UnifiedOrderResult = $this->unifiedOrder($order_info,$timeOut = 6);
if(!array_key_exists("appid", $UnifiedOrderResult)
|| !array_key_exists("prepay_id", $UnifiedOrderResult)
|| $UnifiedOrderResult['prepay_id'] == "")
echo $UnifiedOrderResult['err_code_des'];
$da['appId'] = $UnifiedOrderResult["appid"];
$da['timeStamp'] = "$timeStamp";
$da['nonceStr'] = $this->getNonceStr();
$da['package'] = "prepay_id=" . $UnifiedOrderResult['prepay_id'];
$string = $this->ToUrlParamss($da);
$string = $string . "&key=".$this->KEY;
$result = strtoupper($string);
$da['paySign'] = $result;
$parameters = json_encode($da);
function get_client_ip() {
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$realip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} else if (isset($_SERVER["HTTP_CLIENT_IP"])) {
$realip = $_SERVER["HTTP_CLIENT_IP"];
$realip = $_SERVER["REMOTE_ADDR"];
if (getenv("HTTP_X_FORWARDED_FOR")) {
$realip = getenv("HTTP_X_FORWARDED_FOR");
} else if (getenv("HTTP_CLIENT_IP")) {
$realip = getenv("HTTP_CLIENT_IP");
$realip = getenv("REMOTE_ADDR");
function createNoncestr( $length = 32 ){
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
for ( $i = 0; $i < $length; $i++ ) {
$str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}elseif(isset($_SERVER['HTTP_CLIENT_IP'])){
$ip = $_SERVER['HTTP_CLIENT_IP'];
$ip = $_SERVER['REMOTE_ADDR'];
$ip_arr = explode(',', $ip);
public function postXmlCurlh5($xml,$url,$second = 30){
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);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
$error = curl_errno($ch);
echo "curl出錯,錯誤碼:$error"."<br>";
@return 簽名,本函數不覆蓋sign成員變量,如要設置簽名須要調用SetSign方法賦值
protected function MakeSign($arr) {
$string = $this->ToUrlParams($arr);
$string = $string . "&key=" . $this->KEY;
$result = strtoupper($string);
public function MobileH5Pay($order_info){
$headers[] ='Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/ ;q=0.8';
$headers[] ='Connection: Keep-Alive';
$headers[] ='Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3';
$headers[] ='Accept-Encoding: gzip, deflate';
$headers[] ='User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20100101Firefox/22.0';
$appid = $this->APPID; //應用APPID
$mch_id = $this->MCHID; //微信支付商戶號
$key = $this->KEY; //微信商戶API密鑰
$rand = rand(00000,99999);
$out_trade_no = $order_info['id'];//平臺內部訂單號
$nonce_str = $this->createNoncestr();//隨機字符串
$body = "artflyer.cn";//內容
$total_fee = $order_info['money']; //金額
$spbill_create_ip = $this->getIp(); //IP
$trade_type = 'MWEB';//交易類型 由於是h5支付因此交易類型必須是MWEB
$signA ="appid=$appid&attach=$out_trade_no&body=$body&mch_id=$mch_id&nonce_str=$nonce_str¬ify_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"; //拼接字符串 注意順序微信有個測試網址 順序按照他的來 直接點下面的校訂測試 //包括下面XML 是否正確
$sign = strtoupper(MD5($strSignTmp)); // MD5 後轉換成大寫
<out_trade_no>$out_trade_no</out_trade_no>
<total_fee>$total_fee</total_fee>
<spbill_create_ip>$spbill_create_ip</spbill_create_ip>
<notify_url>$notify_url</notify_url>
<trade_type>$trade_type</trade_type>
<scene_info>$scene_info</scene_info>
<attach>$out_trade_no</attach>
<nonce_str>$nonce_str</nonce_str>
$dataxml = $this->postXmlCurlh5($post_data,$url,$headers); //後臺POST微信傳參地址 同時取得微信返回的參數 POST 方法我寫下面了
$objectxml = (array)simplexml_load_string($dataxml, 'SimpleXMLElement', LIBXML_NOCDATA); //將微信返回的XML 轉換成數組
有問題也能夠發郵件給微信技術 wepayTS@tencent.com
搞的比較亂別罵...... 有問題能夠QQ交流 245864009
歡迎關注本站公眾號,獲取更多信息