模板消息发送
<p>
<a href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277">微信模板消息文档</a>

@param access_token    access_token
@param templateMessage templateMessage
@return TemplateMessageResult
161440
public static TemplateMessageResult messageTemplateSend(String access_token, TemplateMessage templateMessage) {
        String messageJson = JsonUtil.toJSONString(templateMessage);
        HttpUriRequest httpUriRequest = RequestBuilder.post()
                .setHeader(jsonHeader)
                .setUri(BASE_URI + "/cgi-bin/message/template/send")
                .addParameter(PARAM_ACCESS_TOKEN, API.accessToken(access_token))
                .setEntity(new StringEntity(messageJson, Charset.forName("utf-8")))
                .build();
        return LocalHttpClient.executeJsonResult(httpUriRequest, TemplateMessageResult.class);
    }
601093
public function addTemplateMessage($tpl_id){
        $data = array ('template_id_short' =>$tpl_id);
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_post(self::API_URL_PREFIX.self::TEMPLATE_ADD_TPL_URL.'access_token='.$this->access_token,self::json_encode($data));
        if($result){
            $json = json_decode($result,true);
            if (!$json || !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json['template_id'];
        }
        return false;
    }
411511
public static <T> TemplateExpression<T> template(Class<? extends T> cl, String template, Object... args) {
        return template(cl, TemplateFactory.DEFAULT.create(template), ImmutableList.copyOf(args));
    }
253606
public static String format(String templateMessage, Object... args) throws TechnicalException {
        if (null != templateMessage && countWildcardsOccurrences(templateMessage, "%s") == args.length) {
            try {
                return String.format(templateMessage, args);
            } catch (final Exception e) {
                throw new TechnicalException(getMessage(FAIL_MESSAGE_FORMAT_STRING), e);
            }
        } else {
            throw new TechnicalException(getMessage(FAIL_MESSAGE_FORMAT_STRING));
        }
    }
205849
public SendTemplateResponse send(TemplateMsg msg) {
        LOG.debug("发送模版消息......");
        BeanUtil.requireNonNull(msg.getTouser(), "openid is null");
        BeanUtil.requireNonNull(msg.getTemplateId(), "template_id is null");
        BeanUtil.requireNonNull(msg.getData(), "data is null");
//        BeanUtil.requireNonNull(msg.getTopcolor(), "top color is null");
//        BeanUtil.requireNonNull(msg.getUrl(), "url is null");
        String url = BASE_API_URL + "cgi-bin/message/template/send?access_token=#";
        BaseResponse r = executePost(url, msg.toJsonString());
        String resultJson = isSuccess(r.getErrcode()) ? r.getErrmsg() : r.toJsonString();
        SendTemplateResponse result = JSONUtil.toBean(resultJson, SendTemplateResponse.class);
        return result;
    }
21104
private PayloadTemplateMessageBuilder parsePayloadTemplateBuilder(Element messageElement) {
        PayloadTemplateMessageBuilder messageBuilder;
        
        messageBuilder = parsePayloadElement(messageElement);
        
        Element xmlDataElement = DomUtils.getChildElementByTagName(messageElement, "data");
        if (xmlDataElement != null) {
            messageBuilder = new PayloadTemplateMessageBuilder();
            messageBuilder.setPayloadData(DomUtils.getTextValue(xmlDataElement).trim());
        }

        Element xmlResourceElement = DomUtils.getChildElementByTagName(messageElement, "resource");
        if (xmlResourceElement != null) {
            messageBuilder = new PayloadTemplateMessageBuilder();
            messageBuilder.setPayloadResourcePath(xmlResourceElement.getAttribute("file"));
            if (xmlResourceElement.hasAttribute("charset")) {
                messageBuilder.setPayloadResourceCharset(xmlResourceElement.getAttribute("charset"));
            }
        }
        
        if (messageBuilder != null) {
            Map<String, String> overwriteXpath = new HashMap<>();
            Map<String, String> overwriteJsonPath = new HashMap<>();
            List<?> messageValueElements = DomUtils.getChildElementsByTagName(messageElement, "element");
            for (Iterator<?> iter = messageValueElements.iterator(); iter.hasNext();) {
                Element messageValue = (Element) iter.next();
                String pathExpression = messageValue.getAttribute("path");

                if (JsonPathMessageValidationContext.isJsonPathExpression(pathExpression)) {
                    overwriteJsonPath.put(pathExpression, messageValue.getAttribute("value"));
                } else {
                    overwriteXpath.put(pathExpression, messageValue.getAttribute("value"));
                }
            }
            
            if (!overwriteXpath.isEmpty()) {
                XpathMessageConstructionInterceptor interceptor = new XpathMessageConstructionInterceptor(overwriteXpath);
                messageBuilder.add(interceptor);
            }

            if (!overwriteJsonPath.isEmpty()) {
                JsonPathMessageConstructionInterceptor interceptor = new JsonPathMessageConstructionInterceptor(overwriteJsonPath);
                messageBuilder.add(interceptor);
            }
        } 
        
        return messageBuilder;
    }
504706
public function createAccessToken(AccessTokenFactory $accessTokenFactory, $client_id, $user_id, $scope)
    {
        return $accessTokenFactory->createAccessToken($client_id, $user_id, $scope);
    }
1189916
public static String parseTemplate(String template, Object paramObj) {
        String output;
        try {
            output = (String) TemplateRuntime.eval(template, paramObj);
        } catch (Exception e) {
            throw new ParseExpressionException("解析Mvel模板异常，解析出错的模板为:" + template, e);
        }
        return output;
    }
835253
function sendTemplateSMS($to,$datas,$tempId)
    {
        //主帐号鉴权信息验证，对必选参数进行判空。
        $auth=$this->accAuth();
        if($auth!=""){
            return $auth;
        }
        // 拼接请求包体
        if($this->BodyType=="json"){
           $data="";
           for($i=0;$i<count($datas);$i++){
              $data = $data. "'".$datas[$i]."',";
           }
           $body= "{'to':'$to','templateId':'$tempId','appId':'$this->AppId','datas':[".$data."]}";
        }else{
           $data="";
           for($i=0;$i<count($datas);$i++){
              $data = $data. "<data>".$datas[$i]."</data>";
           }
           $body="<TemplateSMS>
                    <to>$to</to> 
                    <appId>$this->AppId</appId>
                    <templateId>$tempId</templateId>
                    <datas>".$data."</datas>
                  </TemplateSMS>";
        }
        $this->showlog("request body = ".$body);
        // 大写的sig参数
        $sig =  strtoupper(md5($this->AccountSid . $this->AccountToken . $this->Batch));
        // 生成请求URL
        $url="https://$this->ServerIP:$this->ServerPort/$this->SoftVersion/Accounts/$this->AccountSid/SMS/TemplateSMS?sig=$sig";
        $this->showlog("request url = ".$url);
        // 生成授权：主帐户Id + 英文冒号 + 时间戳。
        $authen = base64_encode($this->AccountSid . ":" . $this->Batch);
        // 生成包头
        $header = array("Accept:application/$this->BodyType","Content-Type:application/$this->BodyType;charset=utf-8","Authorization:$authen");
        // 发送请求
        $result = $this->curl_post($url,$body,$header);
        $this->showlog("response body = ".$result);
        if($this->BodyType=="json"){//JSON格式
           $datas=json_decode($result);
        }else{ //xml格式
           $datas = simplexml_load_string(trim($result," \t\n\r"));
        }
      //  if($datas == FALSE){
//            $datas = new stdClass();
//            $datas->statusCode = '172003';
//            $datas->statusMsg = '返回包体错误'; 
//        }
        //重新装填数据
        if($datas->statusCode==0){
         if($this->BodyType=="json"){
            $datas->TemplateSMS =$datas->templateSMS;
            unset($datas->templateSMS);
          }
        }

        return $datas;
    }
308414
public static GetResult<?> get(String accessToken, String postJson) {
		HttpUriRequest httpUriRequest = RequestBuilder
				.post()
				.setHeader(jsonHeader)
				.setUri(BASE_URI + "/card/get")
				.addParameter(PARAM_ACCESS_TOKEN, API.accessToken(accessToken))
				.setEntity(new StringEntity(postJson, Charset.forName("utf-8")))
				.build();
		AbstractResult abs = LocalHttpClient.executeJsonResult(httpUriRequest, AbstractResult.class);
		if (!abs.isSuccess()) {
			return abs;
		}

		GetResult<?> result = abs;
		CardType cardType = CardType.valueOf(abs.getCard().getCardType().toUpperCase());
		Class<? extends GetResult<?>> clazz = null;
		switch (cardType) {
		case CASH:
			clazz = GetCashResult.class;
			break;
		case DISCOUNT:
			clazz = GetDiscountResult.class;
			break;
		case GENERAL_COUPON:
			clazz = GetGeneralCouponResult.class;
			break;
		case GROUPON:
			clazz = GetGrouponResult.class;
			break;
		// ...其它卡券类型
		default:
			break;
		}
		if (null != clazz) {
			result = LocalHttpClient.executeJsonResult(httpUriRequest, clazz);
		}
		return result;
	}
329512
protected synchronized void getAccessToken(AipClientConfiguration config) {
        if (!needAuth()) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug(String.format("app[%s] no need to auth", this.appId));
            }
            return;
        }
        JSONObject res = DevAuth.oauth(aipKey, aipToken, config);
        if (res == null) {
            LOGGER.warn("oauth get null response");
            return;
        }
        if (!res.isNull("access_token")) {
            // openAPI认证成功
            state.transfer(true);
            accessToken = res.getString("access_token");

            LOGGER.info("get access_token success. current state: " + state.toString());
            Integer expireSec = res.getInt("expires_in");
            Calendar c = Calendar.getInstance();
            c.add(Calendar.SECOND, expireSec);
            expireDate = c;
            // isBceKey.set(false);
            // 验证接口权限
            String[] scope = res.getString("scope").split(" ");
            boolean hasRight = false;
            for (String str : scope) {
                if (AipClientConst.AI_ACCESS_RIGHT.contains(str)) {
                    // 权限验证通过
                    hasRight = true;
                    break;
                }
            }
            state.transfer(hasRight);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("current state after check priviledge: " + state.toString());
            }
        }
        else if (!res.isNull("error_code")) {
            state.transfer(false);
            LOGGER.warn("oauth get error, current state: " + state.toString());
        }
    }
1259428
public Maybe<AccessToken> isValidToken(String token) {
        return db.findAccessToken(token)
                .flatMap(accessToken -> {
                    LOG.info("token详情:" + accessToken);
                    if (accessToken != null && accessToken.isValid()) {
                        if (accessToken.tokenExpired()) {
                            LOG.info(new JSONObject()
                                    //todo 设计一个打印type日志的Java类，将结构固定下来
                                    .fluentPut("description", "accessToken has expired, client_id= " + accessToken.getClientId())
                                    .fluentPut("accessToken", accessToken)
                                    .fluentPut("type", LogTypeOAuth20.oAuth20TokenExpired));
                            db.updateAccessTokenValidStatus(accessToken.getToken(), false).subscribe();
                            // return empty result if token expired.
                            return Maybe.empty();
                        }
                        return Maybe.just(accessToken);
                    }
                    return Maybe.empty();
                });
    }
802947
private String generateContent(String templateFile) {
		try {
			GStringTemplateEngine gStringEngine = new GStringTemplateEngine();
			URL url = loadTemplate(templateFolder + "/" + templateFile);
			if (url == null) {
				logWarn("NO TEMPLATE FOUND FOR " + templateFile);
			} else {
				logDebug("Loaded template: " + url.getPath());
			}
			if (url == null) return null;
			
			Template template = gStringEngine.createTemplate(url);
			return template.make(modelMap).toString();
		} catch (Exception e) {
			ps.println("### ERROR: Failed generate templatefile: " + templateFile);
			e.printStackTrace(ps);
			return null;
		}
	}
109225
public File getTemplateFile(String templateId) throws HelloSignException {
        String url = BASE_URI + TEMPLATE_FILE_URI + "/" + templateId;
        String fileName = TEMPLATE_FILE_NAME + "." + TEMPLATE_FILE_EXT;
        return httpClient.withAuth(auth).get(url).asFile(fileName);
    }
876327
private Object receiveAndRetry(AmqpTemplate template) throws InterruptedException
    {
        Object message = null;
        try
        {
            message = template.receiveAndConvert();
        }
        catch (AmqpException ex)
        {
            // 接続断のタイミングにより、例外が出力される場合があるため、1秒後にリトライする。
            // 再度発生した例外は呼び出し元に返す。
            Thread.sleep(getRetryInterval());
            message = template.receiveAndConvert();
        }
        return message;
    }
1259616
public function sendTplMsg($tplId, $data, $url, $openid, $topcolor = '#FF0000', $accessToken = null)
    {
        if (is_null($accessToken)) {
            $accessToken = $this->getAccessToken();
        }

        $postData = [
            'touser' => $openid,
            'template_id' => $tplId,
            'url' => $url,
            'topcolor' => $topcolor,
            'data' => $data,
        ];

        $apiUrl = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='.$accessToken;
        $result = $this->_curl($apiUrl, json_encode($postData), 'post');

        if (isset($result['errcode']) && $result['errcode'] == '0') {
            return true;
        } else {
            return $result;
        }
    }
535451
public function sendTemplateMessage($touser, $template_id, $data, $url = null) {
		$this->getData('/cgi-bin/message/template/send', [
			'access_token' => $this->getAccessToken(),
		], Json::encode([
			'touser' => $touser,
			'template_id' => $template_id,
			'url' => $url,
			'data' => $data,
		]));

		return $this->errcode == 0;
	}