微信网页开发_微信网页开发wx.config无反应 - CSDN
精华内容
参与话题
  • 微信公众平台开发网页开发

    万次阅读 2018-07-11 14:28:43
    以前写过一篇《微信公众平台开发的一点收获》,这一篇说说微信公众平台网页开发的知识。微信公众平台应该是国内最大的开放平台,对于技术开发人员来说,不管有没有自己的公众号,应该也要有一定的了解,其实只要有一...

    以前写过一篇《微信公众平台开发的一点收获》,这一篇说说微信公众平台网页开发的知识。微信公众平台应该是国内最大的开放平台,对于技术开发人员来说,不管有没有自己的公众号,应该也要有一定的了解,其实只要有一个域名和虚拟主机,就基本上能够尝试着去开发。

    回顾上篇文章的知识点

    (1)上篇文章的内容可以理解为公众号消息开发,这里的消息可以是公众号文章或者是消息会话,用户为了有权使用公众号的功能,必须关注对应的公众号。因为用户关注公众号了,所以开发者可以间接认为有权利获取用户的基本信息,都直接能够拿到用户的 OpenID(在相关接口中)。

    (2)access_token 概念,公众号开发者为了有权调用公众号 API,必须先经过微信的授权,这个授权码就是 access_token(开发者 access_token),这个 access_token 是和开发者绑定的(而非同用户绑定)。

    什么是公众号网页开发呢?

    公众号消息开发是用户必须加入这个公众号,然后开发者利用公众号平台提供的一些 API (功能)和用户来交互。除了公众号文章这里没有网页的概念(文章虽然是网页,但开发者没有任何能力控制)。

    现在考虑这样一种场景,一个开发者要提供一个电商服务,有他自己的业务逻辑(比如页面),通过公众号消息开发是提供不了这样的服务,为了解决这个问题,开发者可以做一个网页,然后在公众号菜单中引入这个网页,这样用户点击菜单打开网页就能使用电商服务。

    还有一种场景,某个服务商提供了一个调查问卷服务(以网页的形式),然后你的微信好友通过消息发送给你,你打开链接就能使用这个服务了(不一定是在公众号中打开)。

    再举个场景,微信有很多第三方服务,比如大众点评,相当于也是打开一个网页。

    为了有效的提供这样场景的服务,微信公众号官方提供了网页开发这个概念,主要包括三部分:

    (1)在微信中打开服务,这时候微信首先相当于一个浏览器,有浏览器就有 Javascript 操作,为了安全性微信这个“浏览器”肯定要做一些限制;为了提供微信的一些本地功能(比如调用相机),微信也提供了一些 JS-SDK,这样开发者就能调用这个 SDK 提供微信的一些功能。

    (2)既然是开放平台,所有的服务都嵌入在微信中,为了让开发者提供的服务更具有一致性(就是外观),微信也提供了 UI 库,有了 UI 库,开发者开发的网页就能更好的适配,实际上这个功能有点鸡肋,很少有用这个库的,都是为了让自己的网页更个性化。

    (3)假如是在微信中嵌入一个网站的网页,由于这个网页和公众号没有任何关系,那么这个网页怎么知道是那个微信用户(OpenID)打开了这个网页呢?公众号通过授权的方式让开发者能够获取用户的信息,这个授权就是标准的 oAuth 协议,通俗的说就是开发者假如需要获取用户信息,首先要取得用户的同意,这样公众号才能让你获取信息。仔细想下为什么消息公众号开发能够直接获取用户信息?

    概括的说,网页开发包括,网页授权、JS-SDK、UI 库。

    网页授权

    由于自己申请的公众号没有微信认证(就是没交钱),所以网页授权这个服务用不了,不过个人使用过微博开放平台的授权,原理差不多,所以简单的描述下。

    (1)要使用网页授权,在后台配置下回调域名就可以,不同于微博开放平台,不用提供回调 URL ,只要域名就可以。

    (2)scope,有两种授权方式,第一种就是假如一个微信用户已经加入公众号(相当于半授权了),那么这种授权方式叫静默授权(snsapi_base),就是说用户看不到官方的授权页面,会直接进入开发者提供的网页中,这种授权方式只能拿到 OpenID(通过其他接口再获取信息)。
    另外一种授权方式可以称之为完整授权(snsapi_userinfo),就是手用户能看到完整的授权页面,经过用户确认后再进入开发者提供的网页中,这种授权方式能够直接拿到用户信息(省去一次接口调用)。

    (3)授权流程

    假如开发者明白 oAuth 协议,这个流程就非常简单了。

    • 首先开发者通过 authorize 接口(传递回调地址和 appid )获取授权地址。
    • 用户打开授权地址并授权后,微信会回调开发者的回调地址,并返回 code 值。
    • 开发者传递 code 调用 access_token 接口获取用户 access_token 和 OpenID 值,这个值的有效期一般是 7200 秒。
    • 为了避免用户频繁授权,开发者可以用即将过期的 access_token 刷新 access_token(refresh_token接口)。
    • 通过传递用户 access_token 和 OpenID 调用 userinfo 接口获取用户信息。

    这里的用户 access_token 和开发者 access_token 不是一回事,分别代表用户授权和公众号授权。

    PHP-SDK 中通过简单的几个函数调用就能实现授权。

    JS-SDK

    在 PC 网页开发中,通过 Javascript 能够调用浏览器的功能;同理微信其实就是一个浏览器,为了调用浏览器(微信)的功能,微信提供了一个 JS-SDK 包,这样就能调用相应的功能了。

    使用很简单,首先引入对应的 js 文件即可。然后在动态网页中配置 config 信息即可

    <script>
    wx.config({
        debug: true,
        appId: 'wx3505a38e6f83b187',
        timestamp: 1490782160,
        nonceStr: 'ogZFeZaYLMhCQiez',
        signature: 'c1bd73bc505840a4db142873306bf10f243444ff',
        jsApiList: [
        ]
    });
    wx.ready(function () {
        document.querySelector('#checkJsApi').onclick = function () {
        wx.checkJsApi({
            jsApiList: [
            'getNetworkType',
            'previewImage'
            ],
            success: function (res) {
            //alert(JSON.stringify(res));
            }
        });
    };
    </script>
    

    使用 JS-SDK 最关键的包括二部分:

    (1)jsapi_ticket ,使用 jsapi_ticket 也是需要微信公众号平台授权的,否则任何人都能使用了。
    jsapi_ticket 是调用相应接口生成的(传递 access_token 参数),这个 access_token 是消息公众号开发者的 access_token(不是用户的),思考下为啥 JS-SDK 不直接使用 access_token 而要使用 jsapi_ticket ?

    (2)获取到 jsapi_ticket 后,会对时间戳、随机数、jsapi_ticket、当前 URL 签名后生成 wx.config,假如微信验证签名通过后,代表能够使用对应的 JS-SDK。

    PHP-SDK 中通过简单的几个函数调用就能生成签名,非常方便。

    UI 库

    UI 库其实非常简单,就理解为一个小型的 bootstrap 库就可以了。在微信上也很少看到开发者用这个库的。思考了下原因,在 PC 网页和公众号上为了保持样式一致性,开发者会用统一的 UI 库,但是微信没有 PC 网页。

    最后说下,没有经过微信认证的开发权限越来越小了,举个例子,假如没有经过微信认证,微信公众号菜单上无法配置网页的 URL。



    作者:虞大胆
    链接:https://www.jianshu.com/p/cca418ab3a8d
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
    展开全文
  • 微信网页开发

    2020-02-19 21:42:52
    微信网页开发 在进行微信网页开发时,大都需要获取用户的openId,甚至需要进一步获取用户的基本信息,昵称性别等 需要获取openId等需要认证过的公众号(服务号)才能申请获取,并且对回调地址要求是icp备案过的...

    微信网页开发

       在进行微信网页开发时,大都需要获取用户的openId,甚至需要进一步获取用户的基本信息,昵称性别等

      需要获取openId等需要认证过的公众号(服务号)才能申请获取,并且对回调地址要求是icp备案过的域名才行

    展开全文
  • 第一部分、为公众号菜单嵌入网页 一、关键参考文档  微信JS-SDK说明文档 。 二、编辑模式嵌入网页 在公众号平台下,自定义菜单,添加菜单,并选择菜单内容跳转到指定页面地址即可(需认证后方可添加页面地址,个人...

    第一部分、为公众号菜单嵌入网页 


    一、关键参考文档

     微信JS-SDK说明文档 。


    二、编辑模式嵌入网页

    在公众号平台下,自定义菜单,添加菜单,并选择菜单内容跳转到指定页面地址即可(需认证后方可添加页面地址,个人账号暂不支持认证)。

    三、开发者模式嵌入网页(通过微信公众平台接口调试工具动态生成菜单)

    1、基础支持中,通过appid和secret获取access_token,该值有效期为7200秒。(Get请求)

    2、自定义创建菜单,填写access_token,发送body作为菜单项Post请求生成菜单,跳转网页的菜单格式如下。

           {
                "type": "view", 
                "name": "我的网页", 
                "url": "http://www.baidu.com"
            }, 


    第二部分、在网页中调用微信接口

    微信提供了众多接口,可以在网页中调用。如调用扫码接口、支付接口、选择图片等接口。要使用这些接口,需要遵从微信开发规则生成签名,并在网页中注入签名。具体可参考微信JS-SDK说明文档,本文使用测试号调用JS-SDK接口过程如下:


    一、绑定域名

    1、通过ngrok内网穿透工具,将80端口映射到公网(命令:ngrok http 80),获取域名。以下图示域名通过nat123工具获取

    2、在公众测试号上配置“JS接口安全域名



    二、生成签名,获取正确权限(具体请查看微信JS-SDK说明文档附录1)

    1、获取access_token(有效期2小时,每日最多生成2000次)。

    通过微信公众平台接口调试工具,填写appid和secret生成。

    2、获取jsap_ticket值(有效期2小时,频繁刷新会导致api调用受限)

    在浏览器中,输入https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi,同时替换access_token值,通过Get请求方式,浏览器会将jsapi_ticket值通过json格式显示出来,ticket字段即所需。错误请检查access_token是否过期,appid和secret是否正确。

    3、获取签名,

    3.1 微信JS-SDK接口文档附录6,提供了java、node、php、python不同版本的签名算法,在本文中,直接获取java版本的Sign类,添加到项目中,用户生成签名。

    3.2 生成签名需要未过期的jsapi_ticket值和页面跳转的url值作为参数,该url应当与菜单跳转中的url一致,url中应该用域名而不是ip地址,否则不能获取权限。

    3.3 通过签名算法,将jsapi_ticket,noncestr, timestamp,url等值存储在map中,我们需要将其动态添加到jsp页面的权限注入代码中。


    三、为test.jsp网页引入js文件,注入权限

    1、引入js文件,<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

    2、在java服务器获取Sign并将必要数据传入jsp页面

    	@RequestMapping("/test")
    	private ModelAndView regist(HttpServletRequest request) throws Exception{
    		ModelAndView mv = new ModelAndView();
    		
    		Map<String, String> sign = sign("regist");
    		mv.addObject("sign", sign);
    		mv.addObject("appid", WxConst.APP_ID);
    		mv.setViewName("test");
    		return mv;
    	}
    	protected Map<String, String> sign(String action) throws Exception {
    		Map<String, String> map = WxConst.mMap;
    
    		String ticket = "jsapi_ticket";
    		String url = "http://12083054.nat123.cc/Test/wx/test";
    		if (null != ticket && !"".equals(url) && null != url && !"".equals(url)) {
    			Map<String, String> sign = Sign.sign(ticket, url);
    			return sign;
    		}
    		return null;
    	}
    3、test.jsp页面获取数据,并动态为jsp注入权限,并是测试号,添加了beta字段,建议开启debug调试模式,jsApiList即是微信所提供的JS-SDK接口。

    <script type="text/javascript">
    		wx.config({
    			beta:true,
    			debug : true,
    			appId : '${appid}',
    			timestamp : ${sign.timestamp},
    			nonceStr : '${sign.nonceStr}',
    			signature : '${sign.signature}',
    			jsApiList : [ 'checkJsApi', 'onMenuShareTimeline',
    					'onMenuShareAppMessage', 'onMenuShareQQ',
    					'onMenuShareWeibo', 'onMenuShareQZone', 'hideMenuItems',
    					'showMenuItems', 'hideAllNonBaseMenuItem',
    					'showAllNonBaseMenuItem', 'translateVoice', 'startRecord',
    					'stopRecord', 'onVoiceRecordEnd', 'playVoice',
    					'onVoicePlayEnd', 'pauseVoice', 'stopVoice', 'uploadVoice',
    					'downloadVoice', 'chooseImage', 'previewImage',
    					'uploadImage', 'downloadImage', 'getNetworkType',
    					'openLocation', 'getLocation', 'hideOptionMenu',
    					'showOptionMenu', 'closeWindow', 'scanQRCode',
    					'chooseWXPay', 'openProductSpecificView', 'addCard',
    					'chooseCard', 'openCard' ]
    		})
    </script/>
    4、在jsp页面中,使用js语法调用微信提供的接口。
    function onScan(){
    	wx.ready(function(){
    		wx.scanQRCode({
    			needResult : 0,
    			scanType : [ "qrCode", "barCode" ],
    			success : function(res) {
    				var result = res.resultStr;
    			}
    		});
    	})
    }
    5、在微信web开发工具中调试,测试签名是否通过、权限是否获取。

    输入测试网址:http://12083054.nat123.cc/Test/wx/test   (此处模拟跳转菜单的url,生成签名的url应当相同),查看”权限列表“


    当可以获取的权限获取成功时,说明网页也可开始调用JS-SDK接口访问了。

    6、未能成功获取权限、可能存在的问题

    6.1、生成签名时,url参数与菜单跳转的url(本文中为微信web开发工具中输入的网址)不一致

    6.2、未引入js文件:<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

    6.3、appid或appsecret错误。

    6.4、access_token已过期,需要重新生成。

    6.5、jsapi_ticket已过期,需要重新生成。

    6.6、内网穿透工具连接失败,需要重新生成域名。配置所有参数

    常规解决思路:1、检查生成签名的url与菜单url是否一致。2、检查接口配置信息域名是否是最新并且正确。 3、重新通过appid和secret获取access_token和jsapi_ticket值并签名(即重新配置所有参数)。


    第三部分:在网页中获取用户信息(关键字段:openid,加密后的微信号,每个用户对每个公众号的openid是唯一的

    一、获取openid

    方案一:通过微信服务器转发消息,获取用户openid

    对于开发者模式,用户操作包括关注公众号、发送消息、点击菜单、绑定设备等操作,都将由微信服务器转发给开发者服务器,通过解析这些消息,可以获取到微信号对应的openid.

    用户发送消息时,读取输入流解析的数据格式如下。

    <xml><ToUserName><![CDATA[gh_3ec4154bc1424]]></ToUserName>
    <FromUserName><![CDATA[oNAmB1M115AqndH0wluCMQQtQsJog]]></FromUserName>
    <CreateTime>1504950429</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[滚滚长江东逝水]]></Content>
    <MsgId>6463712875121877522</MsgId>
    </xml>
    其中,FromUserName字段,即为所需要的openid.
    然而,由于用户数据由微信服务器转发给开发者服务器,该openid只能在接收微信服务的方法(开发都接口信息配置中的方法)中可获取此值。值得注意的是,该方法与开发者的网页并非处于同一会话中,是无法从会话中传递数据给开发者网页的。因此在网页开发过程上,不建议使用此方法获取openid提供给网页使用。

    方案二:微信网页授权获取openid,即Oauth技术.

    1、给微信测试号添加网页授权域名

    在测试号平台的体验接口权限下,选择”网页账号“修改域名。


    2、用户同意授权,获取code。(具体参考微信技术文档->微信网页授权部分)

    在用户跳转页面中,将菜单跳转url修改为:

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx3efbcdb7f6c647b7&redirect_uri=http://13bbb09b.ngrok.io/Test/wx/test&response_type=code&scope=snsapi_userinfo&state=1&connect_redirect=1#wechat_redirect

    其中appid表示公众号的appid;redicrect_uri为菜单项需要跳转的网页;scope可选择snsapi_base或snsapi_userinfo,state可填写a-zA-Z0-9的参数值。

    3、检测该链接的正确合法性。

    在微信web开发者工具中,输入上述url修改后的值。如果参数正确,调试界面显示如下:


    出现错误时,需针对错误提示进行修改。容易出错点:OAuth授权域名和跳转的url不一致或未配置。

    4、在redirect_uri中获取授权获得的信息,关键参数code参数

    String code = request.getParameter("code")

    5、通过code参数换取网页授权access_token,该值与基础支持中的access_token有差别。同时获取到当前用户的openid值。接口方法如下

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

    返回json数据如下:

    { "access_token":"ACCESS_TOKEN",    
     "expires_in":7200,    
     "refresh_token":"REFRESH_TOKEN",    
     "openid":"OPENID",    
     "scope":"SCOPE" } 
    通过以上方法便获取到了用户的openid值,避免了接口配置信息服务器,与网页开发服务器之间数据传递的麻烦。


    二、根据openid获取用户信息

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

    其中:access_token为授权过程中,通过code获取的值,不能是基础支持中的值。以下代码未处理空指针异常。用户信息以键值对的形式保存在userinfo_jsonObj中。

    	@RequestMapping("/test")
    	private ModelAndView test() throws Exception{
    		ModelAndView mv = new ModelAndView();
    		
    		//1、调用微信授权界面,拿到code
    		HttpServletRequest request = getRequest();
    		String code = request.getParameter("code");
    		//2、使用code获取access_token,此token与基础支持的token不同。有效期2小时
    		String access_token_url_str = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + WxConst.APP_ID + "&secret=" + WxConst.APP_SECRET + "&code=" + code + "&grant_type=authorization_code";
    		String access_token_json = WxRequest.doGet(new URL(access_token_url_str));
    		JSONObject access_token_jsonObj = JSONObject.fromObject(access_token_json);
    		String access_token = access_token_jsonObj.getString("access_token");
    		String openid = access_token_jsonObj.getString("openid");
    		//3、根据openid获取用户信息
    		String userinfo_url_str = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openid;
    		String userinfo_json = WxRequest.doGet(new URL(userinfo_url_str));
    		JSONObject userinfo_jsonObj = JSONObject.fromObject(userinfo_json);
    		
    		mv.setViewName("test");
    		return mv;
    	}
    	public static String doGet(URL url) throws Exception{
    		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    		StringBuffer sb = new StringBuffer();
    		String line = "";
    		BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    		if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
    			while((line = reader.readLine()) != null){
    				sb.append(line);
    			}
    		}
    		System.out.println(sb.toString());
    		reader.close();
    		connection.disconnect();
    		return sb.toString();
    	}
    最终获取到的用户信息json数据格式如下:

    {    "openid":" OPENID",  
     " nickname": NICKNAME,   
     "sex":"1",   
     "province":"PROVINCE"   
     "city":"CITY",   
     "country":"COUNTRY",    
     "headimgurl":    "",  
    "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],    
     "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" 
    } 
    展开全文
  • 微信小程序与微信网页开发

    千次阅读 2018-09-10 11:58:55
    微信web开发只需要code值,但是小程序需要一个code值,一个encryptData,一个iv 首先先看图   箭头部分为微信给我们的,就是前端需要传过来的。 步骤为: 小程序客户端调用wx.login,回调里面包含js_code。 ...

    微信web开发只需要code值,但是小程序需要一个code值,一个encryptData,一个iv

    首先先看图

     

    箭头部分为微信给我们的,就是前端需要传过来的。

    步骤为:

    1. 小程序客户端调用wx.login,回调里面包含js_code。
    2. 然后将js_code发送到服务器A(开发者服务器),服务器A向微信服务器发起请求附带js_code、appId、secretkey和grant_type参数,以换取用户的openid和session_key(会话密钥)。
    3. 服务器A拿到session_key后,生成一个随机数我们叫3rd_session,以3rdSessionId为key,以session_key + openid为value缓存到redis或memcached中;因为微信团队不建议直接将session_key在网络上传输,由开发者自行生成唯一键与session_key关联。其作用是:
      1. 将3rdSessionId返回给客户端,维护小程序登录态。
      2. 通过3rdSessionId找到用户session_key和openid。
    4. 客户端拿到3rdSessionId后缓存到storage,
    5. 通过wx.getUserIinfo可以获取到用户敏感数据encryptedData 。
    6. 客户端将encryptedData、3rdSessionId和偏移量一起发送到服务器A
    7. 服务器A根据3rdSessionId从缓存中获取session_key
    8. 在服务器A使用AES解密encryptedData,从而实现用户敏感数据解密

     

    重点在6、7、8三个环节。
    AES解密三个参数:

    • 密文 encryptedData
    • 密钥 aesKey
    • 偏移向量 iv

    概念性的东西就这些,下面看代码

    首先前端需要传给我们的东西就是三个一个code值,一个encryptData,一个iv,

    先写方法

     

    package com.everest.academy.util;
    
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import lombok.extern.slf4j.Slf4j;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import org.bouncycastle.util.encoders.Base64;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.URL;
    import java.net.URLConnection;
    import java.security.AlgorithmParameters;
    import java.security.Security;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    
    /**
    * @ClassName XcxUtils
    * @Description 微信小程序方法
    * @Author 田野
    * @Data 22:14
    * @Version 1.0
    **/
    @Slf4j
    public class XcxUtils {
    
    
    /**
        * 获取微信小程序 session_key 和 openid
        *
        * @author zhy
        * @param code
        *            调用微信登陆返回的Code
        * @return
        */
       public static JSONObject getSessionKeyOropenid(String code, String appid, String secret) {
    
    String requestUrl = "https://api.weixin.qq.com/sns/jscode2session"; // 请求地址
    
           Map<String, String> requestUrlParam = new HashMap<String, String>();
           requestUrlParam.put("appid", appid); // 开发者设置中的appId
           requestUrlParam.put("secret", secret); // 开发者设置中的appSecret
           requestUrlParam.put("js_code", code); // 小程序调用wx.login返回的code
           requestUrlParam.put("grant_type", "authorization_code"); // 默认参数
    
           // 发送post请求读取调用微信 https://api.weixin.qq.com/sns/jscode2session
           // 接口获取openid用户唯一标识
           JSONObject jsonObject = JSON.parseObject(sendPost(requestUrl, requestUrlParam));
            System.out.println(jsonObject);
           return jsonObject;
    
       }
    
    /**
        * 解密用户敏感数据获取用户信息
        *
        * @author zhy
        * @param sessionKey
        *            数据进行加密签名的密钥
        * @param encryptedData
        *            包括敏感数据在内的完整用户信息的加密数据
        * @param iv
        *            加密算法的初始向量
        * @return
        */
       public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {
    encryptedData=encryptedData.replace(" ", "+");
           sessionKey=sessionKey.replace(" ", "+");
           iv=iv.replace(" ", "+");
           // 被加密的数据
           byte[] dataByte = Base64.decode(encryptedData);
           // 加密秘钥
           byte[] keyByte = Base64.decode(sessionKey);
           // 偏移量
           byte[] ivByte = Base64.decode(iv);
           try {
    // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
               int base = 16;
               if (keyByte.length % base != 0)
    {
    int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                   byte[] temp = new byte[groups * base];
                   Arrays.fill(temp, (byte) 0);
                   System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                   keyByte = temp;
               }
    // 初始化
               Security.addProvider(new BouncyCastleProvider());
               Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
               SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
               AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
               parameters.init(new IvParameterSpec(ivByte));
               cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
               byte[] resultByte = cipher.doFinal(dataByte);
               if (null != resultByte && resultByte.length > 0)
    {
    String result = new String(resultByte, "UTF-8");
                   return JSON.parseObject(result);
               }
    } catch (Exception e) {
    log.error(e.getMessage(), e);
           }
    return null;
       }
    
    /**
        * 向指定 URL 发送POST方法的请求
        *
        * @param url
        *            发送请求的 URL
        * @param
        *
        * @return 所代表远程资源的响应结果
        */
       public static String sendPost(String url, Map<String, ?> paramMap) {
    PrintWriter out = null;
           BufferedReader in = null;
           String result = "";
    
           String param = "";
           Iterator<String> it = paramMap.keySet().iterator();
    
           while (it.hasNext()) {
    String key = it.next();
               param += key + "=" + paramMap.get(key) + "&";
           }
    try {
    URL realUrl = new URL(url);
               // 打开和URL之间的连接
               URLConnection conn = realUrl.openConnection();
               // 设置通用的请求属性
               conn.setRequestProperty("accept", "*/*");
               conn.setRequestProperty("connection", "Keep-Alive");
               conn.setRequestProperty("Accept-Charset", "utf-8");
               conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
               // 发送POST请求必须设置如下两行
               conn.setDoOutput(true);
               conn.setDoInput(true);
               // 获取URLConnection对象对应的输出流
               out = new PrintWriter(conn.getOutputStream());
               // 发送请求参数
               out.print(param);
               // flush输出流的缓冲
               out.flush();
               // 定义BufferedReader输入流来读取URL的响应
               in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
               String line;
               while ((line = in.readLine()) != null) {
    result += line;
               }
    } catch (Exception e) {
    log.error(e.getMessage(), e);
           }
    // 使用finally块来关闭输出流、输入流
           finally {
    try {
    if (out != null)
    {
    out.close();
                   }
    if (in != null)
    {
    in.close();
                   }
    } catch (IOException ex) {
    ex.printStackTrace();
               }
    }
    return result;
       }
    
    }

    注解写的很明白的,应该没什么看不懂。

    之后就是service层

    package com.everest.academy.service.impl;
    
    import com.alibaba.fastjson.JSONObject;
    import com.everest.academy.business.dto.LoginUserDTO;
    import com.everest.academy.business.dto.WechatTokenDto;
    import com.everest.academy.framework.exception.ResourceIsNullException;
    import com.everest.academy.framework.pojo.User;
    import com.everest.academy.persistence.mapper.UserMapper;
    import com.everest.academy.service.WechatService;
    import com.everest.academy.util.WechatUtil;
    import com.everest.academy.util.XcxUtils;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.Date;
    
    /**
    * @ClassName WechatServiceImpl
    * @Description 微信sgervice
    * @Author 田野
    * @Data 20:25
    * @Version 1.0
    **/
    @Slf4j
    @Service
    public class WechatServiceImpl implements WechatService {
    @Autowired
       UserMapper userMapper;
     
    @Override
       public LoginUserDTO getUserByCode(String code, String encryptedData, String iv)throws Exception{
    log.info("传进来的值"+encryptedData+"另一个"+iv);
           JSONObject shopAddress = null;
           if (StringUtils.isNotEmpty(code)) {
    String appid = "填自己的";
               String secret = "填自己的";
               shopAddress = XcxUtils.getSessionKeyOropenid(code, appid, secret);
           }
    assert shopAddress != null;
           String openId = shopAddress.getString("openid");
           String sessionKey = shopAddress.getString("session_key");
           log.info("session_key为:"+sessionKey);
           JSONObject user1 = XcxUtils.getUserInfo(encryptedData, sessionKey, iv);
           //user这里根据用户openId查询是否有这个用户。
           User user=userMapper.findByOpenId(openId);
           LoginUserDTO loginUserDTO=new LoginUserDTO();
           if (user!=null){
    log.info("用户的状态"+user.getState());
               if (user.getState()==1){
    //有的话,直接就进入 ,直接将信息返回给前端
                   loginUserDTO.setId(user.getId());
                   loginUserDTO.setOpenId(openId);
                   return loginUserDTO;
               }
    throw new Exception("无法登录,账号被冻结");
           }
    //没有的话,创建该学生的信息,然后再传给部分数据给前端
           User newUser=new User();
           newUser.setOpenId(openId);
           assert user1 != null;
           newUser.setAddress(user1.getString("city"));
           newUser.setHeadImgUrl(user1.getString("avatarUrl"));
           newUser.setName(user1.getString("nickName"));
           newUser.setState(1);
           newUser.setBeans(0);
           newUser.setBinding(0);
           newUser.setCreate_at(new Date().getTime());
           newUser.setCreate_by("系统创建");
           userMapper.insert(newUser);
           User user2=userMapper.findByOpenId(openId);
           LoginUserDTO loginUserDTO1=new LoginUserDTO();
           loginUserDTO1.setId(user2.getId());
           log.info("id的值"+newUser.getId());
           loginUserDTO1.setOpenId(newUser.getOpenId());
           loginUserDTO1.setBinding(newUser.getState());
           return loginUserDTO1;
       }
    }

    也写的挺清楚的,通过openId判断是否有这个用户

    controller

     

    package com.everest.academy.controller;
    
    import com.everest.academy.business.vo.ResponseVo;
    import com.everest.academy.framework.exception.ResourceIsNullException;
    import com.everest.academy.service.WechatService;
    import com.everest.academy.util.ResultUtil;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiImplicitParams;
    import io.swagger.annotations.ApiOperation;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.Map;
    
    /**
    * @ClassName WechatController
    * @Description 微信登录验证
    * @Author 田野
    * @Data 15:56
    * @Version 1.0
    **/
    @Slf4j
    @Api(tags = "WechatController",description = "微信开发API")
    @RestController
    @RequestMapping("/a/home")
    @Validated
    public class WechatController {
    @Autowired
       WechatService wechatService;
       @ApiOperation(value = "微信登录验证",notes = "通过获取的codeId值登录")
    @PostMapping("/{code}")
    public ResponseVo WechatLogin( @PathVariable("code") String code,
                                      @RequestParam("encryptedData") String encryptedData,@RequestParam("iv") String iv)throws Exception{
    log.info("传进来的未"+encryptedData +"iv为" + iv);
           return ResultUtil.success("微信登录成功",wechatService.getUserByCode(code,encryptedData,iv));
       }
    }

    就有一点问题

    测试的时候,每次传参都读不到+号,每次都把我的+号弄掉。

    所以这里运用了一个replace,完美解决

    微信网页开发,通过codeId得到access_token,通过access_token和openid获取用户基本信息

    package com.everest.academy.util;
    
    import com.everest.academy.business.dto.LoginUserDTO;
    import com.everest.academy.business.dto.WechatTokenDto;
    import com.google.gson.Gson;
    import com.google.gson.JsonObject;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @ClassName WechatUtil
     * @Description TODO
     * @Author 田野
     * @Data 19:25
     * @Version 1.0
     **/
    @Slf4j
    public class WechatUtil {
        public final static String APPID = "自己的";
        public final static String APPSECRET = "自己的";
        /**
         * 获取请求用户信息的access_token
         * @param code
         * @return
         */
        public static WechatTokenDto getUserInfoAccessToken(String code) {
            JsonObject object = null;
            WechatTokenDto wechatTokenDto=new WechatTokenDto();
            Map<String, String> data = new HashMap();
            try {
                String url = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
                        APPID, APPSECRET, code);
                log.info("request accessToken from url: {}", url);
                CloseableHttpClient httpClient =HttpClients.createDefault();
                HttpGet httpGet = new HttpGet(url);
                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                String tokens = EntityUtils.toString(httpEntity, "utf-8");
                Gson token_gson = new Gson();
                object = token_gson.fromJson(tokens, JsonObject.class);
                log.info("request accessToken success. [result={}]", object);
                wechatTokenDto.setOpenid(object.get("openid").toString().replaceAll("\"", ""));
                wechatTokenDto.setAccess_token(object.get("access_token").toString().replaceAll("\"", ""));
                wechatTokenDto.setRefresh_token(object.get("refresh_token").toString().replaceAll("\"", ""));
                wechatTokenDto.setScope(object.get("scope").toString().replaceAll("\"", ""));
                wechatTokenDto.setExpires_in(Integer.parseInt(object.get("expires_in").toString().replaceAll("\"","")));
    //            data.put("openid", object.get("openid").toString().replaceAll("\"", ""));
    //            data.put("access_token", object.get("access_token").toString().replaceAll("\"", ""));
    //            data.put("expires_in",object.get("expires_in").toString().replaceAll("\"",""));
    //            data.put("refresh_token",object.get("refresh_token").toString().replaceAll("\"", ""));
    //            data.put("scope",object.get("scope").toString().replaceAll("\"", ""));
            } catch (Exception ex) {
                log.error("fail to request wechat access token. [error={}]", ex);
            }
            return wechatTokenDto;
        }
    
        /**
         * 通过access_token和openid获取用户基本信息
         * @param accessToken
         * @param openId
         * @return
         */
        public static LoginUserDTO getUserInfo(String accessToken, String openId) {
            LoginUserDTO loginUserDTO=new LoginUserDTO();
            String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN";
            log.info("request user info from url: {}", url);
            JsonObject userInfo = null;
            try {
                CloseableHttpClient httpClient =HttpClients.createDefault();
                HttpGet httpGet = new HttpGet(url);
                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                String response = EntityUtils.toString(httpEntity, "utf-8");
                Gson token_gson = new Gson();
                userInfo = token_gson.fromJson(response, JsonObject.class);
                log.info("get userinfo success. [result={}]", userInfo);
                loginUserDTO.setOpenId(userInfo.get("openid").toString().replaceAll("\"", ""));
                loginUserDTO.setCountry(userInfo.get("country").toString().replaceAll("\"", ""));
                loginUserDTO.setProvince(userInfo.get("province").toString().replaceAll("\"", ""));
                loginUserDTO.setCity(userInfo.get("city").toString().replaceAll("\"", ""));
                loginUserDTO.setHeadImgUrl(userInfo.get("headimgurl").toString().replaceAll("\"", ""));
                loginUserDTO.setSex(Integer.valueOf(userInfo.get("sex").toString().replaceAll("\"", "")));
                loginUserDTO.setNickname(userInfo.get("nickname").toString().replaceAll("\"", ""));
    //            data.put("openid", userInfo.get("openid").toString().replaceAll("\"", ""));
    //            data.put("nickname", userInfo.get("nickname").toString().replaceAll("\"", ""));
    //            data.put("city", userInfo.get("city").toString().replaceAll("\"", ""));
    //            data.put("province", userInfo.get("province").toString().replaceAll("\"", ""));
    //            data.put("country", userInfo.get("country").toString().replaceAll("\"", ""));
    //            data.put("headimgurl", userInfo.get("headimgurl").toString().replaceAll("\"", ""));
            } catch (Exception ex) {
                log.error("fail to request wechat user info. [error={}]", ex);
            }
            return loginUserDTO;
        }
    
    
    }
    @Override
        public LoginUserDTO wechat(String code)throws ResourceIsNullException{
            //调用封装的微信方法,通过code值得到wechatTokenDto
            WechatTokenDto wechatTokenDto=WechatUtil.getUserInfoAccessToken(code);
            String accessToken = wechatTokenDto.getAccess_token();//得到accessToken
            String openId = wechatTokenDto.getOpenid();//得到openId
            //user这里根据用户openId查询是否有这个用户。
            User user=userMapper.findByOpenId(openId);
            LoginUserDTO loginUserDTO=WechatUtil.getUserInfo(accessToken,openId);
            log.info("用户信息"+user);
            if(user!=null){
                //有的话,直接就进入 ,直接将信息返回给前端
    //            loginUserDTO.setOpenId(openId);
                loginUserDTO.setId(user.getId());
                loginUserDTO.setBinding(user.getState());
                return loginUserDTO;
            }else {
                //没有的话,创建该学生的信息,然后再传给部分数据给前端
                User newUser=new User();
                newUser.setOpenId(loginUserDTO.getOpenId());
                newUser.setAddress(loginUserDTO.getCity());
                newUser.setHeadImgUrl(loginUserDTO.getHeadImgUrl());
                newUser.setName(loginUserDTO.getNickname());
                log.info("用户昵称"+loginUserDTO.getNickname());
                newUser.setState(1);
                newUser.setBeans(0);
                newUser.setBinding(0);
                newUser.setCreate_at(new Date().getTime());
                newUser.setCreate_by("系统创建");
                userMapper.insert(newUser);
                LoginUserDTO loginUserDTO1=new LoginUserDTO();
                loginUserDTO1.setId(newUser.getId());
                log.info("id的值"+newUser.getId());
                loginUserDTO1.setOpenId(newUser.getOpenId());
                loginUserDTO1.setBinding(newUser.getState());
                return loginUserDTO1;
            }
        }

    基本就是这个样子,后续看下能不能写的更加详细。

    展开全文
  • 微信网页开发配置步骤

    千次阅读 2016-08-31 15:54:41
    1.微信公众平台—–>开发———>网页账号————>修改授权回调页面域名2.微信公众平台—–>开发———>基本配置————>获取公众号基本配置信息3.微信公众平台—–>微信支付——>开发配置———–>修改支付授权...
  • 微信网页开发之JS-SDK初使用

    千次阅读 2019-02-21 15:23:05
    最近需要做一个页面,该页面使用微信浏览器打开,功能如下: 1、用户打开链接之后获取到用户...1、准备一个通过微信认证的公众号或者申请一个微信测试号,保证该公众号有“网页服务”的权限 二、开始开发 1、微信...
  • 步骤一:申请微信开发者测试账号 https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&amp;amp;amp;amp;amp;t=sandbox/index 步骤二:需要一个服务器,用来获取你要的信息,我使用的是阿里云 ...
  • 微信公众平台开发微信网页授权开发是子恒老师《微信公众平台开发》视频教程的第10部。详细讲解了用php进行微信网页授的开发。内容包含构造授权uri,实现网页授权,优化微信网页授,获取用户信息等等。
  • 清理微信浏览器网页缓存的办法

    万次阅读 2017-12-25 15:31:15
    微信开发是件非常蛋疼的事情,微信网页的缓存是更加蛋疼的东西,今天遇到的问题:一个页面在web开发工具上可以正常授权并获取到openid,放在手机上就死活不行,网上找来的办法如下: 使用微信内置的浏览器打开...
  • 小程序web-view使用方法是子恒老师《子恒说小程序开发》视频...详细讲解了小程序web-view组件的使用,内容包含web view打开网页网页与小程序之间的跳转,在web view中实现微信支付等等。欢迎反馈,微信号:QQ68183131
  • 微信公众h5页面如何在web端调试

    千次阅读 2018-03-06 16:51:24
    由于微信公众页面在手机上不好调试。所以可以选择使用微信开发者工具登录微信公众号-》开发者工具-》绑定微信账号-》下载工具-》安装-》微信扫码-》工具内输入公众号网页地址...
  • 使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发...
  • 怎样解决微信开发中刷新缓存问题

    千次阅读 2016-05-05 10:23:29
    微信开发中安卓数据缓存问题
  • 使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发...
  • 微信公众号开发之绑定微信开发者

    万次阅读 2018-09-03 21:24:39
    第一步:登录微信公众号,绑定网页开发者   在登录后的界面中,我们向下拉在左侧会看到有一个“开发者工具”点击。 这时在开发者工具中,会看到有好几个工具,其中有一个“web开发者工具”,我们点击进入。 ...
  • 使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发...
  • 最近着手开发微信网页扫码登录和公众号授权登录收获颇丰,两者的开发很类似。以下是我个人摸索过程中发现的两者的异同: 两者都可以通过微信客户端扫码授权的方式,让第三方页面获得微信用户的一些基本信息(昵称...
  • 一、登陆微信公众服务号,配置网页授权域名 (1)获取AppID以及AppSecret ...开发 ---》接口权限 ---》网页服务 ---》网页授权 ---》网页授权获取用户基本信息 ---》修改,如下图 点击修改,设置JS接口安
  • 微信公众平台获取网页授权(测试号)

    万次阅读 热门讨论 2016-01-30 15:06:05
    在测试微信公众号的网页开发授权的时候,总是提示scope参数错误啥的,获取不到正确的授权.经多方排查,发现确实是按照官方文档的流程做的,但就是出不来.折腾了半天,在qq群里询问了一下有经验的开发者,这才算是解决了....
  • 开发中我遇到了这样一个问题: 线上环境通过多台主机多实例部署,所以要用redis存储统一的session信息,然后通过一个uid为key来区分,当用户通过微信网页鉴权接口(整个接口的交互我写在了action里面)时会给用户...
1 2 3 4 5 ... 20
收藏数 55,044
精华内容 22,017
关键字:

微信网页开发