- 1、如何利用PHP實現 APP端微信支付功能
- 2、用PHP做微信支付簽名錯誤,請教一下這個是什麼原因
- 3、如何用PHP實現微信支付,求教。新手!說明詳細點
- 4、微信網頁支付V3版js_api_call.php從訂單跳轉到微信支付提示缺少統一支付接口必填參數out_trade_no!
- 5、如何用PHP實現微信支付?
- 6、微信支付遇到簽名驗證失敗的解決方法
一丶 PHP後台後台生成預支付交易單,返回正確的預支付交易回話標識後再在APP裡面調起支付!官方文檔:
根據文檔拼接微信需要的參數,這裡需要幾個方法,直接上代碼!
傳輸給微信的參數要組裝成xml格式發送,傳如參數數組!
public function ToXml($data=array())
{
if(!is_array($data) || count($data) = 0)
{
return ‘數組異常’;
}
$xml = “”;
foreach ($data as $key=$val)
{
if (is_numeric($val)){
$xml.=””.$key.””.$val.””;
}else{
$xml.=””.$key.””;
}
}
$xml.=””;
return $xml;
}
2.生成隨機字符串,微信所需參數! 這裡方法很多,看自己愛好都行!
function rand_code(){
$str = ‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;//62個字符
$str = str_shuffle($str);
$str = substr($str,0,32);
return $str;
}
3.這裡是微信比較重要的一步了,這個方法會多次用到!生成簽名
private function getSign($params) {
ksort($params); //將參數數組按照參數名ASCII碼從小到大排序
foreach ($params as $key = $item) {
if (!empty($item)) { //剔除參數值為空的參數
$newArr[] = $key.’=’.$item; // 整合新的參數數組
}
}
$stringA = implode(“”, $newArr); //使用 符號連接參數
$stringSignTemp = $stringA.”key=”.”************************”; //拼接key
// key是在商戶平台API安全里自己設置的
$stringSignTemp = MD5($stringSignTemp); //將字符串進行MD5加密
$sign = strtoupper($stringSignTemp); //將所有字符轉換為大寫
return $sign;
}
4.傳遞參數給微信,生成預支付訂單! 接收微信返回的數據,在反給APP端,APP端調用支付接口,完成支付 ! APP端所需參數見微信文檔:;index=2
public function wx_pay() {
$nonce_str = $this-rand_code(); //調用隨機字符串生成方法獲取隨機字符串
$data[‘appid’] =’wxdbc5dc*******’; //appid
$data[‘mch_id’] = ‘1493*****’ ; //商戶號
$data[‘body’] = “APP支付測試”;
$data[‘spbill_create_ip’] = $_SERVER[‘HTTP_HOST’]; //ip地址
$data[‘total_fee’] = 1; //金額
$data[‘out_trade_no’] = time().mt_rand(10000,99999); //商戶訂單號,不能重複
$data[‘nonce_str’] = $nonce_str; //隨機字符串
$data[‘notify_url’] = ”; 接收支付後的通知,必須為能直接訪問的網址,不能跟參數
$data[‘trade_type’] = ‘APP’; //支付方式
//將參與簽名的數據保存到數組 注意:以上幾個參數是追加到$data中的,$data中應該同時包含開發文檔中要求必填的剔除sign以外的所有數據
$data[‘sign’] = $this-getSign($data); //獲取簽名
$xml = $this-ToXml($data); //數組轉xml
//curl 傳遞給微信方
$url = “”;
//header(“Content-type:text/xml”);
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
if(stripos($url,”https://”)!==FALSE){
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
} else {
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//嚴格校驗
}
//設置header
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求結果為字符串且輸出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//設置超時
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_POST, TRUE);
//傳輸文件
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//運行curl
$data = curl_exec($ch);
//返回結果
if($data){
curl_close($ch);
//返回成功,將xml數據轉換為數組.
$re = $this-FromXml($data);
if($re[‘return_code’] != ‘SUCCESS’){
json(“201”,’簽名失敗’);
}
else{
//接收微信返回的數據,傳給APP!
$arr =array(
‘prepayid’ =$re[‘prepay_id’],
‘appid’ = ‘wxdbc5dc*****’,
‘partnerid’ = ‘14937****’,
‘package’ = ‘Sign=WXPay’,
‘noncestr’ = $nonce_str,
‘timestamp’ =time(),
);
//第二次生成簽名
$sign = $this-getSign($arr);
$arr[‘sign’] = $sign;
json(‘200′,’簽名成功’,$arr);
}
} else {
$error = curl_errno($ch);
curl_close($ch);
json(‘201’,”curl出錯,錯誤碼:$error”);
}
}
5.將xml數據轉換為數組,接收微信返回數據時用到.
public function FromXml($xml)
{
if(!$xml){
echo “xml數據異常!”;
}
//將XML轉為array
//禁止引用外部xml實體
libxml_disable_entity_loader(true);
$data = json_decode(json_encode(simplexml_load_string($xml, ‘SimpleXMLElement’, LIBXML_NOCDATA)), true);
return $data;
}
二 .APP支付成功後,會調用你填寫的回調地址 . 返回參數詳見微信文檔:;index=3
// 微信支付回調
function wx_notify(){
//接收微信返回的數據數據,返回的xml格式
$xmlData = file_get_contents(‘php://input’);
//將xml格式轉換為數組
$data = $this-FromXml($xmlData);
//用日誌記錄檢查數據是否接受成功,驗證成功一次之後,可刪除。
$file = fopen(‘./log.txt’, ‘a+’);
fwrite($file,var_export($data,true));
//為了防止假數據,驗證簽名是否和返回的一樣。
//記錄一下,返回回來的簽名,生成簽名的時候,必須剔除sign字段。
$sign = $data[‘sign’];
unset($data[‘sign’]);
if($sign == $this-getSign($data)){
//簽名驗證成功後,判斷返回微信返回的
if ($data[‘result_code’] == ‘SUCCESS’) {
//根據返回的訂單號做業務邏輯
$arr = array(
‘pay_status’ = 1,
);
$re = M(‘order’)-where([‘order_sn’=$data[‘out_trade_no’]])-save($arr);
//處理完成之後,告訴微信成功結果!
if($re){
echo ”;exit();
}
}
//支付失敗,輸出錯誤信息
else{
$file = fopen(‘./log.txt’, ‘a+’);
fwrite($file,”錯誤信息:”.$data[‘return_msg’].date(“Y-m-d H:i:s”),time().”\r\n”);
}
}
else{
$file = fopen(‘./log.txt’, ‘a+’);
fwrite($file,”錯誤信息:簽名驗證失敗”.date(“Y-m-d H:i:s”),time().”\r\n”);
}
}
在這裡,微信APP支付流程就成功走完了!謝謝支持!
———————
出現這種情況可能是您的網絡不好,或者是沒有遵循開發規範,導致數字簽名失敗
建議您更換更好的網絡,同時根據開發規範調整後台代碼。
微信公眾號JSAPI支付
一:配置參數
申請成功後,獲取接口文件, 將所有文件放入項目根目錄weixin下,在WxPay.ub.config.php中填入配置賬戶信息;
二:設置授權
開發者中心-網頁服務-網頁授權獲取用戶基本信息-修改;
“授權回調頁面域名修改成你的域名地址即可,須保證網頁授權已獲得,不然會報redirect_uri 參數錯誤;
三:網頁授權獲取用戶openid
js_api_call.php 請求文件中改動(所有傳給微信的參數都在入口文件中接收)
$out_trade_no = $_GET[‘out_trade_no’]; //商戶系統內部訂單號 32個字符內
$total_fee = $_GET[‘total_fee’]*100; //訂單總金額 單位為分,不能帶小數點,所以須把價格乘以100,
不然獲取prepay_id時會報錯誤(設置金額字段時最好設為小數點後2位)
$pay_status = get_pay_status($out_trade_no);//查看訂單支付狀態
$return_url = get_return_url($out_trade_no); //設置支付成功後跳轉頁面
//使用jsapi接口
$jsApi = new JsApi_pub();
//通過code獲得openid
if (!isset($_GET[‘code’])) { //觸發微信返回code碼
//設置redirect_uri參數,返回code碼地址,其實就是重定向到當前頁面,獲取用戶code碼參數
$url = WxPayConf_pub::JS_API_CALL_URL.”?showwxpaytitle=1out_trade_no=$out_trade_nototal_fee=$total_fee”;
$url = $jsApi-createOauthUrlForCode($url);
Header(“Location: $url”);
}else{ //獲取code碼,以獲取openid
$code = $_GET[‘code’];
$jsApi-setCode($code);
$openid = $jsApi-getOpenId(); //用戶標識
}
再就是WxPayHubHelper.php文件 JsApi_pub()類下createOauthUrlForCode($redirectUrl)方法, 第二個參數
改為 $urlObj[“redirect_uri”] = urlencode($redirectUrl); //對$url變量進行url編碼 不然header重定向時無法獲取訂單號和金額
四:設置統一支付接口參數,獲取prepay_id (預支付ID 微信生成的預支付 ID,用於後續接口調用中使用)
微信支付-開發配置-支付測試-測試授權目錄和測試白名單添加
(支付授權目錄需要精確到最細一級的目錄,且在使用時,目錄名稱後直接加文件名,如ccc.com/weixin/)
確保你 WxPayPubHelper.php文件里 UnifiedOrder_pub 這個類的getPrepayId這個方法能正常使用
這一步的調試在 getPrepayId()內 var_dump($this-result); 就能看到錯誤代碼;
posXml這個方法後調用了createXml這個方法
function postXml() {
$xml = $this-createXml();
//**在此處查看xml文件是否正常生成
include_once(“log_.php”);
$log = new Log_();
$log-log_result(“log.txt”,$xml);
//** 由於打印一些xml格式的文件只顯示字符長度,不顯示內容。於是用log的形式寫在服務器上調試
$this-response = $this-postXmlCurl($xml,$this-url,$this-curl_timeout);
return $this-response;
}
保證xml這個變量格式如下;
參數正確,postXmlCurl才能正確提交,提交後就能得到正確的prepay_id,就能彈出支付框了
五:使用jsapi調起支付
根據prepay_id生成jsapi支付參數
$jsApi-setPrepayId($prepay_id);
$jsApiParameters = $jsApi-getParameters();
//調用微信JS api 支付
function jsApiCall() {
WeixinJSBridge.invoke(
‘getBrandWCPayRequest’,
,
function(res){
WeixinJSBridge.log(res.err_msg);
if(res.err_msg == “get_brand_wcpay_request:ok”) { //支付成功後
window.location.href=”” //跳轉地址及訂單操作,在異步頁面也須處理訂單,防止同步時失敗
}else{
alert(“支付失敗”+res.err_code+res.err_desc+res.err_msg);
}
}
);
}(每次請求callpay方法時須判斷訂單狀態,防止重複提交)
六:通用通知接口 異步處理微信返回結果
支付完成後,notify.php中獲取微信的回調
$xml = $GLOBALS[‘HTTP_RAW_POST_DATA’];
//須驗證簽名,並回應微信。
if($notify-checkSign() == TRUE) //簽名驗證通過並更新訂單狀態後
$notify-setReturnParameter(“return_code”,”SUCCESS”); //設置返回碼,保證支付狀態改變後才返回成功
//對後台通知交互時,如果微信收到商戶的應答不是成功或超時,微信認為通知失敗,
//微信會通過一定的策略(如30分鐘共8次)定期重新發起通知,
$returnXml = $notify-returnXml();
echo $returnXml;(將xml數據返回微信 當return_code為SUCCESS時,不會再通知)
//當收到通知進行處理時,首先檢查對應業務數據的狀態,判斷該通知是否已經處理過,如果沒有處理過再進行處理,
如果處理過直接返回結果成功。在對業務數據進行狀態檢查和處理之前,要採用數據鎖進行並發控制,
以避免函數重入造成的數據混亂.
//判斷是否在微信瀏覽器打開
function isWeiXin(){
var ua = window.navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i) == ‘micromessenger’){
return true;
}else{
return false;
}
}
步驟夠詳細了吧,我自己實現過,所以寫了日誌,結合php版本的demo 大致弄得出來了,如果對整個流程不太清楚,仔細的看完微信公眾號支付接口文檔,你申請微信公眾號支付成功了就會有的,
這個out_trade_no你請求過去沒,
這個out_trade_no是你自己網站上的訂單號,流程是這樣的
用戶在你的網站支付,你自己的網站首先生成一個訂單號,比如1234,然後把相關的信息請求給微信,這個out_trade_no也就是你的訂單號(1234),然後微信那邊支付成功之後會回調,他會把這個out_trade_no依然給你,你可以通過這個來識別是誰支付成功了
你的圖片
看到沒,那是個例子,你依然把他注釋了,所以那個$out_trade_no是空的,
商戶支付的訂單號由商戶自定義生成,微信支付要求商戶訂單號保持唯一性(建議根據當前系統時間加隨機序列來生成訂單號)。重新發起一筆支付要使用原訂單號,避免重複支付;已支付過或已調用關單、撤銷(請見後文的API列表)的訂單號不能重新發起支付。
以PHP語言為例,對微信支付的開發流程進行一下說明:
1.獲取訂單信息。
2.根據訂單信息和支付相關的賬號生成sign,並且生成支付參數。
3.將支付參數信息POST到微信服務器,獲取返回信息。
4.根據返回信息生成相應的支付代碼(微信內部)或是支付二維碼(非微信內),完成支付。
1.下單的簽名方式使用MD5方式
2.利用下單獲取到的prepay_id,來進行調起支付階段的paySign的簽名
3.如果提示簽名驗證失敗:
①首先檢查你的5個參數是否完整:timeStamp,nonceStr,package,signType,paySign
②signType 必須是MD5,官方demo不是MD5,改為MD5,這也是大坑,當然我自己用python 寫的時候直接用的MD5
③在做paySign簽名的時候,需要6個參數,上述5個參數去掉paySign(不參與簽名),加上appId(注意是大寫I,這是個大坑,這個錯了那簽名必然失敗)和key
④如果上述步驟沒問題還是失敗,那麼去驗證以下你的簽名是否通過
⑤還有一點簽名的時候必須把所有英文全部轉為大寫
4.歡迎評論,多多交流
原創文章,作者:MEXDF,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/126284.html