添加项目文件。

This commit is contained in:
JianWeie
2021-12-20 21:27:32 +08:00
parent 747486f5cb
commit 82d825b7a5
3514 changed files with 887941 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/30 14:19:49
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreCms.Net.WeChat.Service.Configuration
{
/// <summary>
/// 常见消息类型
/// </summary>
public static class EventType
{
#region
/// <summary>
/// 关注
/// </summary>
public const string Subscribe = "subscribe";
/// <summary>
/// 取消订阅
/// </summary>
public const string Unsubscribe = "unsubscribe";
/// <summary>
/// 上报地理位置事件
/// 用户同意上报地理位置后每次进入公众号会话时都会在进入时上报地理位置或在进入会话后每5秒上报一次地理位置公众号可以在公众平台网站中修改以上设置。上报地理位置时微信会将上报地理位置事件推送到开发者填写的URL。
/// </summary>
public const string Localtion = "LOCATION";
/// <summary>
/// 自定义菜单事件-用户点击自定义菜单后,微信会把点击事件推送给开发者,请注意,点击菜单弹出子菜单,不会产生上报。
/// </summary>
public const string Click = "CLICK";
#endregion
#region
#endregion
#region
#endregion
/// <summary>
/// 图片消息
/// </summary>
public const string Image = "image";
}
}

View File

@@ -0,0 +1,69 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/30 14:19:49
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreCms.Net.WeChat.Service.Configuration
{
/// <summary>
/// 常用常量配置
/// </summary>
public static class RequestMsgType
{
// 各种消息类型,除了扫带二维码事件
/// <summary>
/// 文本消息
/// </summary>
public const string Text = "text";
/// <summary>
/// 图片消息
/// </summary>
public const string Image = "image";
/// <summary>
/// 语音消息
/// </summary>
public const string Voice = "voice";
/// <summary>
/// 视频消息
/// </summary>
public const string Video = "video";
/// <summary>
/// 小视频消息
/// </summary>
public const string ShortVideo = "shortvideo";
/// <summary>
/// 地理位置消息
/// </summary>
public const string Location = "location";
/// <summary>
/// 链接消息
/// </summary>
public const string Link = "link";
/// <summary>
/// 事件推送消息
/// </summary>
public const string MessageEvent = "event";
}
}

View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MediatR" Version="9.0.0" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="1.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CoreCms.Net.Utility\CoreCms.Net.Utility.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,289 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 1:46:08
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreCms.Net.WeChat.Service.Enums
{
public class WeChatReturnCode
{
/// <summary>
/// 公众号返回码JSON
/// 应该更名为ReturnCode_MP但为减少项目中的修改此处依旧用ReturnCode命名
/// </summary>
public enum ReturnCode
{
SenparcWeixinSDK配置错误 = -99, // 0xFFFFFF9D
= -1, // 0xFFFFFFFF
= 0,
_企业已注销 = 101, // 0x00000065
_企业不存在或企业信息未更新 = 102, // 0x00000066
_企业法定代表人姓名不一致 = 103, // 0x00000067
_企业法定代表人身份证号码不一致 = 104, // 0x00000068
_工商数据未更新_请5_15个工作日之后尝试 = 105, // 0x00000069
_企业信息或法定代表人信息不一致 = 1000, // 0x000003E8
= 10700, // 0x000029CC
_对方关闭了接收消息 = 10703, // 0x000029CF
_48小时内用户未互动 = 10706, // 0x000029D2
POST参数非法 = 20002, // 0x00004E22
access_token时AppSecret错误或者access_token无效 = 40001, // 0x00009C41
/// <summary>
/// <para>公众号:不合法的凭证类型</para>
/// <para>小程序:暂无生成权限</para>
/// </summary>
= 40002, // 0x00009C42
OpenID = 40003, // 0x00009C43
= 40004, // 0x00009C44
= 40005, // 0x00009C45
= 40006, // 0x00009C46
id = 40007, // 0x00009C47
_40008 = 40008, // 0x00009C48
= 40009, // 0x00009C49
= 40010, // 0x00009C4A
= 40011, // 0x00009C4B
= 40012, // 0x00009C4C
/// <summary>
/// <para>微信不合法的APPID</para>
/// <para>小程序:生成权限被封禁</para>
/// </summary>
APPID = 40013, // 0x00009C4D
access_token = 40014, // 0x00009C4E
= 40015, // 0x00009C4F
1 = 40016, // 0x00009C50
2 = 40017, // 0x00009C51
= 40018, // 0x00009C52
KEY长度 = 40019, // 0x00009C53
URL长度 = 40020, // 0x00009C54
= 40021, // 0x00009C55
= 40022, // 0x00009C56
= 40023, // 0x00009C57
= 40024, // 0x00009C58
= 40025, // 0x00009C59
KEY长度 = 40026, // 0x00009C5A
URL长度 = 40027, // 0x00009C5B
使 = 40028, // 0x00009C5C
oauth_code = 40029, // 0x00009C5D
refresh_token = 40030, // 0x00009C5E
openid列表 = 40031, // 0x00009C5F
openid列表长度 = 40032, // 0x00009C60
uxxxx格式的字符 = 40033, // 0x00009C61
= 40035, // 0x00009C63
template_id不正确 = 40037, // 0x00009C65
= 40038, // 0x00009C66
URL长度 = 40039, // 0x00009C67
id = 40050, // 0x00009C72
= 40051, // 0x00009C73
/// <summary>
/// <para>公众号:输入参数有误</para>
/// <para>小程序参数expire_time填写错误</para>
/// </summary>
= 40097, // 0x00009CA1
appsecret不正确 = 40125, // 0x00009CBD
IP地址不在白名单中 = 40164, // 0x00009CE4
path填写错误 = 40165, // 0x00009CE5
Appid不存在 = 40166, // 0x00009CE6
query填写错误 = 40212, // 0x00009D14
access_token参数 = 41001, // 0x0000A029
appid参数 = 41002, // 0x0000A02A
refresh_token参数 = 41003, // 0x0000A02B
secret参数 = 41004, // 0x0000A02C
= 41005, // 0x0000A02D
media_id参数 = 41006, // 0x0000A02E
= 41007, // 0x0000A02F
oauth_code = 41008, // 0x0000A030
openid = 41009, // 0x0000A031
form_id不正确_或者过期 = 41028, // 0x0000A044
form_id已被使用 = 41029, // 0x0000A045
page不正确 = 41030, // 0x0000A046
access_token超时 = 42001, // 0x0000A411
refresh_token超时 = 42002, // 0x0000A412
oauth_code超时 = 42003, // 0x0000A413
GET请求 = 43001, // 0x0000A7F9
POST请求 = 43002, // 0x0000A7FA
HTTPS请求 = 43003, // 0x0000A7FB
= 43004, // 0x0000A7FC
= 43005, // 0x0000A7FD
/// <summary>[小程序订阅消息]用户拒绝接受消息,如果用户之前曾经订阅过,则表示用户取消了订阅关系</summary>
= 43101, // 0x0000A85D
= 43104, // 0x0000A860
= 44001, // 0x0000ABE1
POST的数据包为空 = 44002, // 0x0000ABE2
= 44003, // 0x0000ABE3
= 44004, // 0x0000ABE4
= 45001, // 0x0000AFC9
= 45002, // 0x0000AFCA
= 45003, // 0x0000AFCB
= 45004, // 0x0000AFCC
= 45005, // 0x0000AFCD
= 45006, // 0x0000AFCE
= 45007, // 0x0000AFCF
= 45008, // 0x0000AFD0
= 45009, // 0x0000AFD1
= 45010, // 0x0000AFD2
= 45015, // 0x0000AFD7
= 45016, // 0x0000AFD8
= 45017, // 0x0000AFD9
= 45018, // 0x0000AFDA
= 45047, // 0x0000AFF7
100 = 45056, // 0x0000B000
= 45157, // 0x0000B065
30 = 45158, // 0x0000B066
= 46001, // 0x0000B3B1
= 46002, // 0x0000B3B2
= 46003, // 0x0000B3B3
JSON_XML内容错误 = 47001, // 0x0000B799
/// <summary>[小程序订阅消息]模板参数不准确可能为空或者不满足规则errmsg会提示具体是哪个字段出错</summary>
= 47003, // 0x0000B79B
api功能未授权 = 48001, // 0x0000BB81
api = 50001, // 0x0000C351
= 53010, // 0x0000CF12
= 53011, // 0x0000CF13
使 = 53012, // 0x0000CF14
_名称与已有公众号名称重复_小程序_该名称与已有小程序名称重复 = 53013, // 0x0000CF15
_公众号已有_名称A_时_需与该帐号相同主体才可申请_名称A_小程序_小程序已有_名称A_时_需与该帐号相同主体才可申请_名称A_ = 53014, // 0x0000CF16
_该名称与已有小程序名称重复_需与该小程序帐号相同主体才可申请_小程序_该名称与已有公众号名称重复_需与该公众号帐号相同主体才可申请 = 53015, // 0x0000CF17
_该名称与已有多个小程序名称重复_暂不支持申请_小程序_该名称与已有多个公众号名称重复_暂不支持申请 = 53016, // 0x0000CF18
_小程序已有_名称A_时_需与该帐号相同主体才可申请_名称A_小程序_公众号已有_名称A_时_需与该帐号相同主体才可申请_名称A = 53017, // 0x0000CF19
= 53018, // 0x0000CF1A
= 53019, // 0x0000CF1B
= 61070, // 0x0000EE8E
system_error = 61450, // 0x0000F00A
invalid_parameter = 61451, // 0x0000F00B
invalid_kf_account = 61452, // 0x0000F00C
kf_account_exsited = 61453, // 0x0000F00D
/// <summary>
/// 客服帐号名长度超过限制(仅允许10个英文字符不包括@及@后的公众号的微信号)(invalid kf_acount length)
/// </summary>
= 61454, // 0x0000F00E
/// <summary>
/// 客服帐号名包含非法字符(仅允许英文+数字)(illegal character in kf_account)
/// </summary>
= 61455, // 0x0000F00F
/// <summary>客服帐号个数超过限制(10个客服账号)(kf_account count exceeded)</summary>
= 61456, // 0x0000F010
invalid_file_type = 61457, // 0x0000F011
= 61500, // 0x0000F03C
= 61501, // 0x0000F03D
_该用户已被加入黑名单_无法向此发送消息 = 62751, // 0x0000F51F
= 65115, // 0x0000FE5B
= 65118, // 0x0000FE5E
= 85006, // 0x00014C0E
= 85007, // 0x00014C0F
= 85008, // 0x00014C10
= 85009, // 0x00014C11
item_list有项目为空 = 85010, // 0x00014C12
= 85011, // 0x00014C13
id = 85012, // 0x00014C14
= 85015, // 0x00014C17
= 85019, // 0x00014C1B
= 85020, // 0x00014C1C
= 85021, // 0x00014C1D
action非法 = 85022, // 0x00014C1E
15 = 85023, // 0x00014C1F
_填写org_code和other_files参数 = 85024, // 0x00014C20
= 85025, // 0x00014C21
5 = 85026, // 0x00014C22
5 = 85027, // 0x00014C23
= 85028, // 0x00014C24
= 85029, // 0x00014C25
使 = 85031, // 0x00014C27
= 85032, // 0x00014C28
= 85033, // 0x00014C29
15 = 85034, // 0x00014C2A
= 85035, // 0x00014C2B
= 85036, // 0x00014C2C
= 85049, // 0x00014C39
_请勿重复提交 = 85050, // 0x00014C3A
= 85053, // 0x00014C3D
mediaid无效 = 85056, // 0x00014C40
= 85066, // 0x00014C4A
= 85068, // 0x00014C4C
= 85069, // 0x00014C4D
= 85070, // 0x00014C4E
_请勿重复添加 = 85071, // 0x00014C4F
= 85072, // 0x00014C50
= 85073, // 0x00014C51
_小程序必须先发布代码才可以发布二维码跳转规则 = 85074, // 0x00014C52
1 = 85075, // 0x00014C53
线_不能进行灰度 = 85079, // 0x00014C57
= 85080, // 0x00014C58
= 85081, // 0x00014C59
= 85082, // 0x00014C5A
= 85085, // 0x00014C5D
= 85086, // 0x00014C5E
使_api_navigateToMiniProgram_请声明跳转_appid_列表后再次提交 = 85087, // 0x00014C5F
= 86000, // 0x00014FF0
= 86001, // 0x00014FF1
_头像_简介_请先设置完后再重新提交 = 86002, // 0x00014FF2
= 86004, // 0x00014FF4
/// <summary>
/// 小程序为“签名错误”。对应公众号: 87009, “errmsg” : “reply is not exists” //该回复不存在
/// </summary>
= 87009, // 0x000153E1
_不能进行版本回退 = 87011, // 0x000153E3
退_可能的原因_1_无上一个线上版用于回退_2_此版本为已回退版本_不能回退_3_此版本为回退功能上线之前的版本_不能回退 = 87012, // 0x000153E4
= 87014, // 0x000153E6
= 88000, // 0x000157C0
= 88001, // 0x000157C1
= 88002, // 0x000157C2
= 88003, // 0x000157C3
_无法精选 = 88004, // 0x000157C4
= 88005, // 0x000157C5
0 = 88007, // 0x000157C7
= 88008, // 0x000157C8
= 88010, // 0x000157CA
_小程序已经绑定了开放平台帐号 = 89000, // 0x00015BA8
_无需重复设置 = 89019, // 0x00015BBB
_请先在第三方平台中设置小程序业务域名后在调用本接口 = 89020, // 0x00015BBC
= 89021, // 0x00015BBD
_最多可以添加100个业务域名 = 89029, // 0x00015BC5
_setwebviewdomain_接口 = 89231, // 0x00015C8F
= 89247, // 0x00015C9F
_请选择正确类型填写 = 89248, // 0x00015CA0
_距上次任务24h后再试 = 89249, // 0x00015CA1
= 89250, // 0x00015CA2
= 89251, // 0x00015CA3
_企业信息一致性校验中 = 89252, // 0x00015CA4
= 89253, // 0x00015CA5
_补全权限集全网发布后生效 = 89254, // 0x00015CA6
_请稍后再试_如多次失败请通过社区反馈 = 89401, // 0x00015D39
_请检查是否已提交审核或已审完 = 89402, // 0x00015D3A
_请等待正常审核流程 = 89403, // 0x00015D3B
_请勿重复提交 = 89404, // 0x00015D3C
_请提升提审质量以获取更多额度 = 89405, // 0x00015D3D
_请勿重复添加 = 92000, // 0x00016760
线_无法继续添加 = 92002, // 0x00016762
= 92003, // 0x00016763
= 92004, // 0x00016764
= 92005, // 0x00016765
= 92006, // 0x00016766
= 92007, // 0x00016767
= 92008, // 0x00016768
= 92009, // 0x00016769
= 93010, // 0x00016B52
= 93011, // 0x00016B53
_24h_未进行身份证校验 = 100001, // 0x000186A1
_24h_未进行人脸识别校验 = 100002, // 0x000186A2
_24h = 100003, // 0x000186A3
_无法操作 = 200011, // 0x00030D4B
_上限_50_个 = 200012, // 0x00030D4C
_无法选用 = 200013, // 0x00030D4D
tid参数错误 = 200014, // 0x00030D4E
kidList参数错误 = 200020, // 0x00030D54
sceneDesc参数错误 = 200021, // 0x00030D55
}
}
}

View File

@@ -0,0 +1,67 @@
/***********************************************************************
* Project: CoreCms.Net *
* Web: https://CoreCms.Net *
* ProjectName: 核心内容管理系统 *
* Author: 大灰灰 *
* Email: JianWeie@163.com *
* CreateTime: 2020-08-13 23:57:23
* Description: 暂无
***********************************************************************/
using System.Threading;
using System.Threading.Tasks;
using CoreCms.Net.Utility.Helper;
using CoreCms.Net.WeChat.Service.HttpClients;
using CoreCms.Net.WeChat.Service.Models;
using MediatR;
using SKIT.FlurlHttpClient.Wechat.Api;
using SKIT.FlurlHttpClient.Wechat.Api.Events;
namespace CoreCms.Net.WeChat.Service.Mediator
{
/// <summary>
/// 表示 TEXT 事件的数据
/// </summary>
public class ImageMessageEventCommand : IRequest<WeChatApiCallBack>
{
public ImageMessageEvent EventObj { get; set; }
}
/// <summary>
/// 处理TEXT 事件的数据-以被动回复文本消息为例
/// </summary>
public class ImageMessageEventCommandHandler : IRequestHandler<ImageMessageEventCommand, WeChatApiCallBack>
{
private readonly WeChat.Service.HttpClients.IWeChatApiHttpClientFactory _weChatApiHttpClientFactory;
public ImageMessageEventCommandHandler(IWeChatApiHttpClientFactory weChatApiHttpClientFactory)
{
_weChatApiHttpClientFactory = weChatApiHttpClientFactory;
}
public async Task<WeChatApiCallBack> Handle(ImageMessageEventCommand request, CancellationToken cancellationToken)
{
var jm = new WeChatApiCallBack() { Status = true };
if (request.EventObj != null)
{
var client = _weChatApiHttpClientFactory.CreateWxOpenClient();
var replyModel = new SKIT.FlurlHttpClient.Wechat.Api.Events.TransferCustomerServiceReply()
{
ToUserName = request.EventObj.FromUserName,
FromUserName = request.EventObj.ToUserName,
CreateTimestamp = CommonHelper.GetTimeStampByTotalSeconds()
};
var replyXml = client.SerializeEventToXml(replyModel);
jm.Data = replyXml;
}
return await Task.FromResult(jm);
}
}
}

View File

@@ -0,0 +1,67 @@
/***********************************************************************
* Project: CoreCms.Net *
* Web: https://CoreCms.Net *
* ProjectName: 核心内容管理系统 *
* Author: 大灰灰 *
* Email: JianWeie@163.com *
* CreateTime: 2020-08-13 23:57:23
* Description: 暂无
***********************************************************************/
using System.Threading;
using System.Threading.Tasks;
using CoreCms.Net.Utility.Helper;
using CoreCms.Net.WeChat.Service.HttpClients;
using CoreCms.Net.WeChat.Service.Models;
using MediatR;
using SKIT.FlurlHttpClient.Wechat.Api;
using SKIT.FlurlHttpClient.Wechat.Api.Events;
namespace CoreCms.Net.WeChat.Service.Mediator
{
/// <summary>
/// 表示 TEXT 事件的数据
/// </summary>
public class TextMessageEventCommand : IRequest<WeChatApiCallBack>
{
public TextMessageEvent EventObj { get; set; }
}
/// <summary>
/// 处理TEXT 事件的数据-以被动回复文本消息为例
/// </summary>
public class TextMessageEventCommandHandler : IRequestHandler<TextMessageEventCommand, WeChatApiCallBack>
{
private readonly WeChat.Service.HttpClients.IWeChatApiHttpClientFactory _weChatApiHttpClientFactory;
public TextMessageEventCommandHandler(IWeChatApiHttpClientFactory weChatApiHttpClientFactory)
{
_weChatApiHttpClientFactory = weChatApiHttpClientFactory;
}
public async Task<WeChatApiCallBack> Handle(TextMessageEventCommand request, CancellationToken cancellationToken)
{
var jm = new WeChatApiCallBack() { Status = true };
if (request.EventObj != null)
{
var client = _weChatApiHttpClientFactory.CreateWxOpenClient();
var replyModel = new SKIT.FlurlHttpClient.Wechat.Api.Events.TransferCustomerServiceReply()
{
ToUserName = request.EventObj.FromUserName,
FromUserName = request.EventObj.ToUserName,
CreateTimestamp = CommonHelper.GetTimeStampByTotalSeconds()
};
var replyXml = client.SerializeEventToXml(replyModel);
jm.Data = replyXml;
}
return await Task.FromResult(jm);
}
}
}

View File

@@ -0,0 +1,67 @@
/***********************************************************************
* Project: CoreCms.Net *
* Web: https://CoreCms.Net *
* ProjectName: 核心内容管理系统 *
* Author: 大灰灰 *
* Email: JianWeie@163.com *
* CreateTime: 2020-08-13 23:57:23
* Description: 暂无
***********************************************************************/
using System.Threading;
using System.Threading.Tasks;
using CoreCms.Net.Utility.Helper;
using CoreCms.Net.WeChat.Service.HttpClients;
using CoreCms.Net.WeChat.Service.Models;
using MediatR;
using SKIT.FlurlHttpClient.Wechat.Api;
using SKIT.FlurlHttpClient.Wechat.Api.Events;
namespace CoreCms.Net.WeChat.Service.Mediator
{
/// <summary>
/// 表示 TEXT 事件的数据
/// </summary>
public class VoiceMessageEventCommand : IRequest<WeChatApiCallBack>
{
public VoiceMessageEvent EventObj { get; set; }
}
/// <summary>
/// 处理TEXT 事件的数据-以被动回复文本消息为例
/// </summary>
public class VoiceMessageEventCommandHandler : IRequestHandler<VoiceMessageEventCommand, WeChatApiCallBack>
{
private readonly WeChat.Service.HttpClients.IWeChatApiHttpClientFactory _weChatApiHttpClientFactory;
public VoiceMessageEventCommandHandler(IWeChatApiHttpClientFactory weChatApiHttpClientFactory)
{
_weChatApiHttpClientFactory = weChatApiHttpClientFactory;
}
public async Task<WeChatApiCallBack> Handle(VoiceMessageEventCommand request, CancellationToken cancellationToken)
{
var jm = new WeChatApiCallBack() { Status = true };
if (request.EventObj != null)
{
var client = _weChatApiHttpClientFactory.CreateWxOpenClient();
var replyModel = new SKIT.FlurlHttpClient.Wechat.Api.Events.TransferCustomerServiceReply()
{
ToUserName = request.EventObj.FromUserName,
FromUserName = request.EventObj.ToUserName,
CreateTimestamp = CommonHelper.GetTimeStampByTotalSeconds()
};
var replyXml = client.SerializeEventToXml(replyModel);
jm.Data = replyXml;
}
return await Task.FromResult(jm);
}
}
}

View File

@@ -0,0 +1,38 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 1:08:20
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreCms.Net.WeChat.Service.Models
{
/// <summary>
/// 用户绑定手机号解密类
/// </summary>
public class DecodedPhoneNumber : DecodeEntityBase
{
/// <summary>
/// 用户绑定的手机号(国外手机号会有区号)
/// </summary>
public string phoneNumber { get; set; }
/// <summary>
/// 没有区号的手机号
/// </summary>
public string purePhoneNumber { get; set; }
/// <summary>
/// 区号Senparc注国别号
/// </summary>
public string countryCode { get; set; }
}
}

View File

@@ -0,0 +1,32 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 11:09:03
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreCms.Net.WeChat.Service.Models
{
[Serializable]
public class DecodedRunData : DecodeEntityBase
{
public List<DecodedRunData_StepModel> stepInfoList { get; set; }
}
[Serializable]
public class DecodedRunData_StepModel
{
public long timestamp { get; set; }
public long step { get; set; }
}
}

View File

@@ -0,0 +1,53 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 21:25:25
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreCms.Net.WeChat.Service.Models
{
/// <summary>接收加密信息统一基类(同时也支持非加密信息)</summary>
public abstract class EncryptPostModel : IEncryptPostModel
{
/// <summary>指定当前服务账号的唯一领域定义(主要为 APM 服务),例如 AppId</summary>
public abstract string DomainId { get; set; }
/// <summary>Signature</summary>
public string Signature { get; set; }
/// <summary>Msg_Signature</summary>
public string Msg_Signature { get; set; }
/// <summary>Timestamp</summary>
public string Timestamp { get; set; }
/// <summary>Nonce</summary>
public string Nonce { get; set; }
/// <summary>Token</summary>
public string Token { get; set; }
/// <summary>EncodingAESKey</summary>
public string EncodingAESKey { get; set; }
/// <summary>设置服务器内部保密信息</summary>
/// <param name="token"></param>
/// <param name="encodingAESKey"></param>
public virtual void SetSecretInfo(string token, string encodingAESKey)
{
this.Token = token;
this.EncodingAESKey = encodingAESKey;
}
}
}

View File

@@ -0,0 +1,44 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 21:25:02
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreCms.Net.WeChat.Service.Models
{
/// <summary>接收加密信息统一接口(同时也支持非加密信息)</summary>
public interface IEncryptPostModel
{
/// <summary>指定当前服务账号的唯一领域定义(主要为 APM 服务),例如 AppId</summary>
string DomainId { get; set; }
/// <summary>Signature</summary>
string Signature { get; set; }
/// <summary>Msg_Signature</summary>
string Msg_Signature { get; set; }
/// <summary>Timestamp</summary>
string Timestamp { get; set; }
/// <summary>Nonce</summary>
string Nonce { get; set; }
/// <summary>Token</summary>
string Token { get; set; }
/// <summary>EncodingAESKey</summary>
string EncodingAESKey { get; set; }
}
}

View File

@@ -0,0 +1,45 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 21:25:51
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreCms.Net.WeChat.Service.Models
{
/// <summary>
/// 微信公众服务器Post过来的加密参数集合不包括PostData
/// <para>如需使用 NeuChar需要在 MessageHandler 中提供 PostModel 并设置 AppId</para>
/// </summary>
public class PostModel : EncryptPostModel
{
public override string DomainId
{
get => this.AppId;
set => this.AppId = value;
}
public string AppId { get; set; }
/// <summary>设置服务器内部保密信息</summary>
/// <param name="token"></param>
/// <param name="encodingAESKey"></param>
/// <param name="appId"></param>
public void SetSecretInfo(string token, string encodingAESKey, string appId)
{
this.Token = token;
this.EncodingAESKey = encodingAESKey;
this.AppId = appId;
}
}
}

View File

@@ -0,0 +1,36 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/14 16:27:23
* Description: 暂无
***********************************************************************/
using Newtonsoft.Json.Linq;
namespace CoreCms.Net.WeChat.Service.Models
{
/// <summary>
/// 处理器-微信模板消息【小程序,公众号都走这里】
/// </summary>
public class SendWxTemplateMessage
{
/// <summary>
/// 用户序列
/// </summary>
public int userId { get; set; }
/// <summary>
/// 类型
/// </summary>
public string code { get; set; }
/// <summary>
/// 传递数据
/// </summary>
public JObject parameters { get; set; }
}
}

View File

@@ -0,0 +1,35 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 1:09:19
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CoreCms.Net.WeChat.Service.Utilities;
namespace CoreCms.Net.WeChat.Service.Models
{
/// <summary>
/// 水印
/// </summary>
[Serializable]
public class Watermark
{
public string appid { get; set; }
public long timestamp { get; set; }
public DateTimeOffset DateTimeStamp
{
get { return DateTimeHelper.GetDateTimeFromXml(timestamp); }
}
}
}

View File

@@ -0,0 +1,38 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/1/31 21:45:10
* Description: 暂无
***********************************************************************/
namespace CoreCms.Net.WeChat.Service.Models
{
/// <summary>
/// 微信接口回调Json实体
/// </summary>
public class WeChatApiCallBack
{
/// <summary>
/// 提交数据
/// </summary>
public object OtherData { get; set; } = null;
/// <summary>
/// 状态码
/// </summary>
public bool Status { get; set; } = true;
/// <summary>
/// 信息说明。
/// </summary>
public string Msg { get; set; } = "响应成功";
/// <summary>
/// 返回数据
/// </summary>
public string Data { get; set; } = "success";
}
}

View File

@@ -0,0 +1,71 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 1:19:20
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreCms.Net.WeChat.Service.Models
{
/// <summary>
/// 微信小程序用户信息结构
/// </summary>
public class WeChatUserInfo
{
public string openId { get; set; }
public string nickName { get; set; }
public int gender { get; set; }
public string city { get; set; }
public string province { get; set; }
public string country { get; set; }
public string avatarUrl { get; set; }
public string unionId { get; set; }
public Watermark watermark { get; set; }
}
[Serializable]
public class DecodeEntityBase
{
public Watermark watermark { get; set; }
}
/// <summary>
/// 解码后的用户信息
/// </summary>
[Serializable]
public class DecodedUserInfo : DecodeEntityBase
{
public string openId { get; set; }
public string nickName { get; set; }
public int gender { get; set; }
public string city { get; set; }
public string province { get; set; }
public string country { get; set; }
public string avatarUrl { get; set; }
public string unionId { get; set; }
}
}

View File

@@ -0,0 +1,48 @@
using System;
using Microsoft.Extensions.Options;
namespace CoreCms.Net.WeChat.Service.Options
{
public partial class WeChatOptions : IOptions<WeChatOptions>
{
WeChatOptions IOptions<WeChatOptions>.Value => this;
/// <summary>
/// 微信公众号AppId
/// </summary>
public string WeiXinAppId { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string WeiXinAppSecret { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string WeiXinEncodingAESKey { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string WeiXinToken { get; set; } = string.Empty;
/// <summary>
/// 微信小程序
/// </summary>
public string WxOpenAppId { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string WxOpenAppSecret { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string WxOpenToken { get; set; } = string.Empty;
/// <summary>
///
/// </summary>
public string WxOpenEncodingAESKey { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using SKIT.FlurlHttpClient.Wechat.Api;
namespace CoreCms.Net.WeChat.Service.HttpClients
{
public interface IWeChatApiHttpClientFactory
{
/// <summary>
/// 微信公众号请求
/// </summary>
/// <returns></returns>
WechatApiClient CreateWeXinClient();
/// <summary>
/// 微信小程序请求
/// </summary>
/// <returns></returns>
WechatApiClient CreateWxOpenClient();
}
}

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Flurl;
using Flurl.Http;
using Flurl.Http.Configuration;
using Microsoft.Extensions.Options;
using SKIT.FlurlHttpClient;
using SKIT.FlurlHttpClient.Wechat.Api;
namespace CoreCms.Net.WeChat.Service.HttpClients
{
public partial class WeChatApiHttpClientFactory : IWeChatApiHttpClientFactory
{
private readonly System.Net.Http.IHttpClientFactory _httpClientFactory;
private readonly Options.WeChatOptions _weChatOptions;
public WeChatApiHttpClientFactory(
System.Net.Http.IHttpClientFactory httpClientFactory,
IOptions<Options.WeChatOptions> weChatOptions)
{
_httpClientFactory = httpClientFactory;
_weChatOptions = weChatOptions.Value;
FlurlHttp.GlobalSettings.FlurlClientFactory = new DelegatingFlurlClientFactory(_httpClientFactory);
}
/// <summary>
/// 微信公众号请求
/// </summary>
/// <returns></returns>
public WechatApiClient CreateWeXinClient()
{
if (string.IsNullOrEmpty(_weChatOptions.WeiXinAppId) || string.IsNullOrEmpty(_weChatOptions.WeiXinAppSecret))
throw new Exception("未在配置项中找到微信公众号配置讯息。");
var wechatApiClient = new WechatApiClient(new WechatApiClientOptions()
{
AppId = _weChatOptions.WeiXinAppId,
AppSecret = _weChatOptions.WeiXinAppSecret,
});
wechatApiClient.Configure(settings =>
{
settings.JsonSerializer = new FlurlNewtonsoftJsonSerializer();
});
return wechatApiClient;
}
/// <summary>
/// 微信小程序请求
/// </summary>
/// <returns></returns>
public WechatApiClient CreateWxOpenClient()
{
if (string.IsNullOrEmpty(_weChatOptions.WxOpenAppId) || string.IsNullOrEmpty(_weChatOptions.WxOpenAppSecret))
throw new Exception("未在配置项中找到微信小程序配置讯息。");
var WechatApiClient = new WechatApiClient(new WechatApiClientOptions()
{
AppId = _weChatOptions.WxOpenAppId,
AppSecret = _weChatOptions.WxOpenAppSecret
});
WechatApiClient.Configure(settings =>
{
settings.JsonSerializer = new FlurlNewtonsoftJsonSerializer();
});
return WechatApiClient;
}
}
public partial class WeChatApiHttpClientFactory
{
internal class DelegatingFlurlClientFactory : IFlurlClientFactory
{
private readonly System.Net.Http.IHttpClientFactory _httpClientFactory;
public DelegatingFlurlClientFactory(System.Net.Http.IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
}
public IFlurlClient Get(Url url)
{
return new FlurlClient(_httpClientFactory.CreateClient(url.ToUri().Host));
}
public void Dispose()
{
// Do Nothing
}
}
}
}

View File

@@ -0,0 +1,68 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 21:44:44
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using CoreCms.Net.WeChat.Service.Models;
namespace CoreCms.Net.WeChat.Service.Utilities
{
/// <summary>签名验证类</summary>
public class CheckSignature
{
/// <summary>在网站没有提供Token或传入为null的情况下的默认Token建议在网站中进行配置。</summary>
public const string Token = "weixin";
/// <summary>检查签名是否正确</summary>
/// <param name="signature"></param>
/// <param name="postModel">需要提供Timestamp、Nonce、Token</param>
/// <returns></returns>
public static bool Check(string signature, PostModel postModel) => CheckSignature.Check(signature, postModel.Timestamp, postModel.Nonce, postModel.Token);
/// <summary>检查签名是否正确</summary>
/// <param name="signature"></param>
/// <param name="timestamp"></param>
/// <param name="nonce"></param>
/// <param name="token"></param>
/// <returns></returns>
public static bool Check(string signature, string timestamp, string nonce, string token = null) => signature == CheckSignature.GetSignature(timestamp, nonce, token);
/// <summary>返回正确的签名</summary>
/// <param name="postModel">需要提供Timestamp、Nonce、Token</param>
/// <returns></returns>
public static string GetSignature(PostModel postModel) => CheckSignature.GetSignature(postModel.Timestamp, postModel.Nonce, postModel.Token);
/// <summary>返回正确的签名</summary>
/// <param name="timestamp"></param>
/// <param name="nonce"></param>
/// <param name="token"></param>
/// <returns></returns>
public static string GetSignature(string timestamp, string nonce, string token = null)
{
token = token ?? "weixin";
string s = string.Join("", ((IEnumerable<string>)new string[3]
{
token,
timestamp,
nonce
}).OrderBy<string, string>((Func<string, string>)(z => z)).ToArray<string>());
byte[] hash = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(s));
StringBuilder stringBuilder = new StringBuilder();
foreach (byte num in hash)
stringBuilder.AppendFormat("{0:x2}", (object)num);
return stringBuilder.ToString();
}
}
}

View File

@@ -0,0 +1,232 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Net;
namespace CoreCms.Net.WeChat.Service.Utilities
{
class Cryptography
{
public static UInt32 HostToNetworkOrder(UInt32 inval)
{
UInt32 outval = 0;
for (int i = 0; i < 4; i++)
outval = (outval << 8) + ((inval >> (i * 8)) & 255);
return outval;
}
public static Int32 HostToNetworkOrder(Int32 inval)
{
Int32 outval = 0;
for (int i = 0; i < 4; i++)
outval = (outval << 8) + ((inval >> (i * 8)) & 255);
return outval;
}
/// <summary>
/// 解密方法
/// </summary>
/// <param name="Input">密文</param>
/// <param name="EncodingAESKey"></param>
/// <returns></returns>
///
public static string AES_decrypt(String Input, string EncodingAESKey, ref string appid)
{
byte[] Key;
Key = Convert.FromBase64String(EncodingAESKey + "=");
byte[] Iv = new byte[16];
Array.Copy(Key, Iv, 16);
byte[] btmpMsg = AES_decrypt(Input, Iv, Key);
int len = BitConverter.ToInt32(btmpMsg, 16);
len = IPAddress.NetworkToHostOrder(len);
byte[] bMsg = new byte[len];
byte[] bAppid = new byte[btmpMsg.Length - 20 - len];
Array.Copy(btmpMsg, 20, bMsg, 0, len);
Array.Copy(btmpMsg, 20+len , bAppid, 0, btmpMsg.Length - 20 - len);
string oriMsg = Encoding.UTF8.GetString(bMsg);
appid = Encoding.UTF8.GetString(bAppid);
return oriMsg;
}
public static String AES_encrypt(String Input, string EncodingAESKey, string appid)
{
byte[] Key;
Key = Convert.FromBase64String(EncodingAESKey + "=");
byte[] Iv = new byte[16];
Array.Copy(Key, Iv, 16);
string Randcode = CreateRandCode(16);
byte[] bRand = Encoding.UTF8.GetBytes(Randcode);
byte[] bAppid = Encoding.UTF8.GetBytes(appid);
byte[] btmpMsg = Encoding.UTF8.GetBytes(Input);
byte[] bMsgLen = BitConverter.GetBytes(HostToNetworkOrder(btmpMsg.Length));
byte[] bMsg = new byte[bRand.Length + bMsgLen.Length + bAppid.Length + btmpMsg.Length];
Array.Copy(bRand, bMsg, bRand.Length);
Array.Copy(bMsgLen, 0, bMsg, bRand.Length, bMsgLen.Length);
Array.Copy(btmpMsg, 0, bMsg, bRand.Length + bMsgLen.Length, btmpMsg.Length);
Array.Copy(bAppid, 0, bMsg, bRand.Length + bMsgLen.Length + btmpMsg.Length, bAppid.Length);
return AES_encrypt(bMsg, Iv, Key);
}
private static string CreateRandCode(int codeLen)
{
string codeSerial = "2,3,4,5,6,7,a,c,d,e,f,h,i,j,k,m,n,p,r,s,t,A,C,D,E,F,G,H,J,K,M,N,P,Q,R,S,U,V,W,X,Y,Z";
if (codeLen == 0)
{
codeLen = 16;
}
string[] arr = codeSerial.Split(',');
string code = "";
int randValue = -1;
Random rand = new Random(unchecked((int)DateTime.Now.Ticks));
for (int i = 0; i < codeLen; i++)
{
randValue = rand.Next(0, arr.Length - 1);
code += arr[randValue];
}
return code;
}
private static String AES_encrypt(String Input, byte[] Iv, byte[] Key)
{
var aes = new RijndaelManaged();
//秘钥的大小,以位为单位
aes.KeySize = 256;
//支持的块大小
aes.BlockSize = 128;
//填充模式
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = Key;
aes.IV = Iv;
var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] xBuff = null;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
{
byte[] xXml = Encoding.UTF8.GetBytes(Input);
cs.Write(xXml, 0, xXml.Length);
}
xBuff = ms.ToArray();
}
String Output = Convert.ToBase64String(xBuff);
return Output;
}
private static String AES_encrypt(byte[] Input, byte[] Iv, byte[] Key)
{
var aes = new RijndaelManaged();
//秘钥的大小,以位为单位
aes.KeySize = 256;
//支持的块大小
aes.BlockSize = 128;
//填充模式
//aes.Padding = PaddingMode.PKCS7;
aes.Padding = PaddingMode.None;
aes.Mode = CipherMode.CBC;
aes.Key = Key;
aes.IV = Iv;
var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] xBuff = null;
#region PKCS7补位
byte[] msg = new byte[Input.Length + 32 - Input.Length % 32];
Array.Copy(Input, msg, Input.Length);
byte[] pad = KCS7Encoder(Input.Length);
Array.Copy(pad, 0, msg, Input.Length, pad.Length);
#endregion
#region
//ICryptoTransform transform = aes.CreateEncryptor();
//byte[] xBuff = transform.TransformFinalBlock(msg, 0, msg.Length);
#endregion
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
{
cs.Write(msg, 0, msg.Length);
}
xBuff = ms.ToArray();
}
String Output = Convert.ToBase64String(xBuff);
return Output;
}
private static byte[] KCS7Encoder(int text_length)
{
int block_size = 32;
// 计算需要填充的位数
int amount_to_pad = block_size - (text_length % block_size);
if (amount_to_pad == 0)
{
amount_to_pad = block_size;
}
// 获得补位所用的字符
char pad_chr = chr(amount_to_pad);
string tmp = "";
for (int index = 0; index < amount_to_pad; index++)
{
tmp += pad_chr;
}
return Encoding.UTF8.GetBytes(tmp);
}
/**
* 将数字转化成ASCII码对应的字符用于对明文进行补码
*
* @param a 需要转化的数字
* @return 转化得到的字符
*/
static char chr(int a)
{
byte target = (byte)(a & 0xFF);
return (char)target;
}
private static byte[] AES_decrypt(String Input, byte[] Iv, byte[] Key)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.None;
aes.Key = Key;
aes.IV = Iv;
var decrypt = aes.CreateDecryptor(aes.Key, aes.IV);
byte[] xBuff = null;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
{
byte[] xXml = Convert.FromBase64String(Input);
byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
Array.Copy(xXml, msg, xXml.Length);
cs.Write(xXml, 0, xXml.Length);
}
xBuff = decode2(ms.ToArray());
}
return xBuff;
}
private static byte[] decode2(byte[] decrypted)
{
int pad = (int)decrypted[decrypted.Length - 1];
if (pad < 1 || pad > 32)
{
pad = 0;
}
byte[] res = new byte[decrypted.Length - pad];
Array.Copy(decrypted, 0, res, 0, decrypted.Length - pad);
return res;
}
}
}

View File

@@ -0,0 +1,62 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 11:06:40
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreCms.Net.WeChat.Service.Utilities
{
/// <summary>微信日期处理帮助类</summary>
public class DateTimeHelper
{
/// <summary>Unix起始时间</summary>
public static readonly DateTimeOffset BaseTime = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
/// <summary>转换微信DateTime时间到C#时间</summary>
/// <param name="dateTimeFromXml">微信DateTime</param>
/// <returns></returns>
public static DateTime GetDateTimeFromXml(long dateTimeFromXml) => DateTimeHelper.GetDateTimeOffsetFromXml(dateTimeFromXml).LocalDateTime;
/// <summary>转换微信DateTime时间到C#时间</summary>
/// <param name="dateTimeFromXml">微信DateTime</param>
/// <returns></returns>
public static DateTime GetDateTimeFromXml(string dateTimeFromXml) => DateTimeHelper.GetDateTimeFromXml(long.Parse(dateTimeFromXml));
/// <summary>转换微信DateTimeOffset时间到C#时间</summary>
/// <param name="dateTimeFromXml">微信DateTime</param>
/// <returns></returns>
public static DateTimeOffset GetDateTimeOffsetFromXml(long dateTimeFromXml) => DateTimeHelper.BaseTime.AddSeconds((double)dateTimeFromXml).ToLocalTime();
/// <summary>转换微信DateTimeOffset时间到C#时间</summary>
/// <param name="dateTimeFromXml">微信DateTime</param>
/// <returns></returns>
public static DateTimeOffset GetDateTimeOffsetFromXml(string dateTimeFromXml) => (DateTimeOffset)DateTimeHelper.GetDateTimeFromXml(long.Parse(dateTimeFromXml));
/// <summary>获取微信DateTimeUNIX时间戳</summary>
/// <param name="dateTime">时间</param>
/// <returns></returns>
[Obsolete("请使用 GetUnixDateTime(dateTime) 方法")]
public static long GetWeixinDateTime(DateTime dateTime) => DateTimeHelper.GetUnixDateTime(dateTime);
/// <summary>获取Unix时间戳</summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static long GetUnixDateTime(DateTimeOffset dateTime) => (long)(dateTime - DateTimeHelper.BaseTime).TotalSeconds;
/// <summary>获取Unix时间戳</summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static long GetUnixDateTime(DateTime dateTime) => (long)((DateTimeOffset)dateTime.ToUniversalTime() - DateTimeHelper.BaseTime).TotalSeconds;
}
}

View File

@@ -0,0 +1,44 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 23:53:54
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
namespace CoreCms.Net.WeChat.Service.Utilities
{
public static class DocumentExtensions
{
public static XmlDocument ToXmlDocument(this XDocument xDocument)
{
var xmlDocument = new XmlDocument();
using (var xmlReader = xDocument.CreateReader())
{
xmlDocument.Load(xmlReader);
}
return xmlDocument;
}
public static XDocument ToXDocument(this XmlDocument xmlDocument)
{
using (var nodeReader = new XmlNodeReader(xmlDocument))
{
nodeReader.MoveToContent();
return XDocument.Load(nodeReader);
}
}
}
}

View File

@@ -0,0 +1,329 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 1:06:57
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using CoreCms.Net.WeChat.Service.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace CoreCms.Net.WeChat.Service.Utilities
{
/// <summary>
/// 签名及加密帮助类
/// </summary>
public static class EncryptHelper
{
///// <summary>
///// SHA1加密
///// </summary>
///// <param name="str"></param>
///// <returns></returns>
//public static string EncryptToSHA1(string str)
//{
// SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
// byte[] str1 = Encoding.UTF8.GetBytes(str);
// byte[] str2 = sha1.ComputeHash(str1);
// sha1.Clear();
// (sha1 as IDisposable).Dispose();
// return Convert.ToBase64String(str2);
//}
#region
/// <summary>
/// 获得签名
/// </summary>
/// <param name="rawData"></param>
/// <param name="sessionKey"></param>
/// <returns></returns>
public static string GetSignature(string rawData, string sessionKey)
{
var signature = GetSha1(rawData + sessionKey);
//Senparc.Weixin.Helpers.EncryptHelper.SHA1_Encrypt(rawData + sessionKey);
return signature;
}
/// <summary>采用SHA-1算法加密字符串小写</summary>
/// <param name="encypStr">需要加密的字符串</param>
/// <returns></returns>
public static string GetSha1(string encypStr)
{
byte[] hash = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(encypStr));
StringBuilder stringBuilder = new StringBuilder();
foreach (byte num in hash)
stringBuilder.AppendFormat("{0:x2}", (object)num);
return stringBuilder.ToString();
}
/// <summary>
/// 比较签名是否正确
/// </summary>
/// <param name="sessionKey"></param>
/// <param name="rawData"></param>
/// <param name="compareSignature"></param>
/// <exception cref="WxOpenException">当SessionId或SessionKey无效时抛出异常</exception>
/// <returns></returns>
public static bool CheckSignature(string sessionKey, string rawData, string compareSignature)
{
var signature = GetSignature(rawData, sessionKey);
return signature == compareSignature;
}
#endregion
#region
#region
private static byte[] AES_Decrypt(String Input, byte[] Iv, byte[] Key)
{
#if NET45
RijndaelManaged aes = new RijndaelManaged();
#else
SymmetricAlgorithm aes = Aes.Create();
#endif
aes.KeySize = 128;//原始256
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = Key;
aes.IV = Iv;
var decrypt = aes.CreateDecryptor(aes.Key, aes.IV);
byte[] xBuff = null;
//using (ICryptoTransform decrypt = aes.CreateDecryptor(aes.Key, aes.IV) /*aes.CreateDecryptor()*/)
//{
// var src = Convert.FromBase64String(Input);
// byte[] dest = decrypt.TransformFinalBlock(src, 0, src.Length);
// return dest;
// //return Encoding.UTF8.GetString(dest);
//}
try
{
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
{
//cs.Read(decryptBytes, 0, decryptBytes.Length);
//cs.Close();
//ms.Close();
//cs.FlushFinalBlock();//用于解决第二次获取小程序Session解密出错的情况
byte[] xXml = Convert.FromBase64String(Input);
byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
Array.Copy(xXml, msg, xXml.Length);
cs.Write(xXml, 0, xXml.Length);
}
//cs.Dispose();
xBuff = decode2(ms.ToArray());
}
}
catch (System.Security.Cryptography.CryptographicException)
{
//Padding is invalid and cannot be removed.
Console.WriteLine("===== CryptographicException =====");
using (var ms = new MemoryStream())
{
//cs 不自动释放用于避免“Padding is invalid and cannot be removed”的错误 —— 2019.07.27 Jeffrey
var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write);
{
//cs.Read(decryptBytes, 0, decryptBytes.Length);
//cs.Close();
//ms.Close();
//cs.FlushFinalBlock();//用于解决第二次获取小程序Session解密出错的情况
byte[] xXml = Convert.FromBase64String(Input);
byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
Array.Copy(xXml, msg, xXml.Length);
cs.Write(xXml, 0, xXml.Length);
}
//cs.Dispose();
xBuff = decode2(ms.ToArray());
}
}
return xBuff;
}
private static byte[] decode2(byte[] decrypted)
{
int pad = (int)decrypted[decrypted.Length - 1];
if (pad < 1 || pad > 32)
{
pad = 0;
}
byte[] res = new byte[decrypted.Length - pad];
Array.Copy(decrypted, 0, res, 0, decrypted.Length - pad);
return res;
}
#endregion
/// <summary>
/// 解密所有消息的基础方法
/// </summary>
/// <param name="sessionKey">储存在 SessionBag 中的当前用户 会话 SessionKey</param>
/// <param name="encryptedData">接口返回数据中的 encryptedData 参数</param>
/// <param name="iv">接口返回数据中的 iv 参数,对称解密算法初始向量</param>
/// <returns></returns>
public static string DecodeEncryptedData(string sessionKey, string encryptedData, string iv)
{
//var aesCipher = Convert.FromBase64String(encryptedData);
var aesKey = Convert.FromBase64String(sessionKey);
var aesIV = Convert.FromBase64String(iv);
var result = AES_Decrypt(encryptedData, aesIV, aesKey);
var resultStr = Encoding.UTF8.GetString(result);
return resultStr;
}
/// <summary>
/// 解密消息通过SessionId获取
/// </summary>
/// <param name="sessionKey"></param>
/// <param name="encryptedData"></param>
/// <param name="iv"></param>
/// <exception cref="WxOpenException">当SessionId或SessionKey无效时抛出异常</exception>
/// <returns></returns>
public static string DecodeEncryptedDataBySessionId(string sessionKey, string encryptedData, string iv)
{
var resultStr = DecodeEncryptedData(sessionKey, encryptedData, iv);
return resultStr;
}
/// <summary>
/// 检查解密消息水印
/// </summary>
/// <param name="entity"></param>
/// <param name="appId"></param>
/// <returns>entity为null时也会返回false</returns>
public static bool CheckWatermark(this DecodeEntityBase entity, string appId)
{
if (entity == null)
{
return false;
}
return entity.watermark.appid == appId;
}
#region
/// <summary>
/// 解密到实例信息
/// </summary>
/// <typeparam name="T">DecodeEntityBase</typeparam>
/// <param name="sessionKey"></param>
/// <param name="encryptedData"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static T DecodeEncryptedDataToEntity<T>(string sessionKey, string encryptedData, string iv)
{
var jsonStr = DecodeEncryptedDataBySessionId(sessionKey, encryptedData, iv);
//Console.WriteLine("===== jsonStr =====");
//Console.WriteLine(jsonStr);
//Console.WriteLine();
var entity = JsonConvert.DeserializeObject<T>(jsonStr);
return entity;
}
/// <summary>
/// 解密到实例信息
/// </summary>
/// <typeparam name="T">DecodeEntityBase</typeparam>
/// <param name="sessionKey"></param>
/// <param name="encryptedData"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static T DecodeEncryptedDataToEntityEasy<T>(string sessionKey, string encryptedData, string iv)
{
var jsonStr = DecodeEncryptedData(sessionKey, encryptedData, iv);
var entity = JsonConvert.DeserializeObject<T>(jsonStr);
return entity;
}
/// <summary>
/// 解密UserInfo消息通过SessionId获取
/// </summary>
/// <param name="sessionKey"></param>
/// <param name="encryptedData"></param>
/// <param name="iv"></param>
/// <exception cref="WxOpenException">当SessionId或SessionKey无效时抛出异常</exception>
/// <returns></returns>
public static DecodedUserInfo DecodeUserInfoBySessionId(string sessionKey, string encryptedData, string iv)
{
return DecodeEncryptedDataToEntity<DecodedUserInfo>(sessionKey, encryptedData, iv);
}
/// <summary>
/// 解密手机号
/// </summary>
/// <param name="sessionKey"></param>
/// <param name="encryptedData"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static DecodedPhoneNumber DecryptPhoneNumber(string sessionKey, string encryptedData, string iv)
{
return DecodeEncryptedDataToEntity<DecodedPhoneNumber>(sessionKey, encryptedData, iv);
}
/// <summary>
/// 解密手机号(根据sessionKey解密)
/// </summary>
/// <param name="sessionKey"></param>
/// <param name="encryptedData"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static DecodedPhoneNumber DecryptPhoneNumberBySessionKey(string sessionKey, string encryptedData, string iv)
{
//var resultStr = DecodeEncryptedData(sessionKey, encryptedData, iv);
//var entity = SerializerHelper.GetObject<DecodedPhoneNumber>(resultStr);
//return entity;
return DecodeEncryptedDataToEntityEasy<DecodedPhoneNumber>(sessionKey, encryptedData, iv);
}
/// <summary>
/// 解密微信小程序运动步数
/// 2019-04-02
/// </summary>
/// <param name="sessionId"></param>
/// <param name="encryptedData"></param>
/// <param name="iv"></param>
/// <returns></returns>
public static DecodedRunData DecryptRunData(string sessionId, string encryptedData, string iv)
{
return DecodeEncryptedDataToEntity<DecodedRunData>(sessionId, encryptedData, iv);
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,76 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 23:24:45
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
namespace CoreCms.Net.WeChat.Service.Utilities
{
/// <summary>HTTP 请求工具类</summary>
public static class RequestUtility
{
/// <summary>【异步方法】从 Request.Body 中读取流,并复制到一个独立的 MemoryStream 对象中</summary>
/// <param name="request"></param>
/// <param name="allowSynchronousIO"></param>
/// <returns></returns>
public static async Task<Stream> GetRequestMemoryStreamAsync(
this HttpRequest request,
bool? allowSynchronousIO = true)
{
IHttpBodyControlFeature bodyControlFeature = request.HttpContext.Features.Get<IHttpBodyControlFeature>();
if (bodyControlFeature != null && allowSynchronousIO.HasValue)
bodyControlFeature.AllowSynchronousIO = allowSynchronousIO.Value;
return (Stream)new MemoryStream(Encoding.UTF8.GetBytes(await new StreamReader(request.Body).ReadToEndAsync()));
}
/// <summary>从 Request.Body 中读取流,并复制到一个独立的 MemoryStream 对象中</summary>
/// <param name="request"></param>
/// <param name="allowSynchronousIO"></param>
/// <returns></returns>
public static Stream GetRequestStream(
this HttpRequest request,
bool? allowSynchronousIO = true)
{
IHttpBodyControlFeature bodyControlFeature = request.HttpContext.Features.Get<IHttpBodyControlFeature>();
if (bodyControlFeature != null && allowSynchronousIO.HasValue)
bodyControlFeature.AllowSynchronousIO = allowSynchronousIO.Value;
return (Stream)new MemoryStream(Encoding.UTF8.GetBytes(new StreamReader(request.Body).ReadToEnd()));
}
/// <summary>从 Request.Body 中读取流,并复制到一个独立的 MemoryStream 对象中</summary>
/// <param name="request"></param>
/// <param name="allowSynchronousIO"></param>
/// <returns></returns>
public static MemoryStream GetRequestMemoryStream(
this HttpRequest request,
bool? allowSynchronousIO = true)
{
IHttpBodyControlFeature bodyControlFeature = request.HttpContext.Features.Get<IHttpBodyControlFeature>();
if (bodyControlFeature != null && allowSynchronousIO.HasValue)
bodyControlFeature.AllowSynchronousIO = allowSynchronousIO.Value;
return new MemoryStream(Encoding.UTF8.GetBytes(new StreamReader(request.Body).ReadToEnd()));
}
}
}

View File

@@ -0,0 +1,221 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections;
//using System.Web;
using System.Security.Cryptography;
//-40001 签名验证错误
//-40002 : xml解析失败
//-40003 : sha加密生成签名失败
//-40004 : AESKey 非法
//-40005 : appid 校验错误
//-40006 : AES 加密失败
//-40007 AES 解密失败
//-40008 解密后得到的buffer非法
//-40009 : base64加密异常
//-40010 : base64解密异常
namespace CoreCms.Net.WeChat.Service.Utilities
{
public class WXBizMsgCrypt
{
string m_sToken;
string m_sEncodingAESKey;
string m_sAppID;
enum WXBizMsgCryptErrorCode
{
WXBizMsgCrypt_OK = 0,
WXBizMsgCrypt_ValidateSignature_Error = -40001,
WXBizMsgCrypt_ParseXml_Error = -40002,
WXBizMsgCrypt_ComputeSignature_Error = -40003,
WXBizMsgCrypt_IllegalAesKey = -40004,
WXBizMsgCrypt_ValidateAppid_Error = -40005,
WXBizMsgCrypt_EncryptAES_Error = -40006,
WXBizMsgCrypt_DecryptAES_Error = -40007,
WXBizMsgCrypt_IllegalBuffer = -40008,
WXBizMsgCrypt_EncodeBase64_Error = -40009,
WXBizMsgCrypt_DecodeBase64_Error = -40010
};
//构造函数
// @param sToken: 公众平台上开发者设置的Token
// @param sEncodingAESKey: 公众平台上开发者设置的EncodingAESKey
// @param sAppID: 公众帐号的appid
public WXBizMsgCrypt(string sToken, string sEncodingAESKey, string sAppID)
{
m_sToken = sToken;
m_sAppID = sAppID;
m_sEncodingAESKey = sEncodingAESKey;
}
// 检验消息的真实性,并且获取解密后的明文
// @param sMsgSignature: 签名串对应URL参数的msg_signature
// @param sTimeStamp: 时间戳对应URL参数的timestamp
// @param sNonce: 随机串对应URL参数的nonce
// @param sPostData: 密文对应POST请求的数据
// @param sMsg: 解密后的原文当return返回0时有效
// @return: 成功0失败返回对应的错误码
public int DecryptMsg(string sMsgSignature, string sTimeStamp, string sNonce, string sPostData, ref string sMsg)
{
if (m_sEncodingAESKey.Length != 43)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
}
XmlDocument doc = new XmlDocument();
XmlNode root;
string sEncryptMsg;
try
{
doc.LoadXml(sPostData);
root = doc.FirstChild;
sEncryptMsg = root["Encrypt"].InnerText;
}
catch (Exception)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ParseXml_Error;
}
//verify signature
int ret = 0;
ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEncryptMsg, sMsgSignature);
if (ret != 0)
return ret;
//decrypt
string cpid = "";
try
{
sMsg = Cryptography.AES_decrypt(sEncryptMsg, m_sEncodingAESKey, ref cpid);
}
catch (FormatException)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecodeBase64_Error;
}
catch (Exception)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecryptAES_Error;
}
if (cpid != m_sAppID)
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateAppid_Error;
return 0;
}
//将企业号回复用户的消息加密打包
// @param sReplyMsg: 企业号待回复用户的消息xml格式的字符串
// @param sTimeStamp: 时间戳可以自己生成也可以用URL参数的timestamp
// @param sNonce: 随机串可以自己生成也可以用URL参数的nonce
// @param sEncryptMsg: 加密后的可以直接回复用户的密文包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串,
// 当return返回0时有效
// return成功0失败返回对应的错误码
public int EncryptMsg(string sReplyMsg, string sTimeStamp, string sNonce, ref string sEncryptMsg)
{
if (m_sEncodingAESKey.Length != 43)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
}
string raw = "";
try
{
raw = Cryptography.AES_encrypt(sReplyMsg, m_sEncodingAESKey, m_sAppID);
}
catch (Exception)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_EncryptAES_Error;
}
string MsgSigature = "";
int ret = 0;
ret = GenarateSinature(m_sToken, sTimeStamp, sNonce, raw, ref MsgSigature);
if (0 != ret)
return ret;
sEncryptMsg = "";
string EncryptLabelHead = "<Encrypt><![CDATA[";
string EncryptLabelTail = "]]></Encrypt>";
string MsgSigLabelHead = "<MsgSignature><![CDATA[";
string MsgSigLabelTail = "]]></MsgSignature>";
string TimeStampLabelHead = "<TimeStamp><![CDATA[";
string TimeStampLabelTail = "]]></TimeStamp>";
string NonceLabelHead = "<Nonce><![CDATA[";
string NonceLabelTail = "]]></Nonce>";
sEncryptMsg = sEncryptMsg + "<xml>" + EncryptLabelHead + raw + EncryptLabelTail;
sEncryptMsg = sEncryptMsg + MsgSigLabelHead + MsgSigature + MsgSigLabelTail;
sEncryptMsg = sEncryptMsg + TimeStampLabelHead + sTimeStamp + TimeStampLabelTail;
sEncryptMsg = sEncryptMsg + NonceLabelHead + sNonce + NonceLabelTail;
sEncryptMsg += "</xml>";
return 0;
}
public class DictionarySort : System.Collections.IComparer
{
public int Compare(object oLeft, object oRight)
{
string sLeft = oLeft as string;
string sRight = oRight as string;
int iLeftLength = sLeft.Length;
int iRightLength = sRight.Length;
int index = 0;
while (index < iLeftLength && index < iRightLength)
{
if (sLeft[index] < sRight[index])
return -1;
else if (sLeft[index] > sRight[index])
return 1;
else
index++;
}
return iLeftLength - iRightLength;
}
}
//Verify Signature
private static int VerifySignature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, string sSigture)
{
string hash = "";
int ret = 0;
ret = GenarateSinature(sToken, sTimeStamp, sNonce, sMsgEncrypt, ref hash);
if (ret != 0)
return ret;
//System.Console.WriteLine(hash);
if (hash == sSigture)
return 0;
else
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateSignature_Error;
}
}
public static int GenarateSinature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, ref string sMsgSignature)
{
ArrayList AL = new ArrayList();
AL.Add(sToken);
AL.Add(sTimeStamp);
AL.Add(sNonce);
AL.Add(sMsgEncrypt);
AL.Sort(new DictionarySort());
string raw = "";
for (int i = 0; i < AL.Count; ++i)
{
raw += AL[i];
}
SHA1 sha;
ASCIIEncoding enc;
string hash = "";
try
{
sha = new SHA1CryptoServiceProvider();
enc = new ASCIIEncoding();
byte[] dataToHash = enc.GetBytes(raw);
byte[] dataHashed = sha.ComputeHash(dataToHash);
hash = BitConverter.ToString(dataHashed).Replace("-", "");
hash = hash.ToLower();
}
catch (Exception)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ComputeSignature_Error;
}
sMsgSignature = hash;
return 0;
}
}
}

View File

@@ -0,0 +1,33 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 12:25:49
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreCms.Net.WeChat.Service.Utilities
{
/// <summary>
/// 微信公众号帮助类
/// </summary>
public static class WxOfficialHelper
{
public static string geturl(string url, string weXinAppId, int scope = 1)
{
return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + weXinAppId + "&redirect_uri=" + url + "&response_type=code&scope=" + scope + "&state=jshop#wechat_redirect";
}
}
}

View File

@@ -0,0 +1,97 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/7/29 23:21:06
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace CoreCms.Net.WeChat.Service.Utilities
{
/// <summary>XML 工具类</summary>
public static class XmlUtility
{
/// <summary>反序列化</summary>
/// <param name="xml">XML字符串</param>
/// <returns></returns>
public static object Deserialize<T>(string xml)
{
try
{
using (StringReader stringReader = new StringReader(xml))
return new XmlSerializer(typeof(T)).Deserialize((TextReader)stringReader);
}
catch (Exception ex)
{
Console.WriteLine((object)ex);
return (object)null;
}
}
/// <summary>反序列化</summary>
/// <param name="stream"></param>
/// <returns></returns>
public static object Deserialize<T>(Stream stream) => new XmlSerializer(typeof(T)).Deserialize(stream);
/// <summary>
/// 序列化
/// 说明此方法序列化复杂类如果没有声明XmlInclude等特性可能会引发“使用 XmlInclude 或 SoapInclude 特性静态指定非已知的类型。”的错误。
/// </summary>
/// <param name="obj">对象</param>
/// <returns></returns>
public static string Serializer<T>(T obj)
{
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
try
{
xmlSerializer.Serialize((Stream)memoryStream, (object)obj);
}
catch (InvalidOperationException)
{
throw;
}
memoryStream.Position = 0L;
StreamReader streamReader = new StreamReader((Stream)memoryStream);
string end = streamReader.ReadToEnd();
streamReader.Dispose();
memoryStream.Dispose();
return end;
}
/// <summary>序列化将流转成XML字符串</summary>
/// <param name="stream"></param>
/// <returns></returns>
public static XDocument Convert(Stream stream)
{
if (stream.CanSeek)
stream.Seek(0L, SeekOrigin.Begin);
using (XmlReader reader = XmlReader.Create(stream))
return XDocument.Load(reader);
}
/// <summary>序列化将流转成XML字符串</summary>
/// <param name="stream"></param>
/// <returns></returns>
public static string ConvertToString(Stream stream)
{
StreamReader reader = new StreamReader(stream);
string sHtml = reader.ReadToEnd();
return sHtml;
}
}
}