2019-05-15 14:37:23 u012757419 阅读数 87
  • 微信公众平台深度开发v2.0第6季——微信WEB开发、手机...

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    12241 人正在学习 去看看 翟东平

微信开放平台和公众平台的区别

1.公众平台面向的时普通的用户,比如自媒体和媒体,企业官方微信公众账号运营人员使用,当然你所在的团队或者公司有实力去开发一些内容,也可以调用公众平台里面的接口,比如自定义菜单,自动回复,查询功能。目前大多数微信通过认证之后,都在做这个事情。

mp.weixin.qq.com


2.开放平台面向的开发者和第三方独立软件开发商。我觉得开发平台最大的开放就是微信登录。当年腾讯没有花大力气去做统一登录这个事情,导致目前各个网站都要弄一套登录机制。好在他们现在认清了局势。开发者或软件开发商,通过微信开放提供的平台和接口,可以开发适合企业的电子商务网站,扫描二维码进去一个游戏界面,然后去购买商品等。当然后续开放平台要开放支付接口,那么类似口袋通这种软件开发厂商,就可以为大型,中小企业提供微信小店这种服务和软件了。

open.weixin.qq.com

 

公众平台就是服务号订阅号的管理开发后台。

开发平台说得通俗一点就是实现手机里边安装软件的内容一键分享朋友圈;

下面的第三方登陆就是依托于开放平台(open.weixin.qq.com)的功能

 

准备工作

网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。

在进行微信OAuth2.在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程。

授权流程说明

微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。

微信OAuth2.0授权登录目前支持authorization_code模式,适用于拥有server端的应用授权。该模式整体流程为:

  1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;

  2. 通过code参数加上AppID和AppSecret等,通过API换取access_token;

  3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

获取access_token时序图:

 

第一步:请求CODE

第三方使用网站应用授权登录前请注意已获取相应网页授权作用域(scope=snsapi_login),则可以通过在PC端打开以下链接:
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

若提示“该链接无法访问”,请检查参数是否填写错误,如redirect_uri的域名与审核时填写的授权域名不一致或scope不为snsapi_login。

参数说明

参数 是否必须 说明
appid 应用唯一标识
redirect_uri 重定向地址,需要进行UrlEncode
response_type 填code
scope 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可
state 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验

返回说明

用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数

redirect_uri?code=CODE&state=STATE

若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数

redirect_uri?state=STATE

请求示例

登录一号店网站应用

https://passport.yhd.com/wechat/login.do

打开后,一号店会生成state参数,跳转到
https://open.weixin.qq.com/connect/qrconnect?appid=wxbdc5610cc59c1631&redirect_uri=https%3A%2F%2Fpassport.yhd.com%2Fwechat%2Fcallback.do&response_type=code&scope=snsapi_login&state=3d6be0a4035d839573b04816624a415e#wechat_redirect

微信用户使用微信扫描二维码并且确认登录后,PC端会跳转到

https://passport.yhd.com/wechat/callback.do?code=CODE&state=3d6be0a4035d839573b04816624a415e

为了满足网站更定制化的需求,我们还提供了第二种获取code的方式,支持网站将微信登录二维码内嵌到自己页面中,用户使用微信扫码授权后通过JS将code返回给网站。

JS微信登录主要用途:网站希望用户在网站内就能完成登录,无需跳转到微信域下登录后再返回,提升微信登录的流畅性与成功率。 网站内嵌二维码微信登录JS实现办法:

步骤1:在页面中先引入如下JS文件(支持https):

<script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>

步骤2:在需要使用微信登录的地方实例以下JS对象:

                          var obj = new WxLogin({

                              id:"login_container", 

                              appid: "", 

                              scope: "", 

                              redirect_uri: "",

                              state: "",

                              style: "",

                              href: ""

                            });

参数说明

参数 是否必须 说明
id 第三方页面显示二维码的容器id
appid 应用唯一标识,在微信开放平台提交应用审核通过后获得
scope 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可
redirect_uri 重定向地址,需要进行UrlEncode
state 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验
style 提供"black"、"white"可选,默认为黑色文字描述。详见文档底部FAQ
href 自定义样式链接,第三方可根据实际需求覆盖默认样式。详见文档底部FAQ

第二步:通过code获取access_token

通过code获取access_token

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明

参数 是否必须 说明
appid 应用唯一标识,在微信开放平台提交应用审核通过后获得
secret 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
code 填写第一步获取的code参数
grant_type 填authorization_code

返回说明

正确的返回:


"access_token":"ACCESS_TOKEN", 
"expires_in":7200, 
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID", 
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"}

参数 说明
access_token 接口调用凭证
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 授权用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔
 unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。

错误返回样例:

{"errcode":40029,"errmsg":"invalid code"}

刷新access_token有效期

access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:

  1. 1. 若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间;

  2. 2. 若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。

refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权。

请求方法

获取第一步的code后,请求以下链接进行refresh_token:

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

参数说明

参数 是否必须 说明
appid 应用唯一标识
grant_type 填refresh_token
refresh_token 填写通过access_token获取到的refresh_token参数

返回说明

正确的返回:


"access_token":"ACCESS_TOKEN", 
"expires_in":7200, 
"refresh_token":"REFRESH_TOKEN", 
"openid":"OPENID", 
"scope":"SCOPE" 
}

参数 说明
access_token 接口调用凭证
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 授权用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔

错误返回样例:

{"errcode":40030,"errmsg":"invalid refresh_token"}

注意:

1、Appsecret 是应用接口使用密钥,泄漏后将可能导致应用数据泄漏、应用的用户数据泄漏等高风险后果;存储在客户端,极有可能被恶意窃取(如反编译获取Appsecret);

2、access_token 为用户授权第三方应用发起接口调用的凭证(相当于用户登录态),存储在客户端,可能出现恶意获取access_token 后导致的用户数据泄漏、用户微信相关接口功能被恶意发起等行为;

3、refresh_token 为用户授权第三方应用的长效凭证,仅用于刷新access_token,但泄漏后相当于access_token 泄漏,风险同上。

 

建议将secret、用户数据(如access_token)放在App云端服务器,由云端中转接口调用请求。

 

第三步:通过access_token调用接口

获取access_token后,进行接口调用,有以下前提:

  1. 1. access_token有效且未超时;

  2. 2. 微信用户已授权给第三方应用帐号相应接口作用域(scope)。

对于接口作用域(scope),能调用的接口有以下:

授权作用域(scope) 接口 接口说明
snsapi_base /sns/oauth2/access_token 通过code换取access_token、refresh_token和已授权scope
/sns/oauth2/refresh_token 刷新或续期access_token使用
/sns/auth 检查access_token有效性
snsapi_userinfo /sns/userinfo 获取用户个人信息

其中snsapi_base属于基础接口,若应用已拥有其它scope权限,则默认拥有snsapi_base的权限。使用snsapi_base可以让移动端网页授权绕过跳转授权登录页请求用户授权的动作,直接跳转第三方网页带上授权临时票据(code),但会使得用户已授权作用域(scope)仅为snsapi_base,从而导致无法获取到需要用户授权才允许获得的数据和基础功能。

接口调用方法可查阅《微信授权关系接口调用指南》

F.A.Q

1. 什么是授权临时票据(code)?

答:第三方通过code进行获取access_token的时候需要用到,code的超时时间为10分钟,一个code只能成功换取一次access_token即失效。code的临时性和一次保障了微信授权登录的安全性。第三方可通过使用https和state参数,进一步加强自身授权登录的安全性。

 

2. 什么是授权作用域(scope)?

答:授权作用域(scope)代表用户授权给第三方的接口权限,第三方应用需要向微信开放平台申请使用相应scope的权限后,使用文档所述方式让用户进行授权,经过用户授权,获取到相应access_token后方可对接口进行调用。

3. 网站内嵌二维码微信登录JS代码中style字段作用?

答:第三方页面颜色风格可能为浅色调或者深色调,若第三方页面为浅色背景,style字段应提供"black"值(或者不提供,black为默认值),则对应的微信登录文字样式为黑色。相关效果如下:

 

若提供"white"值,则对应的文字描述将显示为白色,适合深色背景。相关效果如下:

 

4.网站内嵌二维码微信登录JS代码中href字段作用?

答:如果第三方觉得微信团队提供的默认样式与自己的页面样式不匹配,可以自己提供样式文件来覆盖默认样式。举个例子,如第三方觉得默认二维码过大,可以提供相关css样式文件,并把链接地址填入href字段

.impowerBox .qrcode {width: 200px;}
.impowerBox .title {display: none;}
.impowerBox .info {width: 200px;}
.status_icon {display:none}
.impowerBox .status {text-align: center;} 

相关效果如下:

 

通过code获取access_token

接口说明

通过code获取access_token的接口。

请求说明

http请求方式: GET

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明

参数 是否必须 说明
appid 应用唯一标识,在微信开放平台提交应用审核通过后获得
secret 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
code 填写第一步获取的code参数
grant_type 填authorization_code

返回说明

正确的返回:


"access_token":"ACCESS_TOKEN", 
"expires_in":7200, 
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID", 
"scope":"SCOPE" 
}

参数 说明
access_token 接口调用凭证
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 授权用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔

错误返回样例:

{
"errcode":40029,"errmsg":"invalid code"
}

刷新或续期access_token使用

接口说明

access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:

  1. 1. 若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间;

  2. 2.若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。

refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权。

请求方法

使用/sns/oauth2/access_token接口获取到的refresh_token进行以下接口调用:

http请求方式: GET

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

参数说明

参数 是否必须 说明
appid 应用唯一标识
grant_type 填refresh_token
refresh_token 填写通过access_token获取到的refresh_token参数

返回说明

正确的返回:


"access_token":"ACCESS_TOKEN", 
"expires_in":7200, 
"refresh_token":"REFRESH_TOKEN", 
"openid":"OPENID", 
"scope":"SCOPE" 
}

参数 说明
access_token 接口调用凭证
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 授权用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔

错误返回样例:

{
"errcode":40030,"errmsg":"invalid refresh_token"
}

接口说明

检验授权凭证(access_token)是否有效

请求说明

http请求方式: GET

https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID

参数说明

参数 是否必须 说明
access_token 调用接口凭证
openid 普通用户标识,对该公众帐号唯一

返回说明

正确的Json返回结果:


"errcode":0,"errmsg":"ok"
}

错误的Json返回示例:


"errcode":40003,"errmsg":"invalid openid"
}

获取用户个人信息(UnionID机制)

接口说明

此接口用于获取用户个人信息。开发者可通过OpenID来获取用户基本信息。特别需要注意的是,如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号,用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。

请求说明

http请求方式: GET

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID

参数说明

参数 是否必须 说明
access_token 调用凭证
openid 普通用户的标识,对当前开发者帐号唯一

返回说明

正确的Json返回结果:


"openid":"OPENID",
"nickname":"NICKNAME",
"sex":1,
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"privilege":[
"PRIVILEGE1", 
"PRIVILEGE2"
],
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"

}

参数 说明
openid 普通用户的标识,对当前开发者帐号唯一
nickname 普通用户昵称
sex 普通用户性别,1为男性,2为女性
province 普通用户个人资料填写的省份
city 普通用户个人资料填写的城市
country 国家,如中国为CN
headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
privilege 用户特权信息,json数组,如微信沃卡用户为(chinaunicom)
unionid 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。

错误的Json返回示例:


"errcode":40003,"errmsg":"invalid openid"
}

调用频率限制

接口名 频率限制
通过code换取access_token 1万/分钟
刷新access_token 5万/分钟
获取用户基本信息 5万/分钟

 

2018-07-10 11:28:44 qq_36147006 阅读数 7162
  • 微信公众平台深度开发v2.0第6季——微信WEB开发、手机...

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    12241 人正在学习 去看看 翟东平

首先说明一下本人用的是java的开发语言,先前做过微信支付、微信公众号开发,对于微信的第三方平台开发是第一次接触,但总的来说这种只需看看文档调用接口的工作还是相对容易的,接下来就讲讲在微信第三方平台开发全网发布遇到的坑。

首先讲一下微信第三方全网发布的微信自动化测试的几大流程

 

  1. 组件ticket正确接收;

  2. 生成预授权码;

  3. 获取授权code;

  4. 授权;

  5. 返回Api文本消息;

  6. 返回普通文本消息;

  7. 发送事件消息;

  8. 取消授权。

以上是微信自动化测试的八个步骤,其实就是模拟人工进行公众号的授权流程。一般来说只要到了这个步骤了在测试环境中都是测试ok了才会进行全网发布,本人呢也是在测试环境测试ok了自信满满的丢到正式环境准备全网发布,但事实是啪啪打脸。主要原因不是出在代码出现BUG上,而是出在微信自动化测试的步骤上,下面开始讲一下我遇到的问题:

以上八个步骤一般会出错的就是5,6,7几个步骤前几个都比较容易过,只要你在测试环境测试ok前几个一般都没问题,

我的问题出现在5,6上,下面附上当时的截图

当时看到这个时候是懵逼的后来看了全网发布接入检测说明才恍然大悟,需要按照他们的步骤来测试完成才能将代码改成你自己想要的需求下面我们来讲一下返回普通文本和Api文本检测出错的问题

返回普通文本检测失败

首先来看文档说明(附上文档链接:点击打开链接

需要注意的是红框部分只有在我们勾选了消息管理权限集时微信才会测试这个步骤。首先看第一步:微信那边会提供一个专门的测试公众号进行授权测试,授权后会模拟粉丝发送文本消息给他们的测试公众号,需要注意的是模拟粉丝发送的内容是一个固定的文本内容:TESTCOMPONENT_MSG_TYPE_TEXT并且是放在content字段中的,而我们需要做的是给他们回复一个固定的文本消息:TESTCOMPONENT_MSG_TYPE_TEXT_callback就行了不必画蛇添足加其他的东西。当时由于我们业务是回复粉丝一段固定的欢迎语而不是测试用的文本信息导致检测失败,后来改了之后立马就通过了检测

返回api文本信息检测失败

首先也是看文档说明

其实我们只要看红框的部分就行了,这里最重要的一个就是微信会模拟发送两次消息给测试公众号我们可以看到第一次发送到content字段内容是:TESTCOMPONENT_MSG_TYPE_TEXT  ,第二次发送的文本content字段内容是 :QUERY_AUTH_CODE:$query_auth_code$  所以我们在后台就可以加个判断分开发送不同的内容就行了

接下来就是调用客服发送消息接口了,具体调用附上详细信息:

 

注意这个access_token是授权测试公众号的access_token不是第三方平台的component_access_token  调用只需用http工具类调用就行了,还有就是我们返回给微信的content的值是:$query_auth_code$_from_api(其中$query_auth_code$需要替换成推送过来的query_auth_code)授权码和固定字符串“_from_api”拼接在一起的大概是这样的String textContent=authorization_code+"_from_api",但是我遇到到的问题是没有调用客服回复接口而是直接回复了图文消息所以失败,因为我的业务不需要用到客服接口,这就有点小坑了大笑,所以如果你需要全网发布的话还得按照官方的来,毕竟他们是大佬。至于后面用不用得到客服接口就看你们自己的业务需求了,一切准备OK再次发起全网发布自动化测试就ok了,全网发布审核大概需要三个工作日和小程序的审核时间差不多。

最后希望这篇文章能解决您在开发中遇到的问题再见

 

 

 

 

2017-12-13 15:49:24 m0_37412958 阅读数 898
  • 微信公众平台深度开发v2.0第6季——微信WEB开发、手机...

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    12241 人正在学习 去看看 翟东平
所有微信开发的相关内容,都需要参考官方文档。

[微信公众平台|开发文档] http://mp.weixin.qq.com/wiki/home/

一、通过网页授权,可以获取用户微信的基本信息。

二、总共有5个步骤:

1 :用户同意授权,获取code

2 :通过code换取网页授权access_token

3 :刷新access_token(如果需要)

4 :拉取用户信息(需scope为 snsapi_userinfo)

5 附:检验授权凭证(access_token)是否有效

三、每一个步骤的实现。

1 :用户同意授权,获取code

[php] view plain copy
  1. /** 
  2.      * @explain 
  3.      * 获取code,用于获取openid和access_token 
  4.      * @remark 
  5.      * code只能使用一次,当获取到之后code失效,再次获取需要重新进入 
  6.      * 不会弹出授权页面,适用于关注公众号后自定义菜单跳转等,如果不关注,那么只能获取openid 
  7.      **/  
  8.     public function getCode()  
  9.     {  
  10.         if (isset($_GET["code"])) {  
  11.             return $_GET["code"];  
  12.         } else {  
  13.             $str = "location: https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $this->appid . "&redirect_uri=" . $this->index_url . "&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";  
  14.             header($str);  
  15.             exit;  
  16.         }  
  17.     }  

2 :通过code换取网页授权access_token

[php] view plain copy
  1. /** 
  2.      * @explain 
  3.      * 用于获取access_token,返回的<span style="font-family: Arial, Helvetica, sans-serif;">$access_token_array中也包含有用户的openid信息。</span> 
  4.  
  5.      **/  
  6.     public function getOpenId()  
  7.     {  
  8.         $access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" . $this->appid . "&secret=" . $this->appsecret . "&code=" . $this->code . "&grant_type=authorization_code";  
  9.         $access_token_json = $this->https_request($access_token_url);  
  10.         $access_token_array = json_decode($access_token_json, TRUE);  
  11.         return $access_token_array;  
  12.     }  

3 :刷新access_token(如果需要)

这一步直接略过。

4 :拉取用户信息(需scope为 snsapi_userinfo)

[php] view plain copy
  1. /** 
  2.      * @explain 
  3.      * 获取到用户的openid之后可以判断用户是否有数据,可以直接跳过获取access_token,也可以继续获取access_token 
  4.      **/  
  5.     public function getUserInfo()  
  6.     {  
  7.           
  8.         $userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$this->access_token['access_token'] ."&openid=" . $this->access_token['openid']."&lang=zh_CN";  
  9.         $userinfo_json = $this->https_request($userinfo_url);  
  10.         $userinfo_array = json_decode($userinfo_json, TRUE);  
  11.         return $userinfo_array;  
  12.     }  
至此四个步骤全部完成。


四、完整代码。实际项目使用TP3.2.3。

[php] view plain copy
  1. <?php  
  2.   
  3. namespace Wechat\Controller;  
  4.   
  5. use Think\Controller;  
  6.   
  7. //微信接口基础类,其他微信类都继承这个基础类。可以自动判断用户状态,获取用户信息。  
  8. class WxbaseController extends Controller  
  9. {  
  10.   
  11.     public $appid = 'wxba09d9f0fed4b84b';                   //微信APPID,公众平台获取  
  12.     public $appsecret = '332c2b1fc1eb282c0136b73723db4237'//微信APPSECREC,公众平台获取  
  13.     public $index_url = "http://www.你的域名.cn/项目目录/index.php?m=分组&c=控制器&a=方法";  //微信回调地址,要跟公众平台的配置域名相同  
  14.     public $code;  
  15.     public $openid;  
  16.   
  17.     /**  
  18.      *检测有无$_SESSION。<span style="font-family: Arial, Helvetica, sans-serif;">如果有,直接忽略。</span>  
  19.      *如果没有$<span style="font-family:Arial, Helvetica, sans-serif;">_SESSION</span>,就依次执行getCode、getOpenId、getUserInfo来获取用户信息。目的是解决CODE只能获取一次,刷新页面openid会丢失的问题。  
  20.      *再判断是否在数据库中,没有则写入数据库。最后将open_id写入session。  
[php] view plain copy
  1. <span style="white-space:pre">    </span>*/  
  2.     public function _initialize()  
  3.     {  
  4.             if (!$_SESSION['openid']) {                             //如果$_SESSION中没有openid,说明用户刚刚登陆,就执行getCode、getOpenId、getUserInfo获取他的信息  
  5.                 $this->code = $this->getCode();  
  6.                 $this->access_token = $this->getOpenId();  
  7.                 $userInfo = $this->getUserInfo();  
  8.                 if ($userInfo) {  
  9.                     $ins = M('Wechat_user_info');<span style="white-space:pre">       </span>    //其他框架请自行调整方法。  
  10.                     $map['openid'] = $userInfo['openid'];  
  11.                     $result = $ins->where($map)->find();            //根据OPENID查找数据库中是否有这个用户,如果没有就写数据库。继承该类的其他类,用户都写入了数据库中。  
  12.                     if (!$result) {  
  13.                         $ins->add($userInfo);  
  14.                     }  
  15.                     session('openid'$userInfo['openid']);         //写到$_SESSION中。微信缓存很坑爹,调试时请及时清除缓存再试。  
  16.                 }  
  17.             }  
  18.   
  19.     }  
  20.   
  21.     /** 
  22.      * @explain 
  23.      * 获取code,用于获取openid和access_token 
  24.      * @remark 
  25.      * code只能使用一次,当获取到之后code失效,再次获取需要重新进入 
  26.      * 不会弹出授权页面,适用于关注公众号后自定义菜单跳转等,如果不关注,那么只能获取openid 
  27.      **/  
  28.     public function getCode()  
  29.     {  
  30.         if (isset($_GET["code"])) {  
  31.             return $_GET["code"];  
  32.         } else {  
  33.             $str = "location: https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $this->appid . "&redirect_uri=" . $this->index_url . "&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";  
  34.             header($str);  
  35.             exit;  
  36.         }  
  37.     }  
  38.   
  39.     /** 
  40.      * @explain 
  41.      * 用于获取用户openid 
  42.      **/  
  43.     public function getOpenId()  
  44.     {  
  45.         $access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" . $this->appid . "&secret=" . $this->appsecret . "&code=" . $this->code . "&grant_type=authorization_code";  
  46.         $access_token_json = $this->https_request($access_token_url);  
  47.         $access_token_array = json_decode($access_token_json, TRUE);  
  48.         return $access_token_array;  
  49.     }  
  50.   
  51.     /** 
  52.      * @explain 
  53.      * 通过code获取用户openid以及用户的微信号信息 
  54.      * @return 
  55.      * @remark 
  56.      * 获取到用户的openid之后可以判断用户是否有数据,可以直接跳过获取access_token,也可以继续获取access_token 
  57.      * access_token每日获取次数是有限制的,access_token有时间限制,可以存储到数据库7200s. 7200s后access_token失效 
  58.      **/  
  59.     public function getUserInfo()  
  60.     {  
  61.   
  62.         $userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$this->access_token['access_token'] ."&openid=" . $this->access_token['openid']."&lang=zh_CN";  
  63.         $userinfo_json = $this->https_request($userinfo_url);  
  64.         $userinfo_array = json_decode($userinfo_json, TRUE);  
  65.         return $userinfo_array;  
  66.     }  
  67.   
  68.   
  69.     /** 
  70.      * @explain 
  71.      * 发送http请求,并返回数据 
  72.      **/  
  73.     public function https_request($url$data = null)  
  74.     {  
  75.         $curl = curl_init();  
  76.         curl_setopt($curl, CURLOPT_URL, $url);  
  77.         curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);  
  78.         curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);  
  79.         if (!empty($data)) {  
  80.             curl_setopt($curl, CURLOPT_POST, 1);  
  81.             curl_setopt($curl, CURLOPT_POSTFIELDS, $data);  
  82.         }  
  83.         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);  
  84.         $output = curl_exec($curl);  
  85.         curl_close($curl);  
  86.         return $output;  
  87.     }  
  88. }  

2019-10-08 11:04:44 yinhaoh 阅读数 9
  • 微信公众平台深度开发v2.0第6季——微信WEB开发、手机...

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    12241 人正在学习 去看看 翟东平
	微信发送的消息如果是服务器配置则可以直接接收消息,如果是第三方授权则需要先进行解密。
	本文用的是spring boot开发。
	注意:回复的消息要5s中以内返回给微信,否则会返回错误给公众号。

微信上消息与事件接收的url要求配置/APPIDAPPID/所以映射的时候也需要加上/{appid}/
微信上第三方平台的配置

@ApiOperation(value = "接收行为消息")
	@RequestMapping(value = "/{appid}/updCustmEvent")
	public String updCustmEventWeiChat(HttpServletRequest request) throws IOException {
		String nonce = request.getParameter("nonce");
		String timestamp = request.getParameter("timestamp");
		String msgSignature = request.getParameter("msg_signature");
		String encryptType = request.getParameter("encrypt_type");
		String signature = request.getParameter("signature");
		String postData;
		postData = StreamUtils.getInputStreamJson(request.getInputStream());
		EventDTO custmEventDTO = new EventDTO();

		//消息解密
		String json = eventService.decryptWeChat(nonce, timestamp, msgSignature, encryptType, signature, postData);
		if(!StringUtils.isEmpty(json)) {
			Document doc;
			try {
				doc = DocumentHelper.parseText(json);
				// 解析xml
				Element rootElt = doc.getRootElement();
				custmEventDTO.setToUserName(rootElt.elementTextTrim("ToUserName"));
				custmEventDTO.setFromUserName(rootElt.elementTextTrim("FromUserName"));
				custmEventDTO.setContent(rootElt.elementTextTrim("Content"));
				custmEventDTO.setCreateTime(Long.parseLong(rootElt.elementTextTrim("CreateTime")));
				custmEventDTO.setEvent(rootElt.elementTextTrim("Event"));
				custmEventDTO.setMsgId(rootElt.elementTextTrim("MsgId"));
				custmEventDTO.setMsgType(rootElt.elementTextTrim("MsgType"));
				custmEventDTO.setEventKey(rootElt.elementText("EventKey"));
				String result = replyService.replyWeChat(custmEventDTO, nonce, timestamp);
				return result;
			} catch (DocumentException e) {
				ExceptionUtils.logError(e);
			}
		}
		String echostr = "";
		return echostr;
	}
	@Override
	public String replyWeChat(CustmEventDTO custmEventDTO, String nonce, String timestamp) {
		String content = custmEventDTO.getContent();
		String fromUserName = custmEventDTO.getFromUserName();
		String toUserName = custmEventDTO.getToUserName();
		WechatAppInfo wechatAppInfo = wechatAppInfoRepository.findByUserName(toUserName);
		String accessToken = wechatService.GetWechatAccessToken(wechatAppInfo.getAppId());
	
		String replyType = "text";
		if(StringUtils.isEmpty(content) || StringUtils.isEmpty(replyType)){
			return ResultUtils.build(CodeEnums.SUCCESS_CODE_NO_DATA);
		}
		ReplyTextMessageDTO we = new ReplyTextMessageDTO();

		String xml = "";
		we.setMessageType(replyType);
	    we.setFuncFlag("0");
	    we.setToUserName(fromUserName);  
        we.setFromUserName(toUserName);
	    XStream xstream = new XStream(new DomDriver()); 
	    xstream.alias("xml", ReplyTextMessageDTO.class);
	    we.setCreateTime(new Long(new Date().getTime()).toString());
	    xstream.aliasField("ToUserName", ReplyTextMessageDTO.class, "toUserName");
        xstream.aliasField("FromUserName", ReplyTextMessageDTO.class, "fromUserName");
        xstream.aliasField("CreateTime", ReplyTextMessageDTO.class, "createTime");
        xstream.aliasField("MsgType", ReplyTextMessageDTO.class, "messageType");
        xstream.aliasField("FuncFlag", ReplyTextMessageDTO.class, "funcFlag");
		if(("text").equals(replyType)) { //回复文本消息
			if("hhh".equals(content)) {
				WechatTemplateDTO wechatTemplateDTO = new WechatTemplateDTO();
				wechatTemplateDTO.setTouser(custmEventDTO.getFromUserName());
				wechatTemplateDTO.setTemplateid("1Ql7pjk-khnA2tFlAsuZ2Q0U1u8OawhgM6-ir9PcAWQ");
				wechatTemplateDTO.setAppId("wx1b208f0bbd201865");
				List<WechatTemplateDataDTO> wechatTemplateDatas  = new ArrayList<WechatTemplateDataDTO>();
				WechatTemplateDataDTO wechatTemplateDataDTO = new WechatTemplateDataDTO();
				wechatTemplateDataDTO.setName("first");
				wechatTemplateDataDTO.setValue("1");
				wechatTemplateDatas.add(wechatTemplateDataDTO);
				WechatTemplateDataDTO wechatTemplateDataDTO1 = new WechatTemplateDataDTO();
				wechatTemplateDataDTO1.setValue("1");
				wechatTemplateDataDTO1.setName("grade1");
				wechatTemplateDatas.add(wechatTemplateDataDTO1);
				WechatTemplateDataDTO wechatTemplateDataDTO2 = new WechatTemplateDataDTO();
				wechatTemplateDataDTO2.setValue("1");
				wechatTemplateDataDTO2.setName("grade2");
				wechatTemplateDatas.add(wechatTemplateDataDTO2);
				WechatTemplateDataDTO wechatTemplateDataDTO3 = new WechatTemplateDataDTO();
				wechatTemplateDataDTO3.setValue("1");
				wechatTemplateDataDTO3.setName("time");
				wechatTemplateDatas.add(wechatTemplateDataDTO3);
				WechatTemplateDataDTO wechatTemplateDataDTO4 = new WechatTemplateDataDTO();
				wechatTemplateDataDTO4.setValue("1");
				wechatTemplateDataDTO4.setName("remark");
				wechatTemplateDatas.add(wechatTemplateDataDTO4);
				wechatTemplateDTO.setWechatTemplateDatas(wechatTemplateDatas);
				weChatAppService.sendWechatTemplateList(wechatTemplateDTO);
			}
		} else if ("image".equals(replyType)) {
	        we.setContent(content);
	        we.setPicUrl("");
	        we.setMediaId("");
	        we.setMsgId(0);
	        xstream.aliasField("PicUrl", ReplyTextMessageDTO.class, "picUrl");
	        xstream.aliasField("MediaId", ReplyTextMessageDTO.class, "mediaId");
	        xstream.aliasField("MsgId", ReplyTextMessageDTO.class, "msgId");
		} else if ("voice".equals(replyType)) {
	        we.setMediaId("");
	        we.setFormat("");
	        we.setMsgId(0);
	        xstream.aliasField("MediaId", ReplyTextMessageDTO.class, "mediaId");
	        xstream.aliasField("Format", ReplyTextMessageDTO.class, "format");
	        xstream.aliasField("MsgId", ReplyTextMessageDTO.class, "msgId");
		} else if ("video".equals(replyType)) {
	        we.setMediaId("");
	        we.setThumbMediaId("");
	        we.setMsgId(0);
	        xstream.aliasField("MediaId", ReplyTextMessageDTO.class, "mediaId");
	        xstream.aliasField("ThumbMediaId", ReplyTextMessageDTO.class, "thumbMediaId");
	        xstream.aliasField("MsgId", ReplyTextMessageDTO.class, "msgId");
		} else if ("shortvideo".equals(replyType)) {
	        we.setMediaId("");
	        we.setThumbMediaId("");
	        we.setMsgId(0);
	        xstream.aliasField("MediaId", ReplyTextMessageDTO.class, "mediaId");
	        xstream.aliasField("ThumbMediaId", ReplyTextMessageDTO.class, "thumbMediaId");
	        xstream.aliasField("MsgId", ReplyTextMessageDTO.class, "msgId");
		} else if ("location".equals(replyType)) {
	        we.setLocationX("");
	        we.setLocationY("");
	        we.setScale("");
	        we.setLabel("");
	        we.setMsgId(0);
	        xstream.aliasField("Location_X", ReplyTextMessageDTO.class, "locationX");
	        xstream.aliasField("Location_Y", ReplyTextMessageDTO.class, "locationY");
	        xstream.aliasField("Scale", ReplyTextMessageDTO.class, "scale");
	        xstream.aliasField("Label", ReplyTextMessageDTO.class, "label");
	        xstream.aliasField("MsgId", ReplyTextMessageDTO.class, "msgId");
		}else if("link".equals(replyType)) { //回复音乐消息
			we.setTitle("");
	        we.setDescription("");
	        we.setUrl("");
	        we.setMsgId(0);
	        xstream.aliasField("Title", ReplyTextMessageDTO.class, "title");
	        xstream.aliasField("Description", ReplyTextMessageDTO.class, "description");
	        xstream.aliasField("Url", ReplyTextMessageDTO.class, "url");
	        xstream.aliasField("MsgId", ReplyTextMessageDTO.class, "msgId");
		}  
        xml =xstream.toXML(we);
        // 返回xml类型,第三方授权返回需要明文加密,不是则不需要
        String ecrypt = ecryptWeChat(xml,  nonce,  timestamp);		
        return ecrypt;
	}

加密:

	@Override
	public String ecryptWeChat(String replyMsg, String nonce, String timestamp) {
		//从配置文件获取appid、token
		String encodingAesKey = weChatComponentProperties.getEncodingAesKey();
		String appId = weChatComponentProperties.getAppId();
		String token = weChatComponentProperties.getToken();
		WXBizMsgCrypt pc;
		String mingwen  = "";
		try {
			pc = new WXBizMsgCrypt(token, encodingAesKey, appId);
			mingwen = pc.encryptMsg(replyMsg, timestamp, nonce);
		} catch (AesException e) {
			e.printStackTrace();
		}
		
		return mingwen;
	}
	
2016-03-24 18:42:05 lamboo_cn 阅读数 11475
  • 微信公众平台深度开发v2.0第6季——微信WEB开发、手机...

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    12241 人正在学习 去看看 翟东平
  如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。

1. 授权回调域名的说明:
(1)、这里填写的是域名(是一个字符串),而不是URL,因此请勿加http://等协议头;
(2)、授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com;
(3)、如果公众号登录授权给了第三方开发者来进行管理,则不必做任何设置,由第三方代替公众号实现网页授权即可

  1. 关于网页授权的两种scope的区别说明:
    (1)、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面);
    (2)、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。

  2. 网页授权access_token和普通access_token的区别:
    (1)、微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息;
    (2)、其他微信接口,需要通过基础支持中的“获取access_token”接口来获取到的普通access_token调用;

  3. 网页授权流程分为三步:
    (1)、第一步:用户同意授权,获取code,

 String appId="微信公众号的APPID";
 String url="微信回调的URL";
 String redirect_uri=URLEncoder.encode(url,"utf-8");
 String state="重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 ";//带这个参数的好处就是防止非法的请求。
String url = "https://open.weixin.qq.com/connect/oauth2/authorize?";
        url = url + "appid=" + this.wxMpConfigStorage.getAppId();
        url = url + "&redirect_uri=" + URIUtil.encodeURIComponent(redirectURI);
        url = url + "&response_type=code";
        url = url + "&scope=" + scope;
        if (state != null) {
            url = url + "&state=" + state;
        }
        url = url + "#wechat_redirect";//进行URL的拼接
response.sendRedirect(url);//调用http请求的,进行微信授权

(2)、第二步:通过code换取网页授权access_token:

//这段代码在你回调的指定的url的Servlet或者action:
String code = request.getParameter("code");
loggerWx.info("code=" + code.toString());
String url="https://api.weixin.qq.com/sns/oauth2/access_token?appid="微信公众号的APPID"&secret="微信公众号的secret"&code=CODE&grant_type=authorization_code";//url的拼接
String wxMpOAuth2AccessToken=httpclient.post(url);//进行网络请求

(3)、第三步:拉取用户信息(需scope为 snsapi_userinfo):

String url="https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";//url的拼接
String wx_User_string=httpclient.post(url);//进行网络请求

最后寄语,有什么问题可以沟通,其实微信的官方文档解释的挺全面的,官方文档的网址:http://mp.weixin.qq.com/wiki/1/8a5ce6257f1d3b2afb20f83e72b72ce9.html

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