微信公众号_微信公众号-- 微信分享功能唤起微信 - CSDN
微信公众号 订阅
微信公众号是开发者或商家在微信公众平台上申请的应用账号,该帐号与QQ账号互通,通过公众号,商家可在微信平台上实现和特定群体的文字、图片、语音、视频的全方位沟通、互动 。形成了一种主流的线上线下微信互动营销方式。2016年1月18日,腾讯在北京发布消息称,中国政务微信公号已逾10万。2018年4月,腾讯已查处9.9万多个违规公众号 [1]  。11月16日,微信公众平台发布公告称,个人注册公众号数量上限调整为1个 [2]  。2019年12月26日,微信公众号文章无法打开,点击文章链接后显示空白。随后,微信团队道歉,公众号后台大部分功能已经修复。 [3-4] 展开全文
微信公众号是开发者或商家在微信公众平台上申请的应用账号,该帐号与QQ账号互通,通过公众号,商家可在微信平台上实现和特定群体的文字、图片、语音、视频的全方位沟通、互动 。形成了一种主流的线上线下微信互动营销方式。2016年1月18日,腾讯在北京发布消息称,中国政务微信公号已逾10万。2018年4月,腾讯已查处9.9万多个违规公众号 [1]  。11月16日,微信公众平台发布公告称,个人注册公众号数量上限调整为1个 [2]  。2019年12月26日,微信公众号文章无法打开,点击文章链接后显示空白。随后,微信团队道歉,公众号后台大部分功能已经修复。 [3-4]
信息
外文名
Wechat Official Account
类    型
开放应用平台
分    类
订阅号和服务号
中文名
微信公众号
认证收费
服务号、订阅号认证均需300元/年
隶属企业
腾讯公司
微信公众号发展历程
2018年6月27日,微信官方宣布,微信公众平台上线开放转载功能,文章可以直接被转载,不需要人工再次确认。 [5]  2018年11月16日,微信公众平台发布公告称,即日起,公众号注册将做调整:个人主体注册公众号数量上限由2个调整为1个;企业类主体注册公众号数量上限由5个调整为2个。 [2]  2018年12月29日,微信公众平台运营功能再次升级,修改已发送文章的错别字上限由5个上调至10个,同时支持增、删和替换,但标题和摘要依然无法修改,修改机会依然有且仅有一次。 [6]  2019年8月,滴滴出行宣布,与万达酒店及度假村达成战略合作。用户可在万达酒店微信公众号内使用滴滴叫车。 [7]  2020年6月29日,微信公众号增加两项新功能,在文章底部新增了“分享”和“赞”。其中,用户点击“分享”可“分享到朋友圈”或“发送给朋友”。这两项新功能已陆续全量开放。 [8] 
收起全文
  • 课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决...
  • 微信公众号+小程序开发》是结合了部分《微信开发深度解析》内容录制的系列课程,独立于书本,包含了更多的操作演示和案例演示。 课程内容分为两大部分: 第一部分:微信公众号及小程序开发基础技能 第二部分:...
  • 通过热门框架spring boot来学习微信公众号开发,帮助同学们快速入门微信公众号开发。
  • 看完昨天的文章「开发微信公众号(一)」 估计不少人已经开始期待我继续更新了,这不赶紧马不停蹄,加班加点给你们更新了第二篇。现在的你已经有了一个属于自己的微信公众号,那么你想如果按照微信公众号的自动回复...


                            


    看完昨天的文章「开发微信公众号(一)」 估计不少人已经开始期待我继续更新了,这不赶紧马不停蹄,加班加点给你们更新了第二篇。


    现在的你已经有了一个属于自己的微信公众号,那么你想如果按照微信公众号的自动回复,来实现用户发送电影名就可以获得想要的电影链接,那是得设置多少的呀,这显然是不可能的,那么我们就要用到服务器来帮我们实现了的,腾讯,阿里云的都可以,当然如果你是学生那么就可以享有购买服务器时的福利了的,有10元/月支持学生购买服务器的,个人感觉还是蛮划算的。那么问题又来了,不是学生党购买似乎会觉得有点贵,这里我直接给大家一个福利,关注我的微信公众号,回复「令牌」,不知道令牌是什么?没关系,先接着往下看的!我直接把我的令牌给大家用,直到服务器崩掉,先到先得,崩了之后我再修改令牌! 但是你如果想做好一个项目的有收益的话,肯定是要付出的,就像你加入张哥的星球也是通过付费获得知识,这是同样的一个道理,就算之后可能会失败,没有收益,但是你收获到了技术上的知识,我想这也是不错的! 


    购买服务器(我以腾讯服务器作为例子)


    1、百度搜索「腾讯云」,学生党百度搜索「腾讯云校园服务」进入腾讯云网站首页


                        


    2、点击--产品--计算--云服务器


                                


    3、进入云服务器选购界面点击--立即购买,如果没有登录的话需要登录,自己的QQ号就可以;


                                


    5、选择需要的配置,提交订单支付即可

    一定要选择选择 Ubuntn Serve !

    一定要选择选择 Ubuntn   Serve !

    一定要选择选择 Ubuntn   Serve !


                            


    重要的事情说三遍,使用 Ubuntn 会比 window 方便太多了的,而且我也是用的Ubuntn,不怎么清楚其他的服务器,如果不知道用没关系,我会详细描述好操作的,而且作为一位优秀的程序员,你迟早的接触到 Linux ,没有图形界面的,这个时候了解一下,绝对是没有坏处的,只会让你变的更优秀!


    接口微信公众号如果你有了自己的服务器之后呢,你需要你的服务器与微信之间产生联系的,这里我们需要用到别人已经开发好的微信公众号开发框架  WeRoBot 建议看到这里了,去百度一下 WeRoBot 官方文档了解,否则可能会有点不知道什么意思!如果现在的你还处于迷茫的状态,也请硬着头皮操作下去,登录进入你的服务器, 现在我们先直接部署好,让你看到效果再解释原因的,看到现在的不懂 Ubuntn 下的 Vim 操作,可以现在就学下的,简单的基本操作,现在请执行好以下命令:


    vim rebot.py     //创建一个rebot.py 

    键盘按下 i      //切换到 vim 的输入模式   复制以下代码   


    import werobot

    robot = werobot.WeRoBot(token='tokenhere') 

    // tokenhere 这里自己可以随便填写的,比如 token = 'aaa'


    @robot.handler

    def hello(message):

        return 'Hello World!'


    # 让服务器监听在 0.0.0.0:80


    robot.config['HOST'] = '0.0.0.0'

    robot.config['PORT'] = 80

    robot.run()


    按下 Esc    然后按下  Shift + :      

      

    //切换到 Vim 下的命令模式 


    输入 wq                     

                     

    //保存并退出


    sudo python3 rebot.py       

       

    //运行程序rebot 接下来不用动了的,按下 Ctr + C 可以取消,但是现在不要动


                            


                           


    回到微信公众号的后台了,基本配置里面,将你的服务器IP 与令牌(token)

    就是你之前代码里写的那个 token ,填入微信公众号后台,消息加密,点随机生成,明文模式,点击启用,OK 到这里应该就是部署好了的,发送消息,微信就会自动回复hello world 是不是特别的激动,没错到了这里就说明接口配置已经成功完成好了的!甚至你还可以回复图文消息,将代码改成这样!相信某些聪明的人大概已经知道实现原理是什么了吧!


    import werobot

    robot = werobot.WeRoBot(token='tokenhere')

    @robot.text

    def articles(message):

        return [

            [

                "title",

                "description",

                "img",

                "url"

            ],

            [

                "whtsky",

                "I wrote WeRoBot",

                "https://secure.gravatar.com/avatar/0024710771815ef9b74881ab21ba4173?s=420",

                "http://whouz.com/"

            ]

        ]

    robot.run()





    这些代码在 Werobot 都可以看得到,所以要多看文档的,如果已经配置成功了的,可以留言扣个1 ,如果存在疑惑,不懂,请多看微信的官方文档以及 Werobot 的官方文档,多看官方文档是最好的学习方法,或者直接私聊我!!

    有人说:我把服务器退出了就实现不了呀,那么 Linux 的强大就体现出来了


    sudo nohup python3 rebot.py &


    一条命令,这样退出服务器,后台也是可以运行的!

    最后,你需要学什么:Vim 的基本操作,Ubuntn 的基本操作,以及 Werobot!终于完成好了服务器接口微信公众号后台了的,下次将会介绍如何建立好自己的数据库!




    推荐阅读:  开发微信公众号(一)



    PS:如果觉得文章还不错的话,还请大家点赞分享下。算是对「fightjiang」最大的支持!



           每 天 分 享 Python 干 货

         

    展开全文
  • 微信公众号使用教程

    2018-11-27 16:29:08
    微信公众号使用,是一套基础课程,为后面的《PHP微信公众号开发》做铺垫。微信几乎是智能手机上必装的软件,很多的商家在微信上开通公众号,想要把公众号的价值发挥大,必须学会公众号的使用,开发和营销。这一套...
  • 微信JS-SDK签名算法

    2020-01-16 10:07:16
    <?php namespace Common\Model; use Think\Model; class JsSdkModel extends Model { private $appId = '***'; private $appSecret = '***'; /** * JS-SDK使用权限签名算法 * access_token是公众号的...
    <?php
    namespace Common\Model;
    use Think\Model;
    
    class JsSdkModel extends Model {
        private $appId = '***';
        private $appSecret = '***';
    
        /**
         * JS-SDK使用权限签名算法
         * access_token是公众号的全局唯一接口调用凭据
         * jsapi_ticket是公众号用于调用微信JS接口的临时票据
         * @return array
         */
        public function getSignPackage() {
            $jsApiTicket = $this->getJsApiTicket();
    
            // 注意 URL 一定要动态获取,不能 hardcode.
            $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
            $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
    
            $timestamp = time();
            $nonceStr = $this->createNonceStr();
            // 这里参数的顺序要按照 key 值 ASCII 码升序排序
            $string = "jsapi_ticket=$jsApiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
            $signature = sha1($string);
            $signPackage = [
                "appId"     => $this->appId,
                "nonceStr"  => $nonceStr,
                "timestamp" => $timestamp,
                "url"       => $url,
                "signature" => $signature,
                "rawString" => $string
            ];
            return $signPackage;
        }
    
        /**
         * 随机字符串
         * @param $length int
         * @return string
         */
        private function createNonceStr($length = 16) {
            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            $str = "";
            for ($i = 0; $i < $length; $i++) {
                $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
            }
            return $str;
        }
    
        /**
         * 根据 access_token 获取 jsapi_ticket
         * @return string
         */
        private function getJsApiTicket() {
            // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
            $data = json_decode(file_get_contents("jsapi_ticket.json"));
            if ($data->expire_time < time()) {
                $accessToken = $this->getAccessToken();
                // 如果是企业号用以下 URL 获取 ticket
                // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
                $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
                $res = json_decode($this->httpGet($url));
                $ticket = $res->ticket;
                if ($ticket) {
                    $data->expire_time = time() + 7000;
                    $data->jsapi_ticket = $ticket;
                    $fp = fopen("jsapi_ticket.json", "w");
                    fwrite($fp, json_encode($data));
                    fclose($fp);
                }
            } else {
                $ticket = $data->jsapi_ticket;
            }
            return $ticket;
        }
    
        /**
         * 获取 access_token
         * @return string
         */
        private function getAccessToken() {
            // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
            $data = json_decode(file_get_contents("access_token.json"));
            if ($data->expire_time < time()) {
                // 如果是企业号用以下URL获取access_token
                // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
                $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";
                $res = json_decode($this->httpGet($url),true);
                $access_token = $res['access_token'];
                if ($access_token) {
                    $data->expire_time = time() + 7000;
                    $data->access_token = $access_token;
                    $fp = fopen("access_token.json", "w");
                    fwrite($fp, json_encode($data));
                    fclose($fp);
                }
            } else {
                $access_token = $data->access_token;
            }
            return $access_token;
        }
    
        /**
         * curl Get请求
         * @param  $url
         * @return mixed
         */
        private function httpGet($url) {
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curl, CURLOPT_TIMEOUT, 500);
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($curl, CURLOPT_URL, $url);
            $res = curl_exec($curl);
            curl_close($curl);
            return $res;
        }
    }
    
    展开全文
  • 一、前言微信接口调用验证最终需要用到的三个参数noncestr、timestamp、signature:接下来将会给出获取这三个参数的详细代码 本文的环境eclipse + maven 本文使用到的技术HttpClient、Json字符串转map、sha1加密二...

    一、前言

    微信接口调用验证最终需要用到的三个参数noncestr、timestamp、signature:

    这里写图片描述

    接下来将会给出获取这三个参数的详细代码
    本文的环境eclipse + maven
    本文使用到的技术HttpClient、Json字符串转map、sha1加密

    二、需要用到的jar包

    maven依赖的包有:

    1、HttpClient包依赖

    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpcore</artifactId>
      <version>4.4.3</version>
    </dependency>
    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <version>4.5.1</version>
    </dependency>

    2、json转map相关包依赖

    <dependency>    
        <groupId>net.sf.json-lib</groupId>   
        <artifactId>json-lib</artifactId>    
        <version>2.4</version>  
        <classifier>jdk15</classifier>  
    </dependency>
    <dependency>
        <groupId>xom</groupId>
        <artifactId>xom</artifactId>
        <version>1.2.5</version>
    </dependency>

    三、运行结果

    这里写图片描述

    四、详细代码

    package com.luo.util;
    
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.UUID;
    import net.sf.json.JSONObject;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.NameValuePair;
    import org.apache.http.ParseException;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.client.methods.HttpUriRequest;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.protocol.HTTP;
    import org.apache.http.util.EntityUtils;
    
    public class HttpXmlClient {
    
        public static String post(String url, Map<String, String> params) {
            DefaultHttpClient httpclient = new DefaultHttpClient();
            String body = null;
            HttpPost post = postForm(url, params);
            body = invoke(httpclient, post);
            httpclient.getConnectionManager().shutdown();
            return body;
        }
    
        public static String get(String url) {
            DefaultHttpClient httpclient = new DefaultHttpClient();
            String body = null;
            HttpGet get = new HttpGet(url);
            body = invoke(httpclient, get);
            httpclient.getConnectionManager().shutdown();
            return body;
        }
    
        private static String invoke(DefaultHttpClient httpclient,
                HttpUriRequest httpost) {
            HttpResponse response = sendRequest(httpclient, httpost);
            String body = paseResponse(response);
            return body;
        }
    
        private static String paseResponse(HttpResponse response) {
            HttpEntity entity = response.getEntity();
            String charset = EntityUtils.getContentCharSet(entity);
            String body = null;
            try {
                body = EntityUtils.toString(entity);
            } catch (ParseException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return body;
        }
    
        private static HttpResponse sendRequest(DefaultHttpClient httpclient,
                HttpUriRequest httpost) {
            HttpResponse response = null;
            try {
                response = httpclient.execute(httpost);
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return response;
        }
    
        private static HttpPost postForm(String url, Map<String, String> params) {
    
            HttpPost httpost = new HttpPost(url);
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
    
            Set<String> keySet = params.keySet();
            for (String key : keySet) {
                nvps.add(new BasicNameValuePair(key, params.get(key)));
            }
    
            try {
                httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
    
            return httpost;
        }
    
        public static void main(String[] args) {
            //获取access_token
            Map<String, String> params = new HashMap<String, String>();
            params.put("corpid","wx5f24fa0db1819ea2");
            params.put("corpsecret","uQtWzF0bQtl2KRHX0amekjpq8L0aO96LSpSNfctOBLRbuYPO4DUBhMn0_v2jHS-9");
            String xml = HttpXmlClient.post("https://qyapi.weixin.qq.com/cgi-bin/gettoken",params);
            JSONObject jsonMap  = JSONObject.fromObject(xml);
            Map<String, String> map = new HashMap<String, String>();
            Iterator<String> it = jsonMap.keys();  
            while(it.hasNext()) {  
                String key = (String) it.next();  
                String u = jsonMap.get(key).toString();
                map.put(key, u);  
            }
            String access_token = map.get("access_token");
            System.out.println("access_token=" + access_token);
    
            //获取ticket
            params.put("access_token",access_token);
            xml = HttpXmlClient.post("https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket",params); 
            jsonMap  = JSONObject.fromObject(xml);
            map = new HashMap<String, String>();
            it = jsonMap.keys();  
            while(it.hasNext()) {  
                String key = (String) it.next();  
                String u = jsonMap.get(key).toString();
                map.put(key, u);  
            }
            String jsapi_ticket = map.get("ticket");
            System.out.println("jsapi_ticket=" + jsapi_ticket);
    
            //获取签名signature
            String noncestr = UUID.randomUUID().toString();
            String timestamp = Long.toString(System.currentTimeMillis() / 1000);
            String url="http://mp.weixin.qq.com";
            String str = "jsapi_ticket=" + jsapi_ticket +
                    "&noncestr=" + noncestr +
                    "&timestamp=" + timestamp +
                    "&url=" + url;
            //sha1加密
            String signature = SHA1(str);
            System.out.println("noncestr=" + noncestr);
            System.out.println("timestamp=" + timestamp);
            System.out.println("signature=" + signature);
            //最终获得调用微信js接口验证需要的三个参数noncestr、timestamp、signature
        }
    
           /** 
         * @author:罗国辉 
         * @date: 2015年12月17日 上午9:24:43 
         * @description: SHA、SHA1加密
         * @parameter:   str:待加密字符串
         * @return:  加密串
        **/
        public static String SHA1(String str) {
            try {
                MessageDigest digest = java.security.MessageDigest
                        .getInstance("SHA-1"); //如果是SHA加密只需要将"SHA-1"改成"SHA"即可
                digest.update(str.getBytes());
                byte messageDigest[] = digest.digest();
                // Create Hex String
                StringBuffer hexStr = new StringBuffer();
                // 字节数组转换为 十六进制 数
                for (int i = 0; i < messageDigest.length; i++) {
                    String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                    if (shaHex.length() < 2) {
                        hexStr.append(0);
                    }
                    hexStr.append(shaHex);
                }
                return hexStr.toString();
    
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    

    五、工程下载

    http://download.csdn.net/detail/u013142781/9382839

    展开全文
  • 引用:access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复...

    转自:http://www.cuiyongzhi.com/post/44.html

    (一)token的介绍

    引用:access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效!

    (二)token的获取参考文档

    获取的流程我们完全可以参考微信官方文档:http://mp.weixin.qq.com/wiki/14/9f9c82c1af308e3b14ba9b973f99a8ba.html 如图:

    1.png

    (三)token获取流程分析

    • 从公众平台获取账号的AppID和AppSecret;

    • token获取并解析存储执行体;

    • 采用任务调度每隔两小时执行一次token获取执行体;

    (四)token的获取流程的具体实现

    ①获取appid和appsecret

    在微信公众平台【开发】——>【基本配置】中可以查看到我们需要的两个参数:

    2.png

    这里我们将他们定义到我们的配置文件【wechat.properties】中,大致代码为:

    1
    2
    3
    4
    #获取到的appid
    appid=wx7e32765bc24XXXX 
    #获取到的AppSecret
    AppSecret=d58051564fe9d86093f9XXXXX

    ②token获取并解析存储执行体的代码编写

    由于在这里我们需要通过http的get请求向微信服务器获取时效性为7200秒的token,所以我在这里写了一个http请求的工具类,以方便我们的使用,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    package com.cuiyongzhi.wechat.util;
     
    import java.io.BufferedInputStream;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.MalformedURLException;
    import java.net.URI;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.zip.GZIPInputStream;
     
    import org.apache.http.HttpResponse;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.protocol.HTTP;
    import org.apache.http.util.EntityUtils;
     
    /**
     * ClassName: HttpUtils
     
     * @Description: http请求工具类
     * @author dapengniao
     * @date 2016年3月10日 下午3:57:14
     */
    @SuppressWarnings("deprecation")
    public class HttpUtils {
     
        /**
         * @Description: http get请求共用方法
         * @param @param reqUrl
         * @param @param params
         * @param @return
         * @param @throws Exception
         * @author dapengniao
         * @date 2016年3月10日 下午3:57:39
         */
        @SuppressWarnings("resource")
        public static String sendGet(String reqUrl, Map<String, String> params)
                throws Exception {
            InputStream inputStream = null;
            HttpGet request = new HttpGet();
            try {
                String url = buildUrl(reqUrl, params);
                HttpClient client = new DefaultHttpClient();
     
                request.setHeader("Accept-Encoding""gzip");
                request.setURI(new URI(url));
     
                HttpResponse response = client.execute(request);
     
                inputStream = response.getEntity().getContent();
                String result = getJsonStringFromGZIP(inputStream);
                return result;
            finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                request.releaseConnection();
            }
     
        }
     
        /**
         * @Description: http post请求共用方法
         * @param @param reqUrl
         * @param @param params
         * @param @return
         * @param @throws Exception
         * @author dapengniao
         * @date 2016年3月10日 下午3:57:53
         */
        @SuppressWarnings("resource")
        public static String sendPost(String reqUrl, Map<String, String> params)
                throws Exception {
            try {
                Set<String> set = params.keySet();
                List<NameValuePair> list = new ArrayList<NameValuePair>();
                for (String key : set) {
                    list.add(new BasicNameValuePair(key, params.get(key)));
                }
                if (list.size() > 0) {
                    try {
                        HttpClient client = new DefaultHttpClient();
                        HttpPost request = new HttpPost(reqUrl);
     
                        request.setHeader("Accept-Encoding""gzip");
                        request.setEntity(new UrlEncodedFormEntity(list, HTTP.UTF_8));
     
                        HttpResponse response = client.execute(request);
     
                        InputStream inputStream = response.getEntity().getContent();
                        try {
                            String result = getJsonStringFromGZIP(inputStream);
     
                            return result;
                        finally {
                            inputStream.close();
                        }
                    catch (Exception ex) {
                        ex.printStackTrace();
                        throw new Exception("网络连接失败,请连接网络后再试");
                    }
                else {
                    throw new Exception("参数不全,请稍后重试");
                }
            catch (Exception ex) {
                ex.printStackTrace();
                throw new Exception("发送未知异常");
            }
        }
     
        /**
         * @Description: http post请求json数据
         * @param @param urls
         * @param @param params
         * @param @return
         * @param @throws ClientProtocolException
         * @param @throws IOException
         * @author dapengniao
         * @date 2016年3月10日 下午3:58:15
         */
        public static String sendPostBuffer(String urls, String params)
                throws ClientProtocolException, IOException {
            HttpPost request = new HttpPost(urls);
     
            StringEntity se = new StringEntity(params, HTTP.UTF_8);
            request.setEntity(se);
            // 发送请求
            @SuppressWarnings("resource")
            HttpResponse httpResponse = new DefaultHttpClient().execute(request);
            // 得到应答的字符串,这也是一个 JSON 格式保存的数据
            String retSrc = EntityUtils.toString(httpResponse.getEntity());
            request.releaseConnection();
            return retSrc;
     
        }
     
        /**
         * @Description: http请求发送xml内容
         * @param @param urlStr
         * @param @param xmlInfo
         * @param @return
         * @author dapengniao
         * @date 2016年3月10日 下午3:58:32
         */
        public static String sendXmlPost(String urlStr, String xmlInfo) {
            // xmlInfo xml具体字符串
     
            try {
                URL url = new URL(urlStr);
                URLConnection con = url.openConnection();
                con.setDoOutput(true);
                con.setRequestProperty("Pragma:""no-cache");
                con.setRequestProperty("Cache-Control""no-cache");
                con.setRequestProperty("Content-Type""text/xml");
                OutputStreamWriter out = new OutputStreamWriter(
                        con.getOutputStream());
                out.write(new String(xmlInfo.getBytes("utf-8")));
                out.flush();
                out.close();
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        con.getInputStream()));
                String lines = "";
                for (String line = br.readLine(); line != null; line = br
                        .readLine()) {
                    lines = lines + line;
                }
                return lines; // 返回请求结果
            catch (MalformedURLException e) {
                e.printStackTrace();
            catch (IOException e) {
                e.printStackTrace();
            }
            return "fail";
        }
     
        private static String getJsonStringFromGZIP(InputStream is) {
            String jsonString = null;
            try {
                BufferedInputStream bis = new BufferedInputStream(is);
                bis.mark(2);
                // 取前两个字节
                byte[] header = new byte[2];
                int result = bis.read(header);
                // reset输入流到开始位置
                bis.reset();
                // 判断是否是GZIP格式
                int headerData = getShort(header);
                // Gzip 流 的前两个字节是 0x1f8b
                if (result != -1 && headerData == 0x1f8b) {
                    // LogUtil.i("HttpTask", " use GZIPInputStream  ");
                    is = new GZIPInputStream(bis);
                else {
                    // LogUtil.d("HttpTask", " not use GZIPInputStream");
                    is = bis;
                }
                InputStreamReader reader = new InputStreamReader(is, "utf-8");
                char[] data = new char[100];
                int readSize;
                StringBuffer sb = new StringBuffer();
                while ((readSize = reader.read(data)) > 0) {
                    sb.append(data, 0, readSize);
                }
                jsonString = sb.toString();
                bis.close();
                reader.close();
            catch (Exception e) {
                e.printStackTrace();
            }
     
            return jsonString;
        }
     
        private static int getShort(byte[] data) {
            return (data[0] << 8) | data[1] & 0xFF;
        }
     
        /**
         * 构建get方式的url
         
         * @param reqUrl
         *            基础的url地址
         * @param params
         *            查询参数
         * @return 构建好的url
         */
        public static String buildUrl(String reqUrl, Map<String, String> params) {
            StringBuilder query = new StringBuilder();
            Set<String> set = params.keySet();
            for (String key : set) {
                query.append(String.format("%s=%s&", key, params.get(key)));
            }
            return reqUrl + "?" + query.toString();
        }
     
    }

    我们在做http请求的时候需要目标服务器的url,这里在项目中为了方便对url的管理我们在资源目录下建立了interface_url.properties用于存放目标url,这里我们将请求token的url存入:

    1
    2
    #获取token的url

    我们需要将我们配置的配置文件在项目初始化后能得到启动,所以我在这里加入一个项目初始化的代码实现,用于项目启动初始化interface_url.properties和wechat.properties中的配置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package com.cuiyongzhi.web.start;
     
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
     
    /**
     * ClassName: InterfaceUrlIntiServlet
     * @Description: 项目启动初始化servlet
     * @author dapengniao
     * @date 2016年3月10日 下午4:08:43
     */
    public class InterfaceUrlIntiServlet extends HttpServlet {
     
        private static final long serialVersionUID = 1L;
     
        @Override
        public void init(ServletConfig config) throws ServletException {
            InterfaceUrlInti.init();
        }
     
    }

    初始化的具体实现,将初始化过后的方法都存入到GlobalConstants中方便项目中随意调用,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    package com.cuiyongzhi.web.start;
     
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
     
    import com.cuiyongzhi.web.util.GlobalConstants;
     
    /**
     * ClassName: InterfaceUrlInti
     * @Description: 项目启动初始化方法
     * @author dapengniao
     * @date 2016年3月10日 下午4:08:21
     */
    public class InterfaceUrlInti {
     
        public synchronized static void init(){
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            Properties props = new Properties();
            if(GlobalConstants.interfaceUrlProperties==null){
                GlobalConstants.interfaceUrlProperties = new Properties();
            }
            InputStream in = null;
            try {
                in = cl.getResourceAsStream("interface_url.properties");
                props.load(in);
                for(Object key : props.keySet()){
                    GlobalConstants.interfaceUrlProperties.put(key, props.get(key));
                }
                 
                props = new Properties();
                in = cl.getResourceAsStream("wechat.properties");
                props.load(in);
                for(Object key : props.keySet()){
                    GlobalConstants.interfaceUrlProperties.put(key, props.get(key));
                }
                 
            catch (IOException e) {
                e.printStackTrace();
            }finally{
                if(in!=null){
                    try {
                        in.close();
                    catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return;
        }
     
    }

    当我们把所有的准备工作都做好了之后我们可以开始真正的去获取token了,这里我们将获取到的token解析之后依然存储到GlobalConstants中方便使用,简单代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    package com.cuiyongzhi.wechat.common;
     
    import java.util.HashMap;
    import java.util.Map;
     
    import net.sf.json.JSONObject;
     
    import com.cuiyongzhi.web.util.GlobalConstants;
    import com.cuiyongzhi.wechat.util.HttpUtils;
     
    /**
     * ClassName: WeChatTask
     * @Description: 微信两小时定时任务体
     * @author dapengniao
     * @date 2016年3月10日 下午1:42:29
     */
    public class WeChatTask {
        /**
         * @Description: 任务执行体
         * @param @throws Exception
         * @author dapengniao
         * @date 2016年3月10日 下午2:04:37
         */
        public void getToken_getTicket() throws Exception {
            Map<String, String> params = new HashMap<String, String>();
            params.put("grant_type""client_credential");
            params.put("appid", GlobalConstants.getInterfaceUrl("appid"));
            params.put("secret", GlobalConstants.getInterfaceUrl("AppSecret"));
            String jstoken = HttpUtils.sendGet(
                    GlobalConstants.getInterfaceUrl("tokenUrl"), params);
            String access_token = JSONObject.fromObject(jstoken).getString(
                    "access_token"); // 获取到token并赋值保存
            GlobalConstants.interfaceUrlProperties.put("access_token", access_token);
                    System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"token为=============================="+access_token);
        }
     
    }

    (三)采用任务调度每隔两小时执行一次token获取执行体

    我们阅读过微信的文档会发现我们的token获取的接口每天是有调用次数限制的,为了防止我们业务量比较大的情况下token的直接调用的接口次数不够用,所以我们需要根据token的时效性(7200s)在自己的业务服务器上做到token的缓存并定时获取,我这里用到的任务调度的方式是采用quartz,有关quartz的使用可以参考文章 http://cuiyongzhi.com/?tags=%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1 ,下面具体代码的实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    package com.cuiyongzhi.wechat.quartz;
     
    import org.apache.log4j.Logger;
     
    import com.cuiyongzhi.wechat.common.WeChatTask;
     
    public class QuartzJob{
        private static Logger logger = Logger.getLogger(QuartzJob.class);
        /**
         * @Description: 任务执行获取token
         * @param    
         * @author dapengniao
         * @date 2016年3月10日 下午4:34:26
         */
        public void workForToken() {
            try {
                WeChatTask timer = new WeChatTask();
                timer.getToken_getTicket();
            catch (Exception e) {
                logger.error(e, e);
            }
        }
     
     
    }

    这里新建配置文件spring-quartz.xml以方便quartz任务的管理和启用,这里将我们需要用到的workForToken()加入到执行任务中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
     
    <beans>
        <!-- 要调用的工作类 -->
        <bean id="quartzJob" class="com.cuiyongzhi.wechat.quartz.QuartzJob"></bean>
         
        <!-- 定义调用对象和调用对象的方法 -->
        <bean id="jobtaskForToken"
            class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
            <!-- 调用的类 -->
            <property name="targetObject">
                <ref bean="quartzJob" />
            </property>
            <!-- 调用类中的方法 -->
            <property name="targetMethod">
                <value>workForToken</value>
            </property>
     
        </bean>
        <!-- 定义触发时间 -->
        <bean id="doTimeForToken" class="org.springframework.scheduling.quartz.CronTriggerBean">
            <property name="jobDetail">
                <ref bean="jobtaskForToken" />
            </property>
            <!-- cron表达式 -->
            <property name="cronExpression">
                <value>0 0/1 * * * ?</value>
            </property>
        </bean>
     
     
        <!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
        <bean id="startQuertz" lazy-init="false" autowire="no"
            class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="triggers">
                <list>
                    <ref bean="doTimeForToken" />
                </list>
            </property>
        </bean>
     
    </beans>

    这里我为了测试将执行间隔时间设置成了1分钟一次,根据需要可以自行修改执行时间;最后我们需要在我们的web.xml启动项中开启quartz的使用:

    1
    2
    3
    4
    5
    <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring.xml,classpath:spring-mybatis.xml,classpath:spring-quartz.xml</param-value>
            <!-- ,classpath:spring-quartz.xml 用于做任务调度 任务定时都可以 -->
        </context-param>

    当这一切都准备完毕之后我们启动项目,会发现每间隔一分钟就会有token获取到,这里我是将其存储在项目变量中,但是如果需要考虑到项目横向扩展这里建议将token存储到缓存中;运行结果如下:

    3.png

    那么到这里token的获取和保存就基本讲完了,下一篇将讲述【多媒体消息的回复】,感谢你的翻阅,如果有需要源码或有疑问可以留言!

    展开全文
  • 接口文档https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115 签名生成校检地址 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign ... import java.security.Me...
  • 微信的平台分为公众平台和开放平台。 公众平台就是面向公众的平台。 分为3类: 订阅号 : 发布信息用的,面向个人或企业俗称自媒体(无微信支付), 。 服务号 : 面向企业的公众平台,比如招行等企业的应用(和钱有关)。 ...
  • 微信公众号开发(一)服务器及接口的配置 关于微信公众号中的订阅号和服务的区别这里不多加讨论,网上有很多资源可以搜到,这里直接进入正题,如果是个人开发者,这里建议使用测试号进行开发学习,测试号的权限要比...
  • 微信平台提供的公众号丶服务号丶订阅号、 企业号,它们之间存在着区别和联系,以下为功能对比 公众号公众号是开发者或商家在微信公众平台上申请的应用账号,该帐号与QQ账号互通,通过公众号,商家可在微信平台上...
  • 微信公众号网页授权登录: 前端时间做了一个微信公众号的项目,就是微信公众号的菜单点击我的个人中心,就向用户授权登录 获取用户的信息,进行业务逻辑的操作,微信公众号官方文档,这是我写的文章,里面有很多...
  • 偶然接触到了公众号开发。说需要调起微信扫一扫。便查看了公众号开发文档     看完文档后,发现js是相对简单的。唯一的难点是在java后台编写的秘钥生成代码。 也就是说。首先需要获取access_token,然后...
  • 微信公众号主要面向名人、政府、媒体、企业等机构推出的合作推广业务。在这里可以通过微信渠道将品牌推广给上亿的微信用户,减少宣传成本,提高品牌知名度,打造更具影响力的品牌形象。 3. 公众平台 微信公众平...
  • 一、前言 这次的项目主要是关于微信公众号的一个开发,本人这次分配的模块是后台微信公众号的支付和退款,第一次接触微信公众的项目刚开始一脸懵逼,开发过程中遇到各种坑,所以想自己写一篇详细的关于微信公众号的...
  • 如果公司需要开发小程序,首先要在公司微信公众号里面申请小程序,快速开通并认证之后才能使用。微信最新推出,只要认证过微信公众号,那么接着认证微信小程序就可以复用微信公众号资质注册小程序流,快速注册认证小...
  • 微信小程序与微信公众号同一用户登录问题 最近在做微信小程序与微信公众号登录合并的接口。整理相关资料以及个人认识的心得写了这篇文章与大家一起分享。 首先,简单说下我遇到的问题是我们的程序调用微信...
  • java开发微信公众号的环境搭建 前言:这段时间接触了下微信公众号的开发,回顾下学习的过程,做了学习的总结。微信公众号的开发有两种模式,第一种微信公众号提供的编辑模式,使用起来还是挺方便的。可以进行信息...
  • 本文承接之前发布的博客《 微信支付V3微信公众号支付PHP教程/thinkPHP5公众号支付》必须阅读上篇文章后才可以阅读这篇文章。由于最近一段时间工作比较忙,博客更新比较慢。如果有任何问题大家可以关注以上公众号,...
1 2 3 4 5 ... 20
收藏数 262,467
精华内容 104,986
关键字:

微信公众号