.netcore2.1 JS-SDK 從后台獲取微信簽名,實現自定義分享標題、描述、圖片


  最近項目移動端需要實現微信自定義分享功能,包含分享自定義標題、描述等。

  • 首先到公眾號的后台,功能設置里面,添加將要被分享的域名,如圖

 

 

  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;
            }
        }    

  注意:

  1. 簽名用的noncestr和timestamp必須與wx.config中的nonceStr和timestamp相同。
  2. 移動端分享時,不能本地測試,需要發布到外網測試,否則報簽名錯誤
  3. 生成的簽名,可以實用校驗工具校驗是否正確。https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM