作者: admin
-
微信jssdk授权签名以及config配置
凡是要想在h5页面使用jweixin.js的功能就必须授权签名才行。以下流程1,申请公众账号测试 或者 是已经有了公众号2,用appID和 appsecret来换取access_tokenaccess_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token`)3,用access_token来换取jsapi_ticketjsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket`)4,有了jsapi_ticket就能生成signatureappidnoncestr 一般自己生成jsapi_tickettimestamp 一般自己生成url //当前页面urlsignature // jsapi_ticket+noncestr+timestamp+url,字符串拼接后用sha1加密 (这里还有点不清楚是不是这样)5,之后就是把生成的参数传给前端如果想获取用户的基本信息,如openid或者unionid,头像、性别什么的,请看《微信公众号授权第三方 OAuth2.0》 -
base64、blob和file数据类型相互转换并使用FormData模拟表单上传
涉及到new FileReader()、new File()、new FormData()、createObjectURL() 上传 压缩
FormData js模拟表单上传
var formData = new FormData(); formData.append("type","2"); formData.append("file",blob,"recorder.mp3"); //添加上传blob数据类型 formData.append("file",file,"1.jpg"); //添加上传file数据类型 $('#xx').click(function () { $.ajax({ beforeSend:function(e){ var type='(jpg|png)' if( !(new RegExp(".+\."+type+"$",'ig').test( $('#file')[0].files[0].name ) ) ){ layer.msg('文件类型不正确'); _this.val('') return false } }, url:"/uploadbase64" //上传接口地址 ,type:"POST" ,contentType:false //让xhr自动处理Content-Type header,multipart/form-data需要生成随机的boundary ,processData:false //不要处理data,让xhr自动处理 ,data:formData ,success:function(v){ console.log("上传成功",v); } ,error:function(s){ console.error("上传失败",s); } }); });//多文件上传 <input id="file" type="file" name="uploads" multiple="multiple" onchange="cb()"><br> function cb(){ for(let i=0;i<$('#file')[0].files.length;i++){ // sendfild(i) } function sendfild(x){ formData = new FormData(); formData.append("uploads",$('#file')[0].files[x],$('#file')[0].files[x].name); //添加上传file数据类型name $.ajax({ beforeSend:function(e){ // var type='(jpg|png)' // if( !(new RegExp(".+\."+type+"$",'ig').test( $('#file')[0].files[0].name ) ) ){ // layer.msg('文件类型不正确'); // _this.val('') // return false // } }, url:"/upload" //上传接口地址 ,type:"POST" ,contentType:false //让xhr自动处理Content-Type header,multipart/form-data需要生成随机的boundary ,processData:false //不要处理data,让xhr自动处理 ,data:formData ,success:function(v){ console.log("上传成功",v); // sendfild(x) } ,error:function(s){ console.error("上传失败",s); } }) } return false }file 转 base64 (FileReader方法)
<input id="fielinput" type="file" multiple="multiple" accept="image/*" onchange="showPreview(this)"> function showPreview(source) { var file = source.files[0]; //判断文件类型 var extfile = file.name; var AllImgExt=".jpg|.jpeg|.gif|.bmp|.png|"; var extName = extfile.substring(extfile.lastIndexOf(".")).toLowerCase();//(把路径中的所有字母全部转换为小写) if(AllImgExt.indexOf(extName+"|")==-1) { var ErrMsg="该文件类型不允许上传。请上传 "+AllImgExt+" 类型的文件,当前文件类型为"+extName; alert(ErrMsg); return false; } if(window.FileReader) { var fr = new FileReader(); fr.readAsDataURL(file); fr.onloadend = function(e) { // e.target.result base64 document.getElementById("fielImg").src = e.target.result; // document.getElementById("baseimg").value = e.target.result; // console.log(convertBase64UrlToBlob(e.target.result)); }; }else{ alert('浏览器不支持预览图片'); } };图片 转 base64 (canvas的toDataURL方法)
*注意toDataURL方法会涉及到跨域问题,要让后台对图片链接的处理
var img = "https://img.alicdn.com/bao/uploaded/TB1qimQIpXXXXXbXFXXSutbFXXX.jpg"; function getBase64Image(img) { var canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, img.width, img.height); var ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase(); var dataURL = canvas.toDataURL("image/"+ext); return dataURL; } var image = new Image(); image.crossOrigin = ''; image.src = img; image.onload = function(){ var base64 = getBase64Image(image); //这里获取base64 }base64 转 file
function base64URLtoFile(base64Data, filename) { //*filename包括后缀名,例如1.png var arr = base64Data.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], filename, { type: mime }); }blob转json
const reader = new FileReader(); reader.readAsText(blobData, 'utf-8'); reader.onload = function (e) { const readerres = reader.result; const parseObj = JSON.parse(readerres); }base64 转 blob
function convertBase64UrlToBlob(urlData){ var bytes=window.atob(urlData.split(',')[1]); //去掉url的头,并转换为byte //处理异常,将ascii码小于0的转换为大于0 var ab = new ArrayBuffer(bytes.length); var ia = new Uint8Array(ab); for (var i = 0; i < bytes.length; i++) { ia[i] = bytes.charCodeAt(i); } return new Blob( [ab] , {type : 'image/png'}); }file 转 blob (createObjectURL方法)
或者file转base64在转blob
url地址转base64
url地址转file对象
var img = "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=508387608,2848974022&fm=26&gp=0.jpg"; //imgurl 就是你的图片路径 function getBase64Image(img) { var canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, img.width, img.height); var ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase(); var dataURL = canvas.toDataURL("image/" + ext); return dataURL; } var image = new Image(); image.src = img; image.setAttribute("crossOrigin", "Anonymous"); image.onload = function() { var base64 = getBase64Image(image); console.log(base64); document.getElementById("img").src = base64; var formData = new FormData(); //转换base64到file var file = btof(base64, "test"); formData.append("imageName", file); }; function btof(data, fileName) { const dataArr = data.split(","); const byteString = atob(dataArr[1]); const options = { type: "image/jpeg", endings: "native" }; const u8Arr = new Uint8Array(byteString.length); for (let i = 0; i < byteString.length; i++) { u8Arr[i] = byteString.charCodeAt(i); } return new File([u8Arr], fileName + ".jpg", options); }数据类型上传
file:直接上传,就是我们平时用的<input type=”file”>
base64:直接传,但需要将data:image/png;base64,这段内容过滤掉,后台才能转为成 图片,
blob:需要转成file类型,可以利用new FormData()
上传还需要涉及到 《post发送数据时的两种编码格式》
前端压缩图片并上传
(1)图片转blob
(2)图片转base64位
———————————–
<script src="js/exif.js"></script> <div class="IDcardA"><input id="zm" @change="getImageBase64($event, 'IDcardA')" type="file" accept="image/*"></div> <div class="IDcardB"><input id="fm" @change="getImageBase64($event, 'IDcardB')" type="file" accept="image/*"></div> function rotateImg(img, step, canvas) { //最小与最大旋转方向,图片旋转4次后回到原方向 var min_step = 0; var max_step = 3; if (img === null) return; //img的高度和宽度不能在img元素隐藏后获取,否则会出错 var height = img.height; var width = img.width; //旋转角度以弧度值为参数 var degree = step * 90 * Math.PI / 180; var ctx = canvas.getContext('2d'); switch (step) { case 0: canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0); break; case 1: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, 0, -height); break; case 2: canvas.width = width; canvas.height = height; ctx.rotate(degree); ctx.drawImage(img, -width, -height); break; case 3: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, -width, 0); break; } return canvas; } methods:{ getImageBase64: function(e, className) { var self = this; // self.jsOpenCamear(); var el = e.target; var imgBase64 = ''; if(!el.files || !el.files.length){ return; } var file = el.files[0]; if (/\.txt/.test(file.name) || !file.size) { Tools.loading(false); return Tools.dialog.alert('请拍照或者上传图片!'); } Tools.loading(true); EXIF.getData(file, function() { self.orientation = EXIF.getTag(file, 'Orientation'); }); var fileName = file.name; var reader = new FileReader(); //读取文件以数据URI的形式保存在reader的result属性中 reader.readAsDataURL(file); //获取图片大小,以M为单位 var fileSize = Math.round(file.size / 1024 / 1024); //获取图片大小,以KB为单位 var fileSizeKB = Math.round(file.size / 1024); //上传图片的尺寸必需大于200KB if (fileSizeKB > 1024) { // Tools.dialog.alert('请上传1MB以内的图片', '好的'); // return; } el.value = ''; reader.onload = function () { var cvs = document.createElement("canvas"); var img = new Image(); img.src = this.result; img.onload = function() { var width = img.width, height = img.height; switch (cvs.width = width, cvs.height = height, self.orientation) { case 3: cvs = rotateImg(this, 2, cvs); break; case 6: cvs = rotateImg(this, 1, cvs); break; case 8: cvs = rotateImg(this, 3, cvs); break; default: cvs = rotateImg(this, 0, cvs); } var imgData = cvs.toDataURL('image/png'); if (fileSizeKB > 60) { compress(imgData, fileSize, 1024, fileName, function(imgBase64Data, fileName){ imgBase64 = imgBase64Data; imgBase64 = imgBase64Data.replace(/data:image\/(png|jpeg|jpg|gif);base64,/g,''); Tools.loading(false); self.uploadProfile(imgBase64, className); },'', 0.6); } else { Tools.loading(false); imgBase64 = imgData; imgBase64 = imgData.replace(/data:image\/(png|jpeg|jpg|gif);base64,/g,''); self.uploadProfile(imgBase64, className); } }; //获取原图的base64信息 }; }, /*预览*/ previewPic: function(imageUrl, className) { if (className == 'IDcardA') { imageIdcardFront=imageUrl; $('.positive').css({background:'#EEF0F1 url('+imageUrl+') no-repeat center',backgroundSize:'contain'}).find('.dele-img').show(); } else if (className == 'IDcardB') { $('.back').css({background:'#EEF0F1 url('+imageUrl+') no-repeat center',backgroundSize:'contain'}).find('.dele-img').show(); imageIdcardBack=imageUrl; } // $('.'+className).css({ // 'background': 'url('+imageUrl+') no-repeat', // 'background-size': 'contain', // 'border': 'dashed .05rem #ccc', // 'border-radius': '.3rem' // }); }, // 上传照片到后台 uploadProfile: function(imgBase64, className) { var self = this; if (!imgBase64) { return Tools.dialog.alert('当前图片不合格,请换一张试试!'); } Tools.loading(true); //-----------需要后台能接收到base64的数据类型并生成图片--------------------- $.ajax({ // xhrFields:{ // withCredentials:true // }, // crossDomain:true, type: 'post', data: JSON.stringify({ strFiles: imgBase64 }), contentType: "application/json", dataType: "json", url: ajaxUrl, timeout: 60000, headers:{ "userToken": sessionStorage.getItem('userToken') }, complete: function(x, t) { if(typeof completeFn == 'function'){ completeFn(x, t); } else { if(Tools && Tools.loading){ Tools.loading(false); } } }, success:function (res) { self.previewPic(res.data, className); }, error:function (res) { } }); //-------------------------------- }, } //methods -
另存为效果
js 另存为 a 下载 html 下载

(推荐)前端方法:
<a href="http://localhost:3000/upload/index_logo.gif" download="xxx">下载11</a> //下载后是xxx.gif
*注意所下载的文件必须是同域名不然无法实现另存为效果,仅仅不兼容IE。谷歌、火狐,Edge兼容
如果下载需要token验证,参考https://sdeno.com/?p=8002
后端方法:
例如php需要设置
header('Content-type: image/jpeg'); header("Content-Disposition: attachment; filename='download.jpg'");这里以koa2为案例:
路由设置
router.get('xxxpath', (ctx) => { ctx.set('Content-disposition','attachment;filename=name.txt'); // 设置你的文件名 const data = new Buffer('Im a example of text') // 创建一个buffer ctx.body = data // 返回在响应体里 });前端设置
<a onclick="window.open('xxxpath')">下载</a> //下载后会得到一个txt,内容是Im a example of text—————————————
为了方便将其他文件也转化为Buffer,推荐使用
npm i urllib -S
const urllib = require('urllib'); router.get('down',async ctx=>{ let file = await urllib.request('https://sdeno.com/wp-content/themes/flat_ui/img/icons/png/jquery.png'); ctx.set('Content-disposition','attachment;filename='+'name.jpg'); ctx.body=file.data; //返回的是 Buffer类型 });https://www.zhangxinxu.com/wordpress/2016/04/know-about-html-download-attribute/
-
微信公众号页面授权获取用户基本信息
微信 授权 微信 公众号 授权
授权仅仅是获取用户的基本信息例如头像,昵称,并非使用jssdk,跟分享和拉起支付没关系。
想看分享功能点击《微信端分享、手机QQ好友分享以及小程序和H5数据交互》
快速了解步骤:
//以下步骤是让H5在公众号能获取到用户的基本信息 1,我们网站的/a 2,授权https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=encodeURIComponent(/a)&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 3,授权后,调回/a?code=123 4,用code换取 token和openid 5,用token和openid,换取用户资料

打开一个微信公众号号,点击一个链接要跳转到,其他页面。但是跳转到其他页面需要授权才能跳转。这就是本教程需要说的。
什么是OAuth
假如本站要获取其他用户的qq基本信息,要通过OAuth开放协议,这样可以在不提供密码的时候把信息拿到,前提是qq用户要授权。
准备条件:(1)“开发 — 接口权限 — 网页服务 — 网页帐号 — 网页授权获取用户基本信息”
的配置选项中,修改授权回调域名。
(2)用户要已关注公众号
注意:使用snsapi_base静默授权,不会弹窗但仅仅能获取到openid,但也足以实现分享、支付功能。
要获取unionid就必须使用snsapi_userinfo。
网页授权文档
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
开始授权
以下教程使用snsapi_base授权,静默授权就是不会弹窗让用户去点击。
1,以下地址由后台去请求,用户授权后获取code:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
案例:
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
*注意redirect_uri参数要做encodeURIComponent(url)处理
用户点击后且没报错说明执行成功并执行回调访问链接且带code参数例如,
http://mascot.duapp.com/oauth2.php?code=00b788e3b42043c8459a57a8d8ab5d9f&state=1 //code码会拼接到redirect_uri地址上返回给我们 http://mascot.duapp.com/oauth2.php //我们之前设置的redirect_uri state=1 //携带的参数同时也传回来 code // 用这个code来换取access_token
2,使用code换取access_token和openid
上一个步骤执行成功就会,再次执行我们后台自己的接口,并且还带有参数:http://mascot.duapp.com/oauth2.php?code=00b788e3b42043c8459a57a8d8ab5d9f&state=1
利用code参数的值去调用以下链接
换取的连接是:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
例如:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx8888888888888888&secret=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&code=00b788e3b42043c8459a57a8d8ab5d9f&grant_type=authorization_code如果成功换成后就会返回类似这样的数据结构
{
“access_token”: “OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-G0ZWEE5-uBjBz941EOPqDQy5sS_GCs2z40dnvU99Y5AI1bw2uqN–2jXoBLIM5d6L9RImvm8Vg8cBAiLpWA8Vw”,
“expires_in”: 7200,
“refresh_token”: “OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-G0ZWEE5-uBjBz941EOPqDQy5sS_GCs2z40dnvU99Y5CZPAwZksiuz_6x_TfkLoXLU7kdKM2232WDXB3Msuzq1A”,
“openid”: “oLVPpjqs9BhvzwPj5A-vTYAX3GLc”,
“scope”: “snsapi_userinfo,”
}注意这里的token有效时间是2个小时,也就是7200秒,所以本地用cookies存储access_token时最好设置过期时间是7000秒保证拉取最新
3,用access_token和openid换取用户基本信息 (如果之前用的是snsapi_userinfo方式授权那么这步也会返回获取unionid)
请求结构是:
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
例如:
https://api.weixin.qq.com/sns/userinfo?access_token=OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-G0ZWEE5-uBjBz941EOPqDQy5sS_GCs2z40dnvU99Y5AI1bw2uqN–2jXoBLIM5d6L9RImvm8Vg8cBAiLpWA8Vw&openid=oLVPpjqs9BhvzwPj5A-vTYAX3GLc成功后会获得类似这样的数据结构:
{
“openid”: “oLVPpjqs9BhvzwPj5A-vTYAX3GLc”,
“nickname”: “刺猬宝宝”,
“sex”: 1,
“language”: “简体中文”,
“city”: “深圳”,
“province”: “广东”,
“country”: “中国”,
“headimgurl”: “http://wx.qlogo.cn/mmopen/utpKYf69VAbCRDRlbUsPsdQN38DoibCkrU6SAMCSNx558eTaLVM8PyM6jlEGzOrH67hyZibIZPXu4BK1XNWzSXB3Cs4qpBBg18/0”,
“privilege”: []
}4,OAuth2认证就完成了
5,如何获取unionid
条件:
如果希望微信公众号和小程序都能获取unionid,必须在微信开放平台同时绑定公众号和小程序。
微信开放平台https://open.weixin.qq.com/



绑定小程序也一样。剩下的教程跟1,2,3步骤一样
http://www.3jke.com/news/2030/?tdsourcetag=s_pcqq_aiomsg
https://www.cnblogs.com/txw1958/p/weixin71-oauth20.html
-
js判断微信、小程序、qq内置浏览器和其他第三方浏览器
js 平台 判断 分享 判断
主要是判断,小程序或者微信。
var ua = navigator.userAgent.toLowerCase(); if(ua.match(/MicroMessenger/i)=="micromessenger") { //ios的ua中无miniProgram,但都有MicroMessenger(表示是微信浏览器) wx.miniProgram.getEnv((res)=>{ if (res.miniprogram) { //alert("在小程序里"); wx.miniProgram.navigateTo({ url: '/pages/user/my-order/my-money', }) } else { //alert("不在小程序里,但在微信里"); window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx231ea8dfba02c266&redirect_uri=http%3a%2f%2fapi.bugegaming.com%2fv1.0.6%2fwx%2fgzh%2fpay%2flogin%2fmenu&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect'; } }) }else{ if (ua.match(/QQ/i) == "qq") { //alert("qq内置浏览器"); }else { //alert("不是微信浏览器或手机qq浏览器,例如自带浏览器"); } }