/** * Copyright (c) 2011-2014, James Zhan 詹波 (jfinal@126.com). * * Licensed under the Apache License, Version 2.0 (the "License"); */ package com.jfinal.weixin.sdk.api; import com.jfinal.weixin.sdk.utils.JsonUtils; import java.math.BigDecimal; import java.math.BigInteger; import java.util.List; import java.util.Map; /** * 封装 API 响应结果,将 json 字符串转换成 java 数据类型 * * jackson 中 json 类型与 java 类型对应关系如下: *
 *  http://wiki.fasterxml.com/JacksonInFiveMinutes
 *  JSON TYPE                JAVA TYPE
 *  object                    LinkedHashMap<String,Object>
 *  array                    ArrayList<Object>
 *  string                    String
 *  number (no fraction)    Integer, Long or BigInteger (smallest applicable)
 *  number (fraction)        Double (configurable to use BigDecimal)
 *  true|false                Boolean
 *  null                    null
 *  
*/ public class ApiResult { private Map attrs; private String json; /** * 通过 json 构造 ApiResult,注意返回结果不为 json 的 api(如果有的话) * @param jsonStr json字符串 */ @SuppressWarnings("unchecked") public ApiResult(String jsonStr) { this.json = jsonStr; try { Map temp = JsonUtils.parse(jsonStr, Map.class); this.attrs = temp; refreshAccessTokenIfInvalid(); } catch (Exception e) { throw new RuntimeException(e); } } /** * 通过 json 创建 ApiResult 对象,等价于 new ApiResult(jsonStr) * @param jsonStr json字符串 * @return {ApiResult} */ public static ApiResult create(String jsonStr) { return new ApiResult(jsonStr); } /** * 如果 api 调用返回结果表明 access_token 无效,则刷新它 * 正常情况下不会出现使用本方法刷新 access_token 的操作,除非以下情况发生: * 1:另一程序重新获取了该公众号的 access_token * 2:使用微信公众平台接口调试工具获取了该公众号的 access_token,此情况本质上与 1 中情况相同 * 3:微信服务器重新调整了过期时间或者发生其它 access_token 异常情况 * * 2016-06-21 by L.cm 添加 synchronized 锁感谢Git@osc #Lucare * */ private synchronized void refreshAccessTokenIfInvalid() { if (isAccessTokenInvalid()) AccessTokenApi.refreshAccessToken(); } public String getJson() { return json; } public String toString() { return getJson(); } /** * APi 请求是否成功返回 * @return {boolean} */ public boolean isSucceed() { Integer errorCode = getErrorCode(); // errorCode 为 0 时也可以表示为成功,详见:http://mp.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E return (errorCode == null || errorCode == 0); } public Integer getErrorCode() { return getInt("errcode"); } public String getErrorMsg() { Integer errorCode = getErrorCode(); if (errorCode != null) { String result = ReturnCode.get(errorCode); if (result != null) return result; } return (String)attrs.get("errmsg"); } @SuppressWarnings("unchecked") public T get(String name) { return (T)attrs.get(name); } public String getStr(String name) { return (String)attrs.get(name); } public Integer getInt(String name) { Number number = (Number) attrs.get(name); return number == null ? null : number.intValue(); } public Long getLong(String name) { Number number = (Number) attrs.get(name); return number == null ? null : number.longValue(); } public BigInteger getBigInteger(String name) { return (BigInteger)attrs.get(name); } public Double getDouble(String name) { return (Double)attrs.get(name); } public BigDecimal getBigDecimal(String name) { return (BigDecimal)attrs.get(name); } public Boolean getBoolean(String name) { return (Boolean)attrs.get(name); } @SuppressWarnings("rawtypes") public List getList(String name) { return (List)attrs.get(name); } @SuppressWarnings("rawtypes") public Map getMap(String name) { return (Map)attrs.get(name); } /** * 判断 API 请求结果失败是否由于 access_token 无效引起的 * 无效可能的情况 error_code 值: * 40001 = 获取access_token时AppSecret错误,或者access_token无效(刷新后也可以引起老access_token失效) * 42001 = access_token超时 * 42002 = refresh_token超时 * 40014 = 不合法的access_token * @return {boolean} */ public boolean isAccessTokenInvalid() { Integer ec = getErrorCode(); return ec != null && (ec == 40001 || ec == 42001 || ec == 42002 || ec == 40014); } }