微信公众号开发
微信公众一共分为三种
1.个人订阅号
2.服务号
公司-工商营业执照
个体户-工商营业执照
3.企业号
公司-工商营业执照
我们需要先注册一下
公众号官网: https://mp.weixin.qq.com
注册之后我们填写完需要填写的信息后
我们找到开发者工具点击公众平台测试账号
我们重点需要三个重要信息
微信号、appID、appsecret
然后我们我们到后面会看到一个URL地址
我们有域名的只需要填写域名就好了
token配置weixin4j
没有域名的我们需要进行内网穿透
natapp: https://natapp.cn/
这里面我们需要进行支付宝实名认证才行
实名认证完之后我们就可以购买一个免费隧道
购买之后我们下载一个客户端进行使用
我们就以windows为例
使用步骤我们可以在官网进行查看
然后下载一个下载一个config.ini文件
我们只需要修改下载一个config.ini文件的一处即可使用然后点击exe文件启动
代码
IndexController
@Controller
@Slf4j
public class IndexController {
@RequestMapping("")
public String toIndex(){
log.info("aaa");
return "index";
}
@RequestMapping("/toHome")
public String toHome(){
return "home";
}
}
ReceiverController
/**
* 微信接入入口
*/
@Controller
@RequestMapping("/weixin/receiver")
public class ReceiverController extends WeixinJieruController {
}
WeixinControlle
@Controller
@Slf4j
@RequestMapping("/wx")
public class WeixinController {
@Autowired
private WeixinTemplate weixinTemplate;
@RequestMapping("/createMenu")
@ResponseBody
public Map<String, Object> createMenu(Model model, HttpServletRequest request) {
log.info("WeixinController.createMenu");
String ctx = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
log.info("ctx=" + ctx);
Map<String, Object> jsonData = new HashMap<String, Object>();
jsonData.put("code", 0);
jsonData.put("message", "微信菜单创建成功");
try {
Menu menu = new Menu();
//创建菜单按钮
List<SingleButton> buttons = new ArrayList<SingleButton>();
menu.setButton(buttons);
//http://tz3ydw.natappfree.cc/wx01/
SingleButton btn1 = new ViewButton("主界面X", ctx + "/");
buttons.add(btn1);
SingleButton btn2 = new ViewButton("Y界面", ctx + "/toHome");
buttons.add(btn2);
SingleButton btn3 = new ClickButton("界面Z", "hello click!");
buttons.add(btn3);
//设置子菜单
System.out.println(menu.toJSONObject().toString());
//创建自定义菜单
Weixin weixin = weixinTemplate.getWeixinFactory().getWeixin();
MenuComponent menu1 = weixin.menu();
menu1.create(menu);
model.addAttribute("message", "微信菜单创建成功");
} catch (Exception e) {
log.error(e.getMessage());
jsonData.put("code", -1);
jsonData.put("message", "微信菜单创建失败,原因:" + e.getMessage());
}
return jsonData;
}
@RequestMapping("/deleteMenu")
@ResponseBody
public Map<String,Object> deleteMenu(){
Map<String, Object> jsonData = new HashMap<String, Object>();
jsonData.put("code", 0);
jsonData.put("message", "微信菜单删除成功");
try {
Weixin weixin = weixinTemplate.getWeixinFactory().getWeixin();
MenuComponent menu = weixin.menu();
menu.delete();
} catch (WeixinException e) {
e.printStackTrace();
jsonData.put("code", -1);
jsonData.put("message", "微信菜单删除失败,原因:"+e.getMessage());
}
return jsonData;
}
}
工具类
MyAtsEventMessageHandler
/**
* 自定义事件消息处理器
*
* @author yangqisheng
*/
@Component
public class MyAtsEventMessageHandler implements IEventMessageHandler {
@Override
public OutputMessage subscribe(SubscribeEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("感谢您的关注!");
return out;
}
@Override
public OutputMessage unSubscribe(UnSubscribeEventMessage msg) {
//取消关注
return null;
}
@Override
public OutputMessage qrsceneSubscribe(QrsceneSubscribeEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("感谢您的关注!,来源:" + msg.getEventKey());
return out;
}
@Override
public OutputMessage qrsceneScan(QrsceneScanEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("你的消息已经收到!A");
return out;
}
@Override
public OutputMessage location(LocationEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("你的消息已经收到!B");
return out;
}
@Override
public OutputMessage click(ClickEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("点击了菜单!C");
return out;
}
@Override
public OutputMessage view(ViewEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("点击了链接!D");
return out;
}
@Override
public OutputMessage scanCodePush(ScanCodePushEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("扫码!E");
return out;
}
@Override
public OutputMessage scanCodeWaitMsg(ScanCodeWaitMsgEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("扫码等待中!F");
return out;
}
@Override
public OutputMessage picSysPhoto(PicSysPhotoEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("发起拍照!G");
return out;
}
@Override
public OutputMessage picPhotoOrAlbum(PicPhotoOrAlbumEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("选择相册!H");
return out;
}
@Override
public OutputMessage picWeixin(PicWeixinEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("上次图片!I");
return out;
}
@Override
public OutputMessage locationSelect(LocationSelectEventMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("选择地理位置!J");
return out;
}
}
MyAtsNormalMessageHandler
/**
* 自定义普通消息处理器
*
* @author yangqisheng
*/
@Component
public class MyAtsNormalMessageHandler implements INormalMessageHandler {
protected final Logger LOG = LoggerFactory.getLogger(MyAtsNormalMessageHandler.class);
@Override
public OutputMessage textTypeMsg(TextInputMessage msg) {
LOG.debug("文本消息:" + msg.getContent());
TextOutputMessage out = new TextOutputMessage();
out.setContent("您发的消息是:" + msg.getContent());
//if
return out;
}
@Override
public OutputMessage imageTypeMsg(ImageInputMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("你的消息已经收到!11");
return out;
}
@Override
public OutputMessage voiceTypeMsg(VoiceInputMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("你的消息已经收到!22");
return out;
}
@Override
public OutputMessage videoTypeMsg(VideoInputMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("你的消息已经收到!33");
return out;
}
@Override
public OutputMessage shortvideoTypeMsg(ShortVideoInputMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("你的消息已经收到!44");
return out;
}
@Override
public OutputMessage locationTypeMsg(LocationInputMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("你的消息已经收到!55");
return out;
}
@Override
public OutputMessage linkTypeMsg(LinkInputMessage msg) {
TextOutputMessage out = new TextOutputMessage();
out.setContent("你的消息已经收到!66");
return out;
}
}
RedisTicketLoader
@Component
@Slf4j
public class RedisTicketLoader implements ITicketLoader {
private static final Logger LOG = LoggerFactory.getLogger(RedisTicketLoader.class);
@Autowired
private StringRedisTemplate stringRedisTemplate;
private String appid;
public RedisTicketLoader() {
this.appid = Configuration.getOAuthAppId();
}
@Override
public Ticket get(TicketType ticketType) {
String key = "";
if (null != ticketType) {
switch (ticketType) {
case JSAPI:
key = "wechat_ticket_jsapi";
break;
case WX_CARD:
key = "wechat_ticket_wxcard";
break;
default:
key = "wechat_ticket";
break;
}
}
String ticket = stringRedisTemplate.opsForValue().get(key);
log.info("wechat ticket:{}", ticket);
return JSON.parseObject(ticket, Ticket.class);
}
@Override
public void refresh(Ticket ticket) {
String key = "";
if (null != ticket.getTicketType()) {
switch (ticket.getTicketType()) {
case JSAPI:
key = "wechat_ticket_jsapi_" + appid;
break;
case WX_CARD:
key = "wechat_ticket_wxcard_" + appid;
break;
default:
key = "wechat_ticket_" + appid;
break;
}
}
log.info("refresh wechat ticket:{}", ticket.toString());
String ticketValue = JSON.toJSONString(ticket);
//ticket.getExpires_in() - 600L,是为了提前10分钟过期
stringRedisTemplate.opsForValue().set(key, ticketValue, ticket.getExpires_in() - 600L, TimeUnit.SECONDS);
}
}
RedisTokenLoader
@Component
@Slf4j
public class RedisTokenLoader implements ITokenLoader {
private final String ACCESS_TOKEN_KEY = "ats_wx100000000001";
@Autowired
private StringRedisTemplate stringRedisTemplate;
private String appid;
public RedisTokenLoader() {
this.appid = Configuration.getOAuthAppId();//从配置文件中读取
}
@Override
public Token get() {
String accessToken = stringRedisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
log.info("wechat access_token:{}", accessToken);
return JSON.parseObject(accessToken, Token.class);
}
@Override
public void refresh(Token token) {
log.info("refresh wechat access_token:{}", token.toString());
String accessToken = JSON.toJSONString(token);
//ticket.getExpires_in() - 600L,是为了提前10分钟过期
stringRedisTemplate.opsForValue().set(ACCESS_TOKEN_KEY, accessToken, token.getExpires_in() - 600L, TimeUnit.SECONDS);
}
}
启动类
@SpringBootApplication
//@MapperScan("com.XXX.xxx.mapper")
@EnableTransactionManagement
//@EnableScheduling
public class Wx01Application {
public static void main(String[] args) {
SpringApplication.run(Wx01Application.class, args);
}
}
配置文件
yml文件
server:
port: 405
servlet:
context-path: /wx01
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8
username: root
password: 1234
redis:
database: 0 # Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0 redis\u670916\u4E2A\u5E93\uFF09
host: 192.168.126.144 # Redis\u670D\u52A1\u5668\u5730\u5740
port: 6379 # Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3
password: 123456 # Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09
jedis: # spirngboot1.x\u4E0E2.x\u533A\u522B\u662F2.x\u6DFB\u52A0\u4E00\u4E2A\u524D\u7F00jedis\u30011.x\u6CA1\u6709
pool:
max-active: 100 # \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
max-idle: 10 # \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5
min-idle: 0 # \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5
max-wait: -1 # \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
timeout: 5000 # \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09\uFF0C\u4E0D\u80FD\u8BBE\u7F6E\u4E3A0\uFF0C\u65F6\u95F4\u592A\u77ED\u8FDE\u63A5\u4E0D\u4E0A\u4F1A\u62A5\u9519
## jpa:
## database: mysql
## show-sql: true
freemarker:
allow-request-override: false
request-context-attribute: req
suffix: .ftl
content-type: text/html;charset=UTF-8
enabled: true
cache: false
template-loader-path: classpath:/templates/
charset: UTF-8
# devtools:
# restart:
# enabled: true #\u70ED\u90E8\u7F72\u751F\u6548
# exclude: WEB-INF/** #classpath\u76EE\u5F55\u4E0B\u7684WEB-INF\u6587\u4EF6\u5939\u5185\u5BB9\u4FEE\u6539\u4E0D\u91CD\u542F
# additional-paths: src/main/java #\u8BBE\u7F6E\u91CD\u542F\u7684\u76EE\u5F55
#
#
mybatis:
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: com.lqx.wx01.model
weixin4j配置
#\u5FAE\u4FE1SDK\u914D\u7F6E\u6587\u4EF6
#\u8BFB\u53D6\u89C4\u5219\uFF1A\u4F18\u5148\u8BFB\u53D6System.getProperty()
#\u518D\u4ECEweixin4j.properties\u8BFB\u53D6,key
#\u5982\u679CSystem.getProperty()\u4E0Eweixin4j.properties\u90FD\u6CA1\u8BBE\u7F6E\uFF0C\u5219\u9ED8\u8BA4\u672ANULL
#\u5F00\u53D1\u8005\u8C03\u8BD5\u8BBE\u7F6E
weixin4j.debug=true
#\u516C\u4F17\u53F7Token
weixin4j.token=weixin4j
#\u516C\u4F17\u53F7\u539F\u59CBID
weixin4j.oauth.originalid=gh_bc691531b661
#\u5F00\u53D1\u8005\u7B2C\u4E09\u65B9\u7528\u6237\u552F\u4E00\u51ED\u8BC1
weixin4j.oauth.appid=wx1480babf741d1554
#\u5F00\u53D1\u8005\u7B2C\u4E09\u65B9\u7528\u6237\u552F\u4E00\u51ED\u8BC1\u5BC6\u94A5
weixin4j.oauth.secret=49953ee39635868fd310b17b3b486cf9
#\u6D88\u606F\u52A0\u5BC6\u65B9\u5F0F 0:\u660E\u6587\u6A21\u5F0F(\u9ED8\u8BA4), 1:\u517C\u5BB9\u6A21\u5F0F, 2:\u5B89\u5168\u6A21\u5F0F(\u63A8\u8350)
weixin4j.oauth.encodingtype=0
#\u6D88\u606F\u52A0\u5BC6\u5BC6\u94A5(43\u4F4D\u5B57\u7B26\u7EC4\u6210A-Za-z0-9)
weixin4j.oauth.encodingaeskey=0123456789abcedfghijklmnopqrstuvwxyzZXCVBNM
#\u7F51\u9875\u5B89\u5168\u6388\u6743URL
weixin4j.oauth.url=
#\u516C\u4F17\u5E73\u53F0\u63A5\u53E3\u57DF\u540D
#\u901A\u7528\u57DF\u540D(api.weixin.qq.com)\uFF0C\u4F7F\u7528\u8BE5\u57DF\u540D\u5C06\u8BBF\u95EE\u5B98\u65B9\u6307\u5B9A\u5C31\u8FD1\u7684\u63A5\u5165\u70B9\uFF1B
#\u4E0A\u6D77\u57DF\u540D(sh.api.weixin.qq.com)\uFF0C\u4F7F\u7528\u8BE5\u57DF\u540D\u5C06\u8BBF\u95EE\u4E0A\u6D77\u7684\u63A5\u5165\u70B9\uFF1B
#\u6DF1\u5733\u57DF\u540D(sz.api.weixin.qq.com)\uFF0C\u4F7F\u7528\u8BE5\u57DF\u540D\u5C06\u8BBF\u95EE\u6DF1\u5733\u7684\u63A5\u5165\u70B9\uFF1B
#\u9999\u6E2F\u57DF\u540D(hk.api.weixin.qq.com)\uFF0C\u4F7F\u7528\u8BE5\u57DF\u540D\u5C06\u8BBF\u95EE\u9999\u6E2F\u7684\u63A5\u5165\u70B9\u3002
weixin4j.api.domain=api.weixin.qq.com
#\u5FAE\u4FE1\u652F\u4ED8_\u5546\u6237ID
weixin4j.pay.partner.id=
#\u5FAE\u4FE1\u652F\u4ED8_\u5546\u6237\u5BC6\u94A5
weixin4j.pay.partner.key=
#\u5FAE\u4FE1\u652F\u4ED8_\u901A\u77E5URL
weixin4j.pay.notify_url=
#\u8FDE\u63A5\u8D85\u65F6\u8BBE\u7F6E
weixin4j.http.connectionTimeout=25000
#\u8BF7\u6C42\u8D85\u65F6\u8BBE\u7F6E
weixin4j.http.readTimeout=25000
#\u8BC1\u4E66\u8DEF\u5F84
weixin4j.http.cert.path=
weixin4j.http.cert.secret=
#\u9ED8\u8BA4\u6D88\u606F\u5904\u7406\u51FD\u6570
weixin4j.handler=org.weixin4j.spi.DefaultMessageHandler
#weixin4j.message.handler.normal=org.weixin4j.spi.DefaultNormalMessageHandler
#weixin4j.message.handler.event=org.weixin4j.spi.DefaultEventMessageHandler
#此处为工具类文件的文件路径
weixin4j.message.handler.normal=com.lqx.wx01.utils.MyAtsNormalMessageHandler
weixin4j.message.handler.event=com.lqx.wx01.utils.MyAtsEventMessageHandler
然后我们只需要启动redis
启动类
over
来源:CSDN
作者:java锦鲤
链接:https://blog.csdn.net/qq_43964268/article/details/103727852