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