C#开发门户及应⽤(39)--使⽤JSSDK实现签到的功能
随着开逐步开放更多JSSDK的接⼝,我们可以利⽤⾃定义⽹页的⽅式来调⽤更多的接⼝,实现我们更加丰富的界⾯功能和效果,例如我们可以在页⾯中调⽤各种⼿机的硬件来获取信息,如摄像头拍照,GPS信息、扫描⼆维码等等,本篇介绍如何利⽤这些JSSDK接⼝实现签到的功能,其中签到需要报送地理坐标和地址,调⽤摄像头实时拍照,以及获取当前⽤户的相关信息等等。
1、JSSDK的说明
JS-SDK是⾯向⽹页开发者提供的基于内的⽹页开发⼯具包。通过使⽤JS-SDK,⽹页开发者可借助⾼效地使⽤拍照、选图、语⾳、位置等⼿机系统的能⼒,同时可以直接使⽤分享、扫⼀扫、卡券、⽀付等特有的能⼒,为⽤户提供更优质的⽹页体验。
⽬前JSSDK⽀持的接⼝分类包括下⾯⼏类:基础接⼝、分享接⼝、图像接⼝、⾳频接⼝、智能接⼝、设备信息、地理位置、摇⼀摇周边、界⾯操作、扫⼀扫、⼩店、卡券、⽀付,随着功能的全部整合,估计更多的接⼝会陆续开放出来。
在的后台进⼊【开发者⽂档】模块,我们可以看到对应的JSSDK的功能分类和介绍,如下所⽰。
从右侧我们可以详细看到各个接⼝的使⽤说明,基本上JSSDK的使⽤⽅法都类似,因此调试通过并掌握其中⼀两个,其他的也就依葫芦画瓢,照着做就可以了。
1)JSSDK使⽤步骤
步骤⼀:绑定域名
先登录公众平台进⼊“设置”的“功能设置”⾥填写“JS接⼝安全域名”。如下所⽰,在公众平台进⾏设置。
备注:登录后可在“开发者中⼼”查看对应的接⼝权限。
步骤⼆:引⼊JS⽂件
在需要调⽤JS接⼝的页⾯引⼊如下JS⽂件,(⽀持https):res.wx.qq/open/js/jweixin-1.0.0.js
如需使⽤摇⼀摇周边功能,请引⼊ res.wx.qq/open/js/jweixin-1.1.0.js
备注:⽀持使⽤ AMD/CMD 标准模块加载⽅法加载
当然,我们⼀般编辑页⾯,为了⽅便实现更多的效果,可能还会引⼊其他JS,如JQuery的类库等等。还有,我们还可以基于WeUI的jquery-weui类库,实现更加丰富的功能,如下是我们案例代码⾥⾯的JS引⽤。
<script src="~/Content/wechat/jquery-weui/lib/jquery-2.1.4.js"></script>
<script src="~/Content/wechat/jquery-weui/js/jquery-weui.js"></script>
<script type="text/javascript" src="res.wx.qq/open/js/jweixin-1.1.0.js"></script>
步骤三:通过config接⼝注⼊权限验证配置
所有需要使⽤JS-SDK的页⾯必须先注⼊配置信息,否则将⽆法调⽤(同⼀个url仅需调⽤⼀次,对于变化url的SPA的web app可在每次url变化时进⾏调⽤,⽬前Android客户端不⽀持pushState的H5新特性,所以使⽤pushState来实现web app的页⾯会导致签名失败,此问题会在Android6.2中修复)。
debug: true, // 开启调试模式,调⽤的所有api的返回值会在客户端alert出来,若要查看传⼊的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,的唯⼀标识
timestamp: , // 必填,⽣成签名的时间戳
nonceStr: '', // 必填,⽣成签名的随机串
signature: '',// 必填,签名,见附录1
jsApiList: [] // 必填,需要使⽤的JS接⼝列表,所有JS接⼝列表见附录2
});
以上的配置就是JSSDK的核⼼所在,⾥⾯需要配置好对应的appid,还有timestamp,nonceStr这些都没有特别之处,最值得注意的是signature的实现机制,这样我们在后台⽣成好对应的值,赋给JS页⾯就可以了,这样也是最为安全的做法。
如下代码是我们实际项⽬⾥⾯,在Asp的视图页⾯⾥⾯的HTML代码,如下所⽰。
<script language="javascript">
var appid = '@ViewBag.appid';
var noncestr = '@str';
var signature = '@ViewBag.signature';
var timestamp = '@ViewBag.timestamp';
debug: false,
appId: appid, // 必填,的唯⼀标识
timestamp: timestamp, // 必填,⽣成签名的时间戳
nonceStr: noncestr, // 必填,⽣成签名的随机串
signature: signature, // 必填,签名,见附录1
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'
]
});
步骤四:通过ready接⼝处理成功验证
// config信息验证后会执⾏ready⽅法,所有接⼝调⽤都必须在config接⼝获得结果之后,config是⼀个客户端的异步操作,所以如果需要在页⾯加载时就调⽤相关接⼝,
//则须把相关接⼝放在ready函数中调⽤来确保正确执⾏。对于⽤户触发时才调⽤的接⼝,则可以直接调⽤,不需要放在ready函数中。
});
这个ready的接⼝,也就是在页⾯顺利加载完毕后的处理内容了,⼀般我们需要做很多操作,都是需要在页⾯加载完毕后才能调⽤相关的对象进⾏赋值、处理等操作。
例如我们在页⾯ready后,获取对应的GPS坐标等操作,可以⽤下⾯的JS代码实现。
type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation⽤的⽕星坐标,可传⼊'gcj02'
success: function (res) {
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
var speed = res.speed; // 速度,以⽶/每秒计
var accuracy = res.accuracy; // 位置精度
$("#lblLoacation").text(latitude + "," + longitude);
}
});
});
步骤五:通过error接⼝处理失败验证
<(function(res){
// config信息验证失败会执⾏error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,
// 也可以在返回的res参数中查看,对于SPA可以在这⾥更新签名。
});
这个error接⼝也就是⽤来处理异常信息的,⼀般情况下可以在这⾥提⽰⽤户出现的错误。
2)、签名算法
签名⽣成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前⽹页的URL,不包含#及其后⾯部分)。对所有待签名参数按照字段名的ASCII 码从⼩到⼤排序(字典序)后,使⽤URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这⾥需要注意的是所有参数名均为⼩写字符。对string1作sha1加密,字段名和字段值都采⽤原始值,不进⾏URL 转义。
即signature=sha1(string1)。⽰例:
noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
url=mp.weixin.qq?params=value
步骤1. 对所有待签名参数按照字段名的ASCII 码从⼩到⼤排序(字典序)后,使⽤URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=mp.weixin.qq?params=value
步骤2. 对string1进⾏sha1签名,得到signature:
0f9de62fce790f9a083d5c99e95740ceb90c27ed
注意事项
1.签名⽤的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
2.签名⽤的url必须是调⽤JS接⼝页⾯的完整URL。
3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。
如出现invalid signature 等错误详见附录5常见错误及解决办法。
以上就是JSSDK总体的使⽤流程,虽然看起来⽐较抽象,但是基本上也就是这些步骤了。
上⾯的过程是具体的参数处理逻辑,我们要对应到C#代码的签名实现,需要对⼏个变量进⾏处理,下
⾯是对应的⽣成noncestr、timestamp、以及签名等操作的代码。
///<summary>
///⽣成时间戳,标准北京时间,时区为东⼋区,⾃1970年1⽉1⽇ 0点0分0秒以来的秒数
///</summary>
///<returns>时间戳</returns>
private static string GetTimeStamp()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalSeconds).ToString();
}
///<summary>
/
//⽣成随机串,随机串包含字母或数字
///</summary>
///<returns>随机串</returns>
private static string GetNonceStr()
{
return Guid.NewGuid().ToString().Replace("-", "");
}
还有我们要实现JSSDK签名的处理,必须先根据⼏个变量,构建好URL字符串,具体的处理过程,我们可以把它们逐⼀放在⼀个Hashtable⾥⾯,如下代码所⽰。
///<summary>
///获取JSSDK所需要的参数信息,返回Hashtable结合
///</summary>
///<param name="appId">AppID</param>
///<param name="jsTicket">根据Token获取到的JSSDK ticket</param>
///<param name="url">页⾯URL</param>
///<returns></returns>
public static Hashtable GetParameters(string appId, string jsTicket, string url)
{
string timestamp = GetTimeStamp();
string nonceStr = GetNonceStr();
// 这⾥参数的顺序要按照 key 值 ASCII 码升序排序
string rawstring = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + url + "";
string signature = GetSignature(rawstring);
Hashtable signPackage = new Hashtable();
signPackage.Add("appid", appId);
signPackage.Add("noncestr", nonceStr);
signPackage.Add("timestamp", timestamp);
signPackage.Add("url", url);
signPackage.Add("signature", signature);
signPackage.Add("jsapi_ticket", jsTicket);
signPackage.Add("rawstring", rawstring);
return signPackage;
}
我们注意到URL参数的字符串组合:
string rawstring = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + url + "";
这⾥我们拼接好URL参数后,就需要使⽤签名的规则来实现签名的处理了,签名的代码如下所⽰,注释代码和上⾯代码等同。
///<summary>
///使⽤SHA1哈希加密算法⽣成签名
///</summary>
///<param name="rawstring">待处理的字符串</param>
///<returns></returns>
private static string GetSignature(string rawstring)
{
return FormsAuthentication.HashPasswordForStoringInConfigFile(rawstring, "SHA1").ToLower();
////下⾯和上⾯代码等价
//SHA1 sha1 = new SHA1CryptoServiceProvider();
//byte[] bytes_sha1_in = System.Text.UTF8Encoding.Default.GetBytes(rawstring);
//byte[] bytes_sha1_out = sha1.ComputeHash(bytes_sha1_in);
//string signature = BitConverter.ToString(bytes_sha1_out);
//signature = signature.Replace("-", "").ToLower();
//return signature;
}
这样我们有了对应的值后,我们就可以把它们的参数全部放在集合⾥⾯了供使⽤。
///<summary>
///获取⽤于JS-SDK的相关参数列表(该⽅法对accessToken和JSTicket都进⾏了指定时间的缓存处理,多次调⽤不会重复⽣成)
///集合⾥⾯包括jsapi_ticket、noncestr、timestamp、url、signature、appid、rawstring
///</summary>
///<param name="appid">应⽤ID</param>
///<param name="appSecret">开发者凭据</param>
///<param name="url">页⾯URL</param>
///<returns></returns>
public Hashtable GetJSAPI_Parameters(string appid, string appSecret, string url)
{
string accessToken = GetAccessToken(appid, appSecret);
string jsTicket = GetJSAPI_Ticket(accessToken);
return JSSDKHelper.GetParameters(appid, jsTicket, url);
}
下⾯我们通过具体的代码案例来介绍使⽤的过程。
2、签到功能的实现处理
其实签到,都可以在和企业号实现,的企业号可能实现更佳⼀些,不过他们使⽤JSSDK的接⼝操作是⼀样的,我们可以拓展过去就可以了。这⾥介绍JSSDK实现签到的功能处理。
签到的功能,我们希望记录⽤户的GPS位置信息,还有就是利⽤拍照功能,拍⼀个照⽚同时上传到服务器,这样我们就可以实现整个业务效果了。
⾸先我们来设计签到的界⾯,代码及效果如下所⽰。
界⾯预览效果如下所⽰:
我们来看看JSSDK⾥⾯对于【获取地理位置接⼝】的说明:
type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation⽤的⽕星坐标,可传⼊'gcj02'
success: function (res) {
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
var speed = res.speed; // 速度,以⽶/每秒计
var accuracy = res.accuracy; // 位置精度
}
});
以及图形接⼝⾥⾯【拍照或从⼿机相册中选图接⼝】的说明:
wx.chooseImage({
count: 1, // 默认9
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认⼆者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认⼆者都有
success: function (res) {
var localIds = res.localIds; // 返回选定照⽚的本地ID列表,localId可以作为img标签的src属性显⽰图⽚
}
});
上传图⽚到服务器接⼝如下所⽰。
wx.uploadImage({
localId: '', // 需要上传的图⽚的本地ID,由chooseImage接⼝获得
isShowProgressTips: 1, // 默认为1,显⽰进度提⽰
success: function (res) {
var serverId = res.serverId; // 返回图⽚的服务器端ID
}
});
备注:上传图⽚有效期3天,可⽤多媒体接⼝下载图⽚到⾃⼰的服务器,此处获得的 serverId 即 media_id。
根据这⼏个接⼝,我们来对它们进⾏包装,以实现我们的业务需求。根据我们的需要,我们对JSSDK接⼝进⾏了调⽤,如下所⽰。
<script language="javascript">
var appid = '@ViewBag.appid';
var noncestr = '@str';
var signature = '@ViewBag.signature';
var timestamp = '@ViewBag.timestamp';
debug: false,
appId: appid, // 必填,的唯⼀标识
timestamp: timestamp, // 必填,⽣成签名的时间戳
nonceStr: noncestr, // 必填,⽣成签名的随机串
signature: signature, // 必填,签名,见附录1
jsApiList: [
'checkJsApi',
'chooseImage',
'previewImage',
'uploadImage',
'downloadImage',
'getNetworkType',
'openLocation',
'getLocation'
]
});
type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation⽤的⽕星坐标,可传⼊'gcj02'
success: function (res) {
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
var speed = res.speed; // 速度,以⽶/每秒计
var accuracy = res.accuracy; // 位置精度
$("#lblLoacation").text(latitude + "," + longitude);
//解析坐标地址
var location = latitude + "," + longitude;
$.ajax({
type: 'GET',
url: '/JSSDKTest/GetAddress?location=' + location,
/
/async: false, //同步
//dataType: 'json',
success: function (json) {
$("#lblAddress").text(json);
},
error: function (xhr, status, error) {
$.messager.alert("提⽰", "操作失败" + sponseText); //sponseText
}
});
如何启用javascript功能}
});
success: function (res) {
var networkType = resworkType; // 返回⽹络类型2g,3g,4g,wifi
$("#lblNetwork").text(networkType);
}
});
chooseImage();
});
</script>
其中的chooseImage()是我们在页⾯开始的时候,让⽤户拍照的操作,具体JS代码如下所⽰。
//拍照显⽰
var localIds;
function chooseImage() {
wx.chooseImage({
count: 1, // 默认9
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认⼆者都有
sourceType: ['camera'], // 可以指定来源是相册还是相机,默认⼆者都有
success: function (res) {
localIds = res.localIds; // 返回选定照⽚的本地ID列表,localId可以作为img标签的src属性显⽰图⽚
$("#imgUpload").attr("src", localIds);
}
});
}
但⽤户使⽤摄像头拍照后,就会返回⼀个res.localIds集合,因为我们拍照⼀个,那么可以把它直接赋值给图⽚对象,让它显⽰当前拍照的图⽚。
拍照完成,我们单击【签到】应该把图⽚和相关的坐标等信息上传到服务器的,图⽚⾸先是保存在服务器的,上传图⽚有效期3天,可⽤多媒体接⼝下载图⽚到⾃⼰的服务器,此处获得的 serverId 即 media_id。
为了实现我们⾃⼰的业务数据,我们需要把图⽚集相关信息存储在⾃⼰的服务器,这样才可以实现信息的保存,最后提⽰【签到操作成功】,具体过程如下所⽰。
//上传图⽚
var serverId;
function upload() {
wx.uploadImage({
localId: localIds[0],
success: function (res) {
serverId = res.serverId;
//提交数据到服务器
//提⽰信息
$.toast("签到操作成功");
},
fail: function (res) {
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论