摘要:前者集成在中,后者主要是為微信用戶提供了另一種支付方式需要在微信的內置瀏覽器中打開頁面,再調起微信支付。步驟商戶后臺收到用戶支付單,調用微信支付統一下單接口。拿到所有參數后,就可以在頁面中發起微信支付的請求了。
微信支付,支持的支付方式比較多:有掃碼支付,刷卡支付,APP支付和公眾號支付。其中,APP和網站上最常用的就是APP支付和公眾號支付。前者集成在APP中,后者主要是為微信用戶提供了另一種支付方式(需要在微信的內置瀏覽器中打開頁面,再調起微信支付)。
同樣的,微信的APP支付和支付寶的APP支付也是很簡單:
APP支付商戶系統和微信支付系統主要交互說明:
步驟1:用戶在商戶APP中選擇商品,提交訂單,選擇微信支付。
步驟2:商戶后臺收到用戶支付單,調用微信支付統一下單接口。參見【統一下單API】。
步驟3:統一下單接口返回正常的prepay_id,再按簽名規范重新生成簽名后,將數據傳輸給APP。參與簽名的字段名為appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式為Sign=WXPay
步驟4:商戶APP調起微信支付。
步驟5:商戶后臺接收支付通知。
步驟6:商戶后臺查詢支付結果。
這里主要的還是后臺干活(獲取 prepay_id,生成隨機字符串 nonceStr 和時間戳 timeStamp ,appId 和 partnerId 均能在后臺管理中查看。)
后臺的步驟也很簡潔,就是上述中的步驟1,2。
獲取 prepayId:
設置獲取 prepayId 所需參數。
此處需要調用微信的統一下單接口。這個過程,官方文檔已經寫得十分之詳細了,包括調用的接口API地址,需要傳遞的參數(必要和非必要的參數),還有返回結果也寫得很清楚。
以下是我在實際項目開發中傳入的參數。
簽名。
簽名都差不多,都是先將所有的帶簽名的參數進行字典排序。
ksort($data);
然后將參數以 {key}={value} 的組合形式,用 & 連接。
$a = array(); foreach ($data as $k => $v) { if ((string) $v === "") { continue; } $a[] = "{$k}={$v}"; } $a = implode("&", $a);
最后拼上 &key={Your apiKey} ,然后對整串字符串進行MD5加密即可。
$sign = strtoupper(md5($a));
將拼好的數據,以 XML 的格式發送給微信,請求 prepayId
沒錯,就是要轉成 XML 格式再發送。
但是,這個XML格式很簡單,只需要進行簡單的拼接即可:
public function arrayToXml(array $data) { $xml = ""; foreach ($data as $k => $v) { if (is_numeric($v)) { $xml .= "<{$k}>{$v}{$k}>"; } else { $xml .= "<{$k}>{$k}>"; } } $xml .= " "; return $xml; }
參數值用XML轉義即可,CDATA標簽用于說明數據不被XML解析器解析。。
然后請求統一下單API即可(url = https://api.mch.weixin.qq.com/pay/unifiedorder)
$ch = curl_init(); curl_setopt($ch, CURLOPT_TIMEOUT, 30); 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); $response = curl_exec($ch); if (!$response) { throw new Exception("CURL Error: " . curl_errno($ch)); } curl_close($ch);
請求回來的數據也為XML格式,只需要簡單做下處理,轉換成array即可:
public function xmlToArray($xml){ return json_decode(json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA)), true); }
如果返回值中的 return_code 和 result_code 都為 SUCCESS 的時候會返回 交易類型 trade_type 和 預支付交易會話標識 prepayId 。到這里,我們就可以獲取到 prepayId。
將獲取的 prepayId 與其他參數拼接,返回給APP即可。
$params = array(); // 商戶號 $params["appid"] = $this->config->appId; // 時間戳 $params["timestamp"] = "" . time(); // 隨機字符串 $params["noncestr"] = md5(uniqid(mt_rand(), true)); // 固定為 "Sign=WXPay" $params["package"] = "Sign=WXPay"; // 步驟3獲取的預支付交易會話標識 $params["prepayid"] = $prepayId; // 合作伙伴id $params["partnerid"] = $this->config->partnerId; // 步驟2生成的簽名。 $params["sign"] = $this->sign($params);
微信APP支付,后臺需要干的活到這里就暫時結束了(因為還有支付成功后的異步通知商戶后面再講)
下面就是web版的微信支付(公司項目是在微信瀏覽器內,選擇微信支付后,在微信中調起的微信支付)
web版微信支付的步驟和APP的大同小異,也是現獲取 prepayId ,再在頁面中,調用jsapi進行支付。
但是,此處有2個坑
坑1: 支付時出現 appid and openid not match 的報錯原因非常的簡單,就是支付時所獲取的 openid 在并不屬于支付的商戶。
這個 openid 為微信用戶在商戶對應appid下的唯一標識。也就是說,必須根據支付的商戶的 appid 去獲取用戶的 openid 。
因為業務邏輯需要,項目中用于微信登錄用的公眾號A與用于支付的公眾號B(其實還和開放平臺用于APP支付的 appId 也是不一樣的)是不一樣的,雖然所獲取unionid是一致,但是 openid 是不!一!樣!的!所以,在獲取 openid 時,需要使用當前支付時所用到的 appid 去請求用戶的 openid ,同時,請求 openid 后的回調也必須是 支付商戶 后臺所設置好的回調地址,要不然就會報 redirect_uri 參數錯誤 的錯誤。
坑2: 參數名大小寫不一致。↑ APP支付的參數
↑ web支付的參數
仔細看看劃橫線的地方。沒錯,app中的參數的key全是小寫,web支付中的key則為駝峰命名方式。而且,簽名方式 signType 是必填的, 簽名的字段也變成了 paySign,其中 package 的值也是不一樣,APP支付是固定的值,web支付則為 prepayId,這也要注意。當然,官方文檔也是很詳細的說明,但是需要細心觀察(所以說嘛,還是直接拷貝必填項最保險了2333)。
拿到所有參數后,就可以在頁面中發起微信支付的請求了。
代碼可以直接使用官方提供的js代碼
function onBridgeReady(){ WeixinJSBridge.invoke( "getBrandWCPayRequest", YOUR_PARAMS, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ) { // success_callback } // 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功后返回 ok,但并不保證它絕對可靠。 } ); } 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(); }
其中 YOUR_PARAMS 是參數轉換成json格式直接渲染至頁面即可。
如果參數沒錯的話,那么就可以順利的調起支付窗口了。
坑3: APP支付和jsapi支付不是同一個號APP支付是在開放平臺中申請下來的,appId和apiKey都是不一樣的。而jsapi支付實質就是公眾號支付,是在公眾平臺中申請得到的。所以,在這里,需要注意一下。
重要的來了,能體現后臺的重要性的地方終于來了 ---
支付結果的異步通知官方文檔寫得也很詳細了(不得不說,微信的開發文檔真的很清晰。很容易找到。就是沒有詳細的步驟區分)。
首先需要申明的是:異步通知的URL是必須能在公網訪問的,而且,必須不能攜帶參數。
也就是說,http://domain.com/payment/wxp... 是沒問題的,但是 http://domain.com/payment/not... 這樣的URL是不行的。如果要想達到這種效果,要不服務器(Nginx , Apache)進行rewrite,要不在notify.php 中,手動修改 $_GET 中的參數。
返回的數據,都是一致的:
這時候,商戶后臺拿到這些異步通知的數據進行簡單的校驗即可,然后修改商戶中相應訂單的支付狀態。
校驗返回碼是否成功
$d = $this->xmlToArray(file_get_contents("php://input")); if (empty($d)) { throw new Exception(__METHOD__); } if ($d["return_code"] != "SUCCESS") { throw new Exception($d["return_msg"]); } if ($d["result_code"] != "SUCCESS") { throw new Exception("[{$d["err_code"]}]{$d["err_code_des"]}"); }
對返回數據進行校驗
和請求 prepayId 時處理數據的方式差不多,先取出簽名 sign,然后除去簽名后,進行字典排序,以 {key}={value} 的方式進行組合,并在最后加上 &key={apiKey}得到待校驗字符串,最后,將待校驗字符串進行MD5加密,和簽名進行比較,若一致則校驗成功,并且支付成功,然后后臺做相應操作。
if (!$this->verify($d)) { throw new Exception("Invalid signature"); } // 驗證函數 if (empty($d["sign"])) { return false; } $sign = $d["sign"]; unset($d["sign"]); return $sign == $this->sign($d);微信退款
有支付肯定就會有退款。微信的退款操作也是很簡單,而且退款速度非常快,測試時基本都是秒退。
但是退款是有注意事項的:
交易時間超過一年的訂單無法提交退款;
微信支付退款支持單筆交易分多次退款,多次退款需要提交原支付訂單的商戶訂單號和設置不同的退款單號。總退款金額不能超過用戶實際支付金額。一筆退款失敗后重新提交,請不要更換退款單號,請使用原商戶退款單號。
退款請求需要證書。
【證書獲取方式:】
微信支付接口中,涉及資金回滾的接口會使用到商戶證書,包括退款、撤銷接口。商家在申請微信支付成功后,收到的相應郵件后,可以按照指引下載API證書,也可以按照以下路徑下載:微信商戶平臺(pay.weixin.qq.com)-->賬戶中心-->賬戶設置-->API安全-->證書下載。
微信退款程序流程:
設置退款時得參數。
請求的參數有:
appid : 公眾賬號ID
mch_id : 商戶號
nonce_str : 隨機字符串
sign: 簽名
transaction_id / out_trade_no :微信訂單號 / 商戶訂單號 二者中傳其中一個即可。
out_refund_no: 商戶退款單號(由商戶自行生成的唯一標識)
total_fee:訂單金額(單位為分)
refund_fee:退款金額(單位為分),退款金額不能大于訂單金額。
op_user_id:操作員帳號, 默認為商戶號
簽名還是老規矩(默認是MD5方式),先將所有參數進行字典排序,然后以$key=$value的形式用&字符拼接成字符串,最后將拼上 &key=YOUR_APIKEY 的待簽名字符串進行MD5加密即可。
將參數列表轉換成XML格式。
發送退款請求。
退款請求需要攜帶微信上下載的證書,請保證證書存放路徑外網不能直接訪問。
解析請求結果。
當返回的結果中, return_code 和 result_code 均為 SUCCESS ,即為退款申請成功。更多返回結果,請移步至 官網
結尾微信支付的官方開發文檔其實算是很詳細了,傳遞的參數,返回結果,如果判斷是否成功,都寫的很好。只是,開發中的邏輯過程需要自己慢慢摸索,理清思路后,開發起來其實都是很迅速的。
但是,開發微信支付時,需要留個心,需要將所有涉及到的微信后臺提供的數據小心保存(比如AppSecret,一當忘記只能重置。)
祝各位開發過程順利進行。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/22906.html
摘要:原文地址支付支付步驟為獲取支付寶的配置信息。將得到的數據請求支付寶客戶端進行支付。端將拼接好的字符串拿去請求支付寶客戶端即可調起支付寶進行支付。向支付寶申請新訂單,獲取支付。成功請求回來后,就可以向支付寶發出一次支付請求。 支付寶在所有支付方式中最好開發的了,因為文檔比較清晰,而且開發起來也比較簡單。因此,支付寶的坑是相對較少的。原文地址 APP支付 APP支付步驟為: 獲取支付寶的...
摘要:微信支付接口下載官方文檔參考配置公眾號信息我們先進行測試,所以先把測試授權目錄和測試白名單添加上。在申請微信支付后發來的郵件中可以找到,則根據郵件提示拜訪官方我們首先需要的是支付。 微信php支付接口demo下載https://pay.weixin.qq.com/wik... 官方文檔參考https://pay.weixin.qq.com/wik... 1. 配置公眾號信息showIm...
摘要:上線時間問題發布審核時間,微信小時內會審核完成,但是支付寶官方公示是上線審核需要三到五個工作日,據親測,實際支付寶審核印版不會超過小時,但是支付寶的審核相比較微信真的很嚴格。 前言: 最近一個月接收一個支付寶小程序項目,并進行原生開發,現將遇到的問題,爬過的坑給大家進行分享,希望讀者可以少走彎路,以下介紹的內容將從大方面到細節進行展開。 廢話少言,直接開始步入正題 ①:上傳、發布問...
摘要:原文見我的博客,點擊進入使用開發微信公眾號下站點的填坑之旅本文為我創業過程中,開發項目的填坑之旅。作為一個技術宅男,我的項目是做一個微信公眾號,前后端全部自己搞定,不浪費國家一分錢。 原文見我的博客,點擊進入使用vue開發微信公眾號下SPA站點的填坑之旅 本文為我創業過程中,開發項目的填坑之旅。作為一個技術宅男,我的項目是做一個微信公眾號,前后端全部自己搞定,不浪費國家一分錢^_^。 ...
摘要:目前正在寫一個微信公眾號的小項目,記錄一下遇到的問題和解決方法主要是前端。前端提交時使用,在后端再取出對應的微信支付看了下文檔,以前是需要用喚起支付,而現在則是把微信內置到了微信的瀏覽器中。 目前正在寫一個微信公眾號的小項目,記錄一下遇到的問題和解決方法(主要是前端)。內容持續更新中~ 主要實現 前后端分離前端為 SPA 單頁面使用微信的JSSDK微信支付 技術方案 后端使用 php ...
閱讀 623·2023-04-26 01:53
閱讀 2749·2021-11-17 17:00
閱讀 2880·2021-09-04 16:40
閱讀 1983·2021-09-02 15:41
閱讀 830·2019-08-26 11:34
閱讀 1222·2019-08-26 10:16
閱讀 1335·2019-08-23 17:51
閱讀 815·2019-08-23 16:50