本文转自: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参数能够添加请求参数。
}