精华内容
下载资源
问答
  • 企业微信开发

    2018-10-02 17:11:49
    企业微信开发Demo
  • 企业微信开发概述篇

    2020-08-07 14:29:20
    1,了解企业微信开发是怎么回事,企业微信开发是开发什么,怎么接入企业微信,接入企业微信能获取什么能力? 2,了解企业微信api及应用类别,自建内部应用与第三方应用有什么区别,适用场景是什么,我该怎么选应用...
  • 充分理解企业微信第三方应用开发流程,带你快速避坑躲雷节约时间精力,从0到1全流程完成企业微信... 另有《企业微信开发概述篇》免费视频系统,对企业微信开发不了解的可前往https://edu.csdn.net/course/detail/30386
  • 企业微信开发Demo

    2018-04-18 15:54:24
    企业微信 开发 实例 公众平台开发 Demo
  • 微信公众平台之企业微信 开发教程.zip
  • 企业微信开发第一步获取AccessToken,企业微信的AccessToken和公众号的不一样,企业微信所有接口调用只需要一个AccessToken,而公众号授权和jssdk是分开的 一、获取企业微信AccessToken import ...

    企业微信开发第一步获取AccessToken,企业微信的AccessToken和公众号的不一样,企业微信所有接口调用只需要一个AccessToken,而公众号授权和jssdk是分开的

    一、获取企业微信AccessToken

    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.bootdo.common.cache.RedisService;
    import com.bootdo.common.utils.Errors;
    import com.bootdo.wx.entity.WxAgent;
    import com.bootdo.wx.mapper.WxAgentMapper;
    import com.hyd.weixin.utils.HttpSender;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import java.io.IOException;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 处理企业微信AccessToken
     * @author laowang
     * @email open@xcloud.com
     */
    @Slf4j
    @Service
    public class WeixinAccessTokenService {
    
        //企业微信
        public static final String URL_PATTERN2 = "https://qyapi.weixin.qq.com/cgi-bin/gettoken" +
                "?corpid={{APPID}}&corpsecret={{SECRET}}";
    
        @Autowired
        WxAgentMapper wxAgentMapper;
    
        @Autowired
        RedisService redisService;
    
        public String getEnterpriseAccessToken(String account) throws IOException {
            String accessToken = "";
            WxAgent wxAgent = selectAgent(account);
            if (wxAgent == null) {
                throw Errors.Account_MissingAccount.ex(account);
            }
            String url = URL_PATTERN2
                    .replace("{{APPID}}", wxAgent.getCorpid())
                    .replace("{{SECRET}}", wxAgent.getAgentSecret());
            if(redisService.keyExists("enterprise_"+wxAgent.getAgentId())){
                accessToken = redisService.get("enterprise_"+wxAgent.getAgentId());
            }else{
                HttpSender httpSender = new HttpSender(url);
                String json = httpSender.sendAndGetResponse();
                JSONObject jsonObject = JSON.parseObject(json);
                if (jsonObject.getInteger("errcode")==0) {
                    accessToken = jsonObject.getString("access_token");
                    redisService.set("enterprise_"+wxAgent.getAgentId(),accessToken,7200, TimeUnit.SECONDS);
                }else{
                    log.error("企业号获取AccessToken错误 原因{}",jsonObject.getString("errmsg"));
                }
            }
            return accessToken;
        }
    
        public WxAgent selectAgent(String account) {
            return wxAgentMapper.selectWxAgent(account);
        }
    }
    

    注:这里获取AccessToken根据自己业务来,做好AccessToken缓存

    二、对所有消息类型的枚举

    public interface WxTempConstant {
    
    	public final String TEMP_TEXT = "text";
    
    	public final String TEMP_IMAGE = "image";
    
    	public final String TEMP_VOICE = "voice";
    
    	public final String TEMP_VIDEO = "video";
    
    	public final String TEMP_FILE = "file";
    
    	public final String TEMP_TEXT_CARD = "textcard";
    
    	public final String TEMP_NEWS = "news";
    
    	public final String TEMP_MPNEWS = "mpnews";
    
    	public final String TEMP_MARKDOWN = "markdown";
    
    	public final String TEMP_MINIPROGEAM_NOTICE = "miniprogram_notice";
    
    	public final String TEMP_TASK_CARD = "taskcard";
    
    }

    三、封装消息节点结构接口

    import java.util.List;
    import java.util.Map;
    
    /**
     * (description)
     * created at 2017/9/30
     *
     * @author laowang
     */
    public interface MapInitializer<K, V> {
    
        void init(Map<K, V> m);
    
        void initListMap(List<Map<K, V>> m);
    }
    

    四、封装消息发送类

    package com.bootdo.wx.service.wechat;
    
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    import com.bootdo.common.utils.MapInitializer;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.http.HttpEntity;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * 处理企业微信消息推送操作
     *
     * @author laowang
     * @email open@xcloud.com
     */
    @Slf4j
    @Service
    public class WeixinMessageService {
    
        //企业微信
        public static final String URL_PATTERN = "https://qyapi.weixin.qq.com/cgi-bin/message/send" +
                "?access_token={{ACCESS_TOKEN}}";
    
        @Autowired
        WeixinAccessTokenService weixinAccessTokenService;
    
        /**
         * 推送企业消息给用户
         *
         * @param agentId     应用ID
         * @param touser      成员ID列表(消息接收者,多个接收者用‘|’分隔,最多支持1000个)。特殊情况:指定为@all,则向关注该企业应用的全部成员发送
         * @param toparty     部门ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
         * @param totag       标签ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
         * @param msgtype     消息类型
         * @param initializer 消息主体参数参考 https://work.weixin.qq.com/api/doc#90000/90135/90236
         */
        public void send(String msgtype, String touser, String toparty, String totag, MapInitializer<String, String> initializer, String agentId) {
    
            log.info("企业应用{}发送{}消息给{}", agentId, msgtype, touser);
            //准备构造json
            JSONObject firstjsonObject = new JSONObject();
            JSONObject msgtypejsonObject = new JSONObject();
            //图文类json构造
            JSONArray jsonArray = new JSONArray();
            JSONObject secandjsonObject = new JSONObject();
            //填充消息参数
            Map<String, String> map = new HashMap<>();
            //填充图文类多节点参数
            List<Map<String, String>> list = new ArrayList<>();
            //构造通用消息参数json
            firstjsonObject.put("touser", touser);
            firstjsonObject.put("toparty", toparty);
            firstjsonObject.put("totag", totag);
            firstjsonObject.put("msgtype", msgtype);
            firstjsonObject.put("agentid", agentId);
            switch (msgtype) {
                case "text":
                    initializer.init(map);
                    //构造消息主体json
                    for (String paramName : map.keySet()) {
                        msgtypejsonObject.put(paramName, map.get(paramName));
                    }
                    firstjsonObject.put("text", msgtypejsonObject);
                    firstjsonObject.put("safe", 0);
                    break;
                case "image":
                    initializer.init(map);
                    //构造消息主体json
                    for (String paramName : map.keySet()) {
                        msgtypejsonObject.put(paramName, map.get(paramName));
                    }
                    firstjsonObject.put("image", msgtypejsonObject);
                    firstjsonObject.put("safe", 0);
                    break;
                case "voice":
                    initializer.init(map);
                    //构造消息主体json
                    for (String paramName : map.keySet()) {
                        msgtypejsonObject.put(paramName, map.get(paramName));
                    }
                    firstjsonObject.put("voice", msgtypejsonObject);
                    break;
                case "video":
                    initializer.init(map);
                    //构造消息主体json
                    for (String paramName : map.keySet()) {
                        msgtypejsonObject.put(paramName, map.get(paramName));
                    }
                    firstjsonObject.put("video", msgtypejsonObject);
                    firstjsonObject.put("safe", 0);
                    break;
                case "file":
                    initializer.init(map);
                    //构造消息主体json
                    for (String paramName : map.keySet()) {
                        msgtypejsonObject.put(paramName, map.get(paramName));
                    }
                    firstjsonObject.put("file", msgtypejsonObject);
                    firstjsonObject.put("safe", 0);
                    break;
                case "textcard":
                    initializer.init(map);
                    //构造消息主体json
                    for (String paramName : map.keySet()) {
                        msgtypejsonObject.put(paramName, map.get(paramName));
                    }
                    firstjsonObject.put("textcard", msgtypejsonObject);
                    break;
                case "news":
                    initializer.initListMap(list);
                    //构造消息主体json
                    for (int i = 0; i <= list.size() - 1; i++) {
                        secandjsonObject = new JSONObject();
                        for (String paramName : list.get(i).keySet()) {
                            secandjsonObject.put(paramName, list.get(i).get(paramName));
                        }
                        jsonArray.add(secandjsonObject);
                    }
                    log.info(jsonArray.toJSONString());
                    msgtypejsonObject.put("articles", jsonArray);
                    firstjsonObject.put("news", msgtypejsonObject);
                    break;
                case "mpnews":
                    initializer.initListMap(list);
                    //构造消息主体json
                    for (int i = 0; i <= list.size() - 1; i++) {
                        secandjsonObject = new JSONObject();
                        for (String paramName : list.get(i).keySet()) {
                            secandjsonObject.put(paramName, list.get(i).get(paramName));
                        }
                        jsonArray.add(secandjsonObject);
                    }
                    log.info(jsonArray.toJSONString());
                    msgtypejsonObject.put("articles", jsonArray);
                    firstjsonObject.put("mpnews", msgtypejsonObject);
                    break;
                case "markdown":
                    initializer.init(map);
                    //构造消息主体json
                    for (String paramName : map.keySet()) {
                        msgtypejsonObject.put(paramName, map.get(paramName));
                    }
                    firstjsonObject.put("markdown", msgtypejsonObject);
                    break;
                case "miniprogram_notice":
                    initializer.init(map);
                    initializer.initListMap(list);
                    //构造消息主体json
                    for (String paramName : map.keySet()) {
                        msgtypejsonObject.put(paramName, map.get(paramName));
                    }
                    //构造消息节点json
                    for (int i = 0; i <= list.size() - 1; i++) {
                        secandjsonObject = new JSONObject();
                        for (String paramName : list.get(i).keySet()) {
                            secandjsonObject.put(paramName, list.get(i).get(paramName));
                        }
                        jsonArray.add(secandjsonObject);
                    }
                    log.info(jsonArray.toJSONString());
                    msgtypejsonObject.put("content_item", jsonArray);
                    firstjsonObject.put("miniprogram_notice", msgtypejsonObject);
                    break;
                case "taskcard":
                    initializer.init(map);
                    initializer.initListMap(list);
                    //构造消息主体json
                    for (String paramName : map.keySet()) {
                        msgtypejsonObject.put(paramName, map.get(paramName));
                    }
                    //构造消息节点json
                    for (int i = 0; i <= list.size() - 1; i++) {
                        secandjsonObject = new JSONObject();
                        for (String paramName : list.get(i).keySet()) {
                            secandjsonObject.put(paramName, list.get(i).get(paramName));
                        }
                        jsonArray.add(secandjsonObject);
                    }
                    log.info(jsonArray.toJSONString());
                    msgtypejsonObject.put("btn", jsonArray);
                    firstjsonObject.put("taskcard", msgtypejsonObject);
                    break;
            }
            sendTo(agentId, firstjsonObject.toJSONString());
        }
    
        /**
         * 推送消息
         * @param agentId
         * @param tempdata
         */
        public void sendTo(String agentId, String tempdata) {
            String accessToken = null;
            try {
                accessToken = weixinAccessTokenService.getEnterpriseAccessToken(agentId);
            } catch (IOException e) {
                e.printStackTrace();
            }
            String url = URL_PATTERN.replace("{{ACCESS_TOKEN}}", accessToken);
            JSONObject jsonObject = post(url, tempdata);
            if (!StringUtils.isEmpty(jsonObject.toJSONString()) && jsonObject.getInteger("errcode") == 0) {
                log.info("消息推送成功");
            } else {
                log.info("消息推送失败 原因:{}", jsonObject.toJSONString());
            }
        }
    
        /**
         * POST请求的RAW参数传递
         *
         * @param url
         * @param body
         * @return
         */
        public static JSONObject post(String url, String body) {
            JSONObject jsonObject = null;
            CloseableHttpClient httpClient = null;
            HttpPost httpPost = null;
            try {
                httpClient = HttpClients.createDefault();
                RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(20000).setConnectTimeout(20000).build();
                httpPost = new HttpPost(url);
                httpPost.setConfig(requestConfig);
                httpPost.setEntity(new StringEntity(body, "utf-8"));
                CloseableHttpResponse response = httpClient.execute(httpPost);
                HttpEntity httpEntity = response.getEntity();
                jsonObject = JSONObject.parseObject(EntityUtils.toString(httpEntity, "utf-8"));
                return jsonObject;
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                return jsonObject;
            }
        }
    }
    

    五、各类型消息推送单元测试(消息主体参数参考 https://work.weixin.qq.com/api/doc#90000/90135/90236)

    package com.bootdo;
    
    
    import com.bootdo.common.utils.MapInitializer;
    import com.bootdo.common.utils.wechat.WxTempConstant;
    import com.bootdo.wx.service.wechat.WeixinMessageService;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    @Slf4j
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class BootdoApplicationTests {
    
        @Autowired
        WeixinMessageService weixinMessageService;
    
        @Test
        public void contextLoads() throws IOException {
    
            final String agentId = "1000002";
            final String touser = "WangLinJun";
            final String toparty = "";
            final String totag = "";
    
            //文本消息
            try {
                weixinMessageService.send(WxTempConstant.TEMP_TEXT, touser, toparty, totag,
                        new MapInitializer<String, String>() {
                            @Override
                            public void init(Map<String, String> m) {
                                m.put("content", "你的快递已到,请携带工卡前往邮件中心领取。\n出发前可查看<a href=\"http://work.weixin.qq.com\">邮件中心视频实况</a>,聪明避开排队。");
                            }
    
                            @Override
                            public void initListMap(List<Map<String, String>> m) {
                            }
                        }, agentId);
            } catch (Exception e) {
                log.error("发送模板消息失败: " + e.getMessage());
                e.printStackTrace();
            }
    
            //图片消息
            try {
                weixinMessageService.send(WxTempConstant.TEMP_IMAGE, touser, toparty, totag,
                        new MapInitializer<String, String>() {
                            @Override
                            public void init(Map<String, String> m) {
                                m.put("media_id", "MEDIA_ID");
                            }
    
                            @Override
                            public void initListMap(List<Map<String, String>> m) {
                            }
                        }, agentId);
            } catch (Exception e) {
                log.error("发送模板消息失败: " + e.getMessage());
                e.printStackTrace();
            }
    
            //语音消息
            try {
                weixinMessageService.send(WxTempConstant.TEMP_VOICE, touser, toparty, totag,
                        new MapInitializer<String, String>() {
                            @Override
                            public void init(Map<String, String> m) {
                                m.put("media_id", "MEDIA_ID");
                            }
    
                            @Override
                            public void initListMap(List<Map<String, String>> m) {
                            }
                        }, agentId);
            } catch (Exception e) {
                log.error("发送模板消息失败: " + e.getMessage());
                e.printStackTrace();
            }
    
            //视频消息
            try {
                weixinMessageService.send(WxTempConstant.TEMP_VIDEO, touser, toparty, totag,
                        new MapInitializer<String, String>() {
                            @Override
                            public void init(Map<String, String> m) {
                                m.put("media_id", "MEDIA_ID");
                            }
    
                            @Override
                            public void initListMap(List<Map<String, String>> m) {
                            }
                        }, agentId);
            } catch (Exception e) {
                log.error("发送模板消息失败: " + e.getMessage());
                e.printStackTrace();
            }
    
            //文件消息
            try {
                weixinMessageService.send(WxTempConstant.TEMP_FILE, touser, toparty, totag,
                        new MapInitializer<String, String>() {
                            @Override
                            public void init(Map<String, String> m) {
                                m.put("media_id", "MEDIA_ID");
                            }
    
                            @Override
                            public void initListMap(List<Map<String, String>> m) {
                            }
                        }, agentId);
            } catch (Exception e) {
                log.error("发送模板消息失败: " + e.getMessage());
                e.printStackTrace();
            }
    
            //文本卡片消息
            try {
                weixinMessageService.send(WxTempConstant.TEMP_TEXT_CARD, touser, toparty, totag,
                        new MapInitializer<String, String>() {
                            @Override
                            public void init(Map<String, String> m) {
                                m.put("title", "领奖通知");
                                m.put("description", "<div class=\"gray\">2016年9月26日</div> <div class=\"normal\">恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class=\"highlight\">请于2016年10月10日前联系行政同事领取</div>");
                                m.put("url", "URL");
                                m.put("btntxt", "更多");
                            }
    
                            @Override
                            public void initListMap(List<Map<String, String>> m) {
                            }
                        }, agentId);
            } catch (Exception e) {
                log.error("发送模板消息失败: " + e.getMessage());
                e.printStackTrace();
            }
    
            //图文消息
            try {
                weixinMessageService.send(WxTempConstant.TEMP_NEWS, touser, toparty, totag,
                        new MapInitializer<String, String>() {
                            @Override
                            public void init(Map<String, String> m) {
                            }
    
                            @Override
                            public void initListMap(List<Map<String, String>> m) {
                                Map<String, String> m1 = new HashMap<>();
                                m1.put("title", "中秋节礼品领取1");
                                m1.put("description", "今年中秋节公司有豪礼相送");
                                m1.put("url", "http://www.baidu.com");
                                m1.put("picurl", "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png");
                                m.add(m1);
    
                                Map<String, String> m2 = new HashMap<>();
                                m2.put("title", "中秋节礼品领取2");
                                m2.put("description", "今年中秋节公司有豪礼相送");
                                m2.put("url", "http://www.baidu.com");
                                m2.put("picurl", "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png");
                                m.add(m2);
                            }
                        }, agentId);
            } catch (Exception e) {
                log.error("发送模板消息失败: " + e.getMessage());
                e.printStackTrace();
            }
    
            //图文消息(mpnews)
            try {
                weixinMessageService.send(WxTempConstant.TEMP_MPNEWS, touser, toparty, totag,
                        new MapInitializer<String, String>() {
                            @Override
                            public void init(Map<String, String> m) {
                            }
    
                            @Override
                            public void initListMap(List<Map<String, String>> m) {
                                Map<String, String> m1 = new HashMap<>();
                                m1.put("title", "Title");
                                m1.put("thumb_media_id", "MEDIA_ID");
                                m1.put("author", "Author");
                                m1.put("content_source_url", "URL");
                                m1.put("content", "content");
                                m1.put("digest", "Digest description");
                                m.add(m1);
    
                                Map<String, String> m2 = new HashMap<>();
                                m2.put("title", "Title");
                                m2.put("thumb_media_id", "MEDIA_ID");
                                m2.put("author", "Author");
                                m2.put("content_source_url", "URL");
                                m2.put("content", "content");
                                m2.put("digest", "Digest description");
                                m.add(m2);
                            }
                        }, agentId);
            } catch (Exception e) {
                log.error("发送模板消息失败: " + e.getMessage());
                e.printStackTrace();
            }
    
            //markdown消息
            try {
                weixinMessageService.send(WxTempConstant.TEMP_MARKDOWN, touser, toparty, totag,
                        new MapInitializer<String, String>() {
                            @Override
                            public void init(Map<String, String> m) {
                                m.put("content", "markdown content");
                            }
    
                            @Override
                            public void initListMap(List<Map<String, String>> m) {
                            }
                        }, agentId);
            } catch (Exception e) {
                log.error("发送模板消息失败: " + e.getMessage());
                e.printStackTrace();
            }
    
            //小程序通知消息
            try {
                weixinMessageService.send(WxTempConstant.TEMP_MINIPROGEAM_NOTICE, touser, toparty, totag,
                        new MapInitializer<String, String>() {
                            @Override
                            public void init(Map<String, String> m) {
                                m.put("appid", "appid");
                                m.put("page", "pages/index?userid=zhangsan&orderid=123123123");
                                m.put("title", "会议室预订成功通知");
                                m.put("description", "appid");
                                m.put("emphasis_first_item", "true");
                            }
    
                            @Override
                            public void initListMap(List<Map<String, String>> m) {
                                Map<String, String> m1 = new HashMap<>();
                                m1.put("key", "会议室");
                                m1.put("value", "402");
                                m.add(m1);
    
                                Map<String, String> m2 = new HashMap<>();
                                m2.put("key", "会议室1");
                                m2.put("value", "403");
                                m.add(m2);
                            }
                        }, agentId);
            } catch (Exception e) {
                log.error("发送模板消息失败: " + e.getMessage());
                e.printStackTrace();
            }
    
            //任务卡片消息
            try {
                weixinMessageService.send(WxTempConstant.TEMP_TASK_CARD, touser, toparty, totag,
                        new MapInitializer<String, String>() {
                            @Override
                            public void init(Map<String, String> m) {
                                m.put("appid", "appid");
                                m.put("page", "pages/index?userid=zhangsan&orderid=123123123");
                                m.put("title", "会议室预订成功通知");
                                m.put("description", "appid");
                                m.put("emphasis_first_item", "true");
                            }
    
                            @Override
                            public void initListMap(List<Map<String, String>> m) {
                                Map<String, String> m1 = new HashMap<>();
                                m1.put("key", "会议室");
                                m1.put("value", "402");
                                m.add(m1);
    
                                Map<String, String> m2 = new HashMap<>();
                                m2.put("key", "会议室1");
                                m2.put("value", "403");
                                m.add(m2);
                            }
                        }, agentId);
            } catch (Exception e) {
                log.error("发送模板消息失败: " + e.getMessage());
                e.printStackTrace();
            }
    
        }
    }
    

    以上代码请根据自己的业务进行更改

    展开全文
  • 在我最近的视频系列《企业微信开发概述篇》(课程章节及链接请在文章最下方获取)有提到过微信和企业微信支持H5网页应用,是因为微信和企业微信内嵌定制浏览器; 今天顺便和大家分享下浏览器相关的知识;后面再...

    加我微信li570467731,拉你进二百多人企业微信开发同行群(文末有二维码)。

    企业微信开发三部曲:

    《企业微信应用开发概述篇(免费)》已完结;

    《企业微信开发第三方应用开发篇》更新中;

    《企业微信开发自建内部应用开发》筹备中;

    关注公众号“ToB Dev”获取最新教程(文末有二维码)。

     

           在我最近的视频系列《企业微信开发概述篇》(课程章节及链接请在文章最下方获取)有提到过微信和企业微信支持H5网页应用,是因为微信和企业微信内嵌定制浏览器;

            今天顺便和大家分享下浏览器相关的知识;后面再分享下微信及企业微信内嵌浏览器在各平台的浏览器信息及H5支持跑分数据;

            开发一个浏览器涉及的东西特别多,浏览器内核为重中之重,其中比较重要的两个是web渲染引擎及js引擎;

    目前全世界满打满算,只有四家有自己的 Web 引擎和 JavaScript 引擎的独立的浏览器厂商,其中三家是全球市值前十的 IT 巨头。而这四家的浏览器引擎的历史都可以追溯到十几年前。

    大多从已有的项目 fork 出来( KHTML -> WebKit -> Blink, Trident -> EdgeHTML)。

    谷歌 / Chrome / Blink内核 / V8

    苹果 / Safari / WebKit内核 / JavaScriptCore

    微软 / Edge / EdgeHTML内核 / ChakraMozilla 

    火狐Firefox / Gecko内核 / SpiderMonkey

    来源:知乎,作者:Thinker,链接:https://zhuanlan.zhihu.com/p/31763298

    其中谷歌的blink 是从webkit 派生而来,从webkit删除了很多东西和做了其它开发;

     

    微信/企业微信内嵌是什么内核浏览器,大家可以猜猜,看再往下看。

     

     

    根据腾讯浏览服务的介绍

     

     

    综合知乎“龙泉寺扫地僧”和腾讯浏览服务2020年的相关更新信息,微信使用的X5内核大概率是改的基于Blink内核的Chromium;

     

    了解到此结束,下面来看下微信/企业微信内嵌浏览器在各平台的浏览器信息及H5支持跑分数据。

    浏览器信息在线查询网址:http://mybrowse.osfipin.com

    H5在线跑分网址:http://html5test.com/

     

    我先给个我电脑上的分数mac浏览器信息及H5跑分分数,用来作参考。

     

     

     

    iPhone微信/企业微信的浏览器信息及H5跑分数据

    微信下

     企业微信下

    可以看到iPhone微信和企业微信内嵌浏览器基本一样,企业微信的user-agent多了wxwork的信息,企业微信内置的微信浏览器版本低了点(可能是我没更新)跑分少了点;

     

     

    Android微信/企业微信的浏览器信息及H5跑分数据

    微信

     

    企业微信

    Andoird微信与企业微信跑分都是477。再由上面手机端浏览器信息来看,微信与企业微信用的基本是同一个内嵌浏览器(毕竟都是属于微信...),下面电脑端就不再跑微信了只跑企业微信。

     

     

    Windows 企业微信的浏览器信息及H5跑分数据

     

     

    Mac下企业微信的浏览器信息及H5跑分数据

     

    总的来看:

    1,基本都是WebKit内核,验证了上面说的基本WebKit(或者Blink,Blink目前好也显示为WebKit),而且根据H5跑分微信、企业微信内嵌浏览器H5支持排名:Windows微信>Android微信>Mac Chrome>iOS微信>Mac微信,Windows与Android微信的内嵌浏览器对H5支持强过电脑...iOS与Mac下的微信内嵌浏览器稍差点但不多。从这样来看,微信、企业微信支持H5网页应用是完全胜任的(想想15年哪会微信内嵌浏览器对网页应用的支持特别差,网上基本都是骂的...)。

     

    2,微信和企业微信在同一手机或者电脑下内嵌浏览器和分数基本一样,基本是同一款企业微信增加在user-agent里加了wxwork信息,在做公众号和企业微信网页应用开发时可以用于判断环境。

     

     

    加我微信,拉你进200+企业微信开发同行群

    关注公众号"ToB Dev",获取更多企业微信发教程

    展开全文
  • 微信 企业微信开发服务端调用集合
  • 企业微信开发是什么? 简单的说,就是我们自己项目的接口,和企业微信的接口之间的互相调用。 具体而言,就是可以把在企业微信后台做的事情,搬到自己的项目中完成,举个例子:我们可以在企业微信后台对成员进行增...

    企业微信开发是什么?

        简单的说,就是我们自己项目的接口,和企业微信的接口之间的互相调用。

        具体而言,就是可以把在企业微信后台做的事情,搬到自己的项目中完成,举个例子:我们可以在企业微信后台对成员进行增删改查的操作,当我们把企业微信接入自己的项目中时,我们可以调用企业微信的接口在自己的项目中完成这项工作,这就使得我不要再进入企业微信的后台。

     什么时候需要接入?

    所谓接入,其实就是让企业微信知道我设定的接口是有用的,并不是在什么时候都需要接入,比如上述的增删改查操作,其实只要按照企业微信接口的规则,调用即可。话说回来,那么为什么需要接入微信后台呢,因为后台需要调用你的接口,比如,在企业微信后台删除一个人,其实他是会向你的项目发送一个请求的(需要配置),接入有种提前测试你的接口的作用。

    其实开源的api基本都是这个套路。

    展开全文
  • 1) 登录企业微信 2)在应用管理下方的自建应用中,找到你要推送消息的应用信息 3) 如下图所示 企业ID(CORPID) 1) 点击“我的企业” 2) 在企业信息中,最下方有个企业ID,如下图所示 待推送的企业微信...

    准备事项

    1. 企业应用ID(AGENTID)和密钥(SECRET)
      1) 登录企业微信
      2)在应用管理下方的自建应用中,找到你要推送消息的应用信息,如下图所示
      在这里插入图片描述

    2. 企业ID(CORPID)
      1) 点击“我的企业”
      2) 在企业信息中,最下方有个企业ID,如下图所示
      在这里插入图片描述

    3. 待推送的企业微信用户ID(wechatId)
      1)通讯录中,找到成员信息,点击查看详情
      2)此处的账号信息,就是企业微信ID,如下图所示
      在这里插入图片描述

    测试步骤

    1. 进入企业微信接口调试工具网址

    2. 点击建立连接,输入corpid(企业ID)和corpsecret(此处是应用的密钥,每个应用密钥不同,一定要注意

    3. 点击调用接口,获取相应的access_token信息,如下图所示(access_token信息无需复制,只要依然停留在接口调试页面,进入其他功能时,access_token信息会自动带入
      在这里插入图片描述

    4. 点击发送消息-发送应用消息
      在这里插入图片描述
      注意事项:
      1、tourser:用上文中查到的用户企业微信ID,多个ID之间用“|”分割
      2、msgtype:应用消息中支持多种消息类型,此处记得要修改,消息类型可以在 企业微信API中查询
      3、agentid:就是你想要推送消息的应用ID

    5. 修改body中的数据后,点击调用接口按钮,就可以在企业微信中,查看相关应用的推送消息
      在这里插入图片描述

    6. 在企业微信APP中查看推送的消息
      在这里插入图片描述

    注意事项:如果调试的时候不成功,可以在企业微信错误码查询工具中查看错误码的含义

    展开全文
  • 企业微信开发踩坑

    2020-10-09 15:41:42
    企业微信开发,调用jsapl在开发者工具上一直报错 在手机上没有问题,建议如果要使用微信jsapl,不要在微信开发者工具上调试,直接在手机上调试.
  • 使用工具类 ... ...-- 企业微信工具集 https://mvnrepository.com/artifact/com.github.binarywang/wx-java --> <dependency> <groupId>com.github.binarywang</groupId>...
  • 企业微信api,企业微信sdk接口 1、企业微信SDK接口API调用-企业微信好友收发消息 /** * 给企业微信好友发消息 * @author wechat:happybabby110 * @blog http://www.wlkankan.cn */ @Async public void ...
  • 企业微信开发建议2

    千次阅读 2017-07-11 10:53:48
    几天前我们发过一篇“企业微信开发建议”,说的是企业微信遇到的坑。 今天,继续这一话题。 经测试,微信企业号升级到企业微信是有坑的。不建议升级!!!不建议升级!!!不建议升级!!! ...
  • 通过官方文档,对企业微信开发的一些重要参数进行理解以及一些基本api进行分析。 二、常用api整理和代码 2.1获取Token /** * 获取 access_token * @param corpid * @param corpsecret * @return access_token *...
  • 手把手教你springboot企业微信开发(二)1、企业微信开发第一步2、weixin-java-cp-demo-master1)、引入thymeleaf改造项目2)增加Configuration3)回到企业号4)穿透内外网5)完善 从这一篇开始,开始从实际项目探索...
  • 企业微信开发总结-获取通讯录

    千次阅读 2020-08-17 11:02:08
    企业微信开发总结-获取通讯录 最近遇到个项目需求,需要能够获取到用户企业的通讯录,同步到我们系统中,这样就不用重复输入一批企业人员了。一开始想的很简单,实际研究下来发现企业微信比个人微信对接起来复杂多了...
  • 总结了开发企业微信过程中遇到的各种问题及解决办法,有效的提升开发能力
  • 企业微信开发02-企业微信消息发送

    千次阅读 2019-06-12 10:00:02
    目前公司需要在培训管理系统中向企业微信发送通知。通知类型为文本。 现在的项目是maven管理的多模块形式,所以考虑新增一个模块,在模块中对外提供公共方法,调用企业微信weixin-java-cp中提供的方法实现消息发送。...
  • 接入验证的 微信加解密包此包封装了对 msg_signature对请求进行校验的相关操作,直接用就可以了二、接收消息服务器配置2.1 接收消息服务器参数配置:在企业微信的管理端后台,进入需要设置接收消息的目标应用,点击...
  • 企业微信开发(1)——接入企业微信

    千次阅读 2018-04-21 15:32:10
    首先得注册个企业微信 其次下载一个加解密的包,免得自己封装 https://work.weixin.qq.com/api/doc#10128/java%E5%BA%93 具体使用方法:下载解压后,将com文件夹拷贝到src下,然后将lib下的jar包拷贝到咱们web...
  • 以前写过一篇公众号的授权登录...网页授权及JS-SDK需要在企业微信上配置可信域名2.企业微信授权登录里面填写你的可信域名调用流程为:A) 用户访问第三方服务,第三方服务通过构造OAuth2链接(参数包括当前第三方服...
  • 个人感觉企业微信开发要比微信开发更简单一些 正文   企业微信开发有三个比较比较重要的东西,也是最经常用到的!!     1)corpid:每个企业都拥有唯一的corpid     2)agentid:每个应用都有唯一的...
  • PS. 企业微信开发,非企业微信号 此问题可能是因为企业微信 API Bug 造成。 若有遇到。可重置应用的 secret key,用新的 secret key 试一下。 我就是这样解决的! ...
  • 获取 code 请看:企业微信开发:网页授权登录    2.获取 access_token 请看:企业微信开发:获取 access_token 根据已经获取的 access_token 和 code 换成员信息   请求方式: GET(HTTPS)   请求地址
  • 企业微信开发应用 添加应用流程 记得给应用配置可信域名(供OAuth鉴权),主页地址url必须在该域名之下才能访问 记得公司给了我个域名,写了上去但是进入应用主页却显示redirect_uri需使用应用可信域名,原因是要...
  • 1、基于企业微信第三方应用开发API文档,做了一个企业微信开发说明文档,总结踩的坑以及对文档的一个补充。 2、本文主要针对第三方应用开发,方便第三方服务商的云应用上架企业微信应用市场 3、实现目标:服务商预先...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,528
精华内容 3,411
关键字:

企业微信开发