JSSDKHelper.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #region Apache License Version 2.0
  2. /*----------------------------------------------------------------
  3. Copyright 2019 Jeffrey Su & Suzhou Senparc Network Technology Co.,Ltd.
  4. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  5. except in compliance with the License. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software distributed under the
  8. License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  9. either express or implied. See the License for the specific language governing permissions
  10. and limitations under the License.
  11. Detail: https://github.com/JeffreySu/WeiXinMPSDK/blob/master/license.md
  12. ----------------------------------------------------------------*/
  13. #endregion Apache License Version 2.0
  14. /*----------------------------------------------------------------
  15. Copyright (C) 2019 Senparc
  16. 文件名:JSSDKHelper.cs
  17. 文件功能描述:JSSDK生成签名的方法等
  18. 创建标识:Senparc - 20150211
  19. 修改标识:Senparc - 20150303
  20. 修改描述:整理接口
  21. 修改标识:HADB - 20150512
  22. 修改描述:将方法调用改为静态方式
  23. 修改标识:Senparc - 20170203
  24. 修改描述:优化代码,更新到最新的Helpers方法调用
  25. 修改标识:Senparc - 20170203
  26. 修改描述:v14.3.137 修改 JSSDKHelper.GetAddrSign 传入参数,应该传入OAuth的AccessToken
  27. 修改标识:Senparc - 20170327
  28. 修改描述:v14.3.138 修改 JSSDKHelper.GetAddrSign() 方法
  29. 修改标识:Senparc - 20170623
  30. 修改描述:v14.4.14 修改 JSSDKHelper.GetcardExtSign()和CreateNonekeySha1() 方法,使用 ASCII 字典排序
  31. 排序规则统一为字典排序(ASCII)
  32. 修改标识:Senparc - 20170817
  33. 修改描述:v14.6.3 添加 JSSDKHelper.GetJsSdkUiPackageAsync() 异步方法
  34. 修改标识:Senparc - 20171010
  35. 修改描述:v14.8.1 修复几处GetNoncestr还在使用GBK编码
  36. 修改标识:Senparc - 20181226
  37. 修改描述:v16.6.2 修改 DateTime 为 DateTimeOffset
  38. ----------------------------------------------------------------*/
  39. using System;
  40. using System.Linq;
  41. using System.Collections;
  42. using System.Text;
  43. using System.Threading.Tasks;
  44. using Senparc.Weixin.Helpers;
  45. using Senparc.Weixin.MP.CommonAPIs;
  46. using Senparc.Weixin.MP.Containers;
  47. using Senparc.CO2NET.Helpers;
  48. namespace Senparc.Weixin.MP.Helpers
  49. {
  50. /// <summary>
  51. /// JS-SDK 帮助类
  52. /// </summary>
  53. public class JSSDKHelper
  54. {
  55. /// <summary>
  56. /// 获取随机字符串
  57. /// </summary>
  58. /// <returns></returns>
  59. public static string GetNoncestr()
  60. {
  61. return EncryptHelper.GetMD5(Guid.NewGuid().ToString(), "UTF-8");
  62. }
  63. /// <summary>
  64. /// 获取时间戳
  65. /// </summary>
  66. /// <returns></returns>
  67. public static string GetTimestamp()
  68. {
  69. //var ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
  70. //return Convert.ToInt64(ts.TotalSeconds).ToString();
  71. var ts = DateTimeHelper.GetUnixDateTime(SystemTime.Now);
  72. return ts.ToString();
  73. }
  74. /// <summary>
  75. /// sha1加密
  76. /// </summary>
  77. /// <returns></returns>
  78. private static string CreateSha1(Hashtable parameters)
  79. {
  80. var sb = new StringBuilder();
  81. var akeys = new ArrayList(parameters.Keys);
  82. akeys.Sort(ASCIISort.Create());
  83. foreach (var k in akeys)
  84. {
  85. if (parameters[k] != null)
  86. {
  87. var v = (string)parameters[k];
  88. if (sb.Length == 0)
  89. {
  90. sb.Append(k + "=" + v);
  91. }
  92. else
  93. {
  94. sb.Append("&" + k + "=" + v);
  95. }
  96. }
  97. }
  98. return EncryptHelper.GetSha1(sb.ToString());
  99. }
  100. /// <summary>
  101. /// 生成cardSign的加密方法
  102. /// </summary>
  103. /// <returns></returns>
  104. private static string CreateCardSha1(Hashtable parameters)
  105. {
  106. var sb = new StringBuilder();
  107. var akeys = new ArrayList(parameters.Keys);
  108. akeys.Sort(ASCIISort.Create());
  109. foreach (var k in akeys)
  110. {
  111. if (parameters[k] != null)
  112. {
  113. var v = (string)parameters[k];
  114. sb.Append(v);
  115. }
  116. }
  117. return EncryptHelper.GetSha1(sb.ToString()).ToString().ToLower();
  118. }
  119. /// <summary>
  120. /// 添加卡券Ext参数的签名加密方法
  121. /// </summary>
  122. /// <param name="parameters"></param>
  123. /// <returns></returns>
  124. private static string CreateNonekeySha1(Hashtable parameters)
  125. {
  126. var sb = new StringBuilder();
  127. var aValues = new ArrayList(parameters.Values);
  128. aValues.Sort(ASCIISort.Create());
  129. foreach (var v in aValues)
  130. {
  131. sb.Append(v);
  132. }
  133. return EncryptHelper.GetSha1(sb.ToString()).ToString().ToLower();
  134. }
  135. /// <summary>
  136. /// 获取JS-SDK权限验证的签名Signature
  137. /// </summary>
  138. /// <param name="ticket"></param>
  139. /// <param name="noncestr"></param>
  140. /// <param name="timestamp"></param>
  141. /// <param name="url"></param>
  142. /// <returns></returns>
  143. public static string GetSignature(string ticket, string noncestr, string timestamp, string url)
  144. {
  145. var parameters = new Hashtable();
  146. parameters.Add("jsapi_ticket", ticket);
  147. parameters.Add("noncestr", noncestr);
  148. parameters.Add("timestamp", timestamp);
  149. parameters.Add("url", url);
  150. return CreateSha1(parameters);
  151. }
  152. /// <summary>
  153. /// 获取位置签名AddrSign
  154. /// </summary>
  155. /// <param name="appId"></param>
  156. /// <param name="oauthAccessToken">必须是OAuth的AccessToken</param>
  157. /// <param name="noncestr"></param>
  158. /// <param name="timestamp"></param>
  159. /// <param name="url"></param>
  160. /// <returns></returns>
  161. public static string GetAddrSign(string appId, string oauthAccessToken, string noncestr, string timestamp,
  162. string url)
  163. {
  164. //TODO:此处的accessToken应该为OAuth的AccessToken
  165. //var accessToken = AccessTokenContainer.TryGetAccessToken(appId, appSecret);
  166. var parameters = new Hashtable();
  167. parameters.Add("appid", appId);
  168. parameters.Add("noncestr", noncestr);
  169. parameters.Add("timestamp", timestamp);
  170. parameters.Add("url", url);
  171. parameters.Add("accesstoken", oauthAccessToken);
  172. return CreateSha1(parameters);
  173. }
  174. /// <summary>
  175. /// 获取卡券签名CardSign
  176. /// </summary>
  177. /// <param name="appId"></param>
  178. /// <param name="appSecret"></param>
  179. /// <param name="locationId"></param>
  180. /// <param name="noncestr"></param>
  181. /// <param name="timestamp"></param>
  182. /// <param name="cardId"></param>
  183. /// <param name="cardType"></param>
  184. /// <returns></returns>
  185. public static string GetCardSign(string appId, string appSecret, string locationId, string noncestr,
  186. string timestamp, string cardId, string cardType)
  187. {
  188. var parameters = new Hashtable();
  189. parameters.Add("appId", appId);
  190. parameters.Add("appsecret", appSecret);
  191. parameters.Add("location_id", locationId);
  192. parameters.Add("nonce_str", noncestr);
  193. parameters.Add("times_tamp", timestamp);
  194. parameters.Add("card_id", cardId);
  195. parameters.Add("card_type", cardType);
  196. return CreateCardSha1(parameters);
  197. }
  198. /// <summary>
  199. ///获取添加卡券时Ext参数内的签名
  200. /// </summary>
  201. /// <param name="api_ticket"></param>
  202. /// <param name="timestamp"></param>
  203. /// <param name="card_id"></param>
  204. /// <param name="nonce_str"></param>
  205. /// <param name="code"></param>
  206. /// <param name="openid"></param>
  207. /// <returns></returns>
  208. public static string GetcardExtSign(string api_ticket, string timestamp, string card_id, string nonce_str = "",
  209. string code = "", string openid = "")
  210. {
  211. var parameters = new Hashtable();
  212. parameters.Add("api_ticket", api_ticket);
  213. parameters.Add("timestamp", timestamp);
  214. parameters.Add("card_id", card_id);
  215. if (!string.IsNullOrEmpty(code))
  216. {
  217. parameters.Add("code", code);
  218. }
  219. if (!string.IsNullOrEmpty(openid))
  220. {
  221. parameters.Add("openid", openid);
  222. }
  223. if (!string.IsNullOrEmpty(nonce_str))
  224. {
  225. parameters.Add("nonce_str", nonce_str);
  226. }
  227. return CreateNonekeySha1(parameters);
  228. }
  229. /// <summary>
  230. /// 获取给UI使用的JSSDK信息包
  231. /// </summary>
  232. /// <param name="appId"></param>
  233. /// <param name="appSecret"></param>
  234. /// <param name="url"></param>
  235. /// <returns></returns>
  236. public static JsSdkUiPackage GetJsSdkUiPackage(string appId, string appSecret, string url)
  237. {
  238. //获取时间戳
  239. var timestamp = GetTimestamp();
  240. //获取随机码
  241. string nonceStr = GetNoncestr();
  242. string ticket = JsApiTicketContainer.TryGetJsApiTicket(appId, appSecret);
  243. //获取签名
  244. string signature = JSSDKHelper.GetSignature(ticket, nonceStr, timestamp, url);
  245. //返回信息包
  246. return new JsSdkUiPackage(appId, timestamp, nonceStr, signature);
  247. }
  248. #if !NET35 && !NET40
  249. #region 异步方法
  250. /// <summary>
  251. /// 【异步方法】获取给UI使用的JSSDK信息包
  252. /// </summary>
  253. /// <param name="appId"></param>
  254. /// <param name="appSecret"></param>
  255. /// <param name="url"></param>
  256. /// <returns></returns>
  257. public static async Task<JsSdkUiPackage> GetJsSdkUiPackageAsync(string appId, string appSecret, string url)
  258. {
  259. //获取时间戳
  260. var timestamp = GetTimestamp();
  261. //获取随机码
  262. string nonceStr = GetNoncestr();
  263. string ticket = await JsApiTicketContainer.TryGetJsApiTicketAsync(appId, appSecret);
  264. //获取签名
  265. string signature = JSSDKHelper.GetSignature(ticket, nonceStr, timestamp, url);
  266. //返回信息包
  267. return new JsSdkUiPackage(appId, timestamp, nonceStr, signature);
  268. }
  269. #endregion
  270. #endif
  271. }
  272. }