微信公众号网页授权summer版

很早前就想了解下微信公众号开发,懒和拖延症让这计划迟迟没落实,正巧新项目有了微信公众号的业务,我心中没数地回应,我来!顿时,无形的压力向上冒,不知何从下手,果然是矛盾体质,好奇向往新事物又恐惧陌生,心中两种声音在争论,保守派说你摊上了,激进派说微信小程序都推行了,还不去了解下公众号开发想当奥特蜗曼呀。是啊,做技术的,学习和创新就是本质工作之一啊。减少社交活动,暂时戒掉部分兴趣爱好...与电脑并肩作战了两个月,时间是长还是短没概念,只知道走了不少弯路也收获了很多,为避免走同样的弯路,把脑子里的零碎整理成了笔记。

在开始coding前做了很多微信相关的功课,回头想想,其实公众号开发和微信只有几毛钱关系,主要的工作量还是在于本身系统的业务逻辑,看的白一点就是把有一定组织架构的h5页面放web服务器,通过微信提供的各种接口调用微信公众号所具备的功能来服务你的系统。微信只是你系统的入口或者客户端,你所需要的技能也是java web那一套。

我的项目采用这样的技术,
后台:
spring + springMVC + ibetis; 原本使用的是最常规架构controller,service,dao,pojo的结构,但为了以后的维护,改成了和主系统一样的架构 controller , model , business command和database command,dao ,pojo,其中controller和平常所说的controller一样主要负责与页面的逻辑,model相当于serice, 继承了pojo, 调用business command, business command对database command进行调用
前端:
html5,css3,bootstrap,jquery;
DB:
Mysql; 
第三方接口:
微信公众号网页授权接口, 微信公众号网页支付接口, 支付宝手机网站支付接口;阿里大于短信接口, 快递100物流接口;
开发工具: idea ,eclipse, sublim, navicat, dbvisualizer, beyond compare,Filezilla, Git,notepad++ ,微信web开发者工具,花生壳, chrome, firefox,还有网易云音乐;
测试环境: 阿里云服务器(linux)+jdk+tomcat8.0+mysql;
实用网址: 图标素材 http://www.iconfont.cn
                bootstrap 说明书 http://v3.bootcss.com/components
                微信公众平台 https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN
                微信公众平台wiki  https://mp.weixin.qq.com/wiki
                微信开放平台 https://open.weixin.qq.com/
                微信商户平台 https://pay.weixin.qq.com/index.php/core/home     /login?return_url=%2Findex.php%2Fcore%2Fhome
              微信服务商平台 https://pay.weixin.qq.com/index.php/partner/public/home
              微信公众平台支付接口调试工具 https://mp.weixin.qq.com/debug/cgi-bin/readtmpl?t=pay/index
              微信公众号接口测试 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
                支付宝商家 https://b.alipay.com/order/signManage.htm
                支付宝开放平台https://www.ant-open.com/platform/home.htm
                相因的服务器新浪sae http://www.sinacloud.com/?from=baidu_web
                阿里大于 http://www.alidayu.com/
                快递100 http://www.kuaidi100.com/
以上网址会在后面的文章中陆续出现。关于接口的调用腾讯有长篇大论的文档,显得很复杂,再看白一点就是将接口需要的参数拼接成接口所要求的格式发送http请求,在发送之前对你的参数进行MD5加密,生成所需要的签名后,再将签名和参数一起向目标地址发送请求,原理满简单吼,但在处理细节时不小心就跳进坑里,所以官方提供的文档一定要看。

切入正题,网页授权开摆...

一、 申请微信公众号

申请地址:https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN

根据自己的需求选择适合的帐号类型


所在项目类似微商城,所以选择了服务号,在申请的时候需要上传公司营业执照等公司信息,个人只能申请普通订阅号,这种帐号类型没有高级接口功能,比如读取用户资料,支付等等等,所以仅仅想学习或者测试接口或以申请测试帐号(http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login)。

二、申请开放平台

公众号申请成功后,coding的事别急,先找接口文档,俗话说不耐心看文档的程序员不是好测试。登录公众平台->接口权限->网页服务->网页授权->网页授权获取用户基本信息(https://mp.weixin.qq.com/wiki)

为什么需要获取用户信息了?

当用户通过微信进入指定系统时(我们这里就叫我们的系统为系统A),系统A需要给访问者唯一标识,以前的系统都是让访问者注册,这里既然客户端是微信那么我们就使用微信的第三方认证方式,但微信出于对用户信息的保护就将这个唯一identity交给了openId和 unionId 在我们项目中openId/unionId的用途如下:


什么是openId?

openId是针对一个公众号开发,用户在这公众号中是唯一的,在不同的公众号中用户的openId不同;

什么是unionId?

unionId是针对同一个公司下多个公众号之间需要用户帐号互通的一种机制;即同一用户在同一开放平台下的公众号是唯一的,当然在不同开放平台下就不同了。

开放平台又是什么?

图片所示


开放平台申请地址(http://open.weixin.qq.com/),过程略,要收费哟,300块。

我们项目的场景是这样的,用户在微信端操作的数据需要传递到app端,刚才的图片已经告诉我们,app和微信间的交互不是通过公众平台,而是开放平台,这时要获取unionId,刚才准备好的公众号就不够用了,就还需要将已申请的公众平台绑定到申请好的开放平台上;

绑定公众号到开放平台

点击顶部 “管理中心”,选择进入“公众号”,再点击“绑定公众号”


三、获取openId和unionId

网页授权类型:snsapi_base和snsapi_userinfo

snsapi_base:静默授权,用户无感知。(需要用户关众该公众号才能获取openId? 网上各种版本都有,腾讯也没说清楚,经过测试不需要)

snsapi_userinfo:需要用户手动同意,由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息,对于已关注公众号的用户,如果用户从公众号的会话或者自定义菜单进入本公众号的网页授权页,即使是scope为snsapi_userinfo,也是静默授权,用户无感知。提示用户是否同意授权的窗口如下图:



网页授权回调

微信授权成功之后,接下来就是进入你所设置的回调地址,他的用途是授权成功后页面的跳转,在这个地址这个地址中session是有效的,可以在这个地址中用request取code的值。该地址需要到公众平台先进行设置 :

开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息

点击修改,填写回调地址所在域名,本想勾出重点,但发现每条都是重点。

如果没有域名可以申请一个sina云(http://www.sinacloud.com/?from=baidu_web),将你的系统部署上去,最低配置的免费。


回调域名除了图片上的要求还需要注意:

1.该域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头;

2、授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com无法进行OAuth2.0鉴权

3、如果公众号登录授权给了第三方开发者来进行管理,则不必做任何设置,由第三方代替公众号实现网页授权即可

授权步骤

网页授权流程分为四步,流程在文档中写的很清楚,我就将每步代码化吧

1、引导用户进入授权页面同意授权,获取code

常量定义如下:

AppID = XXX

APPSECRET = XXX

REDIRECT_URI = http://XXX/common/wechat_auth.html

GET_CODE_URL = https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

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

GET_ACCESSTOKEN_URL = https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

GET_UNIONID_URL = https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID

SCOPE = snsapi_base

在你的action中生成访问的url

String getCodeUrl = Constants.GET_CODE_URL;

getCodeUrl = getCodeUrl.replace("APPID", Constants.APPID);

getCodeUrl = getCodeUrl.replace("REDIRECT_URI",     java.net.URLEncoder.encode(Constants.REDIRECT_URI,"utf-8"));

getCodeUrl = getCodeUrl.replace("SCOPE", Constants.SCOPE);

getCodeUrl = getCodeUrl.replace("STATE", entanceType);

getCodeUrl 成功生成

2、通过code换取网页授权access_token(与基础支持中的access_token不同)

这时能过request到你设置 好的回调地址中取拿到的code.

@RequestMapping("wechat_auth.html")

public ModelAndView wechatOauth2( HttpServletRequest request) {

String code = request.getParameter("code");code到手

String state = request.getParameter("state");

这个state是干嘛的呢,用于传递自定义参数,回过去看在获取code的地址中有传递一个state吧,在返回code的时候state将原样返回。

3、如果需要,开发者可以刷新网页授权access_token,避免过期

4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

/**

* 根据code获取openId和unionId

* @param code

* @return 返回openId和unionId

*/

public static String[] getOpenId(String code ) {

String args[] = new String[2];

//获取openid

String oauth2URL = Constants.GET_OPENID_URL;

oauth2URL = oauth2URL.replace("APPID", Constants.APPID);

oauth2URL = oauth2URL.replace("APPSECRET", Constants.APPSECRET);

oauth2URL = oauth2URL.replace("CODE", code);

System.out.println("oauth2URL::" + oauth2URL);

String authResponseJsonStr = HttpUtils.getUrl(oauth2URL);

System.out.println("authResponseJsonStr::" + authResponseJsonStr);

JSONObject responseJsonObject = JSONObject.parseObject(authResponseJsonStr);

args[0] = responseJsonObject.getString("openid");

//获取token

String tokenUrl2 =Constants.GET_ACCESSTOKEN_URL;

tokenUrl2 = tokenUrl2.replace("APPID", Constants.APPID);

tokenUrl2 = tokenUrl2.replace("APPSECRET", Constants.APPSECRET);

String tokenResponseJsonStr2 = HttpUtils.getUrl(tokenUrl2);

System.out.println("tokenResponseJsonStr2::" + tokenResponseJsonStr2);

JSONObject tokenResponseJsonObject2 = JSONObject.parseObject(tokenResponseJsonStr2);

String accessToken = tokenResponseJsonObject2.getString("access_token");

//根据openid和token获取unionid

String unionidUrl = Constants.GET_UNIONID_URL;

unionidUrl = unionidUrl.replace("ACCESS_TOKEN",accessToken);

unionidUrl = unionidUrl.replace("OPENID",args[0]);

String unionidResponseJsonStr = HttpUtils.getUrl(unionidUrl);

System.out.println("unionidResponseJsonStr::" + unionidResponseJsonStr);

JSONObject unionidresponseJsonObject =     JSONObject.parseObject(unionidResponseJsonStr);

args[1] = unionidresponseJsonObject.getString("unionid");

return args;

}

把得到的数组system.out.print出来,可以去喝点水了。

成功返回的json字符串长这样:

{    "openid":" OPENID",

" nickname": NICKNAME,

"sex":"1",

"province":"PROVINCE"

"city":"CITY",

"country":"COUNTRY",

"headimgurl":    "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ

4eMsv84eavHiaiceqxibJxCfHe/46",

"privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],

"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"

}

这是snsapi_userinfo类型的返回,如果是snsapi_base就没有nickname等个人信息字段。

四 、关于测试

你在测试微信授权时会发现在web浏览器里会被提示"请用微信客户端打开",不管是在手机微信还是电脑端微信测试了又会提示 "网站没有备案"之类的提示,localhost和ip地址更是不可行。这时微信web开发者工具就刚好解决这些难题,不仅可以测试功能,还可以debug, 有着和chrome开发者工具栏类似的功能。当然,如果你的系统授权逻辑还没写好,只有一串获取code的Url,想测试配置是否正确,比如:https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect。直接贴到web开发者工具地址栏,再到你的回调地址中用request.getParameter("code")取得code. 这里的回调地址前面已经提到需要是域名,而且只能是80端口,但你又想在本地调试,这里需要借力于花生壳将本地服务映射成对外访问的域名,再将该域名绑定到你申请好且备案的域名上。


我们在开发过程中经常会考虑自己的成果是否人性化,包括文档和代码的可读性,功能的易操作性...经过调用了很多第三方接口后有了新的认识,产品的人性化固然重要,产品的认可度更重要。看人家的文档和demo再想吐也会吐着看完,反正你非得调用我的接口,不清楚你也会研究,总有一天你会调用成功。当你调用成功后才恍然大悟,晕啊,原来那句话是那意思,说好的人性化呢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,423评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,339评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,241评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,503评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,824评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,262评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,615评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,337评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,989评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,300评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,829评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,193评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,753评论 3 230
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,970评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,708评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,295评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,207评论 2 258

推荐阅读更多精彩内容