自己近期在做一个saas模式的产品研发,公众号只有一个,但服务项目的客户有多种多样,在各客户下又有不同的用户。现在有这样一个要求,当用户扫描仪客户给予的公众号二维码时,会发生相应的客户欢迎标语,而且表明客户的LOGO页面。前提条件是每一个客户的LOGO是不一样的。是否有点儿绕?讲搞清楚点,就假如你一个公众号,要被好几个商家应用,每一个商家都是有自身的用户群,那用户在扫码关注公众号,进到公众号必须表明每一个商家自身的与众不同LOGO。
正常的的关心公众号二维码照片是可以去公众号开发人员后台管理下载。但这也是统一的二维码,没法区别商家。这个时候,大家就必须自已去形成公众号的关心二维码。这一二维码跟在网上自动生成的作用不一样。终究你扫二维码后,还得跟第三方的腾讯官方联接。
一、JAVA编写形成二维码插口
主要参数微信公众号接口https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443433542
大家形成一个永久性带字符串数组的二维码,大家只必须传一个商家的ID,就能鉴别用户关心时,是扫了哪一个二维码,进而表明相应的商家LOGO
Controller层
@ApiOperation(value = \"建立公众号二维码\")
@ResponseBody
public Result createQRCode(
@ApiParam(name = \"type\", value = \"种类(1:临时性二维码;2:永久性主要参数为数据的二维码;3:永久性主要参数为字符串数组的二维码)\") @RequestParam() Integer type,
@ApiParam(name = \"validTime\", value = \"临时性二维码的有效时间(秒,最大2592000秒(30天))\") @RequestParam(required = false) Integer validTime,
@ApiParam(name = \"IntParameter\", value = \"数据主要参数\") @RequestParam(required = false) Integer IntParameter,
@ApiParam(name = \"strParameter\", value = \"字符串数组主要参数\") @RequestParam(required = false) String strParameter,
HttpServletRequest request
){
return wechatPushService.createQRCode(type,validTime,IntParameter,strParameter, this.getUserId(request));
}
领域模型层
//获得公众号二维码
private final static String GET_PERPETUAL_QRCODE_URL = \"https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=ACCESS_TOKEN\";
//获取TICKET相匹配的二维码图
private final static String GET_TICKET_QRCODE_URL = \"https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=\";
public Result createQRCode(Integer type, Integer validTime, Integer IntParameter, String strParameter,String userId) {
String accessToken = weChatPushService.getGzhAccessTokenDefaultCfg();//获得公众号Token
String requestUrl = GET_PERPETUAL_QRCODE_URL.replace(\"ACCESS_TOKEN\", accessToken);//更换URL的主要参数
JSONObject json = new JSONObject();
JSONObject actionInfoJson = new JSONObject();
JSONObject sceneJson = new JSONObject();
String fileName = \"/sys/QRCode/\" strParameter \".jpg\";//照片的下载途径
if(type == 3){//形成永久性带字符串数组主要参数的二维码
json.put(\"action_name\",\"QR_LIMIT_STR_SCENE\");//数值
sceneJson.put(\"scene_str\",strParameter);//strParameter是商家ID的主要参数,也是要跟二维码一同形成的主要参数
actionInfoJson.put(\"scene\",sceneJson);
json.put(\"action_info\",actionInfoJson);
//{\"action_name\": \"QR_LIMIT_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"test\"}}} 启用公众号插口的主要参数文件格式,json值
Map<String, Object> map = RequestUtils.json(requestUrl, json);//POST方式启用第三方公众号插口
String ticket = map.containsKey(\"ticket\")?map.get(\"ticket\").toString():\"\";//从回到主要参数中获得二维码ticket值
if(org.apache.commons.lang.StringUtils.isNotEmpty(ticket)){//应用ticket的值再去启用此外一个插口,下载二维码照片
File file1 = new File(filePath \"sys/QRCode/\");//自身要把照片下载的途径
if(!file1.exists()){//分辨文件路径是不是存有,不会有就建立
file1.mkdirs();
}
downloadPicture(GET_TICKET_QRCODE_URL URLEncoder.encode(ticket),filePath fileName);//下载照片
}
}
return ResultUtil.success(fileName);
}
/**
* 获得默认设置公众号浏览动态口令
*/
public String getGzhAccessTokenDefaultCfg() {
if (StringUtils.isEmpty(defaultGzhAppId) || StringUtils.isEmpty(defaultGzhSecret)) {
initialize();//载入环境变量里公众号的值(appId和appSecret),这两个值在公众号里有,公众号的插口大多数必须这两个主要参数去获得Token
}
return getGzhAccessToken(defaultGzhAppId,defaultGzhSecret);
}
// 获取企业公众号access_token
private final static String company_access_token_url = \"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=CORPID&secret=CORPSECRET\";
// 获得开发者平台的access_token、openid等验证信息内容
private final static String GET_TOKEN_URL = \"https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code\";
/**
* 获得手机微信公众号浏览动态口令
* @param appId appId
* @param appSecret appSecret
*/
public String getGzhAccessToken(String appId, String appSecret) {
String accessToken = \"\";
try {
accessToken = redisService.getDataService(\"WX_AccessToken\").getData().toString();//从Redis缓存文件中获得Token,
} catch (Exception e) {
log.error(\"从缓存文件手机微信公众号token不成功\");
}
if (StringUtils.isEmpty(accessToken)) {//假如缓存文件并没有Token,或到期了,将再次去获得一次
String requestUrl = company_access_token_url.replace(\"CORPID\", appId).replace(\"CORPSECRET\", appSecret);//更换主要参数
Map<String, Object> map = RequestUtils.json(requestUrl, null);//POST插口启用第三方接口
// 假如要求取得成功
if (null != map) {
System.out.print(\"###############################\" map.toString());
try {
accessToken = (String) map.get(\"access_token\");
redisService.strAdd(\"WX_AccessToken\", accessToken, 700);// (存到缓存文件中,防止常常去拿token,接近两小时)
} catch (Exception e) {
log.error(\"获得手机微信公众号token不成功,或token储存至缓存文件不成功 ####accessToken\" accessToken);
}
}
}
return accessToken;
}
POST和GET要求java工具,在获得照片时,必须应用GET
import org.springframework.http.MediaType;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
/**
* 工具类
*/
public class RequestUtils {
@SuppressWarnings(\"unchecked\")
public static Map<String, Object> json(String url, Map<String, Object> params){
String content = null;
if(params != null){
content = JsonUtils.convert(params);
}
String result = post(url, content, MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON);
if(result != null){
return JsonUtils.convert(result, Map.class);
}
return null;
}
public static void main(String[] args) {
String post = post(\"http://www.baidu.com\", \"\", MediaType.APPLICATION_JSON);
System.out.println(post);
}
public static String post(String strURL, String content) {
return post(strURL, content, null);
}
public static String post(String strURL, String content, MediaType mediaType) {
return post(strURL, content, mediaType, mediaType);
}
public static String post(String strURL, String content, MediaType sendMediaType, MediaType receiveMediaType) {
try {
URL url = new URL(strURL);// 建立联接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(content != null);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod(\"POST\"); // 设定要求方法
if(sendMediaType != null) {
connection.setRequestProperty(\"Accept\", receiveMediaType.toString()); // 设定获取数据的文件格式
}
if(sendMediaType != null) {
connection.setRequestProperty(\"Content-Type\", sendMediaType.toString()); // 设定传送数据的文件格式
}
connection.connect();
if(content != null) {
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), \"UTF-8\"); // utf-8编号
out.write(content);
out.flush();
out.close();
}
int code = connection.getResponseCode();
System.out.println(code);
InputStream is = connection.getInputStream();
if (is == null) {
is = connection.getErrorStream();
}
// 载入回应
int length = (int) connection.getContentLength();// 获得长短
if (length != -1) {
byte[] data = new byte[length];
byte[] temp = new byte[1024];
int readLen = 0;
int destPos = 0;
while ((readLen = is.read(temp)) > 0) {
System.arraycopy(temp, 0, data, destPos, readLen);
destPos = readLen;
}
String result = new String(data, \"UTF-8\"); // utf-8编号
return result;
}
} catch (IOException e) {
e.printStackTrace();
}
return null; // 自定错误报告
}
public static String get(String url) {
BufferedReader in = null;
try {
URL realUrl = new URL(url);
// 开启和URL中间的联接
URLConnection connection = realUrl.openConnection();
// 设定通用性的要求特性
connection.setRequestProperty(\"accept\", \"*/*\");
connection.setRequestProperty(\"connection\", \"Keep-Alive\");
connection.setRequestProperty(\"user-agent\", \"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)\");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
// 创建真实的联接
connection.connect();
// 界定 BufferedReader键入流来载入URL的回应
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return null;
}
}
插口写完后,你能单元测试卷启用一下,形成的二维码就可以扫一下,是否会跳到你相匹配的微信公众号页面。自定二维码已经形成了,但如今跟平常的二维码没差别,由于并没有开启事情。下面,撰写一个能让微信公众号启用你的办法的插口。让微信公众号对你说,有些人关心或取关。
二、事情开启插口
controller层
//微信推送事情 url
@RequestMapping(\"/openwx/getticket\")
public void getTicketMessage(HttpServletRequest request, HttpServletResponse response)
throws Exception {
wechatPushService.getTicketMessage(request,response);
}
事件开启逻辑性层,看下面编码时,首先看官方网的文本文档,那样更能了解回到主要参数:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543
public String getTicketMessage(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println(\"1.接到微信服务器信息\");
Map<String, String> wxdata=parseXml(request);
if(null != wxdata){
String key = wxdata.get(\"FromUserName\") \"._\"
wxdata.get(\"ToUserName\") \"__\"
wxdata.get(\"MsgId\") \"._\"
wxdata.get(\"CreateTime\");
Result keyRedisResult = redisService.getDataService(key);
System.out.println(keyRedisResult.getStatus());
if(keyRedisResult.getStatus() == 200){//避免群众反复消息推送信息,因此第一次把信息送缓存文件中,假如出现了也不解决
return null;
}
redisService.strAdd(key,\"1\",3600);//不会有得话,放缓存文件里,还记得加一个无效时长,防止一直存有,占有网络资源
String Event = wxdata.get(\"Event\");
System.out.println(\"Event\" Event);
if(Event.equals(\"subscribe\") || Event.equals(\"SCAN\")){//扫码带主要参数的二维码进到的
String EventKey = wxdata.get(\"EventKey\");//获得主要参数
String FromUserName = wxdata.get(\"FromUserName\");//OpenID
if(EventKey.indexOf(\"_\") != -1){//第一次关心
EventKey = EventKey.substring(EventKey.indexOf(\"_\") 1);
}
System.out.println(\"EventKey:\" EventKey);
Map map = (Map)result.getData();
TextMessage textMessage=new TextMessage();
textMessage.setToUserName(wxdata.get(\"FromUserName\")); //这儿的ToUserName 是刚刚接受xml中的FromUserName
textMessage.setFromUserName(wxdata.get(\"ToUserName\")); //这儿的FromUserName 是刚刚接受xml中的ToUserName 这儿一定要留意,不然会出差错
textMessage.setCreateTime(new Date().getTime());
textMessage.setMsgType(\"text\");
textMessage.setContent(\"欢迎你关心\" map.get(\"departmentTopName\") \"电子送达\");
MessageUtil messageUtil = MessageUtil.getInstance();
String xml=messageUtil.textMessageToXml(textMessage);
System.out.println(\"xml:\" xml);
response.setCharacterEncoding(\"UTF-8\");
PrintWriter out = response.getWriter();
out.print(xml);//客户关心时,发一个欢迎标语给客户
out.close();
}
}
return null;
}
三、开启插口写完后,必须去公众号后台去设定你的插口网络服务器,让微信公众号了解你的插口详细地址。
改动配备,服务器ip给你布署的详细地址,务必另一方能连上去,并且必须80端口号(假如80端口被占用,可以应用Nginx做分享),在配备的情况下,微信公众号会试着启用,调用不上你的插口,会立即提示你。
配备完后,点一下运行。这个时候你再去关心你刚刚生成的主要参数二维码,便会有体现了。还记得在事情开启插口中,提升你的业务流程。客户关心或取关时,你需要干什么。
此外,在运行配备后,你就会发现,你的微信公众号自定义菜单不见了,这个时候不要慌。接下来往下看。
运行菜单栏
这个时候微信公众号上的小菜单栏就拥有。但公众号后台自定义菜单或是看不见?那怎么修改菜单栏呢?
非常简单,先把前边打开的服务器的配置给终止了,随后再改你的菜单栏,改动完菜单栏后,你再逐渐网络服务器。到此就完成了生成及事情监听的全过程
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。