一、Model層,Wxpay.php
appid = $appid; if(!empty($secret)) $this->secret = $secret; if(!empty($mchid)) $this->mchid = $mchid; if(!empty($key)) $this->key= $key; } /* * 微信內H5調起支付 * @params string $openid : 微信用戶openid * @params string $out_trade_no : 商家生成的訂單號(唯一性) * @params int $total_fee : 支付金額,單位分 * return array $ret : 返回支付時所需要的數據 * */ public function payForWeixin($openid,$out_trade_no,$total_fee,$attach="微信支付",$body="微信支付") { //支付數據 $data["openid"] = $openid; $data["out_trade_no"] = $out_trade_no; $data["total_fee"] = $total_fee*100; $data["spbill_create_ip"] = $_SERVER["REMOTE_ADDR"]; $data["attach"] = $attach; $data["body"] = $body; $data["appid"] = $this->appid; $data["mch_id"] = $this->mchid; $data["nonce_str"] = random(12); $data["trade_type"] = "JSAPI"; $data["notify_url"] = "http://****.com/home/wxpaynofiy/notify.html"; $sign = $this->getParam($data); $dataXML = ""; $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $result = $this->https_post($url,$dataXML); $ret = $this->xmlToArray($result); if($ret["return_code"] == "SUCCESS" && $ret["return_msg"] == "OK") { return array( "appId" => $this->appid, "timeStamp" => time(), "nonceStr" => $data["nonce_str"], "package" => "prepay_id=".$ret["prepay_id"], "signType" => "MD5", "paySign" => $sign ); } else { $this->errorLog("微信支付失敗,",$ret); return null; } } /* * 微信二維碼支付 * @params string $openid : 用戶的openid * @params string $out_trade_no : 商戶訂單號 * @params number $total_fee : 訂單金額,單位分 * return string $code_url : 二維碼URL鏈接 */ public function payForQrcode($out_trade_no,$total_fee,$body="魔盒CMS",$attach="微信支付") { //支付數據 $data["out_trade_no"] = $out_trade_no; $data["total_fee"] = $total_fee*100; $data["spbill_create_ip"] = $_SERVER["REMOTE_ADDR"]; $data["attach"] = $attach; $data["body"] = $body; $data["appid"] = $this->appid; $data["mch_id"] = $this->mchid; $data["nonce_str"] = random(12); $data["trade_type"] = "NATIVE"; $data["notify_url"] = "http://****.com/home/wxpaynofiy/notify.html"; $sign = $this->getParam($data); $dataXML = " ".$data["appid"]." ".$data["attach"]." ".$data["body"]."".$data["mch_id"]." ".$data["nonce_str"]." ".$data["notify_url"]." ".$data["openid"]." ".$data["out_trade_no"]." ".$data["spbill_create_ip"]." ".$data["total_fee"]." ".$data["trade_type"]." ".$sign." "; $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $result = $this->https_post($url,$dataXML); $ret = $this->xmlToArray($result); if($ret["return_code"] == "SUCCESS" && $ret["return_msg"] == "OK") { return $ret["code_url"]; } else { $this->errorLog("獲取微信支付二維碼失敗,",$ret); return null; } } /* * 訂單查詢 * @params string $transaction_id : 微信訂單號 * @params string $out_trade_no : 商家訂單號(與微信訂單號二選一) * */ public function findOrder($out_trade_no) { $data["appid"] = $this->appid; $data["mch_id"] = $this->mchid; $data["nonce_str"] = random(12); $data["out_trade_no"] = $out_trade_no; $sign = $this->getParam($data); $dataXML = " ".$data["appid"]." ".$data["attach"]." ".$data["body"]."".$data["mch_id"]." ".$data["nonce_str"]." ".$data["notify_url"]." ".$data["out_trade_no"]." ".$data["spbill_create_ip"]." ".$data["total_fee"]." ".$data["trade_type"]." ".$sign." "; $url = "https://api.mch.weixin.qq.com/pay/orderquery"; $result = $this->https_post($url,$dataXML); $ret = $this->xmlToArray($result); if($ret["return_code"] == "SUCCESS" && $ret["return_msg"] == "OK") { return $ret; } else { $this->errorLog("查詢微信支付訂單失敗,",$ret); return null; } } /* * 退款訂單查詢 * @params string $transaction_id : 微信訂單號 * @params string $out_trade_no : 商家訂單號(與微信訂單號二選一) * */ public function findRefundOrder($out_trade_no) { $data["appid"] = $this->appid; $data["mch_id"] = $this->mchid; $data["nonce_str"] = random(12); $data["out_trade_no"] = $out_trade_no; $sign = $this->getParam($data); $dataXML = " ".$data["appid"]." ".$data["mch_id"]." ".$data["nonce_str"]." ".$data["out_trade_no"]." ".$sign." "; $url = "https://api.mch.weixin.qq.com/pay/refundquery"; $result = $this->https_post($url,$dataXML); $ret = $this->xmlToArray($result); if($ret["return_code"] == "SUCCESS" && $ret["return_msg"] == "OK") { return $ret; } else { $this->errorLog("查詢微信支付退款訂單失敗,",$ret); return $ret["err_code_des"]; } } /* * 申請退款 * @params string $out_trade_no : 商戶訂單號 * @params string $out_refund_no : 商戶退款單號 * @params int $total_fee : 訂單金額 * @params int $refund_fee : 退款金額 * @params string $refund_desc : 退款原因 * */ public function refund($out_trade_no,$out_refund_no,$total_fee,$refund_fee,$refund_desc="退款") { $data["appid"] = $this->appid; $data["mch_id"] = $this->mchid; $data["nonce_str"] = random(12); $data["out_trade_no"] = $out_trade_no; $data["out_refund_no"] = $out_refund_no; $data["total_fee"] = $total_fee*100; $data["refund_fee"] = $refund_fee*100; $data["refund_desc"] = $refund_desc; $data["notify_url"] = "http://*****.com/home/wxpaynofiy/refund.html"; $sign = $this->getParam($data); $dataXML = " ".$data["appid"]." ".$data["mch_id"]." ".$data["nonce_str"]." ".$data["out_trade_no"]." ".$sign." "; $url = "https://api.mch.weixin.qq.com/secapi/pay/refund"; $result = $this->https_post($url,$dataXML,true); $ret = $this->xmlToArray($result); if($ret["return_code"] == "SUCCESS" && $ret["return_msg"] == "OK") { return $ret; } else { $this->errorLog("微信退款失敗,",$ret); return null; } } /* * 企業付款至用戶零錢 * @params string $openid : 用戶openid * @params int $total_fee : 付款金額,單位分 * @params string $out_trade_no : 商家訂單號 * @params string $username : 微信用戶名稱(注意微信昵稱若為空時支付會出錯) * @params string $desc : 付款描述 * @params string $check_name : 是否檢測用戶名 * */ public function payForUser($openid,$total_fee,$out_trade_no,$username="魔盒CMS",$desc="魔盒CMS付款給用戶",$check_name="NO_CHECK") { $data["amount"] = $total_fee*100; $data["check_name"] = $check_name; $data["desc"] = $desc; $data["mch_appid"] = $this->appid; $data["mchid"] = $this->mchid; $data["nonce_str"] = random(12); $data["openid"] = $openid; $data["partner_trade_no"] = $out_trade_no; $data["re_user_name"] = $username; $data["spbill_create_ip"] = $_SERVER["REMOTE_ADDR"]; $sign = $this->getParam($data); $dataXML=" ".$data["appid"]." ".$data["mch_id"]." ".$data["nonce_str"]." ".$data["out_trade_no"]." ".$data["out_refund_no"]." ".$data["total_fee"]." ".$data["refund_fee"]." ".$data["refund_desc"]." ".$data["notify_url"]." ".$sign." "; $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; $result = $this->https_post($url,$dataXML,true); $ret = $this->xmlToArray($result); if($ret["return_code"]=="SUCCESS" && $ret["result_code"] == "SUCCESS") { //支付成功返回商戶訂單號、微信訂單號、微信支付成功時間 $result["partner_trade_no"] = $ret["partner_trade_no"]; $result["payment_no"] = $ret["payment_no"]; $result["payment_time"] = $ret["payment_time"]; return $ret; } else { $this->errorLog("付款給用戶失敗",$ret); return null; } } /* * 普通紅包 * @params string $out_trade_no : 商家訂單號 * @params string $openid : 接收紅包用戶的openid * @params int $total_fee : 紅包金額,單位分 * @params int $total_num : 紅包發放總人數 * @params string $wishing : 紅包祝福語 * @params string $act_name : 活動名稱 * @params string $remark : 備注 * @params string $scene_id :場景值ID。發放紅包使用場景,紅包金額大于200或者小于1元時必傳。PRODUCT_1:商品促銷、PRODUCT_2:抽獎、PRODUCT_3:虛擬物品兌獎 、PRODUCT_4:企業內部福利、PRODUCT_5:渠道分潤、PRODUCT_6:保險回饋、PRODUCT_7:彩票派獎、PRODUCT_8:稅務刮獎 * */ public function redPack($openid,$total_fee,$out_trade_no,$total_num = 1,$wishing = "感謝您光臨***平臺進行購物",$act_name="***購物發紅包",$remark = "購物領紅包") { $data["mch_billno"] = $out_trade_no; $data["mch_id"] = $this->mchid; $data["wxappid"] = $this->appid; $data["send_name"] = "發送紅包者的名稱"; $data["re_openid"] = $openid; $data["total_amount"] = $total_fee; $data["total_num"] = $total_num; $data["wishing"] = $wishing; $data["client_ip"] = $_SERVER["REMOTE_ADDR"]; $data["act_name"] = $act_name; $data["remark"] = $remark; $data["nonce_str"] = random(12); $sign = $this->getParam($data); $dataXML=" ".$data["mch_appid"]." ".$data["mchid"]." ".$data["nonce_str"]." ".$data["partner_trade_no"]." ".$data["openid"]." ".$data["check_name"]." ".$data["re_user_name"]." ".$data["amount"]." ".$data["desc"]." ".$data["spbill_create_ip"]." ".$sign." "; $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack"; $result = $this->https_post($url,$dataXML,true); $ret = $this->xmlToArray($result); if($ret["return_code"]=="SUCCESS" && $ret["result_code"] == "SUCCESS") { return $ret; } else { $this->errorLog("發放普通紅包失敗",$ret); return $ret["err_code_des"]; } } /* * 裂變紅包:一次可以發放一組紅包。首先領取的用戶為種子用戶,種子用戶領取一組紅包當中的一個,并可以通過社交分享將剩下的紅包給其他用戶。 * 裂變紅包充分利用了人際傳播的優勢。 * @params string $out_trade_no : 商家訂單號 * @params string $openid : 接收紅包用戶的openid * @params int $total_fee : 紅包金額,單位分 * @params int $total_num : 紅包發放總人數 * @params string $wishing : 紅包祝福語 * @params string $act_name : 活動名稱 * @params string $remark : 備注 * @params string $scene_id :場景值ID。發放紅包使用場景,紅包金額大于200或者小于1元時必傳。PRODUCT_1:商品促銷、PRODUCT_2:抽獎、PRODUCT_3:虛擬物品兌獎 、PRODUCT_4:企業內部福利、PRODUCT_5:渠道分潤、PRODUCT_6:保險回饋、PRODUCT_7:彩票派獎、PRODUCT_8:稅務刮獎 * */ public function redPackGroup($openid,$total_fee,$out_trade_no,$total_num,$wishing = "感謝您光臨***進行購物",$act_name="**購物發紅包",$remark = "購物領紅包") { $data["mch_billno"] = $out_trade_no; $data["mch_id"] = $this->mchid; $data["wxappid"] = $this->appid; $data["send_name"] = "發送紅包者的名稱"; $data["re_openid"] = $openid; $data["total_amount"] = $total_fee; $data["amt_type"] = "ALL_RAND"; //ALL_RAND—全部隨機,商戶指定總金額和紅包發放總人數,由微信支付隨機計算出各紅包金額 $data["total_num"] = $total_num; $data["wishing"] = $wishing; $data["client_ip"] = $_SERVER["REMOTE_ADDR"]; $data["act_name"] = $act_name; $data["remark"] = $remark; $data["nonce_str"] = random(12); $sign = $this->getParam($data); $dataXML=" ".$sign." ".$data["mch_billno"]." ".$data["mch_id"]." ".$data["wxappid"]." ".$data["send_name"]." ".$data["re_openid"]." ".$data["total_amount"]." ".$data["total_num"]." ".$data["wishing"]." ".$data["client_ip"]." ".$data["act_name"]." ".$data["remark"]." ".$data["nonce_str"]." "; $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack"; $result = $this->https_post($url,$dataXML,true); $ret = $this->xmlToArray($result); if($ret["return_code"]=="SUCCESS" && $ret["result_code"] == "SUCCESS") { return $ret; } else { $this->errorLog("發放裂變紅包失敗",$ret); return $ret["err_code_des"]; } } /* * 查詢紅包記錄 * @params string $out_trade_no : 商家訂單號 * */ public function findRedPack($out_trade_no) { $data["mch_billno"] = $out_trade_no; $data["mch_id"] = $this->mchid; $data["appid"] = $this->appid; $data["bill_type"] = "MCHT"; //MCHT:通過商戶訂單號獲取紅包信息。 $data["nonce_str"] = random(12); $sign = $this->getParam($data); $dataXML=" ".$sign." ".$data["mch_billno"]." ".$data["mch_id"]." ".$data["wxappid"]." ".$data["send_name"]." ".$data["re_openid"]." ".$data["total_amount"]." ".$data["amt_type"]." ".$data["total_num"]." ".$data["wishing"]." ".$data["client_ip"]." ".$data["act_name"]." ".$data["remark"]." ".$data["nonce_str"]." "; $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo"; $result = $this->https_post($url,$dataXML,true); $ret = $this->xmlToArray($result); if($ret["return_code"]=="SUCCESS" && $ret["result_code"] == "SUCCESS") { return $ret; } else { $this->errorLog("查詢紅包記錄失敗",$ret); return $ret["err_code_des"]; } } /* * 獲取用戶微信的OPENID * */ public function openid($c=false) { if($_GET["state"]!="zgm"){ $t = $c ? "snsapi_userinfo" : "snsapi_base"; $url=urlencode(get_url()); $url="https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$this->appid."&redirect_uri=".$url."&response_type=code&scope=".$t."&state=zgm#wechat_redirect"; echo ""; exit; } if($_GET["code"]){ $url="https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appid."&secret=".$this->secret."&code=".$_GET["code"]."&grant_type=authorization_code"; $wx_db=json_decode($this->https_get($url)); if($c){ $url_2="https://api.weixin.qq.com/sns/userinfo?access_token=".$wx_db->access_token."&openid=".$wx_db->openid."&lang=zh_CN"; $db=json_decode($this->https_get($url_2)); return $db; }else{ return $wx_db->openid; } } } /* * 發起網絡GET請求 * @params string $url : URL鏈接 */ private function https_get($url) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($curl, CURLOPT_HEADER, FALSE) ; curl_setopt($curl, CURLOPT_TIMEOUT,60); if (curl_errno($curl)) { return "Errno".curl_error($curl); } else{$result=curl_exec($curl);} curl_close($curl); return $result; } //對參數排序,生成MD5加密簽名 private function getParam($paramArray, $isencode=false) { $paramStr = ""; ksort($paramArray); $i = 0; foreach ($paramArray as $key => $value) { if ($key == "Signature"){ continue; } if ($i == 0){ $paramStr .= ""; }else{ $paramStr .= "&"; } $paramStr .= $key . "=" . ($isencode?urlencode($value):$value); ++$i; } $stringSignTemp=$paramStr."&key=".$this->key; $sign=strtoupper(md5($stringSignTemp)); return $sign; } //POST提交數據 private function https_post($url,$data,$ssl = false) { $ch = curl_init (); curl_setopt ( $ch, CURLOPT_URL, $url ); curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, "POST" ); curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE ); curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE ); if($ssl) { curl_setopt ( $ch,CURLOPT_SSLCERT,$this->sslcert_path); curl_setopt ( $ch,CURLOPT_SSLKEY,$this->sslkey_path); } curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 ); curl_setopt ( $ch, CURLOPT_AUTOREFERER, 1 ); curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data ); curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true ); $result = curl_exec($ch); if (curl_errno($ch)) { return "Errno: ".curl_error($ch); } curl_close($ch); return $result; } /* * XML轉array * @params xml $xml : xml 數據 * return array $data : 轉義后的array數組 */ private function xmlToArray($xml) { libxml_disable_entity_loader(true); $xmlstring = simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA); $val = json_decode(json_encode($xmlstring),true); return $val; } /* * 記錄日志 * @params string $msg : 提示語句 * @params array $ret : 錯誤結果 */ private function errorLog($msg,$ret) { file_put_contents(ROOT_PATH . "runtime/error/wxpay.log", "[" . date("Y-m-d H:i:s") . "] ".$msg."," .json_encode($ret).PHP_EOL, FILE_APPEND); } } ".$sign." ".$data["mch_billno"]." ".$data["mch_id"]." ".$data["appid"]." ".$data["bill_type"]." ".$data["nonce_str"]."
二、Controller層,Test.php
openid(); $pay = $wxpay->payForWeixin($openid,date("YmdHis").rand(1,5),"0.1"); $paySign =strtoupper(MD5("appId=".$pay["appId"]."&nonceStr=".$pay["nonceStr"]."&package=".$pay["package"]."&signType=MD5&timeStamp=".$pay["timeStamp"]."&key=536*****9e8")); $h5 = array( "appId" => $pay["appId"], "timeStamp" => $pay["timeStamp"], "nonceStr" => $pay["nonceStr"], "package" => $pay["package"], "signType" => $pay["signType"], "paySign" => $paySign ); $this->assign("wxpay",$h5); return view(); } }
三、HTML中調用微信支付,wx.html
訂單示例
四、接收微信支付返回結果,支付時設置的notify_url值,確保此鏈接外網能訪問。wxpaynofiy.php
checkSign($data)) { $transaction_id = $data["transaction_id"]; //微信支付訂單號 $out_trade_no = $data["out_trade_no"]; //商家訂單號 $this->errorLog("微信支付返回結果,微信支付訂單號:".$transaction_id.",商家訂單號:".$out_trade_no,[]); } else { $this->errorLog("微信支付返回結果簽名驗證失敗",$data); } } else { $this->errorLog("微信支付返回結果",$data); } echo ""; } /* * 驗證簽名 * @params array $result : 微信支付成功返回的結果數組 * return bool $ret : 成功true,失敗false * */ private function checkSign(array $data) { $str = ""; ksort($data); foreach ($data as $k => $v) { if($k != "sign") $str .= $k."=".$v."&"; } $temp = $str . "key=5363******49e8"; //key:商戶支付密鑰 $sign = strtoupper(md5($temp)); return $sign == $data["sign"] ? true : false; } private function errorLog($msg,$ret) { file_put_contents(ROOT_PATH . "runtime/error/wxpaynofiy.log", "[" . date("Y-m-d H:i:s") . "] ".$msg."," .json_encode($ret).PHP_EOL, FILE_APPEND); } }
五、常見問題
1、H5支付時出現“簽名錯誤”,需要注意的調用微信“統一下單”接口后返回pre_pay_id后,需要用戶再次進行簽名返回給HTML; 2、“支付目錄沒有授權”,進入微信商家管理后臺設置即可;
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/29095.html
摘要:本文是淺析微信支付系列文章的第二篇,主要講解一下普通商戶接入的支付方式以及其中的不同之處。淺析微信支付前篇大綱微信支付是集成在微信客戶端的支付功能,用戶可以通過手機完成快速的支付流程。目前微信支付支持手機系統有蘋果安卓和。 本文是【淺析微信支付】系列文章的第二篇,主要講解一下普通商戶接入的支付方式以及其中的不同之處。 上篇文章講了本系列的大綱,沒有看過的朋友們可以看一下。 淺析微信支...
摘要:本文是淺析微信支付系列文章的第五篇,主要講解如何調用統一下單接口生成預支付單及調起支付頁面。淺析微信支付系列已經更新四篇了喲,沒有看過的朋友們可以看一下哦。 本文是【淺析微信支付】系列文章的第五篇,主要講解如何調用統一下單接口生成預支付單及調起支付頁面。 淺析微信支付系列已經更新四篇了喲~,沒有看過的朋友們可以看一下哦。 淺析微信支付:微信公眾號網頁授權 淺析微信支付:開發前的準備 ...
摘要:這個坑就是要注意回調結束要返回成功的響應這幾天做微信支付暫時遇到的問題就這么多,只能說注意細節吧,爬過的坑記錄下來以后遇到就懂處理了。 前言 其實任何接口開發只要按照給出來的接口文檔和例子開發基本上不會有太大問題的,一些問題都是出在雜七雜八的小細節上,現在分享一下微信支付開發中自己遇到的小細節。按照文檔做完開發前配置,比如JS安全域名配置、網頁授權域名、公眾號授權目錄等等... 坑一:...
摘要:微信支付支付在服務端調用統一下單接口后,服務端需要將返回的訂單數據進行二次簽名后才能返回給端。微信支付服務端提供了類,類中也的確提供了生成簽名方法,即對結果集簽名,源碼如下以版為例,其他語言自行對照。 獲取到 prepay_id 后將參數再次簽名傳輸給 APP 發起支付。 相信有不少同學因為看到統一下單返回的結果中有 sign 字段,會直接將結果返回給 APP 端,結果 APP 端沒辦...
摘要:這幾天在做小程序的支付,沒有用官方的,這里就純用官方的文檔搞一發。 這幾天在做小程序的支付,沒有用官方的SDK,這里就純用官方的文檔搞一發。 * 注作者使用的PHP,不過支付流程都是這樣 開發前必讀 主要流程 小程序前端發送求參請求 接受請求封裝 統一下單 獲取package 小程序接受 統一下單 獲取的package值帶入wx.requestPayment發起支付請求 準備...
閱讀 3638·2021-11-25 09:43
閱讀 636·2021-09-22 15:59
閱讀 1744·2021-09-06 15:00
閱讀 1769·2021-09-02 09:54
閱讀 689·2019-08-30 15:56
閱讀 1176·2019-08-29 17:14
閱讀 1839·2019-08-29 13:15
閱讀 880·2019-08-28 18:28