/// <summary> /// 获取微信SDK配置 /// </summary> [HttpPost] [Route("api/Training/GetWxSdkConfig")] public ResponseMessage GetWxSdkConfig(ReqGetWXsdkConfig req) { var result = new ResponseMessage { Msg = false, Message = CommonMessage.GetFailure, ResultCode = (int)EnumsHelper.MessageResultCode.OpraterError, }; //获取微信支付信息 var weChatModel = MyShoppingCartService.GetMSiteWeChatPayAccount(); if (weChatModel == null) { result.Msg = false; result.Message = string.Empty; result.ResultCode = (int)EnumsHelper.MessageResultCode.OpraterError; return result; } //修改微信配置信息 SetWxJsApiConfig(weChatModel); try { var model = GenerateJsSdkConfig(req.Url); result.Info = model; result.Msg = true; result.Message = CommonMessage.GetSuccess; result.ResultCode = (int)EnumsHelper.MessageResultCode.OpraterSuccess; return result; } catch (Exception ex) { result.Info = string.Format("获取config出现异常:{0}", ex.Message.Replace("'", """)); return result; } } /// <summary> /// 修改微信配置信息 /// </summary> private void SetWxJsApiConfig(T_MSiteWeChatPayAccount weChatModel) { WxPayConfig.APPID = weChatModel.AppId; WxPayConfig.MCHID = weChatModel.MchId; WxPayConfig.KEY = weChatModel.Key; WxPayConfig.APPSECRET = weChatModel.AppSecret; WxPayConfig.NOTIFY_URL = weChatModel.NotifyUrl; } /// <summary> /// 生成SDKConfig(前端调用微信接口用) /// </summary> /// <param name="url">当前页面的url</param> /// <returns>前端所需SDKConfig信息</returns> private JsApiConfig GenerateJsSdkConfig(string url) { var wxJsSdkApi = new WxJsSdkApi(); JsApiConfig config = new JsApiConfig() { //debug = false, appId = WxPayConfig.APPID, nonceStr = wxJsSdkApi.NonceStr, timestamp = wxJsSdkApi.TimeStamp, //signature = signature ////需要使用的JS接口列表 //jsApiList = new string[] { "chooseImage", "previewImage", "uploadImage", "downloadImage" } }; //签名 string signature = wxJsSdkApi.MakeSha1Sign(config.nonceStr,config.timestamp,url); config.signature = signature; return config; }
账号基本配置信息
/** * 配置账号信息 */ public class WxPayConfig { //=======【基本信息设置】===================================== /* 微信公众号信息配置 * APPID:绑定支付的APPID(必须配置) * MCHID:商户号(必须配置) * KEY:商户支付密钥,参考开户邮件设置(必须配置) * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置) */ //public static string APPID = "xxxxxxxxxxxxxx"; public static string APPID = "xxxxxxxxxxx"; public static string MCHID = "xxxxxxxxxxx"; public static string KEY = "xxxxxxxxxxx"; public static string APPSECRET = "xxxxxxxxxxxxxx"; //=======【证书路径设置】===================================== /* 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要) */ public static string SSLCERT_PATH = "cert/apiclient_cert.p12"; public static string SSLCERT_PASSWORD = "1233410002"; //=======【支付结果通知url】===================================== /* 支付结果通知回调url,用于商户接收支付结果 */ public static string NOTIFY_URL = "http://xxxxxx.com/payNotify"; //=======【商户系统后台机器IP】===================================== /* 此参数可手动配置也可在程序中自动获取 */ public static string IP = "8.8.8.8"; //=======【代理服务器设置】=================================== /* 默认IP和端口号分别为0.0.0.0和0,此时不开启代理(如有需要才设置) */ //public static string PROXY_URL = "http://0.0.0.0:0"; public static string PROXY_URL = "http://0.0.0.0:0"; //=======【上报信息配置】=================================== /* 测速上报等级,0.关闭上报; 1.仅错误时上报; 2.全量上报 */ public static int REPORT_LEVENL = 1; //=======【日志级别】=================================== /* 日志等级,0.不输出日志;1.只输出错误信息; 2.输出错误和正常信息; 3.输出错误信息、正常信息和调试信息 */ public static int LOG_LEVENL = 3; }
SDK生成签名
public class WxJsSdkApi { /// <summary> /// 缓存 /// </summary> private RedisInfoHelper redis => new RedisInfoHelper(); /// <summary> /// 微信appid /// </summary> private string appId = WxPayConfig.APPID; /// <summary> /// 微信appsecret /// </summary> private string secret = WxPayConfig.APPSECRET; /// <summary> /// 获取基础支持access_token url 每日调用上限2000次 /// 详情参考:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183 /// </summary> private string WxGetTokenUrl = "https://api.weixin.qq.com/cgi-bin/token"; private string WxGetTokenParam = "grant_type=client_credential&appid={0}&secret={1}"; /// <summary> /// 获取jsapi_ticket url /// 详情参考:https://qydev.weixin.qq.com/wiki/index.php?title=%E5%BE%AE%E4%BF%A1JS-SDK%E6%8E%A5%E5%8F%A3 /// </summary> private string WxGetTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"; private string WxGetTicketParam = "access_token={0}&type=jsapi"; /// <summary> /// 加密字符串的拼接 /// </summary> private string WxSha1SignStr = "jsapi_ticket={0}&noncestr={1}×tamp={2}&url={3}"; /// <summary> /// 通过用户code获取网页授权access_token url /// 详情参考:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 /// </summary> private string WxGetAccessTokenByCodeUrl = "https://api.weixin.qq.com/sns/oauth2/access_token"; private string WxGetAccessTokenByCodeParam = "appid={0}&secret={1}&code={2}&grant_type=authorization_code"; /// <summary> /// 基础支持Access_Token 有效期7200秒 /// </summary> public string BaseAccessToken => GetBaseAccessToken(); /// <summary> /// Ticket 公众号用于调用微信JS接口的临时票据 (有效期7200秒) /// </summary> public string Ticket { get { return GetTicket(); } } /// <summary> /// 生成签名的随机串 /// </summary> public string NonceStr { get; set; } = Guid.NewGuid().ToString().Replace("-", ""); /// <summary> /// 生成签名的时间戳 /// </summary> public string TimeStamp { get { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); } } /// <summary> /// 获取基础支持access_token /// </summary> private string GetBaseAccessToken() { var accesstoken = redis.GetAccessTokenByAppId("wx_" + appId); if ((string.Empty).Equals(accesstoken)) { return GetBaseToken(); } return accesstoken != null ? accesstoken.ToString() : GetBaseToken(); } /// <summary> /// 获取基础支持access_token /// </summary> private string GetBaseToken() { try { string token = string.Empty; //向微信发送请求获取 基础支持accessToken string content = HttpClientHelper.HttpGet(WxGetTokenUrl, string.Format(WxGetTokenParam, appId, secret)); Log4NetHelp.Debug($"微信JSSDK获取基础accessToken参数--appid:{content},secret:{secret}"); Log4NetHelp.Debug($"微信JSSDK获取基础accessToken返回结果--{content}"); if (!string.IsNullOrEmpty(content)) { var obj = JsonConvert.DeserializeObject<BaseTokenResult>(content); if (!obj.errcode.HasValue) { token = obj.access_token; //缓存 access_token redis.SetRedis("wx_" + appId, token, DateTime.Now.AddSeconds(7200)); //获取 ticket GetTicket(token); } } return token; } catch (Exception ex) { return ex.Message; } } /// <summary> /// 获取ticket /// </summary> private string GetTicket(string accessToken = "") { var ticket = string.Empty; accessToken = BaseAccessToken; if (string.Empty.Equals(accessToken)) return ticket; ticket = redis.GetTicketByAccessToken(accessToken); if ((string.Empty).Equals(ticket)) { string content = HttpClientHelper.HttpGet(WxGetTicketUrl, string.Format(WxGetTicketParam, accessToken)); Log4NetHelp.Debug($"微信JSSDK获取ticket参数--accessToken:{accessToken}"); Log4NetHelp.Debug($"微信JSSDK获取ticket返回结果--{content}"); JsApiTicket obj = JsonConvert.DeserializeObject<JsApiTicket>(content); ticket = obj.ticket; redis.SetRedis(accessToken, ticket, DateTime.Now.AddSeconds(7200)); } return ticket; } /// <summary> /// SDK生成签名 (SHA1加密) /// 注意:需要引用System.Security.dll /// </summary> /// <param name="url">当前页面链接</param> public string MakeSha1Sign(string nonceStr, string timeStamp, string url) { string str = string.Format(WxSha1SignStr, Ticket, nonceStr, timeStamp, url); Log4NetHelp.Info($"SDK生成签名加密字符串--{str}"); byte[] StrRes = Encoding.Default.GetBytes(str); HashAlgorithm iSHA = new SHA1CryptoServiceProvider(); StrRes = iSHA.ComputeHash(StrRes); StringBuilder EnText = new StringBuilder(); foreach (byte iByte in StrRes) { EnText.AppendFormat("{0:x2}", iByte); } return EnText.ToString(); } /// <summary> /// 通过code换取网页授权access_token /// </summary> /// <param name="code"></param> /// <returns></returns> public TokenResultInfo GetAccessTokenByCode(string code) { var result = new TokenResultInfo(); //向微信发送请求获取 网页授权accessToken string content = HttpClientHelper.HttpGet(WxGetAccessTokenByCodeUrl, string.Format(WxGetAccessTokenByCodeParam, appId, secret, code)); Log4NetHelp.Info($"通过code换取网页授权access_token参数--appid:{appId}--secret:{secret}--code:{code}"); Log4NetHelp.Info($"通过code换取网页授权access_token返回结果--{content}--appid:{appId}--secret:{secret}--code:{code}"); if (!string.IsNullOrEmpty(content)) { var obj = JsonConvert.DeserializeObject<TokenResult>(content); if (!obj.errcode.HasValue) { result.AccessToken = obj.access_token; result.OpenId = obj.openid; } } return result; } }