WxCardApiTicketContainer.cs 12 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. 文件名:WxCardApiTicketContainer.cs
  17. 文件功能描述:WxCardApiTicketContainer
  18. 创建标识:Senparc - 20180419
  19. 修改标识:Senparc - 20180614
  20. 修改描述:CO2NET v0.1.0 ContainerBag 取消属性变动通知机制,使用手动更新缓存
  21. 修改标识:Senparc - 20180707
  22. 修改描述:v15.0.9 Container 的 Register() 的微信参数自动添加到 Config.SenparcWeixinSetting.Items 下
  23. 修改标识:Senparc - 20181226
  24. 修改描述:v16.6.2 修改 DateTime 为 DateTimeOffset
  25. ----------------------------------------------------------------*/
  26. using System;
  27. using System.Linq;
  28. using System.Threading.Tasks;
  29. using Senparc.Weixin.Containers;
  30. using Senparc.Weixin.Exceptions;
  31. using Senparc.Weixin.MP.Entities;
  32. using Senparc.Weixin.MP.CommonAPIs;
  33. using Senparc.Weixin.Utilities.WeixinUtility;
  34. using Senparc.CO2NET.CacheUtility;
  35. using Senparc.CO2NET.Extensions;
  36. namespace Senparc.Weixin.MP.Containers
  37. {
  38. /// <summary>
  39. /// WxCardApiTicket包
  40. /// </summary>
  41. [Serializable]
  42. public class WxCardApiTicketBag : BaseContainerBag, IBaseContainerBag_AppId
  43. {
  44. public string AppId { get; set; }
  45. // {
  46. // get
  47. // {
  48. // return _appId;
  49. // }
  50. //#if NET35 || NET40
  51. // set { this.SetContainerProperty(ref _appId, value, "AppId"); }
  52. //#else
  53. // set
  54. // {
  55. // this.SetContainerProperty(ref _appId, value);
  56. // }
  57. //#endif
  58. // }
  59. public string AppSecret { get; set; }
  60. // {
  61. // get
  62. // {
  63. // return _appSecret;
  64. // }
  65. //#if NET35 || NET40
  66. // set { this.SetContainerProperty(ref _appSecret, value, "AppSecret"); }
  67. //#else
  68. // set
  69. // {
  70. // this.SetContainerProperty(ref _appSecret, value);
  71. // }
  72. //#endif
  73. // }
  74. public JsApiTicketResult WxCardApiTicketResult { get; set; }
  75. // {
  76. // get
  77. // {
  78. // return _WxCardApiTicketResult;
  79. // }
  80. //#if NET35 || NET40
  81. // set { this.SetContainerProperty(ref _WxCardApiTicketResult, value, "WxCardApiTicketResult"); }
  82. //#else
  83. // set
  84. // {
  85. // this.SetContainerProperty(ref _WxCardApiTicketResult, value);
  86. // }
  87. //#endif
  88. // }
  89. public DateTimeOffset WxCardApiTicketExpireTime { get; set; }
  90. // {
  91. // get
  92. // {
  93. // return _WxCardApiTicketExpireTime;
  94. // }
  95. //#if NET35 || NET40
  96. // set { this.SetContainerProperty(ref _WxCardApiTicketExpireTime, value, "WxCardApiExpireTime"); }
  97. //#else
  98. // set
  99. // {
  100. // this.SetContainerProperty(ref _WxCardApiTicketExpireTime, value);
  101. // }
  102. //#endif
  103. // }
  104. /// <summary>
  105. /// 只针对这个AppId的锁
  106. /// </summary>
  107. internal object Lock = new object();
  108. //private DateTimeOffset _WxCardApiTicketExpireTime;
  109. //private JsApiTicketResult _WxCardApiTicketResult;
  110. //private string _appSecret;
  111. //private string _appId;
  112. }
  113. /// <summary>
  114. /// 通用接口WxCardApiTicket容器,用于自动管理WxCardApiTicket,如果过期会重新获取
  115. /// </summary>
  116. public class WxCardApiTicketContainer : BaseContainer<WxCardApiTicketBag>
  117. {
  118. const string LockResourceName = "MP.WxCardApiTicketContainer";
  119. #region 同步方法
  120. //static Dictionary<string,WxCardApiTicketBag> WxCardApiTicketCollection =
  121. // new Dictionary<string, WxCardApiTicketBag>(StringComparer.OrdinalIgnoreCase);
  122. /// <summary>
  123. /// 注册应用凭证信息,此操作只是注册,不会马上获取Ticket,并将清空之前的Ticket,
  124. /// </summary>
  125. /// <param name="appId"></param>
  126. /// <param name="appSecret"></param>
  127. /// <param name="name">标记JsApiTicket名称(如微信公众号名称),帮助管理员识别。当 name 不为 null 和 空值时,本次注册内容将会被记录到 Senparc.Weixin.Config.SenparcWeixinSetting.Items[name] 中,方便取用。</param>
  128. /*此接口不提供异步方法*/
  129. public static void Register(string appId, string appSecret, string name = null)
  130. {
  131. //记录注册信息,RegisterFunc委托内的过程会在缓存丢失之后自动重试
  132. RegisterFunc = () =>
  133. {
  134. //using(FlushCache.CreateInstance())
  135. //{
  136. WxCardApiTicketBag bag = new WxCardApiTicketBag()
  137. {
  138. Name = name,
  139. AppId = appId,
  140. AppSecret = appSecret,
  141. WxCardApiTicketExpireTime = DateTimeOffset.MinValue,
  142. WxCardApiTicketResult = new JsApiTicketResult()
  143. };
  144. Update(appId, bag, null);
  145. return bag;
  146. //}
  147. };
  148. RegisterFunc();
  149. if (!name.IsNullOrEmpty())
  150. {
  151. Senparc.Weixin.Config.SenparcWeixinSetting.Items[name].WeixinAppId = appId;
  152. Senparc.Weixin.Config.SenparcWeixinSetting.Items[name].WeixinAppSecret = appSecret;
  153. }
  154. }
  155. #region WxCardApiTicket
  156. /// <summary>
  157. /// 使用完整的应用凭证获取Ticket,如果不存在将自动注册
  158. /// </summary>
  159. /// <param name="appId"></param>
  160. /// <param name="appSecret"></param>
  161. /// <param name="getNewTicket"></param>
  162. /// <returns></returns>
  163. public static string TryGetWxCardApiTicket(string appId, string appSecret, bool getNewTicket = false)
  164. {
  165. if (!CheckRegistered(appId) || getNewTicket)
  166. {
  167. Register(appId, appSecret);
  168. }
  169. return GetWxCardApiTicket(appId);
  170. }
  171. /// <summary>
  172. /// 获取可用Ticket
  173. /// </summary>
  174. /// <param name="appId"></param>
  175. /// <param name="getNewTicket">是否强制重新获取新的Ticket</param>
  176. /// <returns></returns>
  177. public static string GetWxCardApiTicket(string appId, bool getNewTicket = false)
  178. {
  179. return GetWxCardApiTicketResult(appId, getNewTicket).ticket;
  180. }
  181. /// <summary>
  182. /// 获取可用Ticket
  183. /// </summary>
  184. /// <param name="appId"></param>
  185. /// <param name="getNewTicket">是否强制重新获取新的Ticket</param>
  186. /// <returns></returns>
  187. public static JsApiTicketResult GetWxCardApiTicketResult(string appId, bool getNewTicket = false)
  188. {
  189. if (!CheckRegistered(appId))
  190. {
  191. throw new UnRegisterAppIdException(null, "此appId尚未注册,请先使用WxCardApiTicketContainer.Register完成注册(全局执行一次即可)!");
  192. }
  193. WxCardApiTicketBag wxCardApiTicketBag = TryGetItem(appId);
  194. using (Cache.BeginCacheLock(LockResourceName, appId))//同步锁
  195. {
  196. if (getNewTicket || wxCardApiTicketBag.WxCardApiTicketExpireTime <= SystemTime.Now)
  197. {
  198. //已过期,重新获取
  199. wxCardApiTicketBag.WxCardApiTicketResult = CommonApi.GetTicket(wxCardApiTicketBag.AppId,
  200. wxCardApiTicketBag.AppSecret,
  201. "wx_card");
  202. wxCardApiTicketBag.WxCardApiTicketExpireTime = ApiUtility.GetExpireTime(wxCardApiTicketBag.WxCardApiTicketResult.expires_in);
  203. Update(wxCardApiTicketBag, null);
  204. }
  205. }
  206. return wxCardApiTicketBag.WxCardApiTicketResult;
  207. }
  208. #endregion
  209. #endregion
  210. #if !NET35 && !NET40
  211. #region 异步方法
  212. #region WxCardApiTicket
  213. /// <summary>
  214. /// 【异步方法】使用完整的应用凭证获取Ticket,如果不存在将自动注册
  215. /// </summary>
  216. /// <param name="appId"></param>
  217. /// <param name="appSecret"></param>
  218. /// <param name="getNewTicket"></param>
  219. /// <returns></returns>
  220. public static async Task<string> TryGetWxCardApiTicketAsync(string appId,
  221. string appSecret,
  222. bool getNewTicket = false)
  223. {
  224. if (!CheckRegistered(appId) || getNewTicket)
  225. {
  226. Register(appId, appSecret);
  227. }
  228. return await GetWxCardApiTicketAsync(appId, getNewTicket);
  229. }
  230. /// <summary>
  231. ///【异步方法】 获取可用Ticket
  232. /// </summary>
  233. /// <param name="appId"></param>
  234. /// <param name="getNewTicket">是否强制重新获取新的Ticket</param>
  235. /// <returns></returns>
  236. public static async Task<string> GetWxCardApiTicketAsync(string appId, bool getNewTicket = false)
  237. {
  238. JsApiTicketResult result = await GetWxCardApiTicketResultAsync(appId, getNewTicket);
  239. return result.ticket;
  240. }
  241. /// <summary>
  242. /// 【异步方法】获取可用Ticket
  243. /// </summary>
  244. /// <param name="appId"></param>
  245. /// <param name="getNewTicket">是否强制重新获取新的Ticket</param>
  246. /// <returns></returns>
  247. public static async Task<JsApiTicketResult> GetWxCardApiTicketResultAsync(string appId,
  248. bool getNewTicket = false)
  249. {
  250. if (!CheckRegistered(appId))
  251. {
  252. throw new UnRegisterAppIdException(null, "此appId尚未注册,请先使用WxCardApiTicketContainer.Register完成注册(全局执行一次即可)!");
  253. }
  254. WxCardApiTicketBag wxCardApiTicketBag = TryGetItem(appId);
  255. using (Cache.BeginCacheLock(LockResourceName, appId))//同步锁
  256. {
  257. if (getNewTicket || wxCardApiTicketBag.WxCardApiTicketExpireTime <= SystemTime.Now)
  258. {
  259. //已过期,重新获取
  260. JsApiTicketResult wxCardApiTicketResult = await CommonApi.GetTicketAsync(wxCardApiTicketBag.AppId,
  261. wxCardApiTicketBag.AppSecret);
  262. wxCardApiTicketBag.WxCardApiTicketResult = wxCardApiTicketResult;
  263. wxCardApiTicketBag.WxCardApiTicketExpireTime = SystemTime.Now.AddSeconds(wxCardApiTicketBag.WxCardApiTicketResult.expires_in);
  264. Update(wxCardApiTicketBag, null);
  265. }
  266. }
  267. return wxCardApiTicketBag.WxCardApiTicketResult;
  268. }
  269. #endregion
  270. #endregion
  271. #endif
  272. }
  273. }