微信扫一扫接口的调用

  

说明本人是个新手,负责人要求我在公司的微信公众号H5界面中添加一个扫一扫功能,这对于我来说还是个不小的挑战,因为之前的公众号开发大部分都是公司的前辈的开发的。对于微信接口的使用,我一点都不熟悉。

废话少说,现在我分享一下调用微信扫一扫的过程及代码,系统框架采用的是SSH框架。

  开发扫一扫的满足条件: 

    一、需要微信公众号的APP_ID

    二、需要微信公众号的开发者密码AppSecret(如何查看AppSecreti:开发-基本配置-开发者密码-重置 管理员扫码即可看到)

    三、需要一个内网穿透的软件,我使用的是natapp

    四、在微信公众号中将自己的本机Ip添加到IP白名单中

满足以上条件,那么我们就可以进行微信扫一扫的接口调用

首先创建微信配置工具类(部分代码是来自网上的大牛们的代码,由于浏览了几天几夜的网页,具体是谁的我也搞不清了)

  微信签名类

  

package com.item.config;
import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.Formatter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;  

public class Sign {
/*    public static void main(String[] args) {
    	//获取ticket
        String ticket = WxUtils.getTicket();
        // 注意 URL 一定要动态获取,不能 hardcode
        String url = "http://"+WxUtils.APP_DOMAIN+"/RAFFLE/gotoLetter";
        Map<String, String> ret = sign(ticket, url);
        for (Map.Entry entry : ret.entrySet()) {
            System.out.println(entry.getKey() + ", " + entry.getValue());
        }
    }*/
	/**
	 * 用于微信签名
	 * //签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分)
	 * @param jsapi_ticket 
	 * @param url 当前网页的URL,不包含#及其后面部分
	 * @return
	 */
    public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        //保证每次请求的签名都不一样
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意这里参数名必须全部小写,且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket +
                  "&noncestr=" + nonce_str +
                  "&timestamp=" + timestamp +
                  "&url=" + url;
        System.out.println(string1);

        try
        {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);

        return ret;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }
    /**
     * 创建随机字符串
     * @return
     */
    private static String create_nonce_str() {
        return UUID.randomUUID().toString().replace("-", "");
    }
    /**
     * 创建随机时间戳,保证每次的都不一样
     * @return
     */
    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}

   获取微信Ticket类

package com.item.config;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import net.sf.json.JSONObject;

public class WxUtils {
    private static String APP_ID = "填写你的APP_ID";
    private static String AppSecret = "填写你的Sercret";
    public static String APP_DOMAIN ="填写你的域名比如xx.com";
  
    public static String getTicket(){
    	//grant_type:获取access_token填写client_credential || appid:第三方用户唯一凭证 || secret:第三方用户唯一凭证密钥
        String urlToken="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+APP_ID+"&secret="+AppSecret+"";
        String backToken = sendGet(urlToken,"utf-8",60000);
        System.out.println("token:"+backToken);
        String accessToken = (String) JSONObject.fromObject(backToken).get("access_token");
        String url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+accessToken+"&type=jsapi";
        String backTicket = sendGet(url,"utf-8",60000);
        System.out.println("Ticket:"+backTicket);
        String ticket = (String) JSONObject.fromObject(backTicket).get("ticket");  
        return ticket;
    }
    /**
     * 
      * @title  getAccessToken
      * @Description 获取访问令牌
      * @Date 2018-5-18上午11:07:18
      * @return
     */
    public static String getAccessToken(){
    	
        String url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+APP_ID+"&secret="+AppSecret+"";
        String backData = sendGet(url,"utf-8",10000);
        String accessToken = (String) JSONObject.fromObject(backData).get("access_token");
        return accessToken;
    }
    /**
     * 
      * @title  sendGet
      * @Description
      * @param url
      * @param charset
      * @param timeout
      * @return
     */
    public static String sendGet(String url, String charset, int timeout)
    {
      String result = "";
      try
      {
        URL u = new URL(url);
        try
        {
          URLConnection conn = u.openConnection();
          conn.connect();
          conn.setConnectTimeout(timeout);
          BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
          String line="";
          while ((line = in.readLine()) != null)
          {
            result = result + line;
          }
          in.close();
        } catch (IOException e) {
          return result;
        }
      }
      catch (MalformedURLException e)
      {
        return result;
      }
      return result;
    }
}

  ScanAction类:进行微信签名并存入Map中

package com.code.action.front;

import java.util.Map;

import com.code.action.BaseAction;
import com.item.config.Sign;
import com.item.config.WxUtils;

public class ScanAction extends BaseAction {
	private Map<String, String> sign;
	/*public static void main(String[] args) {
		// 获取ticket数据
		String jsapi_ticket = WxUtils.getTicket();
		String url = "http://" + WxUtils.APP_DOMAIN + "/调用微信接口所在的路径下的jsp文件,由于我使用的是通过action进行跳转,那么对应的就是写你跳转到该网页的Action";
		Map<String, String> sign = Sign.sign(jsapi_ticket, url);
		 for (Map.Entry entry : sign.entrySet()) {
             System.out.println(entry.getKey() + "," + entry.getValue());
         }
	

	}*/
	/**
	 * 进行微信签名并存入Map中,在再跳转到前端中,Map对象的值通过EL表达式进行获取对象的值
	 * @author chenbufu
	 * @return
	 */
	public String getWxConfig() {
		System.out.println("获取微信配置");
		// 获取ticket数据
		String jsapi_ticket = WxUtils.getTicket();
		String url = "http://" + WxUtils.APP_DOMAIN + "/项目名/xx.action";
		sign = Sign.sign(jsapi_ticket, url);
		 for (Map.Entry entry : sign.entrySet()) {
             System.out.println(entry.getKey() + "," + entry.getValue());
         }

		System.out.println("----------" + jsapi_ticket);

		return "success";
	}

	public Map<String, String> getSign() {
		return sign;
	}

	public void setSign(Map<String, String> sign) {
		this.sign = sign;
	}

	
	
}

  跳转到前端代码:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>管理</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet"
	href="${pageContext.request.contextPath}/pub/js/imgbox/css/lrtk.css"
	type="text/css" media="all" />
<script type="text/javascript"
	src="${pageContext.request.contextPath}/pub/js/imgbox/jquery.min.js"></script>
<script type="text/javascript"
	src="${pageContext.request.contextPath}/pub/js/imgbox/jquery.imgbox.pack.js"></script>
<link rel="stylesheet"
	href="${pageContext.request.contextPath}/pub/css/bg/style.css"
	type="text/css" media="all" />
<script type="text/javascript"
	src="${pageContext.request.contextPath}/pub/js/jquery.idTabs.min.js"></script>


</head>

<body
	style="margin:0px;padding:0px;overflow:hidden;padding-top:5px;widht:320px;">
     《!--用于测试传递过来的参数
	<table>

		<tr>
			<td>jsapi_ticket:</td>
			<td>${sign.jsapi_ticket}</td>
		</tr>
		<tr>
			<td>url:</td>
			<td>${sign.url}</td>
		</tr>
		<tr>
			<td>nonceStr:</td>
			<td>${sign.nonceStr}</td>
		</tr>
		<tr>
			<td>timestamp:</td>
			<td>"${sign.timestamp}"</td>
		</tr>
		<tr>
			<td>signature:</td>
			<td>${sign.signature}</td>
		</tr>
	</table>
--》
<h3 id="menu-scan">微信扫一扫</h3> <span class="desc">调起微信扫一扫接口</span> <button class="btn btn_primary" id="scanQRCode0">scanQRCode(微信处理结果)</button> <button class="btn btn_primary" id="scanQRCode1">scanQRCode(直接返回结果)</button> </body> <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> <script type="text/javascript"> wx.config({ debug : true, appId : 'wx808ff7c908d83c7c',//必填 timestamp : "${sign.timestamp}",//必填 nonceStr : "${sign.nonceStr}",//必填 signature : "${sign.signature}",//必填 jsApiList : [ 'checkJsApi', 'scanQRCode' ]//调用的接口,必填 }); //end_config alert(location.href.split('#')[0]); wx.error(function(res) { alert("出错了:" + res.errMsg); }); // 9 微信原生接口  // 9.1.1 扫描二维码直接跳转 document.querySelector('#scanQRCode0').onclick = function () { wx.scanQRCode(); }; // 9.1.2 扫描二维码并返回结果 document.querySelector('#scanQRCode1').onclick = function () { wx.scanQRCode({ needResult: 1, desc: 'scanQRCode desc', success: function (res) { alert(JSON.stringify(res)); } }); }; </script> </html>

  如果报config: invalid signature..请点击此参考连接进行排查错误:https://www.cnblogs.com/buoge/p/4522666.html

  我之前一直卡在config: invalid signature 这个报错过程中,通过在script代码块中输入alert(location.href.split('#')[0]);语句,发现与我后台的url地址不同,后台写的是具体的jsp路径,而前台打印的是具体的action跳转,于是我把后台的url改成action跳转后就没报错了。

 

posted @ 2019-02-22 15:12  含苞待放会有时  阅读(2352)  评论(0编辑  收藏  举报