微信jsApiSdk对接

博主使用jfinal框架

微信开发文档

https://mp.weixin.qq.com/wiki/11/74ad127cc054f6b80759c40f77ec03db.html

对接过程:
    1.在公众号上面填写好域名指向、获取功能权限
    2.看开发文档、获取签名算法、获取前端接口。
    3.获取access_token、jsapi_ticket
    4.验证
出现的问题:
    签名不一致、
    最后发现是写入txt文件的时候加了"\n\s";
建议:
    从:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
    这个验签中string1 与你打印出来一至的话
    就是可能是timestamp、noncestr、jsapi_ticket出问题
    如果是外写jsapi_ticket更要注意。
其他问题想看文档的:
    附录5-常见错误及解决方法

签名算法用官网的例子 Sign类:

import java.util.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;

public class Sign {
    public static void main(String[] args) {
        String jsapi_ticket = "jsapi_ticket";

        // 注意 URL 一定要动态获取,不能 hardcode
        String url = "http://example.com";
        Map<String, String> ret = sign(jsapi_ticket, url);
        for (Map.Entry entry : ret.entrySet()) {
            System.out.println(entry.getKey() + ", " + entry.getValue());
        }
    }
    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;
    }

    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
        return (int)(System.currentTimeMillis() / 1000)+"";
    }
}

写个周期任务 Task
由于微信的限制访问次数

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by cwq on 2017/3/4.
 * jdk 1.8
 */
public class Task {
    private Runnable runnable = new Runnable() {
        public void run() {
            System.out.println("默认一个小时一次执行任务 !!");
        }
    };//执行线程
    private long initialDelay = 0;//初始化延时
    private long period = 1;//两次开始执行最小间隔时间
    private TimeUnit unit = TimeUnit.HOURS;//计时单位

    public Runnable getRunnable() {
        return runnable;
    }

    public void setRunnable(Runnable runnable) {
        this.runnable = runnable;
    }

    public long getInitialDelay() {
        return initialDelay;
    }

    public void setInitialDelay(long initialDelay) {
        this.initialDelay = initialDelay;
    }

    public long getPeriod() {
        return period;
    }

    public void setPeriod(long period) {
        this.period = period;
    }

    public TimeUnit getUnit() {
        return unit;
    }

    public void setUnit(TimeUnit unit) {
        this.unit = unit;
    }

    public void run() {
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        service.scheduleAtFixedRate(runnable, initialDelay, period, unit);
    }

调用类

package com.se.activities.utils.wechatjs.task;

import com.se.activities.utils.WechatConfig;
import com.se.activities.utils.wechatjs.FileOperation;
import com.se.sdk.oauth.util.HttpKit;
import com.se.utils.PropertyUtil;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;

/**
 * Created by cwq on 2017/3/4.
 * jdk 1.8
 */
public class WeChatJsApiTask {
    private final static Logger logger = LoggerFactory.getLogger(WeChatJsApiTask.class);//日志
    private static String getJsApiAccessToken = "https://api.weixin.qq.com/cgi-bin/token?" +
            "grant_type=client_credential&appid=APPID&secret=APPSECRET";//参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token)
    private static String getJsApiTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?" +
            "access_token=ACCESS_TOKEN&type=jsapi";
    private static String appId = "xxx";//  公众号的唯一标识
    private static String appSecret = "xxx";//公众号的appsecret
    public static String activitiesPicDir = "";//博主使用存文件的方式存tick 文件物理路径


    private Runnable runnable = new Runnable() {
        public void run() {
            getTick();
        }
    };//执行线程

    //更新微信的 js_ticket
    private void getTick(){
        String url = getJsApiAccessToken.replace("APPID", appId).replace("APPSECRET", appSecret);
        String res = HttpKit.get(url);

        String access_token = "0";
        try {
            JSONObject jsonObject = new JSONObject(res);
//            {"access_token":"ACCESS_TOKEN","expires_in":7200}
//            {"errcode":40013,"errmsg":"invalid appid"}
            if(jsonObject.get("access_token")!=null) access_token = jsonObject.getString("access_token");
            if(jsonObject.get("access_token")==null) {
                System.out.println("@WeChatJsApiTask 取access_token失败:["+res+"]");
            }
            if(!access_token.equals("0")){
                url = getJsApiTicket.replace("ACCESS_TOKEN", access_token);
                res = HttpKit.get(url);
//                System.out.println(res);
                jsonObject = new JSONObject(res);
                if(jsonObject.getString("errmsg").equals("ok")){
                    String ticket = jsonObject.getString("ticket");
                    File file = new File(activitiesPicDir+ File.separatorChar+"JsApiTask.txt");
                    FileOperation.createFile(file);
                    FileOperation.writeTxtFile(ticket,file);
                    System.out.println("@WeChatJsApiTask 取js_ticket:["+ticket+"]");
                }else{
                    System.out.println("@WeChatJsApiTask 取ticket失败:["+res+"]");
                }
            }
            /*
            {"errcode":0,"errmsg":"ok",
            "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
            "expires_in":7200
            }
            */
        } catch (JSONException e) {
            logger.error("转换jsonObject有错,或者不在参数", e);
        }
    }

    public void run() {
        Task task = new Task();
        task.setRunnable(runnable);
        task.run();
        System.out.println("执行周期性任务任务>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        System.out.println("微信JS-SDK凭证更新>>>>>>>");
        System.out.println("初始化延时>>>>>>>>>>>>>>>" + task.getInitialDelay());
        System.out.println("两次开始执行最小间隔时间>>>" + task.getPeriod());
        System.out.println("计时单位>>>>>>>>>>>>>>>>>" + task.getUnit());
        System.out.println("执行周期性任务任务<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
    }
}

写入文件用到的类

package com.se.activities.utils.wechatjs;

import java.io.*;

/**
 * Created by cwq on 2017/3/4.
 * jdk 1.8
 */
public class FileOperation {

    /**
     * 创建文件
     *
     * @param fileName
     * @return
     */
    public static boolean createFile(File fileName) {
        boolean flag = false;
        try {
            if (!fileName.exists()) {
                fileName.createNewFile();
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
    /**
     * 读TXT文件内容
     *
     * @param fileName
     * @return
     */
    public static String readTxtFile(File fileName){
        String result = "";
        FileReader fileReader = null;
        BufferedReader bufferedReader = null;
        try {
            fileReader = new FileReader(fileName);
            bufferedReader = new BufferedReader(fileReader);
            try {
                String read = "";
                while ((read = bufferedReader.readLine()) != null) {
                    result = result + read;//可怜的博主在这里+了"/n/s" 然后签名一直都不成功
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
                if (fileReader != null) {
                    fileReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 
     * @param content
     * @param fileName
     * @return
     * @throws Exception
     */
    public static boolean writeTxtFile(String content, File fileName){
        RandomAccessFile mm = null;
        boolean flag = false;
        FileOutputStream o = null;
        try {
            o = new FileOutputStream(fileName);
            o.write(content.getBytes("utf-8"));
            o.close();
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (mm != null) {
                    mm.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return flag;
    }
}

控制器加签名 返回


 HttpServletRequest req = getRequest();
            String httpUrl = req.getScheme() + "://" + req.getServerName() + req.getContextPath()
                    + req.getServletPath() + "?" + req.getQueryString();
            httpUrl = httpUrl.split("#")[0];
            Map<String, String> JsApiSign = createJsApiSign(URLDecoder.decode(httpUrl));
            setAttr("JsApiSign", JsApiSign);
            Map<String, String> JsApi = createJsApiSign(httpUrl);
            JsApi.put("imgUrl", index_child + "/dow_app_icon.svg");
            setAttr("JsApi", JsApi);

创建签名

   private Map<String, String> createJsApiSign(String url) {
        String jsapi_ticket = FileOperation.readTxtFile(new File(activitiesPicDir + File.separatorChar + "JsApiTask.txt"));
        System.out.println("@handle createJsApiSign[jsapi_ticket:" + jsapi_ticket + "]");
        Map<String, String> ret = Sign.sign(jsapi_ticket, url);
        ret.put("appId", appId);
        return ret;
    }

jsp调用文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<c:if test="${JsApiSign!=null}">
    <%--<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>--%>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
    <script>
        wx.config({
            debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: '${JsApiSign.appId}', // 必填,公众号的唯一标识
            timestamp:${JsApiSign.timestamp}, // 必填,生成签名的时间戳
            nonceStr: '${JsApiSign.nonceStr}', // 必填,生成签名的随机串
            signature: '${JsApiSign.signature}',// 必填,签名,见附录1
            jsApiList: ["onMenuShareTimeline", "onMenuShareAppMessage"] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
        });

        var link = "${JsApiSign.url}";
        if (link.indexOf("is_share") == -1) link = link + "&is_share=1";
        wx.ready(function () {
            wx.onMenuShareTimeline({
                title: '', // 分享标题
                link: link, // 分享链接
                imgUrl: '${JsApi.imgUrl}', // 分享图标
                success: function () {
                    // 用户确认分享后执行的回调函数
                    weChatShare(1);//import的时候 页面回调的方法
                },
                cancel: function () {
                    // 用户取消分享后执行的回调函数
                }
            });
            wx.onMenuShareAppMessage({
                title: '', // 分享标题
                desc: '', // 分享描述
                link: link, // 分享链接
                imgUrl: '${JsApi.imgUrl}', // 分享图标
                type: '', // 分享类型,music、video或link,不填默认为link
                dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
                success: function () {
                    weChatShare(2);
                },
                cancel: function () {
                }
            });
        });

    </script>
</c:if>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值