469 lines
19 KiB
C#
469 lines
19 KiB
C#
using Newtonsoft.Json;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Net;
|
||
using System.Net.Http;
|
||
using System.Text;
|
||
using System.Threading;
|
||
|
||
namespace Appointment.Entity
|
||
{
|
||
public class AizhuhotelHelper
|
||
{
|
||
private static readonly log4net.ILog _logger = log4net.LogManager.GetLogger(typeof(AizhuhotelHelper));
|
||
|
||
// ---- 获取公众号 Access_token
|
||
private class LoveInnGetAccessTokenRes
|
||
{
|
||
/// <summary>
|
||
/// 200-成功,400-出错,
|
||
/// </summary>
|
||
public int Code { get; set; }
|
||
|
||
/// <summary>
|
||
/// 返回信息:正确、错误都提示
|
||
/// </summary>
|
||
public string Message { get; set; }
|
||
|
||
/// <summary>
|
||
/// 信息
|
||
/// </summary>
|
||
public GetAccessTokenRes Data { get; set; }
|
||
}
|
||
|
||
private class GetAccessTokenRes
|
||
{
|
||
public string Access_token { get; set; }
|
||
|
||
public int? Expires_in { get; set; }
|
||
|
||
public string Errcode { get; set; }
|
||
|
||
public string Errmsg { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通过爱住接口获取Accesstoken
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public static ApiResult<string> AizhuhotelGetAccesstoken()
|
||
{
|
||
var url = "https://pay.aizhuhotel.com/dlwx/api/WD/LoveInnGetAccessToken";
|
||
|
||
string AppId = BaseConfig.App(new string[] { "WeChatService", "AppId" });
|
||
if (string.IsNullOrWhiteSpace(AppId)) return ApiResult<string>.Failed("配置文件中未获取有效的消息推送AppId");
|
||
string AppName = BaseConfig.App(new string[] { "WeChatService", "AppName" });
|
||
if (string.IsNullOrWhiteSpace(AppName)) return ApiResult<string>.Failed("配置文件中未获取有效的消息推送AppName");
|
||
string AppSecret = BaseConfig.App(new string[] { "WeChatService", "AppSecret" });
|
||
if (string.IsNullOrWhiteSpace(AppSecret)) return ApiResult<string>.Failed("配置文件中未获取有效的消息推送AppSecret");
|
||
|
||
var json = JsonConvert.SerializeObject(new { AppId, AppName, AppSecret });
|
||
|
||
try
|
||
{
|
||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||
request.Proxy = null;
|
||
request.Method = "POST";
|
||
request.ContentType = "application/json";
|
||
// request.Timeout = 10000;
|
||
using (StreamWriter dataStream = new StreamWriter(request.GetRequestStream()))
|
||
{
|
||
dataStream.Write(json);
|
||
dataStream.Close();
|
||
}
|
||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||
if (response == null)
|
||
{
|
||
return ApiResult<string>.Failed("远程服务器没有响应!");
|
||
}
|
||
string encoding = response.ContentEncoding;
|
||
if (encoding == null || encoding.Length < 1)
|
||
{
|
||
encoding = "UTF-8"; //默认编码
|
||
}
|
||
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding));
|
||
string retString = reader.ReadToEnd();
|
||
|
||
var res = JsonConvert.DeserializeObject<LoveInnGetAccessTokenRes>(retString);
|
||
if (res.Code != 200) return ApiResult<string>.Failed(res.Message);
|
||
if (res.Data == null) return ApiResult<string>.Failed("未获取到有效信息");
|
||
return ApiResult<string>.Success(string.Empty, res.Data.Access_token);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.Debug(ex.ToString());
|
||
return ApiResult<string>.Failed("http请求异常,异常信息:" + ex.Message);
|
||
}
|
||
}
|
||
|
||
|
||
// ---- 通过微信服务器获取access_token
|
||
|
||
private static WxAccessTokenData accessCacheToken = null;
|
||
|
||
public class WxAccessTokenData
|
||
{
|
||
/// <summary>
|
||
/// 获取到的access_token
|
||
/// </summary>
|
||
public string Access_token { get; set; }
|
||
|
||
/// <summary>
|
||
/// 获取时间
|
||
/// </summary>
|
||
public DateTime GetDate { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 微信授权返回结果
|
||
/// </summary>
|
||
public class WxAuthorizationCodeRep
|
||
{
|
||
/// <summary>
|
||
/// 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
|
||
/// </summary>
|
||
public string Access_token { get; set; }
|
||
|
||
/// <summary>
|
||
/// access_token接口调用凭证超时时间,单位(秒)
|
||
/// 错误时不返回
|
||
/// </summary>
|
||
public int? Expires_in { get; set; }
|
||
|
||
/// <summary>
|
||
/// 用户刷新access_token
|
||
/// </summary>
|
||
public string Refresh_token { get; set; }
|
||
|
||
/// <summary>
|
||
/// 用户唯一标识
|
||
/// </summary>
|
||
public string Openid { get; set; }
|
||
|
||
/// <summary>
|
||
/// 用户授权的作用域,使用逗号(,)分隔
|
||
/// </summary>
|
||
public string Scope { get; set; }
|
||
|
||
/// <summary>
|
||
/// 错误码:返回码
|
||
/// 正确时不返回
|
||
/// </summary>
|
||
public int? Errcode { get; set; }
|
||
|
||
/// <summary>
|
||
/// 错误信息
|
||
/// </summary>
|
||
public string Errmsg { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取服务号AccessToken
|
||
/// </summary>
|
||
/// <param name="forceUpdate">强制刷新</param>
|
||
/// <returns></returns>
|
||
public static ApiResult<string> GetAccessToken(bool forceUpdate = false)
|
||
{
|
||
try
|
||
{
|
||
string AppId = BaseConfig.App(new string[] { "WeChatService", "AppId" });
|
||
if (string.IsNullOrWhiteSpace(AppId)) return ApiResult<string>.Failed("配置文件中未获取有效的服务号AppId");
|
||
string AppSecret = BaseConfig.App(new string[] { "WeChatService", "AppSecret" });
|
||
if (string.IsNullOrWhiteSpace(AppSecret)) return ApiResult<string>.Failed("配置文件中未获取有效的服务号AppSecret");
|
||
|
||
DateTime now = DateTime.Now;
|
||
|
||
if (forceUpdate == false && accessCacheToken != null && now.AddSeconds(-1 * 55 * 2) < accessCacheToken.GetDate)
|
||
{
|
||
return ApiResult<string>.Success(string.Empty, accessCacheToken.Access_token);
|
||
}
|
||
|
||
var url = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={AppId}&secret={AppSecret}";
|
||
using (var http = new HttpClient(new HttpClientHandler()))
|
||
{
|
||
var res = http.GetAsync(url).Result;
|
||
if (res.StatusCode != HttpStatusCode.OK)
|
||
{
|
||
_logger.Error("获取公众号access_token失败,微信服务接口响应" + res.StatusCode.ToString());
|
||
return ApiResult<string>.Failed("获取公众号access_token失败,微信服务接口响应" + res.StatusCode.ToString());
|
||
}
|
||
|
||
var reContent = res.Content.ReadAsStringAsync().Result;
|
||
if (!string.IsNullOrWhiteSpace(reContent))
|
||
{
|
||
var reToken = JsonConvert.DeserializeObject<WxAuthorizationCodeRep>(reContent);
|
||
if (!string.IsNullOrEmpty(reToken.Access_token))
|
||
{
|
||
accessCacheToken = new WxAccessTokenData()
|
||
{
|
||
Access_token = reToken.Access_token,
|
||
GetDate = now
|
||
};
|
||
return ApiResult<string>.Success(string.Empty, reToken.Access_token);
|
||
|
||
}
|
||
else
|
||
{
|
||
_logger.Error(reContent);
|
||
}
|
||
}
|
||
return ApiResult<string>.Failed(string.Empty);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.Error(ex.Message);
|
||
return ApiResult<string>.Failed(ex.Message);
|
||
}
|
||
}
|
||
|
||
// ---- 获取用户Openid
|
||
|
||
private class WxServiceRes
|
||
{
|
||
public string Access_token { get; set; }
|
||
|
||
public int? Expires_in { get; set; }
|
||
|
||
public string Refresh_token { get; set; }
|
||
|
||
public string Openid { get; set; }
|
||
|
||
public string Errcode { get; set; }
|
||
|
||
public string Errmsg { get; set; }
|
||
}
|
||
|
||
public static ApiResult<string> GetWxSericeOpenId(string code)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(code)) return ApiResult<string>.Failed("未获取到有效的code");
|
||
string AppId = BaseConfig.App(new string[] { "WeChatService", "AppId" });
|
||
if (string.IsNullOrWhiteSpace(AppId)) return ApiResult<string>.Failed("配置文件中未获取有效的消息推送AppId");
|
||
string AppSecret = BaseConfig.App(new string[] { "WeChatService", "AppSecret" });
|
||
if (string.IsNullOrWhiteSpace(AppSecret)) return ApiResult<string>.Failed("配置文件中未获取有效的消息推送AppSecret");
|
||
|
||
|
||
string url = $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={AppId}&secret={AppSecret}&code={code}&grant_type=authorization_code";
|
||
using (var http = new HttpClient(new HttpClientHandler()))
|
||
{
|
||
var response = http.GetAsync(url).Result;
|
||
if (response.StatusCode != HttpStatusCode.OK) return ApiResult<string>.Failed("微信接口无响应");
|
||
|
||
string res = response.Content.ReadAsStringAsync().Result;
|
||
if (!string.IsNullOrWhiteSpace(res))
|
||
{
|
||
var wxServiceRes = JsonConvert.DeserializeObject<WxServiceRes>(res);
|
||
if (!string.IsNullOrWhiteSpace(wxServiceRes.Openid))
|
||
{
|
||
return ApiResult<string>.Success(string.Empty, wxServiceRes.Openid);
|
||
}
|
||
else
|
||
{
|
||
_logger.Error(res);
|
||
return ApiResult<string>.Failed(wxServiceRes.Errcode);
|
||
}
|
||
}
|
||
return ApiResult<string>.Failed("返回空");
|
||
}
|
||
}
|
||
|
||
// ---- 发送消息模板
|
||
|
||
public static ApiResult SendTemplateMsg(string touser, string template_id, string url, string first, string remark, params object[] args)
|
||
{
|
||
try
|
||
{
|
||
string error = string.Empty;
|
||
for (int i = 0; i < 3; i++)
|
||
{
|
||
error = string.Empty;
|
||
var msg = WechatHelper.BuildTemlMsg(touser, template_id, url, first, remark, args);
|
||
|
||
string accessTokenMode = BaseConfig.App(new string[] { "AccessTokenMode" });
|
||
if (string.IsNullOrWhiteSpace(accessTokenMode))
|
||
{
|
||
_logger.Error("配置文件中未获取有效的AccessTokenMode");
|
||
return ApiResult.Failed("配置文件中未获取有效的AccessTokenMode");
|
||
}
|
||
|
||
ApiResult<string> tokenResult = null;
|
||
if (i == 0)
|
||
{
|
||
tokenResult = accessTokenMode == "1" ? AizhuhotelGetAccesstoken() : GetAccessToken();
|
||
}
|
||
else
|
||
{
|
||
tokenResult = accessTokenMode == "1" ? AizhuhotelGetAccesstoken() : GetAccessToken(true);
|
||
}
|
||
if (!tokenResult.IsSuccess)
|
||
{
|
||
error = "配置文件中未获取有效的AccessTokenMode";
|
||
_logger.Error(error);
|
||
continue;
|
||
}
|
||
|
||
var postUrl = $"https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={tokenResult.Info}";
|
||
|
||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUrl);
|
||
request.Proxy = null;
|
||
request.Method = "POST";
|
||
request.ContentType = "application/json";
|
||
// request.Timeout = 10000;
|
||
using (StreamWriter dataStream = new StreamWriter(request.GetRequestStream()))
|
||
{
|
||
dataStream.Write(msg);
|
||
dataStream.Close();
|
||
}
|
||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||
if (response == null)
|
||
{
|
||
error = "远程服务器没有响应!";
|
||
_logger.Error(error);
|
||
continue;
|
||
}
|
||
string encoding = response.ContentEncoding;
|
||
if (encoding == null || encoding.Length < 1)
|
||
{
|
||
encoding = "UTF-8"; //默认编码
|
||
}
|
||
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding));
|
||
string retString = reader.ReadToEnd();
|
||
|
||
if (!string.IsNullOrWhiteSpace(retString))
|
||
{
|
||
var sendTemplateMsgRes = JsonConvert.DeserializeObject<SendTemplateMsgRes>(retString);
|
||
if (sendTemplateMsgRes.Errmsg.ToLower() == "ok")
|
||
{
|
||
return ApiResult.Success(string.Empty);
|
||
}
|
||
else
|
||
{
|
||
error = $"接收者openid:{touser},错误代码{sendTemplateMsgRes.Errcode}";
|
||
_logger.Error(error);
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
return ApiResult.Failed(msg: "", info: error);
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.Debug(ex.ToString());
|
||
return ApiResult.Failed(msg: "", info: ex.Message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送模板消息返回结果
|
||
/// </summary>
|
||
private class SendTemplateMsgRes
|
||
{
|
||
/// <summary>
|
||
/// 返回代码,0-发送成功
|
||
/// </summary>
|
||
public int Errcode { get; set; }
|
||
|
||
/// <summary>
|
||
/// 返回消息:"ok"-成功
|
||
/// </summary>
|
||
public string Errmsg { get; set; }
|
||
|
||
/// <summary>
|
||
/// 发送成功返回编号:失败不返回
|
||
/// </summary>
|
||
public long? Msgid { get; set; }
|
||
}
|
||
|
||
public static void SendTemplateMsg(List<string> tousers, string template_id, string url, string first, string remark, params object[] args)
|
||
{
|
||
if (tousers == null || tousers.Count == 0) return;
|
||
string accessTokenMode = BaseConfig.App(new string[] { "AccessTokenMode" });
|
||
if (string.IsNullOrWhiteSpace(accessTokenMode))
|
||
{
|
||
_logger.Error("配置文件中未获取有效的AccessTokenMode");
|
||
return;
|
||
}
|
||
|
||
ApiResult<string> tokenResult = accessTokenMode == "1" ? AizhuhotelGetAccesstoken() : GetAccessToken();
|
||
if (!tokenResult.IsSuccess)
|
||
{
|
||
_logger.Error(tokenResult.Msg);
|
||
return;
|
||
}
|
||
|
||
List<string> msgList = new List<string>();
|
||
foreach (var touser in tousers)
|
||
{
|
||
msgList.Add(WechatHelper.BuildTemlMsg(touser, template_id, url, first, remark, args));
|
||
}
|
||
|
||
int send = 0;
|
||
_logger.Info($"发送推送消息,模板:{template_id}, 接收者openId:{string.Join(",", msgList)} 。");
|
||
StringBuilder msg = new StringBuilder();
|
||
foreach (var itemMsg in msgList)
|
||
{
|
||
for (int i = 0; i < 3; i++)
|
||
{
|
||
if (i > 0)
|
||
{
|
||
Thread.Sleep(100);
|
||
tokenResult = accessTokenMode == "1" ? AizhuhotelGetAccesstoken() : GetAccessToken(true);
|
||
if (!tokenResult.IsSuccess)
|
||
{
|
||
_logger.Error(tokenResult.Msg);
|
||
continue;
|
||
}
|
||
}
|
||
var postUrl = $"https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={tokenResult.Info}";
|
||
|
||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUrl);
|
||
request.Proxy = null;
|
||
request.Method = "POST";
|
||
request.ContentType = "application/json";
|
||
// request.Timeout = 10000;
|
||
using (StreamWriter dataStream = new StreamWriter(request.GetRequestStream()))
|
||
{
|
||
dataStream.Write(itemMsg);
|
||
dataStream.Close();
|
||
}
|
||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||
if (response == null)
|
||
{
|
||
_logger.Error("微信接口远程服务器没有响应");
|
||
continue;
|
||
}
|
||
string encoding = response.ContentEncoding;
|
||
if (encoding == null || encoding.Length < 1)
|
||
{
|
||
encoding = "UTF-8"; //默认编码
|
||
}
|
||
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding));
|
||
string retString = reader.ReadToEnd();
|
||
_logger.Info("-->" + itemMsg);
|
||
|
||
if (!string.IsNullOrWhiteSpace(retString))
|
||
{
|
||
var sendTemplateMsgRes = JsonConvert.DeserializeObject<SendTemplateMsgRes>(retString);
|
||
if (sendTemplateMsgRes.Errmsg.ToLower() == "ok")
|
||
{
|
||
send += 1;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
if (msg.Length == 0) msg.AppendFormat("消息推送失败:消息模板{0}", template_id);
|
||
msg.AppendFormat("接收者openid:{0},错误代码{1}", itemMsg, sendTemplateMsgRes.Errcode);
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
Thread.Sleep(100);
|
||
}
|
||
if (msg.Length > 0) _logger.Error(msg.ToString());
|
||
|
||
}
|
||
}
|
||
}
|