.netcore2.1 JS-SDK 从后台获取微信签名,实现自定义分享标题、描述、图片
程序员文章站
2022-06-28 20:20:15
最近项目移动端需要实现微信自定义分享功能,包含分享自定义标题、描述等。 首先到公众号的后台,功能设置里面,添加将要被分享的域名,如图 后端签名算法实现 ,参考腾讯开发者文档https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp142114111 ......
最近项目移动端需要实现微信自定义分享功能,包含分享自定义标题、描述等。
- 首先到公众号的后台,功能设置里面,添加将要被分享的域名,如图
- 后端签名算法实现 ,参考腾讯开发者文档
jsapi_ticket
生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信js接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
生成签名步骤,获取accesstoken-》获取jsapiticket-》生成签名
appsettings配置文件添加配置
"api": { "jsjdkbaseapi": "https://api.weixin.qq.com/cgi-bin" }, "jsjdk": { "appid": "***", "secret": "****" }
- 创建签名公用类
public class jssdksignhelper { private static accesstokenresponse singleaccesstoken; private string _tencentapi { get; set; } private string _appid { get; set; } private string _appsecret { get; set; } public jssdksignhelper(iconfiguration config) { _tencentapi = config["api:jsjdkbaseapi"]; _appid = config["jsjdk:appid"]; _appsecret = config["jsjdk:secret"]; } public string getaccesstokensingle(out bool isnewobj) { isnewobj = false; if (singleaccesstoken != null && (singleaccesstoken.expire_out > datetime.now.addhours(2))) { return singleaccesstoken.access_token; } else { var response = getaccesstoken(); if (response.errcode == 0) { response.expire_out = datetime.now.addhours(expirehour); singleaccesstoken = response; isnewobj = true; return response?.access_token; } } return null; } /// <summary> /// 获取access_token /// </summary> /// <returns></returns> private accesstokenresponse getaccesstoken() { string url = _tencentapi + "/token?grant_type=client_credential&appid=" + _appid + "&secret=" + _appsecret; var response = apiclient.getjson<accesstokenresponse>(url); return response; } /// <summary> /// 获取jsapiticket /// </summary> /// <param name="accesstoken"></param> /// <returns></returns> public string getjsapiticket(string accesstoken) { if (string.isnullorwhitespace(accesstoken)) { return null; } string url = _tencentapi + $"/ticket/getticket?type=jsapi&access_token={accesstoken}"; var response = apiclient.getjson<accessticketresponse>(url); return response?.ticket; } /// <summary> /// 获取签名 /// </summary> /// <param name="jsapi_ticket"></param> /// <param name="noncestr">随机字符串(必须与wx.config中的noncestr相同)</param> /// <param name="timestamp">时间戳(必须与wx.config中的timestamp相同)</param> /// <param name="url">当前网页的url,不包含#及其后面部分(必须是调用js接口页面的完整url)</param> /// <returns></returns> public string getsignature(string jsapi_ticket, string noncestr, string timestamp, string url) { if (string.isnullorempty(jsapi_ticket) || string.isnullorempty(noncestr) || string.isnullorempty(timestamp) || string.isnullorempty(url)) return null; var string1builder = new stringbuilder(); string1builder.append("jsapi_ticket=").append(jsapi_ticket).append("&") .append("noncestr=").append(noncestr).append("&") .append("timestamp=").append(timestamp).append("&") .append("url=").append(url.indexof("#") >= 0 ? url.substring(0, url.indexof("#")) : url); return sha1sign(string1builder.tostring()); } /// <summary> /// sha1加密签名 /// </summary> /// <param name="str"></param> /// <returns></returns> public string sha1sign(string str) { sha1 sha1 = new sha1cryptoserviceprovider(); byte[] bytes_sha1_in = system.text.utf8encoding.default.getbytes(str); byte[] bytes_sha1_out = sha1.computehash(bytes_sha1_in); string signature = bitconverter.tostring(bytes_sha1_out); signature = signature.replace("-", "").tolower(); return signature; } }
- 签名定义的model
public class accesstokenresponse: baseresponse { /// <summary> /// 返回access_token值,有效期7200秒 /// </summary> public string access_token { get; set; } /// <summary> /// 过期时间,单位小时 /// </summary> public datetime expire_out { get; set; } } public class accessticketresponse : baseresponse { /// <summary> /// 返回ticket票据,有效期7200秒 /// </summary> public string ticket { get; set; } } public class baseresponse { /// <summary> /// 过期时间,单位秒 /// </summary> public string expire_in { get; set; } /// <summary> /// 错误代码 /// </summary> public int32 errcode { get; set; } /// <summary> /// 错误信息描述 /// </summary> public string errmsg { get; set; } }
- 创建生成签名的时间戳和随机串
/// <summary> /// 获取微信js-jdk时间戳 /// </summary> /// <returns></returns> public static string gettimestamp() { timespan ts = datetime.utcnow - new datetime(1970, 1, 1, 0, 0, 0); return convert.toint64(ts.totalseconds).tostring(); } /// <summary> /// js-jdk 创建随机字符串 /// </summary> /// <returns></returns> public static string creatennonce_str() { random r = new random(); var sb = new stringbuilder(); var length = strs.length; for (int i = 0; i < 15; i++) { sb.append(strs[r.next(length - 1)]); } return sb.tostring(); }
- action中实际调用
[httppost] [route("getsignature")] public string getsignature(string url= "http://www.sina.cn/") { try { if (string.isnullorempty(url)) return "url不能为空"; string _jsticket = null, _signature = null; string _accesstoken = _jssignhelper.getaccesstokensingle(out bool isnewobj); wxconfigmodel model = new wxconfigmodel(); model.appid = appid; model.timestamp = myutil.gettimestamp(); model.noncestr = myutil.creatennonce_str(); if (isnewobj|| _wxconfigmodel.signature==null) { _jsticket = _jssignhelper.getjsapiticket(_accesstoken); _signature = _jssignhelper.getsignature(_jsticket, model.noncestr, model.timestamp, url); model.jsticket = _jsticket; model.signature = _signature; _wxconfigmodel = model; } return jsonconvert.serializeobject(model); } catch (exception ex) { throw ex; } }
注意:
- 签名用的noncestr和timestamp必须与wx.config中的noncestr和timestamp相同。
- 移动端分享时,不能本地测试,需要发布到外网测试,否则报签名错误
- 生成的签名,可以实用校验工具校验是否正确。
上一篇: Java基础语法题目练习
下一篇: Typora的基本使用方法