首页 > 其他分享 >微信公众号发送模板消息实现

微信公众号发送模板消息实现

时间:2024-11-11 18:45:13浏览次数:3  
标签:openid return String 微信 replace 发送 jsonObject null 模板

微信公众号模板消息

文章目录

1、准备工作

1.1、申请公众号

1.2、配置模板消息

2、代码实现

2.1、配置信息

公众号小程序配置信息

# 微信小程序和公众号相关配置
wechat-app:
  config:
    defaultMiniAppId: wxc641315948b111ed05
    wechatConfigs:
      - miniAppId: wxc641315948b111ed05
        miniAppSecret: 6f189d5dc352c8c3afc118f01106e337
        miniVersion: develop
        publicAppId: wx43ada9010218abcc
        publicAppSecret: d14fdef4218676bd1511addc8769903c
        publicReportTemplateId: Mvd24ZSQCiOA9JGcP5zZhCes0MRfX_CxmL5T74GAmz0
        publicReportTemplateInfo: '{"touser":"OPENID","template_id":"Mvd24ZSQCiOA9JGcP5zZhCes0MRfX_CxmL5T74GAmz0","miniprogram":{"appid":"wxc641315948b111ed05","pagepath":"pages_report/report/index?reportType=REPORT_TYPE&startTime=START_TIME&endTime=END_TIME"},"data":{"thing10":{"value":"NOTIFY_PERSON"},"thing9":{"value":"您的值守NOTIFY_TYPE已经生成,请查阅"},"time8":{"value":"DATE_TIME"}}}'
        publicAlarmTemplateId: MIN5UDSlaPssabV7m4cWgj_5cBBDPg-YNmjG07hJAsA
        publicAlarmTemplateInfo: '{"touser":"OPENID","template_id":"MIN5UDSlaPssabV7m4cWgj_5cBBDPg-YNmjG07hJAsA","miniprogram":{"appid":"wxc641315948b111ed05","pagepath":"pages_secure/secure/live"},"data":{"thing72":{"value":"NOTIFY_PERSON"},"thing46":{"value":"ALARM_TYPE"},"time3":{"value":"DATE_TIME"}}}'
      - miniAppId: wx7657707fe455b6ce
        miniAppSecret: ef3779d6260803c705db2b16e969e994
        miniVersion: develop
        publicAppId: wxea5add94fcac1728
        publicAppSecret: 3e0fa49f5a9bb4404e603524c6d9363c9
        publicReportTemplateId: nhyra4N49tDy-JY7waNbg4lnAL2yjYCcqUh5C736a8k
        publicReportTemplateInfo: '{"touser":"OPENID","template_id":"nhyra4N49tDy-JY7waNbg4lnAL2yjYCcqUh5C736a8k","miniprogram":{"appid":"wx7657707fe455b6ce","pagepath":"pages_report/report/index?reportType=REPORT_TYPE&startTime=START_TIME&endTime=END_TIME"},"data":{"thing3":{"value":"NOTIFY_PERSON"},"thing6":{"value":"您的值守NOTIFY_TYPE已经生成,请查阅"},"time4":{"value":"DATE_TIME"}}}'
        publicAlarmTemplateId: oww6Yb9ql9BaNfXet4GAyWwplW0_m9uP5H_U6UyajUI
        publicAlarmTemplateInfo: '{"touser":"OPENID","template_id":"oww6Yb9ql9BaNfXet4GAyWwplW0_m9uP5H_U6UyajUI","miniprogram":{"appid":"wx7657707fe455b6ce","pagepath":"pages_secure/secure/live"},"data":{"thing72":{"value":"NOTIFY_PERSON"},"thing46":{"value":"ALARM_TYPE"},"time3":{"value":"DATE_TIME"}}}'

对应的java类型:
WechatAppConfig.java


import cn.hutool.core.collection.CollectionUtil;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.List;
import java.util.Optional;

/**
 * @author: 可乐加糖
 * @since: 2024/7/26 16:29
 * @description: 微信相关配置信息
 */
@ConfigurationProperties(prefix = "wechat-app.config")
@Configuration
@Data
public class WechatAppConfig {

	/** 默认小程序appid **/
	private String defaultMiniAppId;

	/** 多个小程序配置信息 **/
	private List<WechatConfig> wechatConfigs = null;

	@Data
	public static class WechatConfig {

		/** 微信小程序id appid **/
		private String miniAppId;

		/** 微信小程序密钥 secret **/
		private String miniAppSecret;

		/** 微信小程序版本 **/
		private String miniVersion;

		/** 公众号publicAppId **/
		private String publicAppId;

		/** 公众号publicAppSecret **/
		private String publicAppSecret;

		/** 公众号值守报告模板Id **/
		private String publicReportTemplateId;

		/** 公众号值守报告模板信息 **/
		private String publicReportTemplateInfo;

		/** 公众号告警模板Id **/
		private String publicAlarmTemplateId;

		/** 公众号告警模板信息 **/
		private String publicAlarmTemplateInfo;

		/** 公众号AccessToken **/
		private String publicAccessToken;

	}

	public static WechatConfig getWechatAppConfigByMiniAppId(String miniAppId, List<WechatConfig> wechatConfigs) {
		if (CollectionUtil.isEmpty(wechatConfigs)){
			return null;
		}
		Optional<WechatConfig> foundItem = wechatConfigs.stream()
				.filter(item -> miniAppId.equals(item.getMiniAppId()))
				.findFirst();
		if (!foundItem.isPresent()) {
			return null;
		}
		return foundItem.get();
	}

}

2.2、代码实现

2.2.1、发送业务代码实现
/**
	 * 公众号发送值守报告服务通知
	 *
	 * @param notifyTemplate   通知模板
	 * @param userList 收件人
	 * @param dateStr          日期
	 * @param notifyConfigInfo 配置文件
	 * @param title            主题
	 * @param reportPushSetVo  收件人与模板的关联关系
	 * @param reportType       报告类型编码
	 * @param reportTypeStr    报告类型
	 * @param startTime        开始时间
	 * @param endTime          结束时间
	 */
	private void sendWeChatFwReportMsg(NotifyTemplateVo notifyTemplate, List<ContractPerson> userList, String dateStr, NotifyConfigVo notifyConfigInfo,
							String title, ReportPushSetVo reportPushSetVo, String reportType, String reportTypeStr, String startTime, String endTime) {
		if (CollectionUtil.isEmpty(userList)){
			log.error("公众号发送值守报告:用户列表信息为空!!!");
			return;
		}

		List<Long> userIds = userList.stream().map(ContractPerson::getId).collect(Collectors.toList());
		R<List<ContractPerson>> listUserRWeChat = remoteContractPersonService.selectUserByUserIdsAndWeChat(userIds);
		if (!R.isOk(listUserRWeChat) || listUserRWeChat.getData() == null){
			log.error("公众号发送值守报告 根据用户id查询用户列表为空!!!");
			return;
		}

		List<ContractPerson> userWeChatList = listUserRWeChat.getData();
		List<ContractPerson> contractPersonList = userWeChatList.stream()
				.filter(e -> StrUtil.isNotEmpty(e.getPublicOpenId()) && StrUtil.isNotEmpty(e.getSubFlag()))
				.filter(e -> StrUtil.equals(e.getSubFlag(), EventConstant.SUB_FLAG_1))
				.filter(e -> StrUtil.isNotEmpty(e.getMiniAppId()))
				.collect(Collectors.toList());

		if (CollectionUtil.isEmpty(contractPersonList)) {
			log.error("公众号发送值守报告:当前查询到用户均未关注公众号,subFlag=1 视为已订阅,0:未订阅:{}", JSON.toJSONString(userWeChatList));
			return;
		}

		// 根据miniAppId和publicOpenId去重
		List<ContractPerson> distinctContractPersonList = removeDuplicateFieldByMiniAppId(contractPersonList);

		// 判断公众号是否包含值守报告模板:
		List<WechatAppConfig.WechatConfig> wechatConfigs = wechatAppConfig.getWechatConfigs();
		List<WechatAppConfig.WechatConfig> wechatConfigList = new ArrayList<>();
		distinctContractPersonList.forEach(contractPerson -> {
			WechatAppConfig.WechatConfig wechatConfig = WechatAppConfig.getWechatAppConfigByMiniAppId(contractPerson.miniAppId, wechatConfigs);
			if (wechatConfig == null || org.apache.commons.lang3.StringUtils.isEmpty(wechatConfig.getPublicReportTemplateId())){
				log.error("公众号发送告警通知:小程序对应公众号未配置值守报告模板: miniAppId:{} , publicAppId:{} ", wechatConfig.getMiniAppId(), wechatConfig.getPublicAppId());
				return;
			}

			if(wechatConfigList.size() > 0){
				WechatAppConfig.WechatConfig wechatConfigTemp = wechatConfigList.stream().filter(wechatConfig1 -> contractPerson.miniAppId.equals(wechatConfig1.getMiniAppId())).findFirst().orElse( null);
				if (wechatConfigTemp != null) {
					return;
				}
			}

			String accessToken = remoteAppletService.getPublicAccessToken(contractPerson.miniAppId).getData();
			if (com.pig4cloud.pig.common.core.util.StringUtils.isEmpty(accessToken)){
				log.error("公众号发送告警通知:获取miniAppId:{} 对应的公众号AccessToken为空", contractPerson.miniAppId);
				return;
			}
			wechatConfig.setPublicAccessToken(accessToken);
			wechatConfigList.add(wechatConfig);

		});

		// 获取通知模板信息
		NotifyConfigVo notifyConfig = notifyTemplate.getNotifyConfig();
		JSONObject configJsonObject = JSON.parseObject(notifyConfig.getConfiguration());

		String time = dateStr;
		if (reportType.equals("week")){
			time = startTime+"~"+endTime;
		}
		String messageFormat = notifyTemplate.getMessageFormat();
		String content = String.format(messageFormat, time);

		List<MessageVo> listMessageSms = new ArrayList<>();
		for (ContractPerson contractPerson : distinctContractPersonList) {
			WechatAppConfig.WechatConfig wechatConfigTemp = wechatConfigList.stream().filter(wechatConfig -> contractPerson.miniAppId.equals(wechatConfig.getMiniAppId())).findFirst().orElse( null);
			if (wechatConfigTemp == null || org.apache.commons.lang3.StringUtils.isEmpty(wechatConfigTemp.getPublicAccessToken())) {
				log.error("公众号发送值守报告:模板信息或者公众号AccessToken为空不发送,小程序appId:{}", contractPerson.miniAppId);
				continue;
			}

			String sendUrl = configJsonObject.getString("url").replace("ACCESS_TOKEN", wechatConfigTemp.getPublicAccessToken());
			HttpRequest httpPost = HttpUtil.createPost(sendUrl);

			String template = wechatConfigTemp.getPublicReportTemplateInfo();
			String bodyStr = template.replace("OPENID", contractPerson.getPublicOpenId())
					.replace("REPORT_TYPE", reportType)
					.replace("START_TIME", startTime)
					.replace("END_TIME", endTime)
					.replace("NOTIFY_PERSON", contractPerson.getPhone())
					.replace("NOTIFY_TYPE", reportTypeStr)
					.replace("DATE_TIME", time);

			log.info("公众号发送值守报告:用户:{},手机号:{},发送URL:{}, 发送参数:{} ", contractPerson.getName(), contractPerson.getPhone(), sendUrl, JSONUtil.toJsonStr(bodyStr));
			httpPost.body(bodyStr, "application/json");
			HttpResponse execute = null;
			try {
				execute = httpPost.execute();
				log.info("公众号发送值守报告:用户:{},手机号:{},发送结果:{} ", contractPerson.getName(), contractPerson.getPhone(), execute.body());
			}catch (Exception e){
				log.error("公众号发送值守报告错误: 错误信息:", e);
			}
			Integer status;
			if (StrUtil.isNotEmpty(execute.body())) {
				JSONObject jsonObject = JSON.parseObject(execute.body());
				if (jsonObject.getIntValue("errcode") == 0 && jsonObject.getString("errmsg").equals("ok")) {
					status = MessageSendStatusEnum.SUCCESS.getStatus();
				} else {
					status = MessageSendStatusEnum.FAIL.getStatus();
				}
			} else {
				status = MessageSendStatusEnum.FAIL.getStatus();
			}
			MessageVo message = new MessageVo();
			message.setType(MessageTypeEnum.ON_DUCTY_REPORT.getType());
			message.setTypeName(MessageTypeEnum.ON_DUCTY_REPORT.getName());
			MessageNotifyTypeEnum messageTypeEnumByType = MessageNotifyTypeEnum.getMessageTypeEnumByType(notifyTemplate.getType());
			message.setNotifyType(messageTypeEnumByType.getValue());
			message.setNotifyTypeName(messageTypeEnumByType.getName());
			message.setTitle(title);
			message.setContent(content);
			message.setReferenceId(reportPushSetVo.getId());
			message.setUserId(contractPerson.getId());
			message.setPhone(contractPerson.getPhone());
			message.setNickname(contractPerson.getName());
			message.setCallingNickname(MessageCallingNicknameEnum.CALLING.getName());
			message.setCreateTime(new Date());

			Long orgId = reportPushSetVo.getOrgId();
			message.setOrganId(orgId);
			message.setResult(status);
			message.setResultDesc(StrUtil.isNotEmpty(null) ? null : MessageSendStatusEnum.getMessageSendStatusEnums(status).getName());
			listMessageSms.add(message);
		}
		if (listMessageSms != null && listMessageSms.size() > 0) {
			messageService.saveBatch(listMessageSms, listMessageSms.size());
		}

	}
2.2.2、获取公众号AccessToken

接口入口:

	@Inner
	@Operation(summary = "获取公众号AccessToken", description = "")
	@GetMapping("/getPublicAccessToken")
	public R<String> getPublicAccessToken(@RequestParam(name = "miniAppId") String miniAppId) {

		List<WechatAppConfig.WechatConfig> wechatConfigs = wechatAppConfig.getWechatConfigs();

		WechatAppConfig.WechatConfig wechatAppConfig = WechatAppConfig.getWechatAppConfigByMiniAppId(miniAppId, wechatConfigs);

		WechatConfigInfo wechatConfigInfo = new WechatConfigInfo();
		BeanUtils.copyProperties(wechatAppConfig, wechatConfigInfo);

		return R.ok(appletService.getPublicAccessToken(wechatConfigInfo));
	}

WeixinHandler.java
主要方法为:getPublicAccountAccessToken()


import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.pig4cloud.pig.common.wechat.bean.OAuthInfo;
import com.pig4cloud.pig.common.wechat.bean.PhoneNumberInfo;
import com.pig4cloud.pig.common.wechat.bean.WechatConfigInfo;
import com.pig4cloud.pig.common.wechat.constant.WeChatPlatform;
import com.pig4cloud.pig.common.wechat.util.Configure;
import com.pig4cloud.pig.common.wechat.util.Signature;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 类: WeixinHandler <br>
 * 描述: 微信工具类 <br>
 * 作者: [email protected] <br>
 * 时间: 2017年11月28日 上午11:51:20 <br>
 */
public class WeixinHandler {

	/**
	 * 日志类处理类
	 **/
	private static Logger logger = LoggerFactory.getLogger(WeixinHandler.class);

	/**
	 * 全局缓存 订阅号 accesstoken有效期7200秒
	 **/
	public static String dyAccesstoken = null;

	/**
	 * 全局缓存 服务号 accesstoken有效期7200秒
	 **/
	public static String fwAccesstoken = null;

	/**
	 * 全局缓存 小程序 accesstoken有效期7200秒
	 **/
	public static String miniAccesstoken = null;

	/**
	 * 与接口配置信息中的Token要一致
	 **/
	private static String token = "aidou";

	/**
	 * 全局缓存jsapi_ticket 有效期7200秒 ,jsapi_ticket是公众号用于调用微信JS接口的临时票据
	 * 由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,
	 * 开发者必须在自己的服务全局缓存jsapi_ticket
	 **/
	public static String jsapiTicket = null;

	/**
	 * 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
	 **/
	public static String oauth2Token = null;

	/**
	 * 用户刷新access_token 由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,
	 * refresh_token拥有较长的有效期(7天、30天、60天、90天),当refresh_token失效的后,需要用户重新授权。
	 **/
	public static String refreshToken = null;

	/**
	 * dyAccesstoken超时时间
	 **/
	public static Long lastGetDyAccessTokenTime = null;

	/**
	 * fwAccesstoken超时时间
	 **/
	public static Long lastGetFwAccessTokenTime = null;

	/**
	 * miniAccesstoken超时时间
	 **/
	public static Long lastGetMiniAccessTokenTime = null;

	/**
	 * JsapiTicket超时时间
	 **/
	public static Long lastGetJsapiTicketTime = null;

	/**
	 * oauth2Token超时时间
	 **/
	public static Long lastGetOauth2TokenTime = null;

	/**
	 * 全局缓存 测试1 accesstoken有效期7200秒
	 **/
	public static String oneAccesstoken = null;

	/**
	 * oneAccesstoken超时时间
	 **/
	public static Long lastGetOneAccessTokenTime = null;

	/** ===========================================获取AccessToken==================================================== **/
	/**
	 * 此方法描述的是:订阅号获取access_token(用户获取用户基本信息的accesstoken 与授权的token不一样)
	 *
	 * @return String
	 */
	public static String getDyAccessToken() {
		logger.info("one___:lastGetDyAccessTokenTime:" + lastGetDyAccessTokenTime + "=dyAccesstoken:" + dyAccesstoken);
		if (StringUtils.isBlank(dyAccesstoken) || lastGetDyAccessTokenTime == null || (System.currentTimeMillis() / 1000) - (lastGetDyAccessTokenTime.longValue() / 1000) >= 5000) {
			lastGetDyAccessTokenTime = new Long(System.currentTimeMillis());
			String url = WeChatPlatform.ACCESS_TOKEN_URL.replace("APPID", Configure.getDyAppID()).replace("APPSECRET", Configure.getDyAppSecret());
			JSONObject jsonObject = HttpHandler.doGetStr(url);
			logger.info("get wechat dyAccesstoken result :" + jsonObject);
			if (jsonObject != null) {
				dyAccesstoken = (String) jsonObject.get("access_token");
				if (dyAccesstoken == null) {
					logger.error("get wechat dyAccesstoken error :" + jsonObject);
				}
			}
			logger.info("two___:lastGetDyAccessTokenTime:" + lastGetDyAccessTokenTime + "=dyAccesstoken:" + dyAccesstoken);
			return dyAccesstoken;

		} else {
			logger.info("three___:lastGetDyAccessTokenTime:" + lastGetDyAccessTokenTime + "=dyAccesstoken:" + dyAccesstoken);
			return dyAccesstoken;
		}
	}

	/**
	 * 此方法描述的是:   服务号accessToken
	 *
	 * @return String
	 */
	public static String getFwAccessToken() {
		if (StringUtils.isBlank(fwAccesstoken) || lastGetFwAccessTokenTime == null || (System.currentTimeMillis() / 1000) - (lastGetFwAccessTokenTime.longValue() / 1000) >= 7000) {
			lastGetFwAccessTokenTime = new Long(System.currentTimeMillis());
			String url = WeChatPlatform.ACCESS_TOKEN_URL.replace("APPID", Configure.getFwAppID()).replace("APPSECRET", Configure.getFwAppSecret());
			JSONObject jsonObject = HttpHandler.doGetStr(url);
			logger.info("get wechat fwAccesstoken result :" + jsonObject);
			if (jsonObject != null) {
				fwAccesstoken = (String) jsonObject.get("access_token");
				if (fwAccesstoken == null) {
					logger.error("get wechat fwAccesstoken error :" + jsonObject);
				}
			}
			return fwAccesstoken;
		} else {
			return fwAccesstoken;
		}
	}

	/**
	 * 此方法描述的是:   小程序accessToken
	 *
	 * @return String
	 */
	public static String getMiniAccessToken() {
		if (StringUtils.isBlank(miniAccesstoken) || lastGetMiniAccessTokenTime == null || (System.currentTimeMillis() / 1000) - (lastGetMiniAccessTokenTime.longValue() / 1000) >= 7000) {
			lastGetMiniAccessTokenTime = new Long(System.currentTimeMillis());
			String url = WeChatPlatform.ACCESS_TOKEN_URL.replace("APPID", Configure.getMiniAppID()).replace("APPSECRET", Configure.getMiniAppSecret());
			JSONObject jsonObject = HttpHandler.doGetStr(url);
			logger.info("get wechat miniAccesstoken result :" + jsonObject);
			if (jsonObject != null) {
				miniAccesstoken = (String) jsonObject.get("access_token");
				if (miniAccesstoken == null) {
					logger.error("get wechat miniAccesstoken error :" + jsonObject);
				}
			}
			return miniAccesstoken;
		} else {
			return miniAccesstoken;
		}
	}

	/** ===========================================授权==================================================== **/
	/**
	 * 此方法描述的是:网页授权  默认授权 获取accesstoken
	 *
	 * @param code
	 * @return Map
	 */
	public static Map getSnsapiBaseOpenid(String code) {
		Map<String, String> resultMap = new HashMap<String, String>();
		String openid = null;
		lastGetOauth2TokenTime = new Long(System.currentTimeMillis());
		String url = WeChatPlatform.OAUTH2_ACCESS_TOKEN.replace("APPID", Configure.getFwAppID()).replace("SECRET", Configure.getFwAppSecret()).replace("CODE", code);
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		logger.info("getSnsapiBaseOpenid_jsonObject:" + jsonObject);
		if (jsonObject != null && jsonObject.get("errcode") == null) {
			oauth2Token = (String) jsonObject.get("access_token");
			openid = (String) jsonObject.get("openid");            //用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
			String scope = (String) jsonObject.get("scope");            //用户授权的作用域,使用逗号(,)分隔
			refreshToken = (String) jsonObject.get("refresh_token");   //刷新accesstoken用的
			Integer expiresIn = (Integer) jsonObject.get("expires_in");  // access_token接口调用凭证超时时间,单位(秒)
			resultMap.put("openid", openid);
			resultMap.put("scope", scope);
			resultMap.put("oauth2Token", oauth2Token);
		} else {
			return null;
		}
		return resultMap;
	}

	/**
	 * 此方法描述的是:  获取用户openid
	 *
	 * @param code
	 * @return String
	 */
	public static String getUserOpenid(String code) {
		Map<String, String> resultMap = new HashMap<>();
		String openid = null;
		lastGetOauth2TokenTime = new Long(System.currentTimeMillis());
		String url = WeChatPlatform.OAUTH2_ACCESS_TOKEN.replace("APPID", Configure.getFwAppID()).replace("SECRET", Configure.getFwAppSecret()).replace("CODE", code);
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		if (jsonObject != null) {
			//用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
			openid = (String) jsonObject.get("openid");
		}
		return openid;
	}

	/**
	 * @描述: 网站应用获取用户信息
	 * @创建人: [email protected]
	 * @创建时间: 2018/11/15 17:58
	 */
	public static Map getOAuth2AccessToken(String code) {
		Map<String, String> resultMap = new HashMap<String, String>();
		String openid = null;
		lastGetOauth2TokenTime = new Long(System.currentTimeMillis());
		String url = WeChatPlatform.OAUTH2_ACCESS_TOKEN.replace("APPID", Configure.getAppid()).replace("SECRET", Configure.getAppSecret()).replace("CODE", code);
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		if (jsonObject != null) {
			oauth2Token = (String) jsonObject.get("access_token");
			openid = (String) jsonObject.get("openid");            //用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
			String scope = (String) jsonObject.get("scope");            //用户授权的作用域,使用逗号(,)分隔
			refreshToken = (String) jsonObject.get("refresh_token");   //刷新accesstoken用的
			Integer expiresIn = (Integer) jsonObject.get("expires_in");  // access_token接口调用凭证超时时间,单位(秒)
//			boolean checkToken = checkOAuth2AccessToken(oauth2Token, openid);
//			if(!checkToken){	//token无效 刷新token
//				refreshAccessToken(refreshToken);
//			}
			resultMap.put("openid", openid);
			resultMap.put("scope", scope);
			resultMap.put("oauth2Token", oauth2Token);
		}
		Map auth2UserInfo = getOAuth2UserInfo(openid);
		logger.info("oauth userinfo:" + auth2UserInfo);
		return auth2UserInfo;
	}

	/**
	 * @描述: 服务号获取用户信息
	 * @创建人: [email protected]
	 * @创建时间: 2018/11/15 17:58
	 */
	public static Map getFWOAuth2AccessToken(String code) {
		Map<String, String> resultMap = new HashMap<String, String>();
		String openid = null;
		lastGetOauth2TokenTime = new Long(System.currentTimeMillis());
		String url = WeChatPlatform.OAUTH2_ACCESS_TOKEN.replace("APPID", Configure.getFwAppID()).replace("SECRET", Configure.getFwAppSecret()).replace("CODE", code);
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		if (jsonObject != null) {
			oauth2Token = (String) jsonObject.get("access_token");
			openid = (String) jsonObject.get("openid");            //用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
			String scope = (String) jsonObject.get("scope");            //用户授权的作用域,使用逗号(,)分隔
			refreshToken = (String) jsonObject.get("refresh_token");   //刷新accesstoken用的
			Integer expiresIn = (Integer) jsonObject.get("expires_in");  // access_token接口调用凭证超时时间,单位(秒)
//			boolean checkToken = checkOAuth2AccessToken(oauth2Token, openid);
//			if(!checkToken){	//token无效 刷新token
//				refreshAccessToken(refreshToken);
//			}
			resultMap.put("openid", openid);
			resultMap.put("scope", scope);
			resultMap.put("oauth2Token", oauth2Token);
		}
		Map auth2UserInfo = getOAuth2UserInfo(openid);
		logger.info("oauth userinfo:" + auth2UserInfo);
		return auth2UserInfo;
	}

	/**
	 * @描述: 移动app获取用户信息
	 * @创建人: [email protected]
	 * @创建时间: 2018/11/15 17:58
	 */
	public static Map getWebOAuth2AccessToken(String code) {
		Map<String, String> resultMap = new HashMap<String, String>();
		String openid = null;
		lastGetOauth2TokenTime = new Long(System.currentTimeMillis());
		String url = WeChatPlatform.OAUTH2_ACCESS_TOKEN.replace("APPID", Configure.getWebAppID()).replace("SECRET", Configure.getWebAppSecret()).replace("CODE", code);
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		if (jsonObject != null) {
			try {
				oauth2Token = (String) jsonObject.get("access_token");
				openid = (String) jsonObject.get("openid");            //用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
				String scope = (String) jsonObject.get("scope");            //用户授权的作用域,使用逗号(,)分隔
				refreshToken = (String) jsonObject.get("refresh_token");   //刷新accesstoken用的
				Integer expiresIn = (Integer) jsonObject.get("expires_in");  // access_token接口调用凭证超时时间,单位(秒)
//				boolean checkToken = checkOAuth2AccessToken(oauth2Token, openid);
//				if(!checkToken){	//token无效 刷新token
//					refreshAccessToken(refreshToken);
//				}
				resultMap.put("openid", openid);
				resultMap.put("scope", scope);
				resultMap.put("oauth2Token", oauth2Token);
			} catch (Exception e) {
				logger.debug("微信webapp授权登录出错 %s", e.getMessage());
				resultMap.put("result", "1");
				return resultMap;
			}
		}
		Map auth2UserInfo = getOAuth2UserInfo(openid);
		auth2UserInfo.put("result", "0");
		logger.info("oauth userinfo:" + auth2UserInfo);
		return auth2UserInfo;
	}

	/** ===========================================小程序获取用户信息==================================================== **/
	/**
	 * @描述: 小程序获取用户信息
	 * @创建人: [email protected]
	 * @创建时间: 2018/11/15 17:58
	 */
	public static Map getMiniAppLoginInfo(WechatConfigInfo wechatConfigInfo, String code) {
		Map<String, String> resultMap = new HashMap<>();
		String url = WeChatPlatform.GETMINI_LOGIN_URL.replace("APPID", wechatConfigInfo.getMiniAppId()).replace("SECRET", wechatConfigInfo.getMiniAppSecret()).replace("JSCODE", code);
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		logger.info("微信小程序登录结果: {}", jsonObject);
		if (jsonObject != null) {
			try {
				Integer errcode = (Integer) jsonObject.get("errcode");  // 错误码
				String errmsg = (String) jsonObject.get("errmsg");  // 错误信息
				String openid = (String) jsonObject.get("openid");            //用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
				String unionid = (String) jsonObject.get("unionid");   //用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回
				String session_key = (String) jsonObject.get("session_key");            //会话密钥

				resultMap.put("errcode", errcode + "");
				resultMap.put("errmsg", errmsg);
				resultMap.put("openid", openid);
				resultMap.put("unionid", unionid);
				resultMap.put("session_key", session_key);
				return resultMap;
			} catch (Exception e) {
				logger.debug("微信小程序登录出错 %s", e.getMessage());
				resultMap.put("result", "1");
				return resultMap;
			}
		}
		return resultMap;
	}

	/**
	 * @描述: 服务号获取用户信息
	 * @创建人: [email protected]
	 * @创建时间: 2018/11/15 17:58
	 */
	public static String getMiniAuthorizerAccessToken(WechatConfigInfo wechatConfigInfo) {
		String url = WeChatPlatform.ACCESS_TOKEN_URL.replace("APPID", wechatConfigInfo.getMiniAppId()).replace("APPSECRET", wechatConfigInfo.getMiniAppSecret());
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		logger.info("微信小程序获取AuthorizerAccessToken: {}", JSONUtil.toJsonStr(jsonObject));
		if (jsonObject != null) {
			return oauth2Token = (String) jsonObject.get("access_token");
		}
		logger.error("微信小程序获取AuthorizerAccessToken错误: {}", JSONUtil.toJsonStr(jsonObject));
		return "";
	}

	public static PhoneNumberInfo getMiniAppPhoneNumberByAccesstoken(String access_token, String code) {
		Map<String, String> resultMap = new HashMap<>();
		String url = WeChatPlatform.GET_USER_PHONENUMBER.replace("ACCESS_TOKEN", access_token);

		Map<String, String> params = new HashMap<String, String>();
		params.put("code", code);
		String json = JSONObject.fromObject(params).toString();
		JSONObject jsonObject = HttpHandler.doPostStr(url, json);
		logger.info("微信小程序获取手机号响应结果: {}", jsonObject);
		if (jsonObject != null) {
			try {
				Object errmsg = jsonObject.get("errmsg").toString();
				if (errmsg.equals("ok")) {
					String phoneInfo = jsonObject.get("phone_info").toString();
					PhoneNumberInfo phoneNumberInfo = JSONUtil.toBean(phoneInfo, PhoneNumberInfo.class);
					return phoneNumberInfo;
				}
				return null;
			} catch (Exception e) {
				logger.debug("微信小程序获取手机号出错 %s", e.getMessage());
				resultMap.put("result", "1");
				return null;
			}
		}
		logger.error("微信小程序获取手机号响应结果出错: {}", jsonObject);
		return null;
	}

	public static Map getMiniAppPhoneNumber(String code) {
		Map<String, String> resultMap = new HashMap<>();
		String url = WeChatPlatform.GETMINI_LOGIN_URL.replace("APPID", Configure.getMiniAppID()).replace("SECRET", Configure.getMiniAppSecret()).replace("JSCODE", code);
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		logger.info("微信小程序获取手机号响应结果: {}", jsonObject);
		if (jsonObject != null) {
			try {
				String openid = (String) jsonObject.get("openid");            //用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
				String session_key = (String) jsonObject.get("session_key");            //会话密钥
				resultMap.put("openid", openid);
				resultMap.put("session_key", session_key);
				return resultMap;
			} catch (Exception e) {
				logger.debug("微信小程序登录出错 %s", e.getMessage());
				resultMap.put("result", "1");
				return resultMap;
			}
		}
		return resultMap;
	}


	/**
	 * 此方法描述的是: 验证 accessToken是否有效
	 *
	 * @param oauth2Token
	 * @param openid
	 * @return boolean
	 */
	public static boolean checkOAuth2AccessToken(String oauth2Token, String openid) {
		boolean isUse = true;
		String url = WeChatPlatform.OAUTH2_AUTH_TOKEN.replace("ACCESS_TOKEN", oauth2Token).replace("OPENID", openid);
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		if (jsonObject != null) {
			Integer errcode = (Integer) jsonObject.get("errcode");
			String errmsg = (String) jsonObject.get("errmsg");
			logger.info("errcode:" + errcode + "/" + "errmsg:" + errmsg);
			if (errcode != 0) {
				isUse = false;
			}
		}
		return isUse;
	}

	/**
	 * 此方法描述的是: 刷新OAuthaccesstoken
	 *
	 * @param refAccessToken
	 * @return String
	 */
	public static String refreshAccessToken(String refAccessToken) {
		String accessToken = null;
		Map<String, String> resultMap = new HashMap<String, String>();
		String url = WeChatPlatform.OAUTH2_REFRESH_TOKEN.replace("APPID", Configure.getFwAppID()).replace("REFRESH_TOKEN", refAccessToken);
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		if (jsonObject != null) {
			oauth2Token = (String) jsonObject.get("access_token");
			String openid = (String) jsonObject.get("openid");            //用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
			logger.info("openid:" + openid);
			String scope = (String) jsonObject.get("scope");            //用户授权的作用域,使用逗号(,)分隔
			refreshToken = (String) jsonObject.get("refresh_token");   //刷新accesstoken用的
			Integer expiresIn = (Integer) jsonObject.get("expires_in");  // access_token接口调用凭证超时时间,单位(秒)
			resultMap.put("openid", openid);
			resultMap.put("scope", scope);
			resultMap.put("oauth2Token", oauth2Token);
			accessToken = oauth2Token;
		}
		return accessToken;
	}

	/**
	 * 此方法描述的是:
	 * 第一步:用户同意授权,获取code(引导关注者打开如下页面:)
	 * 获取 code、state
	 *
	 * @return String
	 */
	public static String getStartURLToGetCode() {
		String takenUrl = WeChatPlatform.USER_AUTHORIZE;
		takenUrl = takenUrl.replace("APPID", Configure.getAppid());
		takenUrl = takenUrl.replace("REDIRECT_URI", Configure.getRedirectUrl());
		//FIXME : snsapi_userinfo
		takenUrl = takenUrl.replace("SCOPE", "snsapi_userinfo");
		return takenUrl;
	}

	/**
	 * 获取access_token、openid
	 * 第二步:通过code获取access_token
	 *
	 * @param code url = "https://api.weixin.qq.com/sns/oauth2/access_token
	 *             ?appid=APPID
	 *             &secret=SECRET
	 *             &code=CODE
	 *             &grant_type=authorization_code"
	 */
	public static OAuthInfo getAccess_token(String code) {
		String authUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code ";
		authUrl = authUrl.replace("APPID", Configure.getDyAppID());
		authUrl = authUrl.replace("SECRET", Configure.getDyAppSecret());
		authUrl = authUrl.replace("CODE", code);
		String jsonString;
		OAuthInfo auth = null;
		try {
			jsonString = HttpHandler.httpPost(authUrl, null, null);
			logger.info("jsonString: " + jsonString);
			auth = (OAuthInfo) JSONObject.toBean(JSONObject.fromObject(jsonString), OAuthInfo.class);
		} catch (Exception e) {
			logger.debug("通过code获取access_token出错 %s", e.getMessage());
			e.printStackTrace();
		}
		return auth;
	}

	/** ===========================================网页授权获取用户基本信息==================================================== **/
	/**
	 * 此方法描述的是:网页授权获取用户基本信息
	 *
	 * @param openid
	 * @return JSONObject
	 */
	public static JSONObject getOAuth2UserInfo(String openid) {
		String url = WeChatPlatform.OAUTH2_USER_INFO.replace("ACCESS_TOKEN", oauth2Token).replace("OPENID", openid);
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		return jsonObject;
	}

	/**
	 * 此方法描述的是:网页授权获取用户基本信息
	 *
	 * @param openid
	 * @param oauth2Token 全局ACCESS_TOKEN
	 * @return JSONObject
	 */
	public static JSONObject getOAuth2UserInfo(String openid, String oauth2Token) {
		if (StringUtils.isEmpty(openid) || StringUtils.isEmpty(oauth2Token)) {
			logger.error("openid or oauth2Token is empty, oauth2Token " + oauth2Token + ",openid = " + openid);
			return null;
		}
		String url = WeChatPlatform.OAUTH2_USER_INFO.replace("ACCESS_TOKEN", oauth2Token).replace("OPENID", openid);
		JSONObject jsonObject = HttpHandler.doGetStr(url);
		return jsonObject;
	}

	public static boolean verifyWeixinNotify(Map<String, Object> map) {
		SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();
		String sign = (String) map.get("sign");
		for (Object keyValue : map.keySet()) {
			if (!keyValue.toString().equals("sign")) {
				parameterMap.put(keyValue.toString(), map.get(keyValue));
			}
		}
		String createSign = Signature.getSign(parameterMap);
		if (createSign.equals(sign)) {
			return true;
		} else {
			return false;
		}

	}

	/** ===========================================微信签名==================================================== **/
	/**
	 * @return
	 * @Description:jsapi_ticket 公众号用于调用微信JS接口的临时票据
	 * 生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
	 * @author wangbing
	 * @Since:2015年11月20日
	 */
	public static String getJsapiTicket() {
		if (StringUtils.isBlank(jsapiTicket) || lastGetJsapiTicketTime == null || (System.currentTimeMillis() / 1000) - (lastGetJsapiTicketTime.longValue() / 1000) >= 7000) {
			lastGetJsapiTicketTime = new Long(System.currentTimeMillis());
			String dyAccessToken2 = WeixinHandler.getDyAccessToken();
			logger.info("dyAccessToken2", dyAccessToken2);
			String url = WeChatPlatform.GETTICKET_URL.replace("ACCESS_TOKEN", WeixinHandler.getDyAccessToken());
			logger.info("url========={}", url);
			JSONObject jsonObject = HttpHandler.doGetStr(url);
			if (jsonObject != null) {
				jsapiTicket = (String) jsonObject.get("ticket");
			}
			return jsapiTicket;
		} else {
			return jsapiTicket;
		}

	}

	/**
	 * 此方法描述的是:   验证签名
	 *
	 * @param signature
	 * @param timestamp
	 * @param nonce
	 * @return boolean
	 */
	public static boolean checkSignature(String signature, String timestamp, String nonce) {
		String[] arr = new String[]{token, timestamp, nonce};
		// 将token、timestamp、nonce三个参数进行字典序排序 Arrays.sort(arr);
		Signature.sort(arr);
		StringBuilder content = new StringBuilder();
		for (int i = 0; i < arr.length; i++) {
			content.append(arr[i]);
		}
		MessageDigest md = null;
		String tmpStr = null;

		try {
			md = MessageDigest.getInstance("SHA-1");
			// 将三个参数字符串拼接成一个字符串进行sha1加密
			byte[] digest = md.digest(content.toString().getBytes());
			tmpStr = Signature.byteToStr(digest);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		content = null;
		// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
		return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
	}

	/**
	 * 此方法描述的是:微信语义理解接口
	 *
	 * @param query
	 * @param uid
	 * @param appid
	 * @param accessToken
	 * @return JSONObject
	 */
	public static JSONObject getSemanticSearch(String query, String uid, String appid, String accessToken) {
		String result = null;
		String url = WeChatPlatform.CREATE_QRCODE_URL.replace("ACCESS_TOKEN", accessToken);
		Map<String, Object> post = new HashMap<String, Object>();
		Map<String, Map> sceneMap = new HashMap<String, Map>();
		Map<String, Object> strMap = new HashMap<String, Object>();
		//strMap.put("scene_str", sceneStr);
		//strMap.put("scene_id", sceneId);
		sceneMap.put("scene", strMap);
		post.put("action_name", "QR_LIMIT_STR_SCENE");
		post.put("action_info", sceneMap);
		String json = JSONObject.fromObject(post).toString();
		logger.info(json);
		JSONObject jsonObject = HttpHandler.doPostStr(url, json);
		if (jsonObject != null) {
			result = jsonObject.getString("ticket");
		}
		return jsonObject;
	}

	/**
	 * @Description 发送公众号模板消息
	 * @Since 2016年11月7日下午1:58:31
	 */
	public static String sendTemplateMessage(String url, String template_id, String touser, String accessToken, HashMap<String, Object> template, HashMap<String, Object> miniprogram) {
		String postUrl = WeChatPlatform.TEMPLATE_SEND.replace("ACCESS_TOKEN", accessToken);
		Map<String, Object> post = new HashMap<>();
		post.put("touser", touser);
		post.put("template_id", template_id);
		post.put("url", url);
		post.put("data", template);
		post.put("miniprogram", miniprogram);
		String json = JSONObject.fromObject(post).toString();
		System.out.println(json);
		JSONObject jsonObject = HttpHandler.doPostStr(postUrl, json);
		return jsonObject.toString();
	}

	/**
	 * @Description 发送小程序模板消息
	 * @Since 2016年11月7日下午1:58:31
	 */
	public static String sendMiniTemplateMessage(String touser, String template_id, String url, String formId, HashMap<String, Object> miniData, String emphasisKeyword, String accessToken) {
		String postUrl = WeChatPlatform.TEMPLATE_SEND_MINI.replace("ACCESS_TOKEN", accessToken);
		Map<String, Object> post = new HashMap<>();
		post.put("touser", touser);
		post.put("template_id", template_id);
		post.put("page", url);
		post.put("form_id", formId);
		post.put("data", miniData);
		post.put("emphasis_keyword", emphasisKeyword);
		String json = JSONObject.fromObject(post).toString();
		JSONObject jsonObject = HttpHandler.doPostStr(postUrl, json);
		return jsonObject.toString();
	}

	/**
	 * @Description 发送小程序模板消息
	 * @Since 2016年11月7日下午1:58:31
	 */
	public static String sendMiniSubscribeMessage(String touser, String template_id, String page, HashMap<String, Object> miniData, String accessToken) {
		String postUrl = WeChatPlatform.SUBSCRIBE_SEND_MINI.replace("ACCESS_TOKEN", accessToken);
		Map<String, Object> post = new HashMap<>();
		post.put("touser", touser);
		post.put("template_id", template_id);
		post.put("page", page);
		post.put("data", miniData);
		String json = JSONObject.fromObject(post).toString();
		JSONObject jsonObject = HttpHandler.doPostStr(postUrl, json);
		return jsonObject.toString();
	}

	/**
	 * @Description 获取小程序模板列表发送小程序模板消息
	 * @Since 2016年11月7日下午1:58:31
	 */
	public static String getTemplateList(String accessToken) {
		String postUrl = WeChatPlatform.GET_TEMPLATE_LIST.replace("ACCESS_TOKEN", accessToken);
		JSONObject jsonObject = HttpHandler.doGetStr(postUrl);
		if (jsonObject != null) {
			return jsonObject.toString();
		}
		return null;
	}

	/**
	 * @Description 获取公众号AccessToken
	 * @return 返回AccessToken
	 */
	public static String getPublicAccountAccessToken(WechatConfigInfo wechatConfigInfo) {
		logger.info("输出公众号appid:{},appSecret:{}",Configure.getPublicAppID(),Configure.getPublicSecret());
		String url = WeChatPlatform.ACCESS_TOKEN_URL.replace("APPID", wechatConfigInfo.getPublicAppId()).replace("APPSECRET", wechatConfigInfo.getPublicAppSecret());
		HttpResponse response = HttpUtil.createGet(url).execute();
		String body = response.body();
		logger.info("输出获取公众号accessToken的结果:{}",body);
		if (JSONUtil.isTypeJSON(body)) {
			return JSONUtil.parseObj(body).getStr("access_token");
		} else {
			return "";
		}
	}
}

至此,相关核心代码已完善!!!

标签:openid,return,String,微信,replace,发送,jsonObject,null,模板
From: https://blog.csdn.net/u013289939/article/details/143691123

相关文章

  • 二分答案模板
    本篇主要介绍二分答案的几个模板1.常用二分模板整数二分模板1将区间划分为[l,mid]和[mid+1,r]则对应的边界更新操作为r=mid,和l=mid+1;中点mid不要+1(相当于向下取整);//整数二分模板1intbsearch_1(intl,intr){while(l<r){......
  • VUE3实现好看的通用网站源码模板
    文章目录1.设计来源1.1网站主界面1.2登录界面1.3注册界面1.4图文列表模板界面1.5简洁列表模板界面1.6文章内容左右侧模板界面1.7文章内容模板界面2.效果和源码2.1动态效果2.2源代码2.3目录结构源码下载万套模板,程序开发,在线开发,在线沟通作者:xcLeigh文章......
  • 如何处理微信小程序大量未捕获的异常
    1)如何处理微信小程序大量未捕获的异常2)如何关闭代码创建的纹理的读写,或者创建不带读写的图片3)回收带有贴图和Collider的Mesh,如何正确用对象池维护4)Cloth组件使用在一个篮筐上,运行后篮网扭曲,是什么原因这是第408篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社......
  • 【模板】如何实现链表元素的反转
    反转链表是链表操作中一个经典的问题,也是面试中常见的考题。本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作。我们将使用C++代码演示具体实现,同时分析时间复杂度和空间复杂度。问题定义给定一个单链表,我们需要将链表的节点顺序反转。例如,链表1......
  • 微信平台收付通,电商资金管理的得力助手,让分账更简单
    大家好,我是小悟。微信平台收付通,以前叫微信电商收付通,这是一款让电商平台老板们又爱又恨,但又欲罢不能的神秘利器。让你的资金流转像吃薯片一样顺畅无阻的神器。首先,让我们来揭开平台收付通的神秘面纱。简单来说,它是微信支付为电商行业量身定制的一款支付与结算解决方案。......
  • 【模板】可持久化线段树 2(洛谷P3834)
    #include<bits/stdc++.h>#defineendl'\n'usingll=longlong;typedefunsignedlonglongull;usingnamespacestd;voidGordenGhost();constexprintN=2e5+7;intn,m,a[N],b[N];introot[N],tot;//根节点所有节点个数intls[N*40],rs[N*40],sum......
  • 基于SpringBoot+Vue+Uniapp微信小程序的医院预约挂号系统设计与实现(精选计算机毕业设
    文章目录1.前言2.详细视频演示3.文档参考3.1论文参考3.2流程设计图3.3数据库表结构设计3.4系统测试部分4.项目运行截图5.技术框架5.1后端采用SpringBoot框架5.2前端框架Vue6.选题推荐毕设案例8.系统测试8.1系统测试的目的8.2系统功能测试9.代码参考10......
  • ROS2_机器人节点模板01_(万字?)_基于动作的实现
    事先声明在typora上做笔记时曾发生过数据丢失的问题,同时在转传到csdn上的时候也有轻微的问题,图片以及mermaid图。如果看的不够清晰可以留言,我将视情况提供原版markdown文件。一些建议请在阅读这份笔记时充分利用目录本笔记包含非常多拓展内容和衍生知识,你可以先阅读重......
  • 单调栈基础模板
    #include<bits/stdc++.h>usingnamespacestd;constintN=1000005;intn,ansl[N],ansr[N],a[N];intf[N],r,x;intmain(){cin>>n;for(inti=0;i<n;i++)cin>>a[i],ansl[i]=ansr[i]=-1;for(inti=0;i<n;i++){......
  • MDPI之Applied Science word 模板下载
    因为之前找过很多资料,都没有word模板下载的教程,所以在这里留个记号。官网点此一、进入如下页面 二、下拉找到Submissionchecklist在这里有 MicrosoftWord模板和 LaTeX模板(在此处单击或去官网点击即可自行下载)。......