微信JS-SDK开发(自定义分享)

本文详细介绍了如何在微信公众号开发中自定义公司logo和文案的过程,包括申请微信公众号账号、获取API所需参数、生成签名以及实现分享功能的关键步骤,并解决开发过程中遇到的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

因为工作需要,最近在做微信公众号开发,主要是在微信分享时自定义公司的logo和文案,开发过程中遇到了一些问题,总结如下:

开发前首先得去微信公众号平台申请注册一个账号,注册成功后拿到appid和secret。具体申请流程请参考微信公众号平台。
开发步骤:
1.通过appid,secret和“client_credential”获取token,因为获取token的api调用次数有限且有限时长为2小时,所以第一次取到token后必须全局缓存(放到数据库还是前端根据业务需要)。
2.通过第一步得到的token,调用微信jsapi获取ticket,同样ticket也需要进行全局缓存。
3.通过获取到的ticket,随机串,时间戳和当前页面的url,按照微信生成签名的规则进行加密并生成签名。
4.把上述得到的数据返回给前端。

开发过程中遇到了一些问题:
1.2小时内尽管token,ticket,timestamp等都是不变的,但是每次进入新的页面时url是变化的,所以sign得相应的变化。
2.自定义的图片太大时会出现图片显示不出来的问题,所以要将图片压缩,最好在10K以内。

JavaScript代码:
!function() {
	var dataForWeixin = {
		title: "",
		desc: "",
		imgUrl:“logo.png",
		link: ”要分享的链接“
	};
	
	var href = location.origin + location.pathname + location.search;
	
	$.ajax({
		url: '/ebusiness/auto/getWechatConfigParams.do',
		data: {
			'href': href,
			'ticket': localStorage.getItem('ticket') || "",
			'nonceStr': localStorage.getItem('nonceStr') || "",
			'timestamp': localStorage.getItem('timestamp') || ""
		},
		datatype: 'json',
		cache: false,
		async: false,
		success: function(msg) {
			var result = JSON.parse(msg);
			if (result.code == 1) {
				localStorage.setItem('appId', result.appId);
				localStorage.setItem('accessToken', result.access_token);
				localStorage.setItem('timestamp', result.timestamp);
				localStorage.setItem('ticket', result.ticket);
				localStorage.setItem('nonceStr', result.nonceStr);
				localStorage.setItem('signature', result.signature);
				dataForWeixin.title = result.title;
				dataForWeixin.desc = result.desc;
			} else if (result.code == 2) {
				localStorage.setItem('signature', result.signature);
				dataForWeixin.title = result.title;
				dataForWeixin.desc = result.desc;
			} else {
				console.log("获取token异常!");
			}
		},
		error: function(msg) {
			console.log("请求数据失败!");
		}
	});	

	
	wx.config({
		debug : false,
		appId : localStorage.getItem('appId'),
		timestamp : localStorage.getItem('timestamp'),
		nonceStr : localStorage.getItem('nonceStr'),
		signature : localStorage.getItem('signature'),
		jsApiList : [ 'checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ' ]
	});

	wx.ready(function() {
		wx.checkJsApi({
			jsApiList : ['onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ' ],
			fail: function(res) {
				console.log("微信版本过低,请升级到新版本!");
			}
		});
		
		wx.onMenuShareTimeline({
			title : dataForWeixin.desc,
			link : dataForWeixin.link,
			imgUrl : dataForWeixin.imgUrl,      
			success: function (res) {
		        console.log("分享到朋友圈成功!");
		    },
			fail: function(res) {
				console.log("分享到朋友圈失败!");
			}
		});
		
		wx.onMenuShareAppMessage({
			title : dataForWeixin.title,
			desc : dataForWeixin.desc,
			link : dataForWeixin.link,
			imgUrl : dataForWeixin.imgUrl,      
			success: function (res) {
		        console.log("分享到微信好友成功!");
		    },
			fail: function(res) {
				console.log("分享到微信好友失败!");
			}
		});
		
	    wx.onMenuShareQQ({
	        title: dataForWeixin.title,
	        desc: dataForWeixin.desc,
	        link: dataForWeixin.link,
	        imgUrl: dataForWeixin.imgUrl,      
			success: function (res) {
		        console.log("分享到QQ好友成功!");
		    },
			fail: function(res) {
				console.log("分享到QQ好友失败!");
			}
	     });
	});

	wx.error(function(res) {
		console.log(res.errMsg);
	});
}();

java代码:
public class GetWechatConfigParamsController extends AbstractController {
	private static final String APP_ID = "";
	private static final String SECRET = "";
	private static final String GRANT_TYPE = "client_credential";
	private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
	private static final String TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
	private static final String WECHAT_TITLE = "wechat.title";
	private static final String WECHAT_DESC = "wechat.desc";	
	
	private Logger logger = Logger.getLogger(this.getClass());

	@Override
	protected ModelAndView handleRequestInternal(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String href = request.getParameter("href");
		String ticket = request.getParameter("ticket");
		String nonceStr = request.getParameter("nonceStr");
		String timestamp = request.getParameter("timestamp");
		long curTimestmap = (long)(new Date().getTime() / 1000);
		
		JSONObject result = new JSONObject();
		
		if (!this.isNullOrEmpty(ticket) && !this.isNullOrEmpty(nonceStr) && !this.isNullOrEmpty(timestamp)
				&& (curTimestmap - Long.parseLong(timestamp) <= 7000)) {
			logger.info("已缓存token且没有超过2小时!");
			result.put("code", 2);
			result.put("appId", APP_ID);
			result.put("timestamp", timestamp);
			result.put("ticket", ticket);
			result.put("nonceStr", nonceStr);
			
			String signature = CoderUtils.encodeSHA(this.constructEncryptString(href, nonceStr, result));
			logger.info("进行sha1签名后的字符串为---> " + signature);
			result.put("signature", signature);
			result.put("title", Configuration.getValue(WECHAT_TITLE));
			result.put("desc", Configuration.getValue(WECHAT_DESC));
		} else {
			logger.info("开始获取access_token!");
			String accessTokenResult = this.getWechatInfoByGetMethod(this.constructAccessTokenUrl(GRANT_TYPE, APP_ID, SECRET));
			logger.info("获取到的access_token信息为:" + accessTokenResult);
			
			result = JSONObject.fromObject(accessTokenResult);
			
			//用于给页面的标识:0表示失败,1表示成功,2表示已缓存相关值
			if (null != accessTokenResult) {
				result.put("code", 1);
				result.put("appId", APP_ID);
				result.put("timestamp", (long)(new Date().getTime() / 1000));
				logger.info("开始获取jsapi_ticket!");
				String ticketResult = this.getWechatInfoByGetMethod(this.constructTicketUrl(result.getString("access_token"), "jsapi"));
				logger.info("获取到的jsapi_ticket信息为:" + ticketResult);
				JSONObject ticketJson = JSONObject.fromObject(ticketResult);
				if (0 == ticketJson.getInt("errcode") && 
					"ok".equals(ticketJson.getString("errmsg").toLowerCase())) {  //成功
					result.put("ticket", ticketJson.getString("ticket"));
					String nonceString = this.createRandomString();
					result.put("nonceStr", nonceString);
					String signature = CoderUtils.encodeSHA(this.constructEncryptString(href, nonceString, result));
					logger.info("进行sha1签名后的字符串为:" + signature);
					result.put("signature", signature);
					result.put("title", Configuration.getValue(WECHAT_TITLE));
					result.put("desc", Configuration.getValue(WECHAT_DESC));
				}
			} else {
				result.put("code", 0);
			}
		}
		
		logger.info("返回给页面的数据:" + result.toString());
		
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		response.getWriter().print(result);
		
		return null;
	}
	
	/**
	 * @param grant_type
	 * @param appId
	 * @param secret
	 * @return  组装好的获取access_token的url
	 */
	private String constructAccessTokenUrl(String grant_type, String appId, String secret) {
		StringBuffer url = new StringBuffer(ACCESS_TOKEN_URL);
		url.append("?")
			.append("grant_type=" + grant_type)
			.append("&")
			.append("appid=" + appId)
			.append("&")
			.append("secret=" + secret);
		
		logger.info("获取微信access_token的URL为:" + url.toString());
		
		return url.toString();
	}
	
	/**
	 * @param accessToken
	 * @param jsApi
	 * @return 获取jsapi_ticket的url
	 */
	private String constructTicketUrl(String accessToken, String jsApi) {
		StringBuffer url = new StringBuffer(TICKET_URL);
		url.append("?")
				   .append("access_token=" + accessToken)
				   .append("&")
				   .append("type=" + jsApi);
		
		logger.info("获取微信jsapi_ticket的URIL为:" + url.toString());
		
		return url.toString();
	}
	
	/**
	 * @param url 获信息的url
	 * @return 获取到的微信信息
	 */
	private String getWechatInfoByGetMethod(String url) {
		HttpClient httpClient = HttpClientUtils.getHttpClient();
		GetMethod getMethod = new GetMethod(url);
		
		try {
			if (HttpStatus.SC_OK == httpClient.executeMethod(getMethod)) {
				return getMethod.getResponseBodyAsString();
			}
		} catch (HttpException e) {
			logger.error("http请求错误!请求路径为:" + url);
			e.printStackTrace();
		} catch (IOException e) {
			logger.error("io读写错误!");
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * @return 生成随机字符串
	 */
	private String createRandomString() {
		StringBuffer result = new StringBuffer();
		String fromString = "0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ";
		int length = fromString.length();
		Random random = new Random();
		
		for (int index = 0; index < 16; index++) {
			result.append(fromString.charAt(random.nextInt(length)));
		}
		
		logger.info("随机字符串为:" + result.toString());
		return result.toString();
	}
	
	/**
	 * @param href 链接
	 * @param randomString 随机串
	 * @param jsonStr json对象
	 * @return 拼接后的字符串
	 */
	private String constructEncryptString(String href, String randomString, JSONObject jsonStr) {
		StringBuffer result = new StringBuffer();
		result.append("jsapi_ticket=" + jsonStr.getString("ticket"))
				.append("&")
				.append("noncestr=" + randomString)
				.append("&")
				.append("timestamp=" + jsonStr.getString("timestamp"))
				.append("&")
				.append("url=" + href);
		
		
		logger.info("拼接后的待签名字符串为:" + result.toString());
		return result.toString();
	}
	
	/**
	 * @param str 待判断的字符串
	 * @return 空返回true,非空返回fasle
	 */
	private boolean isNullOrEmpty(String str) {
		if (null == str || str.isEmpty() || "".equals(str)) {
			return true;
		}
		return false;
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值