2018-03-21 17:06:07 AIkiller 阅读数 10497
  • 微信公众平台开发入门

    本套课程的设计完全是为初学者量身打造,课程内容由浅入深,课程讲解通俗易懂,代码实现简洁清晰。通过本课程的学习,学员能够入门微信公众平台开发,能够胜任企业级的订阅号、服务号、企业号的应用开发工作。 通过本课程的学习,学员能够对微信公众平台有一个清晰的、系统性的认识。例如,公众号是什么,它有什么特点,它能做什么,怎么开发公众号。 其次,通过本课程的学习,学员能够掌握微信公众平台开发的方法、技术和应用实现。例如,开发者文档怎么看,开发环境怎么搭建,基本的消息交互如何实现,常用的方法技巧有哪些,真实应用怎么开发。

    385071 人正在学习 去看看 刘运强

1.首先,你需要一个具有公网IP的域名

例如www.demo.com,它的域名解析的IP是123.123.123.123

2.在微信公众平台登录你的账号

微信公众平台:https://mp.weixin.qq.com

进入 开发->开发者工具 页面
点击 公众平台测试账号 如下图所示:
这里写图片描述

3.配置服务器和js接口安全域名

如下图所示:
这里写图片描述
第一步,配置服务器。点击修改,修改URL 为你的服务器域名。例如:http://www.demo.com(http不能省略)。在这里需要注意的是,
在你的域名的根目录下需要创建index.php文件,文件中代码如下:

<?php

echo $_GET['echostr'];

修改好后,点击提交即可。验证完成后,这些代码可以删除。

第二步,配置js接口安全域名。点击修改,修改域名为你的服务器域名,例如:www.demo.com(没有http)。在这里需要注意的是,在你的域名的根目录下需要有名字为 MP_verify_Gn6UzVhiyHGnf87j.txt 的文件,下载链接是https://mp.weixin.qq.com/cgi-bin/mpverifytxt?lang=zh_CN&token=1136165103,在“公众号设置”->“功能设置”->“JS接口安全域名”中修改时的弹窗中也有下载链接。修改好后,点击提交即可。

4.配置网页回调页面域名

如图打开配置弹窗
这里写图片描述

这里写图片描述

在这里需要注意的和配置服务器域名那里一样,都要在域名指向的根目录下的index.php文件中写入下面代码:

<?php

echo $_GET['echostr'];

修改好后,点击提交即可。验证完成后,这些代码可以删除。

2019-11-28 14:09:14 u013015301 阅读数 2168
  • 微信公众平台开发入门

    本套课程的设计完全是为初学者量身打造,课程内容由浅入深,课程讲解通俗易懂,代码实现简洁清晰。通过本课程的学习,学员能够入门微信公众平台开发,能够胜任企业级的订阅号、服务号、企业号的应用开发工作。 通过本课程的学习,学员能够对微信公众平台有一个清晰的、系统性的认识。例如,公众号是什么,它有什么特点,它能做什么,怎么开发公众号。 其次,通过本课程的学习,学员能够掌握微信公众平台开发的方法、技术和应用实现。例如,开发者文档怎么看,开发环境怎么搭建,基本的消息交互如何实现,常用的方法技巧有哪些,真实应用怎么开发。

    385071 人正在学习 去看看 刘运强

1.申请域名,该域名指向的端口必须是80
因为是本地进行测试,肯定没有需要ICP备案的域名了,这里我采用的做法是在花生壳申请一个免费的域名,下载网址:https://hsk.oray.com/download/,这里以linux服务器为例来讲解
(1)打开网址
在这里插入图片描述(2)点击“下载”,我根据服务器的系统选择对应的版本,我选择的是centOS Linux(X86_64)。
在这里插入图片描述(3)下载完成后,把下载的phddns-3.0.2.x86_64.rpm
文件放到服务器上的任意目录下,并到该目录下。
(4)打开对应版本的帮助
花生壳 3.0 for Linux 相关安装使用文档(5)安装(注:根据服务器系统)
在这里插入图片描述(6)安装完成后,输入phddns回车后,可以看到扩展的功能:
phddns start(启动)| stop(停止)| status(状态)| restart(重启)|
phddns reset(重置)
phddns version(版本)
(7)查看SN码
在服务器上执行:phddns status,查看SN码
在这里插入图片描述
(7)phddns的使用
浏览器输入远程管理地址b.oray.com进入花生壳远程管理页面
在这里插入图片描述
输入安装花生壳时生成的SN码及默认密码admin进入;
安装步骤操作,注意需要开通内网穿透功能,并绑定手机号。
在这里插入图片描述
(8)在账号列表中,找到SN码的信息,点击进入后,如下图
在这里插入图片描述(9)点击上图中的“加号”,进入
在这里插入图片描述映射类型选择HTTP,这里不是免费的,需要付6元的费用,然后外网端口一定选择80,内网主机和内网端口具体看你服务器的ip内部监听的端口了,点击“确定”。域名申请操作全部完成,这里我得域名是http://2c79743143.oicp.vip
注意:一个花生壳帐号只能在一台设备上登录使用,多处登录会导致连接不稳定

2.微信公众平台的配置
(1)打开,微信公众平台网址:https://mp.weixin.qq.com/ ,登录
(2)找到开发者工具,点击在这里插入图片描述(3)点击“公众平台测试账号”
在这里插入图片描述(4)点击 接口配置信息“修改”
在这里插入图片描述(5)把获取的域名加接口地址填进去
在这里插入图片描述(6)找到 网页授权获取用户基本信息 后面的“修改”,点击进入
在这里插入图片描述(7)填写本地的ip(一定要是IP,此处填写新申请的域名不行,微信认为不安全,不让使用),保存即可。
在这里插入图片描述
3.创建微信菜单
创建微信菜单使用的地址要和上面的授权回调页面域名一致,否则回报10003错误。

2014-05-28 10:58:34 ljz0898 阅读数 25359
  • 微信公众平台开发入门

    本套课程的设计完全是为初学者量身打造,课程内容由浅入深,课程讲解通俗易懂,代码实现简洁清晰。通过本课程的学习,学员能够入门微信公众平台开发,能够胜任企业级的订阅号、服务号、企业号的应用开发工作。 通过本课程的学习,学员能够对微信公众平台有一个清晰的、系统性的认识。例如,公众号是什么,它有什么特点,它能做什么,怎么开发公众号。 其次,通过本课程的学习,学员能够掌握微信公众平台开发的方法、技术和应用实现。例如,开发者文档怎么看,开发环境怎么搭建,基本的消息交互如何实现,常用的方法技巧有哪些,真实应用怎么开发。

    385071 人正在学习 去看看 刘运强

配置URL的时候老提示失败,如下图:





解决的办法是:由于我的WSServlet的doGet()方法里面没有返回微信请求的随机字符串 ,在doGet里面添加如下代码 就可以


              // 微信加密签名  
       String signature = request.getParameter("signature");  
       // 时间戳  
       String timestamp = request.getParameter("timestamp");  
       // 随机数  
       String nonce = request.getParameter("nonce");  
       // 随机字符串  
       String echostr = request.getParameter("echostr");  
 
       PrintWriter out = response.getWriter();  
       out.print(echostr);



2018-03-21 22:49:11 u014740338 阅读数 2544
  • 微信公众平台开发入门

    本套课程的设计完全是为初学者量身打造,课程内容由浅入深,课程讲解通俗易懂,代码实现简洁清晰。通过本课程的学习,学员能够入门微信公众平台开发,能够胜任企业级的订阅号、服务号、企业号的应用开发工作。 通过本课程的学习,学员能够对微信公众平台有一个清晰的、系统性的认识。例如,公众号是什么,它有什么特点,它能做什么,怎么开发公众号。 其次,通过本课程的学习,学员能够掌握微信公众平台开发的方法、技术和应用实现。例如,开发者文档怎么看,开发环境怎么搭建,基本的消息交互如何实现,常用的方法技巧有哪些,真实应用怎么开发。

    385071 人正在学习 去看看 刘运强

最近在搞微信的开发者模式,对于第一次接触这东西的人来说还真是没有头绪,因为需要跟微信进行交互,难免会碰到一些问题,不像我们在本机开发那样,很快就能把逻辑代码写完。今天主要是让测试耽误了时间,由于微信只能绑定域名,不能使用ip地址,但是在公司中域名直接解析到线上服务器,但是线上服务器该域名下已经有服务在运行,所以不能使用线上服务器直接进行开发测试,也不能把已有的服务号打开开发者模式,因为打开开发者模式之后好多已有的自动回复就不能使用了,总之遇到了各种问题,记录下开发过程。


申请测试账号

进入申请地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

点击登录按钮,会弹出一个二维码,使用手机微信扫描即可

登录成功之后会出现下面的界面


appID和appsecret在调用微信接口的时候会用到,这里是微信自动给我们生成好的,直接使用就可以。

URL:是我们自己服务器的URL,用户微信推送用户消息和事件用的。这里只能配置域名,不能使用IP。这个URL是用来接收微信的token认证和消息事件用的,我们自己的服务器要能对这个url的请求进行处理并相应,所以要求该域名必须是外网可以访问的,否则在点“提交”按钮的时候会报token异常。

Token:是验证签名用的,此处填写的要与代码中的Token保持一致否则验证不过。

URL和Token都填好之后点击提交按钮,若验证通过,会返回配置成功,否则返回配置失败。

配置失败的原因可能有几个:

1、URL地址不能访问

2、Token填写错误

注意:在点击提交按钮之前一定要先把服务端的代码写好,否则会返回配置失败,具体实现代码在后面演示。

到此为止,我们的接口配置信息就算完成了。

扫描测试号二维码就可以来测试我们的功能了


Token认证

我配置的URL是,http://www.xxx.com/XX/wxProcess/service,所以微信会把所有的请求都发到我的/service路径上,包括Token认证和事件处理,我使用两个方法来处理的,但是请求类型不同,Token认证是用的GET请求,事件处理使用的是POST请求。演示代码如下:

/**
     * 打开开发者模式签名认证
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/service", method = RequestMethod.GET)
    public Object defaultView(String signature, String timestamp, String nonce, String echostr) {
        if (echostr == null || echostr.isEmpty()) {
            return nonce;
        }
        if (SignUtil.checkSignature(signature, timestamp, nonce)) {
            return echostr;
        }
        return nonce;
    }

    /**
     * 事件处理
     * @param signature
     * @param timestamp
     * @param nonce
     * @param message
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/service", method = RequestMethod.POST, consumes = "text/xml", produces = "text/xml;charset=UTF-8")
    public String defaultViewHandler(String signature, String timestamp, String nonce, @RequestBody String message) {
        String result = "";
        if (SignUtil.checkSignature(signature, timestamp, nonce)) {
            result = coreService.processRequest(message);
        }
        return result;
    }

做签名认证的时候会调用我的defaultView方法,其他的事件都走defaultViewHandler方法。

coreService.processRequest(): 是对所有的请求事件进行处理

CoreService.java主要代码实现如下:

@Override
    public String processRequest(String msg) {
        String respMessage = null;
        try {
            // 默认返回的文本消息内容
            String respContent = "";

            // xml请求解析
            Map<String, String> requestMap = MessageUtil.parseXml(msg);

            // 发送方帐号(open_id)
            String fromUserName = requestMap.get("FromUserName");
            // 公众帐号
            String toUserName = requestMap.get("ToUserName");
            // 消息类型
            String msgType = requestMap.get("MsgType");
            String eventType = requestMap.get("Event");

            // 存在事件类型且类型有效 或者 消息类型可以处理,才需要进行身份处理,防止没有意义的事件引起发送大量绑定消息
            if ((!StringUtils.isEmpty(eventType) && !eventArrays.contains(eventType)) || !msgArrays.contains(msgType)) {
                return "";
            }

            respMessage = handleWxMessage(requestMap);
        } catch (Exception e) {
            LOGGER.error("error", e);
            e.printStackTrace();
        }
        return respMessage;
    }

    @Override
    public String handleWxMessage(Map<String, String> requestMap) {
        // 发送方帐号(open_id)
        String fromUserName = requestMap.get("FromUserName");
        // 公众帐号
        String toUserName = requestMap.get("ToUserName");
        // 消息类型
        String msgType = requestMap.get("MsgType");
        // 回复文本消息
        String respContent = "";
        BaseMessage textMessage = new TextMessage();
        textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
        switch (msgType) {
            case MessageUtil.REQ_MESSAGE_TYPE_TEXT:
                // 文本类型消息,暂时设置成用户发什么就回复什么
                String content = requestMap.get("Content");
                respContent = "";
                break;
            case MessageUtil.REQ_MESSAGE_TYPE_VOICE:
                // 使用语音识别功能需要开启微信公众号相关权限
                // 语音识别结果
                String recognizeText = requestMap.get("Recognition");
                respContent = "";
                break;
            case MessageUtil.REQ_MESSAGE_TYPE_EVENT:
                // 事件类型
                String eventType = requestMap.get("Event");
                // 事件KEY值,qrscene_为前缀,后面为二维码的参数值
                String eventKey = requestMap.get("EventKey");
                // 自定义事件
                switch (eventType) {
                    // 用户未关注时,进行关注后的事件推送
                    case MessageUtil.EVENT_TYPE_SUBSCRIBE:
                        if (isUserBuyLastActivity(fromUserName)) {
                            textMessage = getAddClassTextMessage(fromUserName);
                        } else {
                            textMessage = getDefaultTextMessage(fromUserName);
                        }
                        Integer eventKeyValue = 1;// 带参数的情景值
                        if (!StringUtils.isEmpty(eventKey) && eventKey.contains("qrscene_")) {
                            eventKey = eventKey.replace("qrscene_", "");
                            // 渠道ID
                            eventKeyValue = Integer.parseInt(eventKey);
                        }
                        subscribeAction(fromUserName, eventKeyValue);
                        break;
                    // 取消关注
                    case MessageUtil.EVENT_TYPE_UNSUBSCRIBE:
                        unSubscribeAction(fromUserName);
                        break;
                    // 用户已关注时的事件推送
                    case MessageUtil.EVENT_TYPE_SCAN:
                        textMessage = getDefaultTextMessage(fromUserName);
                        break;
                    default:
                        respContent = "";
                        break;
                }
                break;
            default:
                respContent = "";
                break;
        }

        if (textMessage instanceof TextMessage) {
            // 文本内容为空且是文本消息返回空字符串,防止微信发送异常消息
            String content = ((TextMessage) textMessage).getContent();
            if (StringUtils.isEmpty(respContent) && StringUtils.isEmpty(content)) {
                return "";
            }
            if (org.apache.commons.lang.StringUtils.isBlank(content)) {
                ((TextMessage) textMessage).setContent(respContent);
            }
        }
        textMessage.setToUserName(fromUserName);
        textMessage.setFromUserName(toUserName);
        textMessage.setCreateTime(new Date().getTime());
        String xmlString = MessageUtil.messageToXml(textMessage);
        return xmlString;
    }

上面只是展示了部分核心代码,具体代码可以去我的GitHub下载,地址:https://github.com/liuyanmin/wxDemo

下面是微信开发相关的链接:

申请个人测试账号:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

微信被动回复消息开发文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543

微信错误码文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543


2018-12-08 14:26:57 wangb_java 阅读数 254
  • 微信公众平台开发入门

    本套课程的设计完全是为初学者量身打造,课程内容由浅入深,课程讲解通俗易懂,代码实现简洁清晰。通过本课程的学习,学员能够入门微信公众平台开发,能够胜任企业级的订阅号、服务号、企业号的应用开发工作。 通过本课程的学习,学员能够对微信公众平台有一个清晰的、系统性的认识。例如,公众号是什么,它有什么特点,它能做什么,怎么开发公众号。 其次,通过本课程的学习,学员能够掌握微信公众平台开发的方法、技术和应用实现。例如,开发者文档怎么看,开发环境怎么搭建,基本的消息交互如何实现,常用的方法技巧有哪些,真实应用怎么开发。

    385071 人正在学习 去看看 刘运强

本篇以测试号为例,介绍如何接收微信的消息,同时回复消息hello world。

环境

jdk1.8,spring boot2,外网域名,内网穿透。

内网穿透

在开发微信公众号的时候,不仅我们需要调用微信的接口,微信也需要调用我们的接口,给我们发送各种消息。所以我们的项目要部署到互联网上才能接收到微信的消息。然而,在开发调试过程中我们往往处于局域网环境,不可能每改一次代码就部署到外网上去看效果。内网穿透的作用就是穿透我们的局域网,让外网域名直接绑定到我们的局域网电脑。当我们在本机修改代码时,外网可以马上看到效果。

花生壳

实现内网穿透方法有很多,但目前我知道的最简单方便的就是花生壳。我在上面申请了免费域名,并开通了内网穿透功能。配置非常简单,这里不多说了。内网穿透现在好像要6元钱,永久使用。双11有免费优惠,不知道双12还有没有。当解决了域名和内网穿透的问题,以下正式进入微信环节。

测试账号

登录地址 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

点击登录按钮,然后用你的个人微信扫码即可确认登录。

基本信息

登录以后有很多信息,现在只看接口配置信息

URL:就是微信给我们发消息时,会调用到我们的接口url。这个接口需要我们自己开发并部署到网上,http://xxx.imwork.net是我在花生壳申请的免费域名,handler就是我在spring mvc中配置的Mapping地址,.xml是扩展url,因为微信要求的消息格式是xml。图中是已经配置成功的,新账号需要先开发这个接口的get方法并上线,然后配置URL和Token,提交后微信会用get方法请求这个URL,正确完成请求才算配置成功。

Token:请求URL接口的token,以后再讲,现在可以随便填,自己记得就行。

验证接口

只要将微信发过来的echostr参数返回给他,前面的URL和Token就可以配置成功。如下,这里并没有做验证,也是以后再讲,现在先把hello world走通。

	@GetMapping("/handler")
	public String handler(@RequestParam Map<String,String> map)  {
		return map.get("echostr");

当微信用get方法请求上面的handler成功之后,就算对接配置成功了。以后再有正式的业务消息,微信都会用post方法请求handler。比如当用户关注我们的微信号时,微信也会用post发消息给handler,我们下面就给他回复一条消息,hello world!

xml格式消息

微信给我们发送的消息是xml格式,同样我们回复的消息也必须是xml格式。如何接收和响应xml,参考spring boot2 (36)-xml。下面再重复一下必须的相关配置,引入依赖和全局参数

     <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
    </dependency>

spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-registered-suffix-pattern=true

文本消息参数

微信给我们发的关注消息,和我们回复的hello world消息都是文本消息类型,都有以下5个参数。注意,参数首字母要大写。

@JacksonXmlRootElement(localName = "xml")
public class TextMessage {

	@JacksonXmlProperty(localName = "ToUserName")	
	private String toUserName;  	//消息接收者
	@JacksonXmlProperty(localName = "FromUserName")
	private String fromUserName;	//消息发送者
	@JacksonXmlProperty(localName = "CreateTime")
	private long createTime;		//当前时间(秒)
	@JacksonXmlProperty(localName = "MsgType")
	private String msgType;			//消息类型
	@JacksonXmlProperty(localName = "Content")
	private String content;			//消息内容
	//省略get/set

ToUserName:消息接收者。

FromUserName:消息发送者。

注意:假如是用户触发的消息,FromUserName就是用户id,ToUserName就是我们公众号的id,这两个id都是由微信生成的。而当我们回复消息时,则需要将ToUserName和FromUserName的身份即id互换。

CreateTime:当前时间,在微信中是以秒为单位,即System.currentTimeMillis()/1000。

MsgType:消息类型,文本消息即text。

content:消息内容,即hello world。

post方法响应微信消息

	@PostMapping(value="/handler")
	public Object handler(@RequestBody Map<String,String> map) throws JsonProcessingException  {

		TextMessage textMessage = new TextMessage();
		textMessage.setToUserName(map.get("FromUserName"));	//map是微信发过来的消息参数
		textMessage.setFromUserName(map.get("ToUserName"));
		textMessage.setCreateTime(System.currentTimeMillis()/1000);
		textMessage.setMsgType("text");
		textMessage.setContent("hello world");
		return textMessage;

关注微信测试账号,回复hello world

测试账号登录页面中间,有一个二维码,扫码即可关注。

关注后进入公众号即会收到一条消息,hello world

 

没有更多推荐了,返回首页