微信公众号开发(个人订阅号)

吃可爱长大的小学妹 提交于 2019-12-28 12:12:26

微信公众号开发

微信公众一共分为三种
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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!