當(dāng)前位置:
首頁(yè) >
微信支付-我遇到的那些问题
發(fā)布時(shí)間:2025/4/16
25
豆豆
生活随笔
收集整理的這篇文章主要介紹了
微信支付-我遇到的那些问题
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
現(xiàn)在,越來(lái)越多公司,選擇借微信的勢(shì)來(lái)發(fā)展自己的平臺(tái),進(jìn)入工作沒(méi)多久,我也被告知了要對(duì)接微信支付的需求。原本以為這樣的對(duì)接,跟著文檔走,應(yīng)該沒(méi)多大的難度的,可是后來(lái),我才發(fā)現(xiàn),原來(lái)我太天真了。在此,留下印記,說(shuō)說(shuō)我在微信支付上面遇到的那些問(wèn)題。 ? ? ?1、關(guān)于微信支付 ? ? ?首先說(shuō)下微信支付。隨著微信的紅火,微信支付在第三方支付也占了一大塊地盤(pán),越來(lái)越多的公司在自己的APP或者網(wǎng)站上集成了微信支付。從微信支付的官網(wǎng)https://pay.weixin.qq.com/index.php/home/login?return_url=/?可以看出,微信支付主要分為四大塊,公眾號(hào)支付、APP支付、掃碼支付(網(wǎng)站)、刷卡支付。工作上,我接觸到了前三種,遇到了各種各樣的問(wèn)題。 ? ? ?2、關(guān)于官方文檔 ? ? ?對(duì)于開(kāi)發(fā)者來(lái)說(shuō),對(duì)接這種第三方支付,看其官方文檔尤其重要。開(kāi)發(fā)者可以通過(guò)官網(wǎng),查到對(duì)應(yīng)不同支付模塊的官方文檔,但是,請(qǐng)大家注意,該文檔有待完善,完全照著文檔做,可能實(shí)現(xiàn)不了你的功能 ?3、微信支付流程 微信支付的流程,在微信支付官網(wǎng)上也有所顯示,這里更加泛化的說(shuō)一下,其實(shí)微信支付需要的是集成了微信SDK的客戶(hù)端,客戶(hù)先通過(guò)客戶(hù)端瀏覽完成訂單,然后后臺(tái)首先在業(yè)務(wù)系統(tǒng)生成了訂單,訂單生成后,業(yè)務(wù)系統(tǒng)請(qǐng)求微信服務(wù)器,進(jìn)行統(tǒng)一下單。統(tǒng)一下單完成后,微信返回相關(guān)信息,后臺(tái)就可以形成相應(yīng)的支付二維碼或者是封裝出可以調(diào)起微信支付需要的信息。接下來(lái),用戶(hù)只要通過(guò)掃一掃或者點(diǎn)擊確認(rèn)支付,便可以調(diào)出微信支付。支付成功后,微信會(huì)給用戶(hù)發(fā)送信息,同時(shí)也會(huì)對(duì)業(yè)務(wù)系統(tǒng)指定的地址發(fā)送對(duì)應(yīng)的回調(diào)信息,將支付結(jié)果告知微信。同時(shí),微信支付信息也可以通過(guò)后臺(tái)直接請(qǐng)求微信支付來(lái)進(jìn)行確認(rèn)。 ? ? ? 4、微信支付相關(guān) ? ? ? ? ??首先,微信支付有一個(gè)最重要的過(guò)程,就是統(tǒng)一下單,簡(jiǎn)單的說(shuō),開(kāi)發(fā)者需要將業(yè)務(wù)系統(tǒng)中的訂單信息發(fā)送給微信,讓微信后臺(tái)形成在微信那邊的一個(gè)支付訂單。在向微信請(qǐng)求的時(shí)候,傳送的數(shù)據(jù)為xml格式,微信要求xml傳送的數(shù)據(jù)需要進(jìn)行一次加密,然后將加密的字符串附加在xml中一起傳輸?shù)椒?wù)器端,服務(wù)器端驗(yàn)證通過(guò)之后才能進(jìn)行下訂單操作。具體的算法說(shuō)明地址https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3 ? ? ? ? ? 以下,是基于java實(shí)現(xiàn)的加密算法: 1 /**
2 * 微信支付加密工具,需要加入key
3 */
4 public static String signature(Map<String, String> map, String key) {
5 Set<String> keySet = map.keySet();
6 String[] str = new String[map.size()];
7 StringBuilder tmp = new StringBuilder();
8 // 進(jìn)行字典排序
9 str = keySet.toArray(str);
10 Arrays.sort(str);
11 for (int i = 0; i < str.length; i++) {
12 String t = str[i] + "=" + map.get(str[i]) + "&";
13 tmp.append(t);
14 }
15 if (StringUtils.isNotBlank(key)) {
16 tmp.append("key=" + key);
17 }
18 String tosend = tmp.toString();
19 MessageDigest md = null;
20 byte[] bytes = null;
21 try {
22
23 md = MessageDigest.getInstance("MD5");
24 bytes = md.digest(tosend.getBytes("utf-8"));
25 } catch (Exception e) {
26 e.printStackTrace();
27 }
28
29 String singe = byteToStr(bytes);
30 return singe.toUpperCase();
31
32 } 微信支付第一個(gè)問(wèn)題,數(shù)據(jù)加密的key。這個(gè)坑在于不細(xì)心,微信支付有很多key,包括我們微信綁定時(shí)候自己輸入的key,還有微信給的隨機(jī)字符key,而這里,在用于加密的key,并不是我們微信公眾號(hào)中的 AppSecret,而是在微信支付商戶(hù)后臺(tái)設(shè)置的key,設(shè)置的位置為: key設(shè)置路徑:微信商戶(hù)平臺(tái)(pay.weixin.qq.com)-->賬戶(hù)設(shè)置-->API安全-->密鑰設(shè)置 如果不是使用該Key,哪怕是你的算法寫(xiě)對(duì)了,數(shù)據(jù)傳到用戶(hù)那里,依然返回的是簽名錯(cuò)誤。 ? ? ?PS:微信官方給出了一個(gè)驗(yàn)證簽名準(zhǔn)確性的工具,該工具地址為https://pay.weixin.qq.com/wiki/tools/signverify/,AnyWay,正如剛才說(shuō)了,如果key設(shè)置的不正確,比如說(shuō)使用了AppSecret ,那么,你會(huì)發(fā)現(xiàn),該工具的出的加密字符串和自己得出的一模一樣,然后當(dāng)你發(fā)送給微信服務(wù)端的時(shí)候,永遠(yuǎn)返回的是錯(cuò)誤。 ? ? 微信支付第二個(gè)問(wèn)題,post編碼問(wèn)題。當(dāng)組裝好數(shù)據(jù)后,需要通過(guò)POST的形式向微信服務(wù)器發(fā)送數(shù)據(jù)。可是,問(wèn)題來(lái)了,微信的數(shù)據(jù)封裝的完全正確,key也設(shè)置正確了,在官方的驗(yàn)證工具上驗(yàn)證出來(lái)也是正確的,可是,微信總是提示簽名錯(cuò)誤。這個(gè)問(wèn)題出現(xiàn)在post請(qǐng)求的編碼問(wèn)題上,遇到這個(gè)問(wèn)題的情況是,在封裝數(shù)據(jù)的時(shí)候,xml里面加入了中文,然后每次請(qǐng)求就會(huì)報(bào)錯(cuò),可是如果中文去掉,下單成功。最后才發(fā)現(xiàn),原來(lái)POST的時(shí)候,沒(méi)有設(shè)置編碼,設(shè)置成為UTF8之后就沒(méi)事了。可是,返回的簽名錯(cuò)誤,也真心難排查啊 ? ? ? 微信支付第三個(gè)問(wèn)題,js-sdk調(diào)起支付控件。這一步時(shí)講在微信里面H5調(diào)起支付控件的。需要注意的是要在H5上面調(diào)出支付控件,第一件事需要在微信公眾要后臺(tái)添加指定域名允許該域名調(diào)起控件,否則,是不能調(diào)起的。設(shè)置的教程在這:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3?。 ?????設(shè)置完成之后,接下來(lái)是通過(guò)js調(diào)起,在此吐槽一下,我第一次做的時(shí)候,是直接copy的官方的js下來(lái)改的,可是。。。。。。。官方的JS上面全角半角的字符混合,導(dǎo)致的別說(shuō)是他的JS了,就是我自己寫(xiě)的JS最后都沒(méi)調(diào)出來(lái)。。。。。然后,關(guān)于提示,,蘋(píng)果版還好,安卓版的微信,如果調(diào)不出控件,它一點(diǎn)反應(yīng)都不會(huì)有的。。相對(duì)而言,蘋(píng)果版會(huì)有一個(gè)彈框提示,所以后期,只要出現(xiàn)問(wèn)題,都先用蘋(píng)果測(cè)測(cè)看看出了什么錯(cuò)。 ? ? ? 微信支付第四個(gè)問(wèn)題,app端數(shù)據(jù)封裝。能夠統(tǒng)一下單了,這樣一來(lái)就是對(duì)數(shù)據(jù)封裝返回給前端了,這一部,還是需要進(jìn)行簽名,按理來(lái)說(shuō),前面和前面采用的是同樣的方法,應(yīng)該問(wèn)題不大才對(duì)。確實(shí),在web端和掃碼支付都沒(méi)多大問(wèn)題,可是,app端問(wèn)題來(lái)了。我在公司剛開(kāi)始和安卓的同事調(diào)這個(gè)的時(shí)候,本來(lái)以為一個(gè)下午能搞定了。可是,卻不如我們所想。我們?nèi)坎捎玫氖枪俜浇o的要求進(jìn)行封裝的數(shù)據(jù),我后臺(tái)統(tǒng)一下單完成之后,給到安卓,結(jié)果安卓死活調(diào)不出支付控件,而且一直都返回-1的結(jié)果,該結(jié)果,可以說(shuō)一點(diǎn)用處都沒(méi)有。安卓端的同時(shí)調(diào)了好久,一直沒(méi)有找到解決方案,值得一說(shuō)的是,它官方給的Demo是可以調(diào)出結(jié)果界面,可是也是調(diào)不出支付控件的。而且,他的java文件,utf-8和GBK兩種編碼混在一起的。最后說(shuō)一下,為啥app調(diào)不出支付控件。 圖1 1 //網(wǎng)頁(yè)調(diào)起的時(shí)候
2 String time = Long.toString(System.currentTimeMillis());
3 back.put("appId", mchappid);
4 back.put("timeStamp", time);
5 back.put("nonceStr", "5K8264ILTKCH16CQ2502SI8ZNMTM67VS");
6 back.put("package", "prepay_id=" + order.getPrepay_id());
7 back.put("signType", "MD5");
8 String sign2 = SignatureUtils.signature(back, wx_key);
9
10 JSONObject jsonObject = new JSONObject();
11 jsonObject.put("appId", mchappid);
12 jsonObject.put("timeStamp", time);
13 jsonObject.put("nonceStr", "5K8264ILTKCH16CQ2502SI8ZNMTM67VS");
14 jsonObject.put("package", "prepay_id=" + order.getPrepay_id());
15 jsonObject.put("signType", "MD5");
16 jsonObject.put("paySign", sign2);
17
18 result.put("status", "success");
19 result.put("msg", "下單成功");
20 result.put("obj", jsonObject);
21 return result; 1 //APP調(diào)起的時(shí)候,請(qǐng)注意,安卓端不能用駝峰法,所有的key必須使用小寫(xiě)
2 String time = Long.toString(System.currentTimeMillis());
3 back.put("appid", app_mchappid);
4 back.put("timestamp", time);
5 back.put("partnerid", app_mchid);
6 back.put("noncestr", "5K8264ILTKCH16CQ2502SI8ZNMTM67VS");
7 back.put("prepayid", order.getPrepay_id());
8 back.put("package", "Sign=WXPay");
9 String sign2 = SignatureUtils.signature(back, wx_key);
10
11 JSONObject jsonObject = new JSONObject();
12 jsonObject.put("appid", app_mchappid);
13 jsonObject.put("timestamp", time);
14 jsonObject.put("partnerid", app_mchid);
15 jsonObject.put("noncestr", "5K8264ILTKCH16CQ2502SI8ZNMTM67VS");
16 jsonObject.put("prepayid", order.getPrepay_id());
17 //jsonObject.put("package", "Sign=WXPay");
18 jsonObject.put("sign", sign2);
19 result.put("status", "success");
20 result.put("msg", "下單成功");
21 result.put("obj", jsonObject);
22 return result;
至今為止遇到的問(wèn)題大致如上,做下筆記,同時(shí)希望對(duì)同為開(kāi)發(fā)的朋友有用 最后,附上本人在github上的一個(gè)基于java的微信支付后臺(tái)Demo?https://github.com/Seanid/wechatPay
?
如圖,圖1為微信官方文檔中安卓調(diào)起支付控件的示例代碼,接下來(lái)為web端調(diào)起支付控件時(shí)候進(jìn)行加密的算法,最后為解決問(wèn)題后返回給APP數(shù)據(jù)時(shí)候數(shù)據(jù)封裝的代碼。問(wèn)題所在就是在于,它數(shù)據(jù)的封裝不像官網(wǎng)所說(shuō)的使用駝峰法,app的時(shí)候,需要把所有的字符小寫(xiě),,,小寫(xiě),,,,,,,。還有,官方說(shuō)的packageValue是錯(cuò)的,要用package,就是因?yàn)檫@些錯(cuò),加密出來(lái)的數(shù)據(jù)是錯(cuò)的,所以app端才調(diào)不出支付控件。在此,為我那個(gè)調(diào)到奔潰的同事默哀。至今為止遇到的問(wèn)題大致如上,做下筆記,同時(shí)希望對(duì)同為開(kāi)發(fā)的朋友有用 最后,附上本人在github上的一個(gè)基于java的微信支付后臺(tái)Demo?https://github.com/Seanid/wechatPay
轉(zhuǎn)載于:https://www.cnblogs.com/Seanit/p/5136551.html
總結(jié)
以上是生活随笔為你收集整理的微信支付-我遇到的那些问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Matlab使用技巧:Rapid Cod
- 下一篇: spring websocket Con