本文轉自:http://www.javashuo.com/article/p-sisebraj-o.htmlhtml
因公司須要將支付寶和微信的二維碼合成一個,無論用戶用支付寶掃仍是微信掃都能打開對應的支付頁面,在網上找了一些文章,很感謝各位大神的經驗,我也記錄下我是如何將兩個二維碼合二爲一的~。java
原理:支付寶或微信生成的二維碼中本質都內嵌了一個url,在掃碼時實際是定向去訪問二維碼中內嵌的url,這樣我就能夠將這個url指定到個人一個控制器,在控制器中判斷是微信仍是支付寶軟件掃的,而後去喚醒各自的支付便可。web
1.首先生成二維碼:ajax
folderName:存儲二維碼圖片的文件夾名json
imageName:二維碼圖片名稱api
content:是在二維碼中寫入的內容,這裏我傳入的是URL:指定我判斷軟件類型的控制器微信
- public static String genQRImage(String folderName, String imageName, String content) {
-
- String fileName = imageName + ".png";
-
- try {
-
-
- File file = new File(folderName);
- if (!file.exists() && !file.isDirectory()) {
- file.mkdir();
- }
- folderName = file.getAbsolutePath();
-
- int width = 200;
- int height = 200;
- String format = "png";
-
- Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
- hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
- hints.put(EncodeHintType.MARGIN, 1);
- BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
- Path path = FileSystems.getDefault().getPath(folderName, fileName);
- MatrixToImageWriter.writeToPath(bitMatrix, format, path);
- log.info("二維碼已經生成," + path);
- fileName = path.toString();
-
- } catch (Exception e) {
- log.error(e.getMessage(), e);
- fileName = null;
- }
- return fileName;
- }
2.定義類型控制器:app
你們必定都想問是如何判斷打開軟件的類型,把Request Header Cookie 都看看就明白了,掃碼二維碼時不會傳入任何參數,webapp
但會有一個請求頭,就是這個請求頭告知了我打開軟件的類型。微信支付
使用request獲取名爲User-Agent的請求頭,
支付寶的請求頭:ucbrowser/1.0.0.100 u3/0.8.0 mobile safari/534.30 alipaydefined(nt:wifi,ws:360|604|3.0) aliapp(ap/9.9.7.112401) alipayclient/9.9.7.112401 language/zh-hans usestatusbar/true
微信的請求頭: mqqbrowser/6.8 tbs/036887 safari/537.36 micromessenger/6.3.31.940 nettype/wifi language/zh_cn
就是根據這兩個請求頭去判斷對應的軟件類型,根據不一樣的軟件類型去喚醒不一樣的支付。
- @RequestMapping("qrcallback")
- public void qrcallback(HttpServletRequest request, HttpServletResponse response) throws IOException, AlipayApiException {
-
- String agent = request.getHeader("User-Agent").toLowerCase();
- System.out.println("響應頭的類型:"+agent);
- if (agent.indexOf("micromessenger") > 0) {
- System.out.println("微信支付");
- } else if (agent.indexOf("alipayclient") > 0) {
- System.out.println("阿里支付");
-
- String form = testService.aliPay();
- response.setContentType("text/html;charset=UTF-8");
- response.getWriter().write(form);
- response.getWriter().flush();
- }
- }
3.先說簡單的,喚醒支付寶支付,其實使用的是 支付寶手機網站支付:這個須要簽約噢~
https://b.alipay.com/signing/productDetail.htm?productId=I1011000290000001001
這個喚起支付能夠看看官網是怎麼寫的:https://doc.open.alipay.com/docs/doc.htm?treeId=203&articleId=105285&docType=1
有兩種方式:一種是頁面喚醒,本身構建請求form參數而後請求支付寶喚醒支付操做,另外一種是服務端調用支付寶的SDK去生
成form參數而後去請求支付寶,我使用的是第二種。
步驟:{
1.首先引入pom.xml依賴
- <span style="white-space:pre;"> </span>
- <dependency>
- <groupId>com.twt.charge</groupId>
- <artifactId>alipay-sdk-java</artifactId>
- <version>20160519120058</version>
- </dependency>
2.生成form參數:
裏面的參數本身填寫從支付寶獲取的那些參數,copy個人確定出錯哈
- public String aliPay() throws AlipayApiException {
- AlipayClient alipayClient = new DefaultAlipayClient(openapi, SecurityUtil.decodeBase64(appid),
- SecurityUtil.decodeBase64(rsa_private_key), "json", "utf-8", SecurityUtil.decodeBase64(alipay_pub_key));
- AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
- alipayRequest.setReturnUrl("http://192.168.1.219:22222/ali.html");
- alipayRequest.setNotifyUrl("http://192.168.1.219:22222/callback");// 在公共參數中設置回跳和通知地址
- alipayRequest.setBizContent("{" + " \"out_trade_no\":\"20160320020192222\"," + " \"total_amount\":66.66,"
- + " \"subject\":\"主題\"," + " \"seller_id\":\"213215dsa\"," +
-
- " }");
- String form = alipayClient.pageExecute(alipayRequest).getBody();
-
- return form;
- }
將這個form以流的形式輸出便可。
如:
- <span style="white-space:pre;"> </span>response.setContentType("text/html;charset=UTF-8");
- response.getWriter().write(form);
- response.getWriter().flush();
}
喚起支付寶支付就這麼簡單,但要注意參數中的帳單號要是商戶系統中惟一的帳單號。
4.喚起微信支付:喚起的實際上是微信公衆號支付,作過公衆號支付的同窗都知道,調用微信公衆號的統一下單API時
須要傳入openID,即用戶在該公衆號的下的惟一標識,這個過程須要用於受權登陸該公衆號,這個過程是一個缺點,
用戶僅僅只是微信的掃碼支付,但你中間不是黑箱子的形式展現,而是在支付中多出了一個受權登陸的頁面,而且
也比較繁瑣,在喚醒微信支付的過程當中請求次數較多,因此微信支付會比正在的掃碼支付會慢不少。
喚起微信公衆號支付:{
步驟:
1.首先拼裝好你的受權登陸url。在類型控制中判斷若是是微信支付則重定向到微信受權登陸頁面,微信會重定向到
你在受權登陸url中設置重定向url參數的頁面,
2.跳轉到這個頁面後,先獲取到用戶code而後利用ajax訪問服務端,
3.服務端使用code去獲取用戶的openID,
4.根據openID去調用微信公衆號的統一下單API生成參數,而後返回給頁面喚醒支付,這就是整個微信的流程,
中間訪問了3次微信獲取數據,整個流程共6次請求,須要將微信跳轉的頁面放到官網的微信目錄下。
在寫這篇博文的時候由於支付寶我尚未簽約,因此沒有調通,而微信也只成功了一次,但第二次什麼都沒改的狀況
下就不行了,寫這篇博文順便捋捋思路,怎麼更簡單。
注:訪問微信受權頁面中的redirect_url參數能夠添加請求參數。
}