微信开发 返回提示_ios开发微信支付成功后点击返回商家结果返回微信首页 - CSDN
  • 微信浏览器左上角返回按钮的监听

    万次阅读 热门讨论 2018-03-10 21:28:46
    微信开发的时候,在公众号菜单中打开一个H5页面(如:个人中心),在这个页面上的一些操作,经过多次跳转后,点击左上角的返回按钮,发现会原封不动的返回至上一级页面。 即 公众号菜单->A->B->...

    问题描述1:

    微信开发的时候,在公众号菜单中打开一个H5页面(如:个人中心),在这个页面上的一些操作,经过多次跳转后,点击左上角的返回按钮,发现会原封不动的返回至上一级页面。

    即 公众号菜单->A->B->C,点击返回后,返回了B(且无刷新),目的是要在C直接跳转至A(公众号菜单->A->B->C,C->A),虽然可以在C上添加按钮之类的操作进行跳转(公众号菜单->A->B->C->A),但当点击左上角返回按钮后,依然是会返回C页面,并且,也无法确保用户不去点击左上角的返回按钮。

    解决方式:

    在C页面中添加如下javascript代码:

    $(function(){  
        pushHistory();  
    
        window.addEventListener("popstate", function(e) {  //回调函数中实现需要的功能
            alert("我监听到了浏览器的返回按钮事件啦"); 
            location.href='你要跳转的链接';  //在这里指定其返回的地址
        }, false);  
    });  
    function pushHistory() {  
        var state = {  
            title: "title",  
            url: "__SELF__"  
        };  
        window.history.pushState(state, state.title, state.url);  
    }

    问题描述2:

    以上,解决了返回按钮的监听与控制,但是又出现了新的问题,即当从C->A后,点击返回按钮,依然会返回C页面,目的是在A页面点击返回则关闭网页返回至公众号对话页面。

    解决方式:

    PS:评论区中有人(@一路博客博主)指出新版微信jdk的关闭页面api已经改变,已在代码中标出
    本人未亲自测试,各位可以两种方法都试试。

    在A页面中添加如下javascript代码:

    $(function(){
        pushHistory();
    
        window.addEventListener("popstate", function(e) {
        // 新版中使用wx.closeWindow()方法
            WeixinJSBridge.call('closeWindow');
        }, false);
    });
    
    function pushHistory() {
        var state = {
            title: "myCenter",
            url: "__SELF__"
        };
        window.history.pushState(state, state.title, state.url);
    }

    问题描述3:

    在微信中进入页面就触发了popstate事件。然后页面会处于一直刷新状态。

    解决方式:

    定义boolean 变量bool=false。在页面加载后,采用setTimeout方法设置1.5s的超时,在超时执行方法中设置bool=true。

    在popstate监听当中增加对bool的判断,当bool=true时,执行内容。
    代码如下:

    $(function(){  
        pushHistory();  
        var bool=false;  
        setTimeout(function(){  
            bool=true;  
        },1500);  
        window.addEventListener("popstate", function(e) {  
            if(bool){  
                alert("我监听到了浏览器的返回按钮事件啦");
            } 
        }, false);  
    });  
    展开全文
  • 上一篇《微信开发学习总结(一)——微信开发环境搭建》我们已经完成了微信开发的准备工作,准备工作完成之后,就要开始步入正题了。 一、微信公众平台的基本原理  在开始做之前,先简单介绍了微信公众平台的基本...

    上一篇《微信开发学习总结(一)——微信开发环境搭建》我们已经完成了微信开发的准备工作,准备工作完成之后,就要开始步入正题了。

    一、微信公众平台的基本原理

      在开始做之前,先简单介绍了微信公众平台的基本原理。

      微信服务器就相当于一个转发服务器,终端(手机、Pad等)发起请求至微信服务器,微信服务器然后将请求转发给我们的应用服务器。应用服务器处理完毕后,将响应数据回发给微信服务器,微信服务器再将具体响应信息回复到微信App终端。

      通信协议为:HTTP

      数据传输格式为:XML

      具体的流程如下图所示:

      

      来一张更加直观的图吧:

      

      我们需要做的事情,就是对微信服务器转发的HTTP请求做出响应。具体的请求内容,我们按照特定的XML格式去解析,处理完毕后,也要按照特定的XML格式返回。

    二、微信公众号接入

      在微信公众平台开发者文档上,关于公众号接入这一节内容在接入指南上写的比较详细的,文档中说接入公众号需要3个步骤,分别是:

      1、填写服务器配置
      2、验证服务器地址的有效性
      3、依据接口文档实现业务逻辑

      其实,第3步已经不能算做公众号接入的步骤,而是接入之后,开发人员可以根据微信公众号提供的接口所能做的一些开发。

      第1步中服务器配置包含服务器地址(URL)、Token和EncodingAESKey。

      服务器地址即公众号后台提供业务逻辑的入口地址,目前只支持80端口,之后包括接入验证以及任何其它的操作的请求(例如消息的发送、菜单管理、素材管理等)都要从这个地址进入。接入验证和其它请求的区别就是,接入验证时是get请求,其它时候是post请求;

      Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性);

      EncodingAESKey由开发者手动填写或随机生成,将用作消息体加解密密钥。本例中全部以未加密的明文消息方式,不涉及此配置项。

      第2步,验证服务器地址的有效性,当点击“提交”按钮后,微信服务器将发送一个http的get请求到刚刚填写的服务器地址,并且携带四个参数:

      

      接到请求后,我们需要做如下三步,若确认此次GET请求来自微信服务器,原样返回echostr参数内容,则接入生效,否则接入失败。

      1. 将token、timestamp、nonce三个参数进行字典序排序
      2. 将三个参数字符串拼接成一个字符串进行sha1加密
      3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

      下面我们用Java代码来演示一下这个验证过程

      使用IDE(Eclipse或者IntelliJ IDEA)创建一个JavaWeb项目,这里我使用的是IntelliJ IDEA,项目目录结构如下图所示:

      

      编写一个servlevt,在其中的doGet方法中定义校验方法,具体代码如下:

    复制代码
      1 package me.gacl.wx.web.servlet;
      2 
      3 import javax.servlet.ServletException;
      4 import javax.servlet.annotation.WebServlet;
      5 import javax.servlet.http.HttpServlet;
      6 import javax.servlet.http.HttpServletRequest;
      7 import javax.servlet.http.HttpServletResponse;
      8 import java.io.IOException;
      9 import java.security.MessageDigest;
     10 import java.security.NoSuchAlgorithmException;
     11 import java.util.Arrays;
     12 
     13 /**
     14  * Created by xdp on 2016/1/25.
     15  * 使用@WebServlet注解配置WxServlet,urlPatterns属性指明了WxServlet的访问路径
     16  */
     17 @WebServlet(urlPatterns="/WxServlet")
     18 public class WxServlet extends HttpServlet {
     19 
     20     /**
     21      * Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
     22      * 比如这里我将Token设置为gacl
     23      */
     24     private final String TOKEN = "gacl";
     25 
     26     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     27 
     28     }
     29 
     30     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     31         System.out.println("开始校验签名");
     32         /**
     33          * 接收微信服务器发送请求时传递过来的4个参数
     34          */
     35         String signature = request.getParameter("signature");//微信加密签名signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
     36         String timestamp = request.getParameter("timestamp");//时间戳
     37         String nonce = request.getParameter("nonce");//随机数
     38         String echostr = request.getParameter("echostr");//随机字符串
     39         //排序
     40         String sortString = sort(TOKEN, timestamp, nonce);
     41         //加密
     42         String mySignature = sha1(sortString);
     43         //校验签名
     44         if (mySignature != null && mySignature != "" && mySignature.equals(signature)) {
     45             System.out.println("签名校验通过。");
     46             //如果检验成功输出echostr,微信服务器接收到此输出,才会确认检验完成。
     47             //response.getWriter().println(echostr);
     48             response.getWriter().write(echostr);
     49         } else {
     50             System.out.println("签名校验失败.");
     51         }
     52 
     53     }
     54 
     55     /**
     56      * 排序方法
     57      *
     58      * @param token
     59      * @param timestamp
     60      * @param nonce
     61      * @return
     62      */
     63     public String sort(String token, String timestamp, String nonce) {
     64         String[] strArray = {token, timestamp, nonce};
     65         Arrays.sort(strArray);
     66         StringBuilder sb = new StringBuilder();
     67         for (String str : strArray) {
     68             sb.append(str);
     69         }
     70 
     71         return sb.toString();
     72     }
     73 
     74     /**
     75      * 将字符串进行sha1加密
     76      *
     77      * @param str 需要加密的字符串
     78      * @return 加密后的内容
     79      */
     80     public String sha1(String str) {
     81         try {
     82             MessageDigest digest = MessageDigest.getInstance("SHA-1");
     83             digest.update(str.getBytes());
     84             byte messageDigest[] = digest.digest();
     85             // Create Hex String
     86             StringBuffer hexString = new StringBuffer();
     87             // 字节数组转换为 十六进制 数
     88             for (int i = 0; i < messageDigest.length; i++) {
     89                 String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
     90                 if (shaHex.length() < 2) {
     91                     hexString.append(0);
     92                 }
     93                 hexString.append(shaHex);
     94             }
     95             return hexString.toString();
     96 
     97         } catch (NoSuchAlgorithmException e) {
     98             e.printStackTrace();
     99         }
    100         return "";
    101     }
    102 }
    复制代码

      我这里用的Servlet3.0,使用Servlet3.0的好处就是可以直接使用@WebServlet注解映射Servlet的访问路径,不再需要在web.xml文件中进行配置.

      将WxStudy项目部署到Tomcat服务器中运行,直接启动项目,然后用ngrok将本地8080端口映射到外网(如何使用ngrok请参考博客《微信开发学习总结(一)——微信开发环境搭建》)。如下图所示:

      

      测试是否可以通过http://xdp.ngrok.natapp.cn地址正常访问,测试结果如下:

      

      可以看到,我们的项目已经可以被外网正常访问到了。

      进入微信测试公众号管理界面,在接口配置信息中填入映射的外网地址和token,如下图所示:

     

      点击提交按钮,页面会提示配置成功,

      

      IDE的控制台中输出了校验通过的信息,如下图所示:

      

      到此,我们的公众号应用已经能够和微信服务器正常通信了,也就是说我们的公众号已经接入到微信公众平台了。

    三、access_token管理

    3.1、access_token介绍

      我们的公众号和微信服务器对接成功之后,接下来要做的就是根据我们的业务需求调用微信公众号提供的接口来实现相应的逻辑了。在使用微信公众号接口中都需要一个access_token。

      关于access_token,在微信公众平台开发者文档上的获取接口调用凭据有比较详细的介绍:access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token,开发者需要妥善保存access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。并且每天调用获取access_token接口的上限是2000次。

      总结以上说明,access_token需要做到以下两点:

      1.因为access_token有2个小时的时效性,要有一个机制保证最长2个小时重新获取一次。

      2.因为接口调用上限每天2000次,所以不能调用太频繁。

    3.2、微信公众平台提供的获取access_token的接口

      关于access_token的获取方式,在微信公众平台开发者文档上有说明,公众号可以调用一个叫"获取access token"的接口来获取access_token。

      获取access token接口调用请求说明

        http请求方式: GET

        请求的URL地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
        
      

      我们可以看到,调用过程中需要传递appID和AppSecret,appID和AppSecret是在申请公众号的时候自动分配给公众号的,相当于公众号的身份标示,使用微信公众号的注册帐号登录到腾讯提供的微信公众号管理后台就可以看到自己申请的公众号的AppID和AppSecret,如下图所示:

      

      这是我申请公众号测试帐号时分配到的AppID和AppSecret。

    3.3、获取access_token方案以及具体实现

      这里采用的方案是这样的,定义一个默认启动的servlet,在init方法中启动一个Thread,这个进程中定义一个无限循环的方法,用来获取access_token,当获取成功后,此进程休眠7000秒(7000秒=1.944444444444444小时),否则休眠3秒钟继续获取。流程图如下:

      

      下面正式开始在工程中实现以上思路,因为返回的数据都是json格式,这里会用到阿里的fastjson库,为构造请求和处理请求后的数据序列化和反序列化提供支持。

      1.定义一个AccessToken实体类

    复制代码
     1 package me.gacl.wx.entry;
     2 
     3 /**
     4  * AccessToken的数据模型
     5  * Created by xdp on 2016/1/25.
     6  */
     7 public class AccessToken {
     8 
     9     //获取到的凭证
    10     private String accessToken;
    11     //凭证有效时间,单位:秒
    12     private int expiresin;
    13 
    14     public String getAccessToken() {
    15         return accessToken;
    16     }
    17 
    18     public void setAccessToken(String accessToken) {
    19         this.accessToken = accessToken;
    20     }
    21 
    22     public int getExpiresin() {
    23         return expiresin;
    24     }
    25 
    26     public void setExpiresin(int expiresin) {
    27         this.expiresin = expiresin;
    28     }
    29 }
    复制代码

     2.定义一个AccessTokenInfo类,用于存放获取到的AccessToken,代码如下:

    复制代码
     1 package me.gacl.wx.Common;
     2 
     3 import me.gacl.wx.entry.AccessToken;
     4 
     5 /**
     6  * Created by xdp on 2016/1/25.
     7  */
     8 public class AccessTokenInfo {
     9 
    10     //注意是静态的
    11     public static AccessToken accessToken = null;
    12 }
    复制代码

      3.编写一个用于发起https请求的工具类NetWorkHelper,代码如下:

    复制代码
     1 package me.gacl.wx.util;
     2 
     3 import javax.net.ssl.*;
     4 import java.io.BufferedReader;
     5 import java.io.InputStream;
     6 import java.io.InputStreamReader;
     7 import java.net.URL;
     8 import java.security.cert.CertificateException;
     9 import java.security.cert.X509Certificate;
    10 
    11 /**
    12  * 访问网络用到的工具类
    13  */
    14 public class NetWorkHelper {
    15 
    16     /**
    17      * 发起Https请求
    18      * @param reqUrl 请求的URL地址
    19      * @param requestMethod
    20      * @return 响应后的字符串
    21      */
    22     public String getHttpsResponse(String reqUrl, String requestMethod) {
    23         URL url;
    24         InputStream is;
    25         String resultData = "";
    26         try {
    27             url = new URL(reqUrl);
    28             HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
    29             TrustManager[] tm = {xtm};
    30 
    31             SSLContext ctx = SSLContext.getInstance("TLS");
    32             ctx.init(null, tm, null);
    33 
    34             con.setSSLSocketFactory(ctx.getSocketFactory());
    35             con.setHostnameVerifier(new HostnameVerifier() {
    36                 @Override
    37                 public boolean verify(String arg0, SSLSession arg1) {
    38                     return true;
    39                 }
    40             });
    41 
    42 
    43             con.setDoInput(true); //允许输入流,即允许下载
    44 
    45             //在android中必须将此项设置为false
    46             con.setDoOutput(false); //允许输出流,即允许上传
    47             con.setUseCaches(false); //不使用缓冲
    48             if (null != requestMethod && !requestMethod.equals("")) {
    49                 con.setRequestMethod(requestMethod); //使用指定的方式
    50             } else {
    51                 con.setRequestMethod("GET"); //使用get请求
    52             }
    53             is = con.getInputStream();   //获取输入流,此时才真正建立链接
    54             InputStreamReader isr = new InputStreamReader(is);
    55             BufferedReader bufferReader = new BufferedReader(isr);
    56             String inputLine;
    57             while ((inputLine = bufferReader.readLine()) != null) {
    58                 resultData += inputLine + "\n";
    59             }
    60             System.out.println(resultData);
    61 
    62         } catch (Exception e) {
    63             e.printStackTrace();
    64         }
    65         return resultData;
    66     }
    67 
    68     X509TrustManager xtm = new X509TrustManager() {
    69         @Override
    70         public X509Certificate[] getAcceptedIssuers() {
    71             return null;
    72         }
    73 
    74         @Override
    75         public void checkServerTrusted(X509Certificate[] arg0, String arg1)
    76                 throws CertificateException {
    77 
    78         }
    79 
    80         @Override
    81         public void checkClientTrusted(X509Certificate[] arg0, String arg1)
    82                 throws CertificateException {
    83 
    84         }
    85     };
    86 }
    复制代码

      getHttpsResponse方法是请求一个https地址,参数requestMethod为字符串“GET”或者“POST”,传null或者“”默认为get方式。

      4.定义一个默认启动的servlet,在init方法中启动一个新的线程去获取accessToken

    复制代码
     1 package me.gacl.wx.web.servlet;
     2 
     3 import com.alibaba.fastjson.JSON;
     4 import com.alibaba.fastjson.JSONObject;
     5 import me.gacl.wx.Common.AccessTokenInfo;
     6 import me.gacl.wx.entry.AccessToken;
     7 import me.gacl.wx.util.NetWorkHelper;
     8 
     9 import javax.servlet.ServletException;
    10 import javax.servlet.annotation.WebInitParam;
    11 import javax.servlet.annotation.WebServlet;
    12 import javax.servlet.http.HttpServlet;
    13 
    14 /**
    15  * 用于获取accessToken的Servlet
    16  * Created by xdp on 2016/1/25.
    17  */
    18 @WebServlet(
    19         name = "AccessTokenServlet",
    20         urlPatterns = {"/AccessTokenServlet"},
    21         loadOnStartup = 1,
    22         initParams = {
    23                 @WebInitParam(name = "appId", value = "wxbe4d433e857e8bb1"),
    24                 @WebInitParam(name = "appSecret", value = "ccbc82d560876711027b3d43a6f2ebda")
    25         })
    26 public class AccessTokenServlet extends HttpServlet {
    27 
    28     @Override
    29     public void init() throws ServletException {
    30         System.out.println("启动WebServlet");
    31         super.init();
    32 
    33         final String appId = getInitParameter("appId");
    34         final String appSecret = getInitParameter("appSecret");
    35 
    36         //开启一个新的线程
    37         new Thread(new Runnable() {
    38             @Override
    39             public void run() {
    40                 while (true) {
    41                     try {
    42                         //获取accessToken
    43                         AccessTokenInfo.accessToken = getAccessToken(appId, appSecret);
    44                         //获取成功
    45                         if (AccessTokenInfo.accessToken != null) {
    46                             //获取到access_token 休眠7000秒,大约2个小时左右
    47                             Thread.sleep(7000 * 1000);
    48                             //Thread.sleep(10 * 1000);//10秒钟获取一次
    49                         } else {
    50                             //获取失败
    51                             Thread.sleep(1000 * 3); //获取的access_token为空 休眠3秒
    52                         }
    53                     } catch (Exception e) {
    54                         System.out.println("发生异常:" + e.getMessage());
    55                         e.printStackTrace();
    56                         try {
    57                             Thread.sleep(1000 * 10); //发生异常休眠1秒
    58                         } catch (Exception e1) {
    59 
    60                         }
    61                     }
    62                 }
    63 
    64             }
    65         }).start();
    66     }
    67 
    68     /**
    69      * 获取access_token
    70      *
    71      * @return AccessToken
    72      */
    73     private AccessToken getAccessToken(String appId, String appSecret) {
    74         NetWorkHelper netHelper = new NetWorkHelper();
    75         /**
    76          * 接口地址为https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET,其中grant_type固定写为client_credential即可。
    77          */
    78         String Url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, appSecret);
    79         //此请求为https的get请求,返回的数据格式为{"access_token":"ACCESS_TOKEN","expires_in":7200}
    80         String result = netHelper.getHttpsResponse(Url, "");
    81         System.out.println("获取到的access_token="+result);
    82         //使用FastJson将Json字符串解析成Json对象
    83         JSONObject json = JSON.parseObject(result);
    84         AccessToken token = new AccessToken();
    85         token.setAccessToken(json.getString("access_token"));
    86         token.setExpiresin(json.getInteger("expires_in"));
    87         return token;
    88     }
    89 }
    复制代码

      AccessTokenServlet采用注解的方式进行配置
      至此代码实现完毕,将项目部署,看到控制台输出如下:

      

      为了方便看效果,可以把休眠时间设置短一点,比如10秒获取一次,然后将access_token输出。

      下面做一个测试jsp页面,并把休眠时间设置为10秒,这样过10秒刷新页面,就可以看到变化

    复制代码
     1 <%-- Created by IntelliJ IDEA. --%>
     2 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
     3 <%@ page import="me.gacl.wx.Common.AccessTokenInfo"%>
     4 <html>
     5   <head>
     6     <title></title>
     7   </head>
     8   <body>
     9     微信学习
    10     <hr/>
    11     access_token为:<%=AccessTokenInfo.accessToken.getAccessToken()%>
    12   </body>
    13 </html>
    复制代码

      

      10秒钟后刷新页面,access_token变了,如下图所示:

      

    四、接收微信服务器发送的消息并做出响应

      经过上述的三步,我们开发前的准备工作已经完成了,接下来要做的就是接收微信服务器发送的消息并做出响应

      从微信公众平台接口消息指南中可以了解到,当用户向公众帐号发消息时,微信服务器会将消息通过POST方式提交给我们在接口配置信息中填写的URL,而我们就需要在URL所指向的请求处理类WxServlet的doPost方法中接收消息、处理消息和响应消息。

    4.1.编写一个用于处理消息的工具类

      编写处理消息的工具栏,工具类代码如下:

    复制代码
      1 package me.gacl.wx.util;
      2 
      3 import org.dom4j.Document;
      4 import org.dom4j.Element;
      5 import org.dom4j.io.SAXReader;
      6 
      7 import javax.servlet.http.HttpServletRequest;
      8 import java.io.InputStream;
      9 import java.text.DateFormat;
     10 import java.text.SimpleDateFormat;
     11 import java.util.Date;
     12 import java.util.HashMap;
     13 import java.util.List;
     14 import java.util.Map;
     15 
     16 /**
     17  * 消息处理工具类
     18  * Created by xdp on 2016/1/26.
     19  */
     20 public class MessageHandlerUtil {
     21 
     22     /**
     23      * 解析微信发来的请求(XML)
     24      * @param request
     25      * @return map
     26      * @throws Exception
     27      */
     28     public static Map<String,String> parseXml(HttpServletRequest request) throws Exception {
     29         // 将解析结果存储在HashMap中
     30         Map<String,String> map = new HashMap();
     31         // 从request中取得输入流
     32         InputStream inputStream = request.getInputStream();
     33         System.out.println("获取输入流");
     34         // 读取输入流
     35         SAXReader reader = new SAXReader();
     36         Document document = reader.read(inputStream);
     37         // 得到xml根元素
     38         Element root = document.getRootElement();
     39         // 得到根元素的所有子节点
     40         List<Element> elementList = root.elements();
     41 
     42         // 遍历所有子节点
     43         for (Element e : elementList) {
     44             System.out.println(e.getName() + "|" + e.getText());
     45             map.put(e.getName(), e.getText());
     46         }
     47 
     48         // 释放资源
     49         inputStream.close();
     50         inputStream = null;
     51         return map;
     52     }
     53 
     54     // 根据消息类型 构造返回消息
     55     public static String buildXml(Map<String,String> map) {
     56         String result;
     57         String msgType = map.get("MsgType").toString();
     58         System.out.println("MsgType:" + msgType);
     59         if(msgType.toUpperCase().equals("TEXT")){
     60             result = buildTextMessage(map, "孤傲苍狼在学习和总结微信开发了,构建一条文本消息:Hello World!");
     61         }else{
     62             String fromUserName = map.get("FromUserName");
     63             // 开发者微信号
     64             String toUserName = map.get("ToUserName");
     65             result = String
     66                     .format(
     67                             "<xml>" +
     68                                     "<ToUserName><![CDATA[%s]]></ToUserName>" +
     69                                     "<FromUserName><![CDATA[%s]]></FromUserName>" +
     70                                     "<CreateTime>%s</CreateTime>" +
     71                                     "<MsgType><![CDATA[text]]></MsgType>" +
     72                                     "<Content><![CDATA[%s]]></Content>" +
     73                                     "</xml>",
     74                             fromUserName, toUserName, getUtcTime(),
     75                             "请回复如下关键词:\n文本\n图片\n语音\n视频\n音乐\n图文");
     76         }
     77 
     78         return result;
     79     }
     80 
     81     /**
     82      * 构造文本消息
     83      *
     84      * @param map
     85      * @param content
     86      * @return
     87      */
     88     private static String buildTextMessage(Map<String,String> map, String content) {
     89         //发送方帐号
     90         String fromUserName = map.get("FromUserName");
     91         // 开发者微信号
     92         String toUserName = map.get("ToUserName");
     93         /**
     94          * 文本消息XML数据格式
     95          * <xml>
     96              <ToUserName><![CDATA[toUser]]></ToUserName>
     97              <FromUserName><![CDATA[fromUser]]></FromUserName>
     98              <CreateTime>1348831860</CreateTime>
     99              <MsgType><![CDATA[text]]></MsgType>
    100              <Content><![CDATA[this is a test]]></Content>
    101              <MsgId>1234567890123456</MsgId>
    102          </xml>
    103          */
    104         return String.format(
    105                 "<xml>" +
    106                         "<ToUserName><![CDATA[%s]]></ToUserName>" +
    107                         "<FromUserName><![CDATA[%s]]></FromUserName>" +
    108                         "<CreateTime>%s</CreateTime>" +
    109                         "<MsgType><![CDATA[text]]></MsgType>" +
    110                         "<Content><![CDATA[%s]]></Content>" + "</xml>",
    111                 fromUserName, toUserName, getUtcTime(), content);
    112     }
    113 
    114     private static String getUtcTime() {
    115         Date dt = new Date();// 如果不需要格式,可直接用dt,dt就是当前系统时间
    116         DateFormat df = new SimpleDateFormat("yyyyMMddhhmm");// 设置显示格式
    117         String nowTime = df.format(dt);
    118         long dd = (long) 0;
    119         try {
    120             dd = df.parse(nowTime).getTime();
    121         } catch (Exception e) {
    122 
    123         }
    124         return String.valueOf(dd);
    125     }
    126 }
    复制代码

      为了方便解析微信服务器发送给我们的xml格式的数据,这里我们借助于开源框架dom4j去解析xml(这里使用的是dom4j-2.0.0-RC1.jar)

      

    4.2.在WxServlet的doPost方法中处理请求

      WxServlet的doPost方法的代码如下:

    复制代码
     1  /**
     2      * 处理微信服务器发来的消息
     3      */
     4     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     5         // TODO 接收、处理、响应由微信服务器转发的用户发送给公众帐号的消息
     6         // 将请求、响应的编码均设置为UTF-8(防止中文乱码)
     7         request.setCharacterEncoding("UTF-8");
     8         response.setCharacterEncoding("UTF-8");
     9         System.out.println("请求进入");
    10         String result = "";
    11         try {
    12             Map<String,String> map = MessageHandlerUtil.parseXml(request);
    13             System.out.println("开始构造消息");
    14             result = MessageHandlerUtil.buildXml(map);
    15             System.out.println(result);
    16             if(result.equals("")){
    17                 result = "未正确响应";
    18             }
    19         } catch (Exception e) {
    20             e.printStackTrace();
    21             System.out.println("发生异常:"+ e.getMessage());
    22         }
    23         response.getWriter().println(result);
    24     }
    复制代码

      到此,我们的WxServlet已经可以正常处理用户的请求并做出响应了.接下来我们测试一下我们开发好的公众号应用是否可以正常和微信用户交互

      将WxStudy部署到Tomcat服务器,启动服务器,记得使用ngrok将本地Tomcat服务器的8080端口映射到外网,保证接口配置信息的URL地址:http://xdp.ngrok.natapp.cn/WxServlet可以正常与微信服务器通信

      登录到我们的测试公众号的管理后台,然后用微信扫描一下测试号的二维码,如下图所示:

      

     

      

      

      关注成功后,我们开发好的公众号应用会先给用户发一条提示用户操作的文本消息,微信用户根据提示操作输入"文本",我们的公众号应用接收到用户请求后就给用户回复了一条我们自己构建好的文本消息,如下图所示:

      

      我们的公众号应用响应给微信用户的文本消息的XML数据如下:

    复制代码
    1 <xml>
    2   <ToUserName><![CDATA[ojADgs0eDaqh7XkTM9GvDmdYPoDw]]></ToUserName>
    3   <FromUserName><![CDATA[gh_43df3882c452]]></FromUserName>
    4   <CreateTime>1453755900000</CreateTime>
    5   <MsgType><![CDATA[text]]></MsgType>
    6   <Content><![CDATA[孤傲苍狼在学习和总结微信开发了,构建一条文本消息:Hello World!]]></Content>
    7 </xml>
    复制代码

      测试公众号的管理后台也可以看到关注测试号的用户列表,如下图所示:

      

      通过这个简单的入门程序,我们揭开了微信开发的神秘面纱了.

      本篇的内容就这么多了。本文的内容和代码参考了用java开发微信公众号:公众号接入和access_token管理(二)这篇博客,在此对作者"风的姿态"表示感谢。

      下载测试项目部署运行时,由于项目中使用的是Servlet3.0,所以要求部署的Tomcat必须是7.x,以前也写过几篇关于Servlet3.0的博客,大家有兴趣的话可以去看看,本篇博文对应的测试项目代码下载http://pan.baidu.com/s/1hrfcGks

    展开全文
  • 前提:最近一直在跟微信公众号开发打交道,所以特此写了一个"微信全局返回码"的枚举类,方便日后将出现的错误打印到日志,方便错误的排查。为什么非要自己写一个呢,是因为在网上找了半天,也没有现成的...

    前提:最近一直在跟微信公众号开发打交道,所以特此写了一个"微信全局返回码"的枚举类,方便日后将出现的错误打印到日志,方便错误的排查。

    为什么非要自己写一个呢,是因为在网上找了半天,也没有现成的代码可以用,所以就自己写了。其实,就算是拷贝下来,还得对照最新的微信公众号开发文档进行校验,还不如自己写的实在!!!

    有需要的人士,如不嫌弃,可以直接拷贝走,省去不必要的麻烦~~~

    现,此枚举类是依据2018年5月9日的《微信公众平台技术文档》-"全局返回码说明"所写,如果日后有更新,再做修改。

    代码:

    /**
     * @author {KevenPotter}
     * @description {This enumeration class is designed to declare the WeChat global return code.
     * The developer can debug the interface based on the return code information and troubleshoot the error.}
     * @description {此枚举类旨在声明微信全局返回码,开发者可以根据返回码信息调试接口,排查错误。}
     */
    package com.hh.core.constant;
    
    public enum WeChatGlobalReturnCodeEnum {
        SYSTEM_BUSY("0-系统繁忙", "0"),
        REQUEST_SUCCESSFUL("-1-请求成功", "-1"),
        APPSECRET_ERROR("40001-AppSecret错误", "40001"),
        INVALID_CERTIFICATE_TYPE("40002-不合法的凭证类型", "40002"),
        ILLEGAL_OPENID("40003-不合法的 OpenID ,请开发者确认 OpenID (该用户)是否已关注公众号,或是否是其他公众号的 OpenID", "40003"),
        INVALID_MEDIA_FILE_TYPE("40004-不合法的媒体文件类型", "40004"),
        INVALID_FILE_TYPE("40005-不合法的文件类型", "40005"),
        INVALID_FILE_SIZE("40006-不合法的文件大小", "40006"),
        ILLEGAL_MEDIA_FILE_ID("40007-不合法的媒体文件 id", "40007"),
        INVALID_MESSAGE_TYPE("40008-不合法的消息类型", "40008"),
        INVALID_IMAGE_FILE_SIZE("40009-不合法的图片文件大小", "40009"),
        INVALID_VOICE_FILE_SIZE("40010-不合法的语音文件大小", "40010"),
        INVALID_VIDEO_FILE_SIZE("40011-不合法的视频文件大小", "40011"),
        INVALID_THUMBNAIL_FILE_SIZE("40012-不合法的缩略图文件大小", "40012"),
        INVALID_APPID("40013-不合法的AppID,请开发者检查 AppID 的正确性,避免异常字符,注意大小写", "40013"),
        INVALID_ACCESS_TOKEN("40014-不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口", "40014"),
        ILLEGAL_MENU_TYPE("40015-不合法的菜单类型", "40015"),
        THE_NUMBER_OF_ILLEGAL_BUTTONS_1("40016-不合法的按钮个数", "40016"),
        THE_NUMBER_OF_ILLEGAL_BUTTONS_2("40017-不合法的按钮个数", "40017"),
        ILLEGAL_BUTTON_NAME_LENGTH("40018-不合法的按钮名字长度", "40018"),
        ILLEGAL_BUTTON_KEY_LENGTH("40019-不合法的按钮 KEY 长度", "40019"),
        ILLEGAL_BUTTON_URL_LENGTH("40020-不合法的按钮 URL 长度", "40020"),
        ILLEGAL_MENU_VERSION_NUMBER("40021-不合法的菜单版本号", "40021"),
        INVALID_SUBMENU_LEVEL("40022-不合法的子菜单级数", "40022"),
        THE_NUMBER_OF_ILLEGAL_SUBMENU_BUTTONS("40023-不合法的子菜单按钮个数", "40023"),
        INVALID_SUBMENU_BUTTON_TYPE("40024-不合法的子菜单按钮类型", "40024"),
        ILLEGAL_SUBMENU_BUTTON_NAME_LENGTH("40025-不合法的子菜单按钮名字长度", "40025"),
        INVALID_SUBMENU_BUTTON_KEY_LENGTH("40026-不合法的子菜单按钮 KEY 长度", "40026"),
        INVALID_SUBMENU_BUTTON_URL_LENGTH("40027-不合法的子菜单按钮 URL 长度", "40027"),
        ILLEGAL_CUSTOM_MENU_USAGE_USER("40028-不合法的自定义菜单使用用户", "40028"),
        INVALID_OAUTH_CODE("40029-不合法的 oauth_code", "40029"),
        ILLEGAL_REFRESH_TOKEN("40030-不合法的 refresh_token", "40030"),
        ILLEGAL_OPENID_LIST("40031-不合法的 openid 列表", "40031"),
        ILLEGAL_OPENID_LIST_LENGTH("40032-不合法的 openid 列表长度", "40032"),
        ILLEGAL_REQUEST_CHARACTER("40033-不合法的请求字符,不能包含 \\uxxxx 格式的字符", "40033"),
        INVALID_PARAMETERS("40035-不合法的参数", "40035"),
        INVALID_REQUEST_FORMAT("40038-不合法的请求格式", "40038"),
        INVALID_URL_LENGTH("40039-不合法的 URL 长度", "40039"),
        INVALID_GROUP_ID("40050-不合法的分组 id", "40050"),
        THE_GROUP_NAME_IS_ILLEGAL_1("40051-分组名字不合法", "40051"),
        THE_SPECIFIED_ARTICLE_IDX_IS_ILLEGAL("40060-删除单篇图文时,指定的 article_idx 不合法", "40060"),
        THE_GROUP_NAME_IS_ILLEGAL_2("40117-分组名字不合法", "40117"),
        ILLEGAL_MEDIA_ID_SIZE("40118-media_id 大小不合法", "40118"),
        WRONG_BUTTON_TYPE_1("40119-button 类型错误", "40119"),
        WRONG_BUTTON_TYPE_2("40120-button 类型错误", "40120"),
        INVALID_MEDIA_ID_TYPE("40121-不合法的 media_id 类型", "40121"),
        MICRO_SIGNAL_IS_ILLEGAL("40132-微信号不合法", "40132"),
        UNSUPPORTED_IMAGE_FORMAT("40137-不支持的图片格式", "40137"),
        ADD_ANOTHER_PUBLIC_NUMBER_HOMEPAGE_LINK("40155-请勿添加其他公众号的主页链接", "40155"),
        MISSING_ACCESS_TOKEN_PARAMETER("41001-缺少 access_token 参数", "41001"),
        MISSING_APPID_PARAMETER("41002-缺少 appid 参数", "41002"),
        MISSING_REFRESH_TOKEN_PARAMETER("41003-缺少 refresh_token 参数", "41003"),
        MISSING_SECRET_PARAMETER("41004-缺少 secret 参数", "41004"),
        MISSING_MULTIMEDIA_FILE_DATA("41005-缺少多媒体文件数据", "41005"),
        MISSING_MEDIA_ID_PARAMETER("41006-缺少 media_id 参数", "41006"),
        MISSING_SUBMENU_DATA("41007-缺少子菜单数据", "41007"),
        MISSING_OAUTH_CODE("41008-缺少 oauth code", "41008"),
        MISSING_OPENID("41009-缺少 openid", "41009"),
        ACCESS_TOKEN_TIMEOUT("42001-access_token 超时,请检查 access_token 的有效期,请参考基础支持 - 获取 access_token 中,对 access_token 的详细机制说明", "42001"),
        REFRESH_TOKEN_TIMEOUT("42002-refresh_token 超时", "42002"),
        OAUTH_CODE_TIMEOUT("42003-oauth_code 超时", "42003"),
        USER_MODIFIED_WECHAT_PASSWORD("42007-用户修改微信密码, accesstoken 和 refreshtoken 失效,需要重新授权", "42007"),
        NEED_GET_REQUEST("43001-需要 GET 请求", "43001"),
        NEED_POST_REQUEST("43002-需要 POST 请求", "43002"),
        NEED_HTTPS_REQUEST("43003-需要 HTTPS 请求", "43003"),
        NEED_THE_ATTENTION_OF_THE_RECIPIENT("43004-需要接收者关注", "43004"),
        NEED_A_FRIEND("43005-需要好友关系", "43005"),
        NEED_TO_REMOVE_THE_RECEIVER_FROM_THE_BLACK_LIST("43019-需要将接收者从黑名单中移除", "43019"),
        MULTIMEDIA_FILE_IS_EMPTY("44001-多媒体文件为空", "44001"),
        POST_PACKET_IS_EMPTY("44002-POST 的数据包为空", "44002"),
        IMAGE_MESSAGE_IS_EMPTY("44003-图文消息内容为空", "44003"),
        TEXT_MESSAGE_IS_EMPTY("44004-文本消息内容为空", "44004"),
        MULTIMEDIA_FILE_SIZE_EXCEEDS_LIMIT("45001-多媒体文件大小超过限制", "45001"),
        MESSAGE_CONTENT_EXCEEDS_LIMITS("45002-消息内容超过限制", "45002"),
        TITLE_FIELD_EXCEEDS_LIMIT("45003-标题字段超过限制", "45003"),
        DESCRIPTION_FIELD_EXCEEDS_LIMIT("45004-描述字段超过限制", "45004"),
        LINK_FIELD_EXCEEDS_LIMIT("45005-链接字段超过限制", "45005"),
        IMAGE_LINK_FIELD_EXCEEDS_LIMIT("45006-图片链接字段超过限制", "45006"),
        VOICE_PLAY_TIME_EXCEEDS_LIMIT("45007-语音播放时间超过限制", "45007"),
        GRAPHIC_MESSAGE_EXCEEDS_LIMIT("45008-图文消息超过限制", "45008"),
        INTERFACE_CALL_EXCEEDS_LIMIT("45009-接口调用超过限制", "45009"),
        CREATED_MENUS_EXCEEDS_THE_LIMIT("45010-创建菜单个数超过限制", "45010"),
        API_CALLS_TOO_OFTEN("45011-API 调用太频繁,请稍候再试", "45011"),
        RESPONSE_TIME_EXCEEDS_LIMIT("45015-回复时间超过限制", "45015"),
        SYSTEM_GROUPING("45016-系统分组,不允许修改", "45016"),
        GROUP_NAME_IS_TOO_LONG("45017-分组名字过长", "45017"),
        THE_NUMBER_OF_GROUPS_EXCEEDS_THE_LIMIT("45018-分组数量超过上限", "45018"),
        CUSTOMER_SERVICE_INTERFACES_DOWN_EXCEEDS_THE_UPPER_LIMIT("45047-客服接口下行条数超过上限", "45047"),
        NO_MEDIA_DATA_EXISTS("46001-不存在媒体数据", "46001"),
        NON_EXISTENT_MENU_VERSION("46002-不存在的菜单版本", "46002"),
        NON_EXISTENT_MENU_DATA("46003-不存在的菜单数据", "46003"),
        NON_EXISTENT_USER("46004-不存在的用户", "46004"),
        PARSING_JSON_XML_CONTENT_ERROR("47001-解析 JSON/XML 内容错误", "47001"),
        API_FEATURE_NOT_AUTHORIZED("48001-api 功能未授权,请确认公众号已获得该接口,可以在公众平台官网 - 开发者中心页中查看接口权限", "48001"),
        FANS_REJECTED_MESSAGE("48002-粉丝拒收消息(粉丝在公众号选项中,关闭了 '接收消息' )", "48002"),
        API_INTERFACE_BANNED("48004-api 接口被封禁,请登录 mp.weixin.qq.com 查看详情", "48004"),
        API_DISABLES_DELETION("48005-api 禁止删除被自动回复和自定义菜单引用的素材", "48005"),
        API_SUPPRESS_ZERO_CALLS("48006-api 禁止清零调用次数,因为清零次数达到上限", "48006"),
        NO_SEND_PERMISSION_FOR_THIS_TYPE_OF_MESSAGE("48008-没有该类型消息的发送权限", "48008"),
        THE_USER_DID_NOT_AUTHORIZE_THIS_API("50001-用户未授权该 api", "50001"),
        USER_LIMITED("50002-用户受限,可能是违规后接口被封禁", "50002"),
        USER_DID_NOT_PAY_ATTENTION_TO_THE_PUBLIC_NUMBER("50005-用户未关注公众号", "50005"),
        INVALID_PARAMETER("61451-参数错误", "61451"),
        INVALID_KF_ACCOUNT("61452-无效客服账号", "61452"),
        KF_ACCOUNT_EXSITED("61453-客服帐号已存在", "61453"),
        INVALID_KF_ACOUNT_LENGTH("61454-客服帐号名长度超过限制 ( 仅允许 10 个英文字符,不包括 @ 及 @ 后的公众号的微信号 )", "61454"),
        ILLEGAL_CHARACTER_IN_KF_ACCOUNT("61455-客服帐号名包含非法字符 ( 仅允许英文 + 数字 )", "61455"),
        KF_ACCOUNT_COUNT_EXCEEDED("61456-客服帐号个数超过限制 (10 个客服账号 )", "61456"),
        INVALID_AVATAR_FILE_TYPE("61457-无效头像文件类型", "61457"),
        SYSTEM_ERROR("61450-系统错误", "61450"),
        DATE_FORMAT_IS_WRONG("61500-日期格式错误", "61500"),
        NO_PERSONALIZED_MENU_FOR_THIS_MENUID("65301-不存在此 menuid 对应的个性化菜单", "65301"),
        NO_CORRESPONDING_USER("65302-没有相应的用户", "65302"),
        NO_DEFAULT_MENU("65303-没有默认菜单,不能创建个性化菜单", "65303"),
        MATCHRULE_INFORMATION_IS_EMPTY("65304-MatchRule 信息为空", "65304"),
        LIMITED_NUMBER_OF_PERSONALIZED_MENUS("65305-个性化菜单数量受限", "65305"),
        NOT_SUPPORT_PERSONALIZED_MENUS("65306-不支持个性化菜单的帐号", "65306"),
        PERSONALIZED_MENU_INFORMATION_IS_EMPTY("65307-个性化菜单信息为空", "65307"),
        CONTAINS_NO_RESPONSE_TYPE_BUTTON("65308-包含没有响应类型的 button", "65308"),
        PERSONALIZED_MENU_SWITCH_IS_OFF("65309-个性化菜单开关处于关闭状态", "65309"),
        COUNTRY_INFORMATION_CANNOT_BE_EMPTY("65310-填写了省份或城市信息,国家信息不能为空", "65310"),
        PROVINCIAL_INFORMATION_CANNOT_BE_EMPTY("65311-填写了城市信息,省份信息不能为空", "65311"),
        ILLEGAL_COUNTRY_INFORMATION("65312-不合法的国家信息", "65312"),
        ILLEGAL_PROVINCE_INFORMATION("65313-不合法的省份信息", "65313"),
        ILLEGAL_CITY_INFORMATION("65314-不合法的城市信息", "65314"),
        TOO_MANY_DOMAIN_NAME_JUMPS("65316-该公众号的菜单设置了过多的域名外跳(最多跳转到 3 个域名的链接)", "65316"),
        ILLEGAL_URL("65317-不合法的 URL", "65317"),
        POST_DATA_PARAMETER_IS_ILLEGAL("9001001-POST 数据参数不合法", "9001001"),
        REMOTE_SERVICE_UNAVAILABLE("9001002-远端服务不可用", "9001002"),
        TICKET_IS_ILLEGAL("9001003-Ticket 不合法", "9001003"),
        FAILED_TO_SHAKE_PERIPHERAL_USER_INFORMATION("9001004-获取摇周边用户信息失败", "9001004"),
        FAILED_TO_GET_BUSINESS_INFORMATION("9001005-获取商户信息失败", "9001005"),
        FAILED_TO_GET_OPENID("9001006-获取 OpenID 失败", "9001006"),
        MISSING_UPLOAD_FILE("9001007-上传文件缺失", "9001007"),
        THE_UPLOADED_FILE_IS_OF_AN_ILLEGAL_FILE_TYPE("9001008-上传素材的文件类型不合法", "9001008"),
        THE_FILE_SIZE_OF_THE_UPLOADED_MATERIAL_IS_ILLEGAL("9001009-上传素材的文件尺寸不合法", "9001009"),
        UPLOAD_FAILED("9001010-上传失败", "9001010"),
        ACCOUNT_IS_ILLEGAL("9001020-帐号不合法", "9001020"),
        DEVICE_ACTIVATION_RATE_IS_LESS_THAN_FIFTY_PERCENT("9001021-已有设备激活率低于 50% ,不能新增设备", "9001021"),
        THE_NUMBER_OF_DEVICE_APPLICATIONS_IS_ILLEGAL("9001022-设备申请数不合法,必须为大于 0 的数字", "9001022"),
        EXISTING_DEVICE_ID_APPLICATION_IN_REVIEW("9001023-已存在审核中的设备 ID 申请", "9001023"),
        QUERY_DEVICE_IDS_CANNOT_EXCEED_FIFTY("9001024-一次查询设备 ID 数量不能超过 50", "9001024"),
        DEVICE_ID_IS_ILLEGAL("9001025-设备 ID 不合法", "9001025"),
        PAGE_ID_IS_ILLEGAL("9001026-页面 ID 不合法", "9001026"),
        PAGE_PARAMETER_IS_ILLEGAL("9001027-页面参数不合法", "9001027"),
        DELETED_PAGE_IDS_CANNOT_EXCEED_TEN("9001028-一次删除页面 ID 数量不能超过 10", "9001028"),
        PAGE_IS_ALREADY_APPLIED_TO_THE_DEVICE("9001029-页面已应用在设备中,请先解除应用关系再删除", "9001029"),
        ONE_QUERY_PAGE_ID_CANNOT_EXCEED_FIFTY("9001030-一次查询页面 ID 数量不能超过 50", "9001030"),
        THE_TIME_INTERVAL_IS_ILLEGAL("9001031-时间区间不合法", "9001031"),
        SAVE_DEVICE_AND_PAGE_BINDING_PARAMETERS_ERROR("9001032-保存设备与页面的绑定关系参数错误", "9001032"),
        STORE_ID_IS_ILLEGAL("9001033-门店 ID 不合法", "9001033"),
        DEVICE_NOTE_INFORMATION_IS_TOO_LONG("9001034-设备备注信息过长", "9001034"),
        DEVICE_APPLICATION_PARAMETERS_ARE_ILLEGAL("9001035-设备申请参数不合法", "9001035"),
        QUERY_START_VALUE_IS_NOT_LEGAL("9001036-查询起始值 begin 不合法", "9001036");
    
        // 提示信息
        private String name;
        // 返回码
        private String code;
    
        /**
         * @param {name:提示信息}
         * @param {value:全局返回码}
         * @description {Constructor with parameters}
         * @description {有参构造函数}
         */
        WeChatGlobalReturnCodeEnum(String name, String code) {
            this.name = name;
            this.code = code;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        @Override
        public String toString() {
            return "WeChatGlobalReturnCodeEnum{" +
                    "name='" + name + '\'' +
                    ", code=" + code +
                    '}';
        }
    
        public static String getEnum(String code) {
            for (WeChatGlobalReturnCodeEnum codeEnum : WeChatGlobalReturnCodeEnum.values()) {
                if (codeEnum.code.equals(code)) {
                    return codeEnum.name;
                }
            }
            return "Unknown WeChat Global Return Code.";
        }
    }

    展开全文
  • 在使用微信Weui开发网页时,监听手机上的物理返回键。当按下返回键时:提示你是否退出。确定---》退出。 取消---》还在原页面。微信没有提供这样的接口,按下返回键,默认会触发window.history.back()方法,回到上一...

    <p>在使用微信Weui开发网页时,监听手机上的物理返回键。<strong><span style="color: rgb(255, 0, 0);">当按下返回键时</span></strong>:提示你是否退出。<strong><span style="font-size: 18px;">确定---》退出</span></strong>。   <strong><span style="font-size: 18px;">取消---》还在原页面。</span></strong></p><p>微信没有提供这样的接口,按下<strong><span style="color: rgb(255, 0, 0);">返回键</span></strong>,<strong><span style="font-size: 18px;">默认</span></strong>会触发<strong><span style="font-size: 18px;">window.history.back()</span></strong>方法,回到上一个页面。</p><p>我们可以使用pushState()方法想history中加入URL连接,并且让窗体监听popstate事件,从而检测到从history中弹出URL链接。</p><p>思路:</p><p><span style="white-space: pre;">	</span>1.在页面加载时,使用pushstate()方法想history中添加一个空连接</p><p><span style="white-space: pre;">	</span>2.让页面监听popstate事件,在方法中,弹出一个对话框,如果确定的话,就返回上一页,如果取消,就添加一个空连接,(注意,但你按下返回键时,那个空连接就弹出了)</p><p>
    </p><p>代码如下:</p>
    </pre><pre code_snippet_id="1630727" snippet_file_name="blog_20160331_3_134785" name="code" class="javascript">
    $(document).ready(function(){
    //在页面初始化时,加入一个空连接
    pushHistory();
    });


    //让窗口监听popstate事件
    setTimeout(function(){
    window.addEventListener("popstate",function(e){
    //方法一:
    //这里使用jqueryweui.js
    $.confirm("你确认要退出吗",function(){
    //单击确定触发
    window.history.back();
    },function(){
    //取消是触发,添加一个空连接
    pushHistory();
    });
    //方法二:
    //如果是单独的js
    var i=confirm("你确认要退出吗");
    if(i){
    window.history.back();
    }else{
    pushHistory();
    }
    });
    },300);


    //在history加入空连接
    function pushHistory(){
    var state={title:"title",url:"#"};
    window.history.pushState(state,"title","#");
    };
    
    

    展开全文
  • 先去检查检查微信开发平台是否配置授权目录,授权配置的网址要比使用的网址高一级。 例如,授权目录配置 www.baidu.com/pay 使用的网址应该是 www.baidu.com/pay/order 项目路由也要配置正确,需要指向使用微信...
  • Android微信支付返回-1的解决方案

    千次阅读 2018-05-22 16:00:24
    相信各位小伙伴在接入微信支付的时候,一定遇到过返回-1的这个问题,说实话,这个问题真的很恶心,微信开放平台提供的文档在关于-1这个问题的描述(可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的...
  • 微信开发(二)--上传图片和附件

    千次阅读 2018-06-22 11:11:36
    今天整理一下微信开发中遇到的图片和附件的上传问题。 开发环境参考:微信开发(一)--分享接口 点击打开链接 由于是基于weixin-java-tools 封装的java sdk,所以在微信底层处理上我们可以直接调用WxMpService. ...
  • 微信公众号项目返回上一页因为是ajax动态数据,返回上一页微信浏览器会自动刷新页面, 不符合用户场景,需要返回上一页停留在原来点击的列表页处 尝试方案一: 寻找微信官方解决方案,未找到解决方案,有解决方案...
  • 微信公众号开发系列-获取微信OpenID

    万次阅读 多人点赞 2015-05-21 22:51:30
    微信开发时候在做消息接口交互的时候需要使用带微信加密ID(OpenId),下面讲讲述2中类型方式获取微信OpenID,接收事件推送方式和网页授权获取用户基本信息方式获取。
  • 说到帮他做一个微信公众号,于是今天在折腾这个,在微信页面添加服务器配置之后,点提交,自己搭建的web服务器收到了微信转发过来的请求,然后按要求返回传过来的随机字符串之后,微信页面提示请求URL超时,于是就...
  • 微信开发文档,进入了以后,我们首先要找到微信的授权,在微信网页开发下有网页授权 点击网页授权后会出现一堆文字,你可能啥都看不懂没关系,跟着我的脚步,摩擦,摩擦 往下面找你会找到一个这个, https://open...
  • 微信公众号主要有以下几个步骤 微信公众号的通讯机制 微信公众号简介 1.注册微信公众号 2.注册测试公众号 3.搭建微信本地调试环境 1)下载客户端natapp: 2)安装natapp: 4.微信公众号接入(校验签名) 第1步中...
  • 微信公众号开发技术要点

    千次阅读 多人点赞 2019-03-08 09:29:26
    微信公众号开发技术要点 微信公众号开发技术要点 微信公众号及其接口功能介绍 基本概念 公众号开发者模式 代码验证及图示 Open ID与Union ID 基本概念 使用说明 Access_token 基本介绍 注意事项 获取流程 ...
  • 原因:订单总金额为0,即total_fee不能为0 调用微信支付的统一下单接口,订单总金额不能为0,否则会返回这个错误提示
  • C#微信开发

    千次阅读 2017-12-24 10:35:37
    C#开发微信门户及应用教程   作者:伍华聪   C#开发微信门户及应用(1)--开始使用微信接口 6 1、微信账号 6 2、微信菜单定义 7 3、接入微信的链接处理 8 4、使用开发方式创建菜单 14 5、我创建的菜单案例 17 C#...
  • 网上流传着一个“微信开发调试小工具”,谁做都不知道了。反正我觉得那个东西看起来挺不爽的,因为其信息发送类型不是很全面,于是我就把它反编译过来自己重写一个了。 我复用了它原本项目的一个类和几个方法 。与...
  • 微信开发一(与自己的后台交互)

    千次阅读 2017-08-27 21:37:21
    在进入微信开发前,首先我们要将我们的ip映射成url访问地址,这里我用的是natapp,感觉还是挺稳定的,只不过映射的地址搁一段时间会被替换掉natapp的下载地址https://natapp.cn/接下来进入到微信的公众号平台里面去...
  • 微信公众号 返回40163

    2019-12-03 20:19:29
    微信得文档中,看到code 得说明,当时没注意, 文档地址 产生这个错误得原因是,我自己代码得逻辑问题,把已经code 做了缓存,而且使用后没有清除。 导致登录得时候,会从缓存中读取酒code用来登录,到处报错 ...
  • 微信网页授权 所谓的微信网页授权说白了就是 用户微信客户端内访问第三方网页,公众号可以根据网页授权这个机制来获取用户的基本信息,然后进行相应的逻辑处理。...可以参考文档 第二章 “微信开发之环境...
1 2 3 4 5 ... 20
收藏数 24,414
精华内容 9,765
关键字:

微信开发 返回提示