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