在使用微信的 JS-SDK 进行微信公众号开发或是企业微信开发时,首先需要通过服务端程序去生成对应于前端每个页面的签名。 本文演示如何在 .NET Core 3.1 以上版本中生成该签名。
获取企业通讯的Token
要生成 JS-SDK 的签名,首先需要通过微信服务端API获取对应的通讯 JS Ticket, 而要获取 JS Ticket, 必须先获取与企业API访问相关的 Token。
为获取 Token , 我们使用微信服务端API, URL 为(可参考):
1
| https://qyapi.weixin.qq.com/cgi-bin/gettoken
|
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| private async Task<CropToken> getWxToken(string corpId, string secret) {
using (HttpClient client = new HttpClient()) { string url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"; url += "?corpid=" + corpId; url += "&corpsecret=" + secret;
HttpResponseMessage response = await client.GetAsync(url); response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
var res = JsonSerializer.Deserialize<WxApiGetToken>(responseBody);
using (var db = new WxContext()) { CropToken cropToken = db.CropTokens.SingleOrDefault<CropToken>(t => t.CorpId == this.corpId); if (cropToken != null) { cropToken.AccessToken = res.accessToken; cropToken.ExpiresIn = res.expiresIn; cropToken.LastUpdateTime = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds(); db.CropTokens.Update(cropToken); } else { cropToken = new CropToken(); cropToken.CorpId = corpId; cropToken.AppSecret = secret; cropToken.AccessToken = res.accessToken; cropToken.ExpiresIn = res.expiresIn; cropToken.LastUpdateTime = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds(); db.CropTokens.Add(cropToken); }
await db.SaveChangesAsync(); return cropToken; }
} }
|
注意: 在上面的代码中,为了避免频繁的访问微信服务端API, 我们将获取到的token 保存在本地数据库中
获取 JS Ticket
获取了 Token 以后,就可以用该 Token 继续获取 JS Ticket 了。 参考微信服务端API文档, 对应的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| private async Task<JsTicket> GetJsTicket() {
using (HttpClient client = new HttpClient()) {
using (var db = new WxContext()) {
CropToken cropToken = db.CropTokens.SingleOrDefault<CropToken>(t => t.CorpId == this.corpId);
if (cropToken == null) {
cropToken = await getWxToken(this.corpId, this.secret); }
string url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; url += "?access_token=" + cropToken.AccessToken;
HttpResponseMessage response = await client.GetAsync(url); response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
var res = JsonSerializer.Deserialize<WxApiJsTicket>(responseBody);
JsTicket jsTicket = new JsTicket(); jsTicket.CorpId = this.corpId; jsTicket.Ticket = res.ticket; jsTicket.ExpiresIn = res.expiresIn; jsTicket.LastUpdateTime = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
db.JsTickets.Add(jsTicket);
await db.SaveChangesAsync();
return jsTicket;
} } }
|
生成 JS-SDK 需要的签名
因为 JS-SDK 签名是针对前端的每个页面的,因此需要前端将当前页面的 URL 作为参数传到后端,后端的示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| [HttpGet("enable")] public async Task<ApiResult> enableJsSDK() { string url = Request.Query["url"];
_logger.LogDebug("enableJsSDK, url = {0}", url);
long timestamp = (new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()) / 1000; string noncestr = getRandomStr(); string jsapiTicket = (await GetJsTicket()).Ticket; string signature = SHA1_Hash("jsapi_ticket=" + jsapiTicket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url);
ApiResult result = new ApiResult(); result.Succ = true;
ConfigVo config = new ConfigVo(); config.Timestamp = timestamp; config.NonceStr = noncestr; config.Signature = signature; config.AppId = this.corpId;
result.Data = config;
return result; }
|
返回的数据为前端在页面上配置 js-sdk 时需要的信息。
其中分别调用生成随机串和生成 SHA1 加密串的程序,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| private string getRandomStr() {
Random rnd = new Random(); string res = ""; for (int i = 0; i < 16; i++) { res += RANDOM_STR.ElementAt(rnd.Next(RANDOM_STR.Length)); } return res; }
public string SHA1_Hash(string str_sha1_in) { SHA1 sha1 = new SHA1CryptoServiceProvider(); byte[] bytes_sha1_in = System.Text.UTF8Encoding.Default.GetBytes(str_sha1_in); byte[] bytes_sha1_out = sha1.ComputeHash(bytes_sha1_in); string str_sha1_out = BitConverter.ToString(bytes_sha1_out); str_sha1_out = str_sha1_out.Replace("-", "").ToLower(); return str_sha1_out; }
|