【Win10 UWP】微信SDK基本使用方法和基本原理
上回讲到,作为一个长期散播温暖,散播希望的小清新无公害WP开发者,继QQ SDK之后,又把UWP微信SDK这茬了结了,仅供学习交流。
1.安装微信SDK for UWP
微信官方此前明确说明短时间内暂不提供RT版和UWP版的微信SDK,但眼见UWP开发之势愈烈,微信分享也必然是许多应用的标配功能,那怎么办呢,自己移植成UWP版吧。拙者提供的微信SDK是基于官方silverlight版sdk反编译后重新打包封装成UWP版本的,对部分内容稍加修改,命名空间、使用方法基本与官方文档无异。
通过nuget下载并安装微信SDK,链接https://www.nuget.org/packages/WeChatSDK/
或者在控制台输入PM> Install-Package WeChatSDK
注意项目会引用依赖Google.ProtocolBuffersLite,如果安装完成之后该依赖未自动安装,建议您Unload后Reload一下项目,或者手动安装该依赖
PM> Install-Package Google.ProtocolBuffersLite
另外,本项目代码已放在github上,请高手帮忙改进https://github.com/zhxilin/WeChatSDK
2.申请微信开放平台应用Id
到微信开放平台官网https://open.weixin.qq.com/,创建应用获得AppId和AppSecret。
3.配置Package.appxmanifest文件
与QQ SDK不同,微信SDK仅使用文件关联协议进行应用间通信,为此需要对配置文件进行配置。打开Package.appxmanifest文件,在<Extensions>节点下添加windows.fileTypeAssociation的声明:
<Extensions><uap:Extension Category="windows.fileTypeAssociation"><uap:FileTypeAssociation Name="wechat"><uap:SupportedFileTypes><uap:FileType>.[YOUR APP ID]</uap:FileType></uap:SupportedFileTypes></uap:FileTypeAssociation></uap:Extension> </Extensions>
注意不要漏了appid前面的“.”
4.调用微信SDK进行分享
微信消息的基类是WXBaseMessage类,包含属性Title、Description和ThumbData,其中Title的最大长度为512B,Description最大长度为1K,ThumbData最大长度为32K,否则会引发WXException错误。根据不同场合消息又分为8种类型,均集成自WXBaseMessage类:
WXTextMessage,文本消息,Type = WXBaseMessage.TYPE_TEXT
WXImageMessage,图片消息,Type = WXBaseMessage.TYPE_IMAGE
WXMusicMessage,音乐消息,Type = WXBaseMessage.TYPE_MUSIC
WXVideoMessage,视频消息,Type = WXBaseMessage.TYPE_VIDEO
WXWebpageMessage,网页消息,Type = WXWebpageMessage.TYPE_URL
WXFileMessage,文件消息,Type = WXWebpageMessage.TYPE_FILE
WXAppExtendMessage,App扩展消息,Type = WXWebpageMessage.TYPE_APPDATA
WXEmojiMessage,表情消息,Type = WXEmojiMessage.TYPE_EMOJI
根据常用性,这里列举文本、图片和网页三种消息的分享方法,直接列举代码说明。以下是消息分享均通过打包消息数据后,发送SendMessageToWX.Req类型的请求来呼起微信客户端。
(1)分享文本消息
1 try 2 { 3 var scene = SendMessageToWX.Req.WXSceneTimeline; 4 var message = new WXTextMessage 5 { 6 Title = "Sharing a text title!", 7 Text = "This is text content", 8 Description = "This is a text message.这是一个文本消息。", 9 ThumbData = null 10 }; 11 SendMessageToWX.Req req = new SendMessageToWX.Req(message, scene); 12 IWXAPI api = WXAPIFactory.CreateWXAPI("[YOUR APP ID]"); 13 var isValid = await api.SendReq(req); 14 } 15 catch (WXException ex) 16 { 17 Debug.WriteLine(ex.Message); 18 }
其中scene有3种类型可以选择:
SendMessageToWX.Req.WXSceneChooseByUser // 用户自行选择 SendMessageToWX.Req.WXSceneSession // 分享给好友 SendMessageToWX.Req.WXSceneTimeline // 分享到朋友圈
其中Text属性是Text类型消息的专有属性,最大长度640K。
(2)分享图片消息
1 try 2 { 3 var scene = SendMessageToWX.Req.WXSceneTimeline; 4 var file = await Package.Current.InstalledLocation.GetFileAsync("1.png"); 5 using (var stream = await file.OpenReadAsync()) 6 { 7 var pic = new byte[stream.Size]; 8 await stream.AsStream().ReadAsync(pic, 0, pic.Length); 9 var message = new WXImageMessage 10 { 11 Title = "Sharing a picture!", 12 Description = "This is a image message.这是一个图片消息", 13 ThumbData = pic, 14 ImageUrl = "http://tp3.sinaimg.cn/1882347990/180/5725518284/1" 15 }; 16 SendMessageToWX.Req req = new SendMessageToWX.Req(message, scene); 17 IWXAPI api = WXAPIFactory.CreateWXAPI("[YOUR APP ID]"); 18 var isValid = await api.SendReq(req); 19 } 20 } 21 catch (WXException ex) 22 { 23 Debug.WriteLine(ex.Message); 24 }
其中ImageUrl和ImageData只能设置一个,ImageData不能超过10M。
(3)分享网页消息
1 try 2 { 3 var scene = SendMessageToWX.Req.WXSceneTimeline; 4 var file = await Package.Current.InstalledLocation.GetFileAsync("1.png"); 5 using (var stream = await file.OpenReadAsync()) 6 { 7 var pic = new byte[stream.Size]; 8 await stream.AsStream().ReadAsync(pic, 0, pic.Length); 9 var message = new WXWebpageMessage 10 { 11 WebpageUrl = "http://www.baidu.com", 12 Title = "Sharing a link!", 13 Description = "This is a link message.这是一个链接消息", 14 ThumbData = pic 15 }; 16 SendMessageToWX.Req req = new SendMessageToWX.Req(message, scene); 17 IWXAPI api = WXAPIFactory.CreateWXAPI("[YOUR APP ID]"); 18 var isValid = await api.SendReq(req); 19 } 20 } 21 catch (WXException ex) 22 { 23 Debug.WriteLine(ex.Message); 24 }
其中WebpageUrl不能超过10K。
(4)登录授权
登录授权向微信客户端发出的请求类型是SendAuth.Req
1 try 2 { 3 SendAuth.Req req = new SendAuth.Req("[YOUR SCOPE]", "test"); 4 IWXAPI api = WXAPIFactory.CreateWXAPI("[YOUR APP ID]"); 5 var isValid = await api.SendReq(req); 6 } 7 catch (WXException ex) 8 { 9 Debug.WriteLine(ex.Message); 10 }
其中[YOUR SCOPE]指的是在开放平台注册应用,开通登录授权后的权限范围。
(5)微信支付
SDK也提供了微信支付的请求类型SendPay.Req,由于支付权限申请比较困难,暂时没有测试,以后有实际场景再试。
5.回调结果处理
微信SDK提供了WXEntryBasePage类,继承自Page类,用来响应微信的回调。
如果你的页面基类仍然是Page,可以替换为WXEntryBasePage作为你的Page基类,直接重载各种Response方法即可得到回调结果;如果你已有自定义的Page基类,则通过另外的途径获取回调结果。
WXEntryBasePage类提供public void Handle(FileActivatedEventArgs e)方法来处理回调,我们仅需在App.xaml.cs中重载OnFileActivated方法,将参数传入Hadle方法即可进行结果解析,并将不同类型的消息结果通过不同的响应方法进行通知。
WXEntryBasePage类包含以下Response方法:
1 public virtual void OnSendAuthResponse(SendAuth.Resp response) 2 { 3 } 4 5 public virtual void OnSendMessageToWXResponse(SendMessageToWX.Resp response) 6 { 7 } 8 9 public virtual void OnSendPayResponse(SendPay.Resp response) 10 { 11 }
以上三种Response方法分别对应登录授权、消息分享以及支付等操作的结果。
- 如果你的Page基类已改成WXEntryBasePage,那么直接重载对应的这三个方法即可,如:
1 public override async void OnSendMessageToWXResponse(SendMessageToWX.Resp response) 2 { 3 base.OnSendMessageToWXResponse(response); 4 var dialog = new MessageDialog(response.ErrCode == 0 ? "分享成功": "分享失败"); 5 await dialog.ShowAsync(); 6 }
- 如果你的Page基类没有改成WXEntryBasePage,那么你需要自己实现一个Callback类,继承自WXEntryBasePage:
1 public class WeChatCallback : WXEntryBasePage 2 { 3 }
并在App.xaml.cs的OnFileActivated方法中,创建该对象,并调用其Handle方法:
1 protected override void OnFileActivated(FileActivatedEventArgs args) 2 { 3 base.OnFileActivated(args); 4 try 5 { 6 var wechat = new WeChatCallback(); 7 wechat.Handle(args); 8 } 9 catch (Exception) 10 { 11 // ignored 12 } 13 }
对于消息分享的Response,参数类型是SendMessageToWX.Resp,ErrCode == 0时表示分享成功,否则分享失败;
对于登录授权的Response,参数类型是SendAuth.Resp,其中Code即OAuth授权第一步所需的code,通过这个code,调用微信的Open API换取AccessToken,之后才能得到用户的基本资料。微信SDK并不实现Open API,所以需要自行实现。我还写了一个WeChatSDK.Extensions类库,提供WeChatSns类,封装了部分Open API,直接调用封装好的接口即可完成整个OAuth:
1 public override async void OnSendAuthResponse(SendAuth.Resp response) 2 { 3 base.OnSendAuthResponse(response); 4 if (response.ErrCode == 0) 5 { 6 if (!string.IsNullOrEmpty(response.Code)) 7 { 8 var token = await WeChatSns.GetAccessTokenAsync(response.Code); 9 if (token != null) 10 { 11 var user = await WeChatSns.GetUserInfoAsync(token.AccessToken, token.OpenId); 12 var dialog = new MessageDialog($"name:{user.Nickname}\r\nopenid:{user.OpenId}","授权成功"); 13 await dialog.ShowAsync(); 14 } 15 } 16 } 17 else 18 { 19 var dialog = new MessageDialog("授权失败"); 20 await dialog.ShowAsync(); 21 } 22 }
WeChatSDK.Extensions类库源码已贴在Github上,欢迎补充https://github.com/zhxilin/WeChatSDK/tree/master/UWP/WeChatSDK.Extensions
更多微信Open API请参考官方文档:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&lang=zh_CN
6.剖析微信SDK的原理
说完微信SDK的用法,下面谈谈它的实现原理。
要理解微信SDK的实现原理,首先要解决一个问题,理解什么是Protocol Buffers。可能很多人都注意到了微信SDK需要引用Google.ProtocolBuffersLite类库。
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式。它可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前支持C++、Java、Python、C#等语言。
...
是Google 公司内部的混合语言数据标准
使用Protocol Buffers比XML的好处在于更简单、更快、更小,对于微信这种频繁数据序列化和反序列化的场景来说非常实用。微信的数据交换在设计之初必须考虑实现消息的跨平台传输,那么对于平台无关、可扩展性超高的Protocol Buffers技术来说,就有了很大的用武之地。
对Protocol Buffers有兴趣的朋友可以多查阅一下相关资料
http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/index.html
http://kb.cnblogs.com/page/77621/
http://www.cnblogs.com/wu-jian/archive/2011/02/22/1961104.html
简单来说,对于服务端,只需要传输定义好结构的序列化文件 .proto文件到不同平台的客户端,通过Google提供的工具,如protoc、ProtoGen等工具即可反序列化为对应平台的具体对象。可以通过一张图来理解:
.proto文件会转成二进制序列protobuf进行传输,客户端接收到二进制序列后,按照指定的格式读取到对应平台的结构类型中就可以了。整个解析过程需要 Protocol Buffers框架和Protobuf 编译器生成的代码共同完成。比如protoc将.proto文件转成二进制文件,再通过protogen读取二进制文件转成C#代码。
了解了以上知识之后,我们来看看微信SDK是怎么做的。
比如分享消息,SDK将每个消息的结构整理后填入TransactionData中,该类包含ToProto方法和FromProto方法,分别将数据结构序列化成.proto对象和将.proto对象反序列化成数据结构。ToProto方法调用了Goolge.ProtocolBuffersLite类库提供的GeneratedBuilderLite<TMessage, TBuilder>.Build()方法完成序列化;FromProto方法则调用了BuildParsed()方法,将二进制序列反序列化成数据结构。
1 internal TransactDataP ToProto() 2 { 3 TransactDataP.Builder builder = TransactDataP.CreateBuilder(); 4 // ... 将TransactData中的属性填入builder后Build 5 return builder.Build(); 6 }
public static SendAuthResp ParseFrom(byte[] data) {return CreateBuilder().MergeFrom(data).BuildParsed(); }
我们的应用将数据打包放入一个后缀为.wechat的文件中,通过Launcher启动这个文件,自然只有微信客户端能识别这个文件,所以微信被呼叫起来并通过protobuf机制处理这个文件,完成我们的请求。
至于文件关联协议,之前讲过,在Package.appxmanifest中使用AppId(如wx0123456789abcdef)填写的声明,就是为了保证微信在处理完分享或者完成登录授权后,生成数据并写入文件.wx0123456789abcdef中,通过FileTypeAssociation协议,这种后缀的文件,也只能由我们的应用来打开了,这样就保证了互调关系的唯一性。OnFileActivated接收到文件之后,把文件内的数据通过protobuf机制反序列出来就能得到结果了。
转载于:https://www.cnblogs.com/zhxilin/p/5005112.html
【Win10 UWP】微信SDK基本使用方法和基本原理相关推荐
- 【Win10 UWP】QQ SDK(一):SDK基本使用方法
每当开发一个应用需要社交分享的应用时,总是心里咯噔一下:到底什么时候分享能加上QQ和微信?除了WP8.0版本的微信SDK,官方似乎从未正面发布过适应时代发展的QQ SDK,就连后台,也没有一个可以创建 ...
- win10 uwp DataContext
本文告诉大家DataContext的多种绑法. 适合于WPF的绑定和UWP的绑定. 我告诉大家很多个方法,所有的方法都有自己的优点和缺点,可以依靠自己喜欢的用法使用.当然,可以在新手面前秀下,一个页面 ...
- 前端使用微信sdk上传图片的坑,及万千种方法比较实用的一种,亲测有效
vue 公众端使用微信sdk上传图片大坑 第一个坑 第二个坑 第一个坑 使用微信sdk拿到的图片并没有base64的前缀 所以我们需要自己加 iSrc = 'data:image/jpeg;base6 ...
- Win32 C++项目移植到 Win10 UWP
本文可能对谁有帮助 如果你正在做将现有的Win32 静态库 或 DLL 工程移植到Win10 UWP(通用 Windows) 环境,这篇文章可能会对你有帮助. 概述 在VS2015的 新建项目 -&g ...
- Win10 UWP开发系列:使用VS2015 Update2+ionic开发第一个Cordova App
安装VS2015 Update2的过程是非常曲折的.还好经过不懈的努力,终于折腾成功了. 如果开发Cordova项目的话,推荐大家用一下ionic这个框架,效果还不错.对于Cordova.PhoneG ...
- win10 uwp 毛玻璃
原文:win10 uwp 毛玻璃 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee.io 访问博 ...
- win10 uwp 使用 Matrix3DProjection 进行 3d 投影
win10 uwp 使用 Matrix3DProjection 进行 3d 投影 原文:win10 uwp 使用 Matrix3DProjection 进行 3d 投影 版权声明:博客已迁移到 htt ...
- win10 uwp 线程池
win10 uwp 线程池 原文:win10 uwp 线程池 如果大家有开发 WPF 或以前的程序,大概知道线程池不是 UWP 创造的,实际上在很多技术都用到线程池. 为什么需要线程池,他是什么?如何 ...
- win10 uwp unix timestamp 时间戳 转 DateTime
win10 uwp unix timestamp 时间戳 转 DateTime 原文:win10 uwp unix timestamp 时间戳 转 DateTime 有时候需要把网络的 unix ti ...
最新文章
- tx2 undefined reference to PyExc_ImportError'
- java pdf添加透明水印_如何在PDF文件中添加透明水印
- 一、MySQL数据库基础
- innodb_flush_log_at_trx_commit配置
- C#实现多态之一抽象
- 如何安装部署秋色园QBlog站点
- db2 删除存储过程_数据库教程-SQL Server存储过程使用及异常处理
- 机房线路故障,引发多家公司不能上网,和自己de经历有感
- SQL Server和Oracle的差异
- jquery中常容易出错的checkbox的获得值
- RHCE盘点(5)—— 打印机
- 判断浏览器是否为微信内置浏览器
- 服务器自动ip使用,自动或手动设置IP地址图解教程
- ie浏览器html状态栏隐藏,我的IE浏览器忽然上面的菜单栏及地址栏都不见了
- 嬴彻科技日: 发布《自动驾驶卡车量产白皮书》分享从量产走向无人技术路线
- 2022年指数与指数公司行业研究报告
- ImportError: No module named urlgrabber.grabber
- vlc-android源码git下载
- MySQL week()函数及参数mode详解
- 大二学生JavaScript实训大作业——动漫秦时明月7页 期末网页制作 html css javascript 网页设计实例 企业网站制作
热门文章
- 跨境电商推广干货:掘金东南亚和这几个推广平台
- 用函数求最大公约数c语言,C语言求最大公约数公式分享
- mysql 开源聊天系统_轻量级的开源企业聊天软件 喧喧聊天(界面很不错)
- android和MTKP60区别,联发科P60和高通骁龙660哪个好?骁龙660与联发科P60区别对比详细评测...
- 百里挑一:ICLR 2021杰出论文奖出炉!
- 时间序列:Shapelets
- android adb修复工具,Android——adb修复build.prop
- 想要改变客户态度 这些销售话术需掌握
- 30 个案例教你用纯 CSS 实现常见的几何图形
- QT界面,鼠标滚轮实现缩放问题