From bcdac0394cf2231284ddf77db44b28babe54ffbe Mon Sep 17 00:00:00 2001
From: wtp <1813748440@qq.com>
Date: Mon, 29 Jan 2024 15:14:33 +0800
Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=94=AF=E4=BB=98=E3=80=81?=
=?UTF-8?q?=E8=BD=AC=E8=B4=A6=E3=80=81=E7=94=A8=E6=88=B7=E6=8E=A7=E5=88=B6?=
=?UTF-8?q?=E3=80=81=E6=96=B0=E5=A2=9E=E8=AF=81=E4=B9=A6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
GDZZ.Application/Entity/UserScope.cs | 23 ++
GDZZ.Application/Enum/MerchantErrorEnum.cs | 55 ++++
GDZZ.Application/GDZZ.Application.csproj | 2 +
GDZZ.Application/GDZZ.Application.xml | 68 ++++-
GDZZ.Application/Help/CacheService.cs | 4 +-
GDZZ.Application/Help/ICacheService.cs | 2 +-
GDZZ.Application/Service/Auth/AuthService.cs | 286 ++++++++++--------
.../Service/Auth/DTO/WxRefundInput.cs | 4 +-
.../Dto/LiveHistoryContactsInput.cs | 2 +-
.../LiveHistoryContactsService.cs | 25 +-
.../Service/WXPay/Dto/Merchant.cs | 20 ++
GDZZ.Application/Service/WXPay/JsApiPay.cs | 84 +++--
.../Service/WXPay/WXPayService.cs | 19 +-
GDZZ.Core/ConfigOption/ConfigOptions.cs | 2 +
GDZZ.Core/Enum/ErrorCode.cs | 6 +
GDZZ.Core/GDZZ.Core.xml | 5 +
GDZZ.Core/Manager/UserManager.cs | 2 -
GDZZ.Web.Core/applicationconfig.json | 6 +-
.../App_Data/cert/apiclient_cert.p12 | Bin 0 -> 2782 bytes
.../App_Data/cert/apiclient_cert.pem | 25 ++
.../App_Data/cert/apiclient_key.pem | 28 ++
21 files changed, 475 insertions(+), 193 deletions(-)
create mode 100644 GDZZ.Application/Entity/UserScope.cs
create mode 100644 GDZZ.Application/Enum/MerchantErrorEnum.cs
create mode 100644 GDZZ.Application/Service/WXPay/Dto/Merchant.cs
create mode 100644 GDZZ.Web.Entry/App_Data/cert/apiclient_cert.p12
create mode 100644 GDZZ.Web.Entry/App_Data/cert/apiclient_cert.pem
create mode 100644 GDZZ.Web.Entry/App_Data/cert/apiclient_key.pem
diff --git a/GDZZ.Application/Entity/UserScope.cs b/GDZZ.Application/Entity/UserScope.cs
new file mode 100644
index 0000000..d615c9d
--- /dev/null
+++ b/GDZZ.Application/Entity/UserScope.cs
@@ -0,0 +1,23 @@
+using System;
+using SqlSugar;
+using System.ComponentModel;
+using GDZZ.Core.Entity;
+namespace GDZZ.Application
+{
+ ///
+ /// 业务用户关联表
+ ///
+ [SugarTable("baseuser_sysuser_scope")]
+ [Description("业务用户关联表")]
+ public class UserScope
+ {
+ ///
+ /// 业务用户ID
+ ///
+ public long BaseUserID { get; set; }
+ ///
+ /// 系统用户ID
+ ///
+ public long SysUserID { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/GDZZ.Application/Enum/MerchantErrorEnum.cs b/GDZZ.Application/Enum/MerchantErrorEnum.cs
new file mode 100644
index 0000000..8adafb3
--- /dev/null
+++ b/GDZZ.Application/Enum/MerchantErrorEnum.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace GDZZ.Application.Enum
+{
+ public enum MerchantErrorEnum
+ {
+
+
+ ///
+ /// 系统错误
+ ///
+ [Description("系统错误")] SYSTEM_ERROR = 0,
+
+ ///
+ /// 商户号和appid没有绑定关系
+ ///
+ [Description("商户号和appid没有绑定关系")] APPID_MCHID_NOT_MATCH = 1,
+
+ ///
+ /// 系统错误
+ ///
+ [Description("参数错误")] PARAM_ERROR = 2,
+ ///
+ /// 系统错误
+ ///
+ [Description("请求参数符合参数格式,但不符合业务规则")] INVALID_REQUEST = 3,
+ ///
+ /// 系统错误
+ ///
+ [Description("商户信息不合法")] NO_AUTH = 4,
+ ///
+ /// 系统错误
+ ///
+ [Description("资金不足")] NOT_ENOUGH = 5,
+ ///
+ /// 系统错误
+ ///
+ [Description("商户账户付款受限")] ACCOUNTERROR = 6,
+ ///
+ /// 系统错误
+ ///
+ [Description("超出商户单日转账额度")] QUOTA_EXCEED =7,
+
+ ///
+ /// 系统错误
+ ///
+ [Description("频率超限")] FREQUENCY_LIMITED = 0,
+
+ }
+}
diff --git a/GDZZ.Application/GDZZ.Application.csproj b/GDZZ.Application/GDZZ.Application.csproj
index 2f209e6..1fd7d9f 100644
--- a/GDZZ.Application/GDZZ.Application.csproj
+++ b/GDZZ.Application/GDZZ.Application.csproj
@@ -7,6 +7,8 @@
+
+
diff --git a/GDZZ.Application/GDZZ.Application.xml b/GDZZ.Application/GDZZ.Application.xml
index cb79e1f..ec3d039 100644
--- a/GDZZ.Application/GDZZ.Application.xml
+++ b/GDZZ.Application/GDZZ.Application.xml
@@ -804,6 +804,21 @@
求职联系费用
+
+
+ 业务用户关联表
+
+
+
+
+ 业务用户ID
+
+
+
+
+ 系统用户ID
+
+
活动类型
@@ -834,6 +849,51 @@
解除合作
+
+
+ 系统错误
+
+
+
+
+ 商户号和appid没有绑定关系
+
+
+
+
+ 系统错误
+
+
+
+
+ 系统错误
+
+
+
+
+ 系统错误
+
+
+
+
+ 系统错误
+
+
+
+
+ 系统错误
+
+
+
+
+ 系统错误
+
+
+
+
+ 系统错误
+
+
热招
@@ -1667,7 +1727,7 @@
退款消息
-
+
商户ID
@@ -4260,16 +4320,16 @@
JsApiPay 的摘要说明
-
+
V3版本请求接口
微信的接口地址
post请求的数据,json格式
apiclient_key.pem中的内容,不要-----BEGIN PRIVATE KEY----- -----END PRIVATE KEY-----
- 发起请求的商户(包括直连商户、服务商或渠道商)的商户号 mchid
+ 发起请求的商户(包括直连商户、服务商或渠道商)的商户号 mchid
商户证书号
-
+
diff --git a/GDZZ.Application/Help/CacheService.cs b/GDZZ.Application/Help/CacheService.cs
index 29fe629..65d5a9a 100644
--- a/GDZZ.Application/Help/CacheService.cs
+++ b/GDZZ.Application/Help/CacheService.cs
@@ -57,10 +57,10 @@ namespace GDZZ.Application.Help
///
///
[NonAction]
- public async Task DelLiveHistoryService(long UserID)
+ public async Task DelLiveHistoryService(long UserID)
{
string cacheKey = SystemConst.LIVE_HISTORYLIST + $"{UserID}";
- await _redisCache.DelAsync(cacheKey);
+ return await _redisCache.DelAsync(cacheKey)>0;
}
#endregion
diff --git a/GDZZ.Application/Help/ICacheService.cs b/GDZZ.Application/Help/ICacheService.cs
index afab3e7..7165046 100644
--- a/GDZZ.Application/Help/ICacheService.cs
+++ b/GDZZ.Application/Help/ICacheService.cs
@@ -13,7 +13,7 @@ namespace GDZZ.Application.Help
public interface ICacheService
{
#region 聊天接口
- Task DelLiveHistoryService(long UserID);
+ Task DelLiveHistoryService(long UserID);
Task> GetLiveHistoryService(long UserID);
Task SetLiveHistoryService(long UserID, List liveMessageLists);
#endregion
diff --git a/GDZZ.Application/Service/Auth/AuthService.cs b/GDZZ.Application/Service/Auth/AuthService.cs
index 8cde910..ee5f56b 100644
--- a/GDZZ.Application/Service/Auth/AuthService.cs
+++ b/GDZZ.Application/Service/Auth/AuthService.cs
@@ -33,6 +33,8 @@ namespace GDZZ.Application.Service.Auth
#region 仓储
private readonly SqlSugarRepository Baseuser; // wx用户仓储
private readonly SqlSugarRepository _sysUserRep; // 用户表仓储
+ private readonly SqlSugarRepository UserScope; //用户业务关联仓储 _
+
private readonly SqlSugarRepository _sysTenantRep; //租户仓储
private readonly SqlSugarRepository Self; //职业仓储
private readonly SqlSugarRepository CompanyRep;
@@ -59,6 +61,7 @@ namespace GDZZ.Application.Service.Auth
public AuthService(
IOptions options,
+ SqlSugarRepository UserScope,
SqlSugarRepository Baseuser,
SqlSugarRepository sysTenantRep,
SqlSugarRepository sysUserRep,
@@ -75,6 +78,7 @@ namespace GDZZ.Application.Service.Auth
IEventPublisher eventPublisher,
IHttpContextAccessor httpContextAccessor)
{
+ this.UserScope = UserScope;
this.CompanyRep= CompanyRep;
this._eventPublisher= eventPublisher;
this._sysUserRep = sysUserRep;
@@ -102,133 +106,144 @@ namespace GDZZ.Application.Service.Auth
public async Task SignInAsync(PhoneModel phoneModel)
{
AuthUserOut authUserOut = new AuthUserOut();
-
Company company = new Company();
-
- //读取凭证
- var tokenModel = await this._wechatOAuth.GetCode2SessionAsync(phoneModel.Code);
- //解析电话
- var phoneInfo = MiniProgramUtil.AESDecrypt(phoneModel.EncryptedDataStr, tokenModel.SessionKey, phoneModel.Iv);
-
-
- //查询系统用户
- var sysUser = this._sysUserRep.AsQueryable()
- .Filter("TenantId", true)
- .First(x => x.Phone == phoneInfo.PhoneNumber);
-
- var wxUser = await this.Baseuser.AsQueryable()
- .Filter("TenantId", true)
- .Where(x => x.OpenID == tokenModel.OpenId).SingleAsync();
-
-
-
- //账号不存在 生成系统账号
- if (sysUser.IsEmpty())
+ try
{
- sysUser = await this._sysUserRep.InsertReturnEntityAsync(new SysUser()
+ this.UserScope.BeginTran(); //开启事务
+ //读取凭证
+ var tokenModel = await this._wechatOAuth.GetCode2SessionAsync(phoneModel.Code);
+ //解析电话
+ var phoneInfo = MiniProgramUtil.AESDecrypt(phoneModel.EncryptedDataStr, tokenModel.SessionKey, phoneModel.Iv);
+ //系统用户
+ var sysUser = this._sysUserRep.AsQueryable()
+ .Filter("TenantId", true)
+ .First(x => x.Phone == phoneInfo.PhoneNumber);
+ //业务用户
+ var wxUser = await this.Baseuser.AsQueryable()
+ .Filter("TenantId", true)
+ .Where(x => x.OpenID == tokenModel.OpenId).SingleAsync();
+
+ //账号不存在 生成系统账号
+ if (sysUser.IsEmpty())
{
- Account = phoneInfo.PurePhoneNumber,
- AdminType = AdminType.None,
- Avatar = "https://gdzongzhi.com/assets/img/logo.png",
- Birthday = DateTime.Now,
- CreatedTime = DateTime.Now,
- CreatedUserId = null,
- CreatedUserName = null,
- Sex = Gender.UNKNOWN,
- Status = CommonStatus.ENABLE,
- Email = null,
- IsDeleted = false,
- Name = phoneInfo.PhoneNumber,
- Password = MD5Encryption.Encrypt("123456"),
- TenantId = 392820661919813,
- Phone = phoneInfo.PhoneNumber,
- NickName = "",
- Tel = null,
- });
- }
-
- if (wxUser.IsEmpty())
- {
- wxUser = await this.Baseuser.InsertReturnEntityAsync(new BaseUser()
+ //wxUser = await this.UserScope.InsertAsync(new UserScope)
+ sysUser = await this._sysUserRep.InsertReturnEntityAsync(new SysUser()
+ {
+ Account = phoneInfo.PurePhoneNumber,
+ AdminType = AdminType.None,
+ Avatar = "https://gdzongzhi.com/assets/img/logo.png",
+ Birthday = DateTime.Now,
+ CreatedTime = DateTime.Now,
+ CreatedUserId = null,
+ CreatedUserName = null,
+ Sex = Gender.UNKNOWN,
+ Status = CommonStatus.ENABLE,
+ Email = null,
+ IsDeleted = false,
+ Name = phoneInfo.PhoneNumber,
+ Password = MD5Encryption.Encrypt("123456"),
+ TenantId = 392820661919813,
+ Phone = phoneInfo.PhoneNumber,
+ NickName = "",
+ Tel = null,
+ });
+ }
+
+ if (wxUser.IsEmpty())
{
- UnionId = tokenModel.Unionid,
- CreatedUserId = sysUser.Id,
- CreatedTime = DateTime.Now,
- CreatedUserName = sysUser.Name,
- AvatarUrl = "https://gdzongzhi.com/assets/img/logo.png",
- Status = (int)CommonStatus.ENABLE,
- OpenID = tokenModel.OpenId,
- UserName = phoneModel.Phone.ToString(),
- });
- }
- //区分账号类型
- switch (phoneModel.LogInType)
- {
- case (int)UserEnum.JOB:
- wxUser.Type = (int)UserEnum.JOB;
- await this.Baseuser.UpdateAsync(wxUser);
- break;
- case (int)UserEnum.HEADHUNTERS:
- wxUser.Type = (int)UserEnum.HEADHUNTERS;
- await this.Baseuser.UpdateAsync(wxUser);
- break;
- case (int)UserEnum.ADVERTISE:
- wxUser.Type = (int)UserEnum.ADVERTISE;
- await this.Baseuser.UpdateAsync(wxUser);
- //获取公司信息
- company = await this.CompanyRep.FirstOrDefaultAsync(x => x.Id == wxUser.CompanyID);
- authUserOut.companyDto = company.Adapt();
- break;
- default:
- break;
- }
+ wxUser = await this.Baseuser.InsertReturnEntityAsync(new BaseUser()
+ {
+ UnionId = tokenModel.Unionid,
+ CreatedUserId = sysUser.Id,
+ CreatedTime = DateTime.Now,
+ CreatedUserName = sysUser.Name,
+ AvatarUrl = "https://gdzongzhi.com/assets/img/logo.png",
+ Status = (int)CommonStatus.ENABLE,
+ OpenID = tokenModel.OpenId,
+ UserName = phoneModel.Phone.ToString(),
+ });
+ }
+ //区分账号类型
+ switch (phoneModel.LogInType)
+ {
+ case (int)UserEnum.JOB:
+ wxUser.Type = (int)UserEnum.JOB;
+ await this.Baseuser.UpdateAsync(wxUser);
+ break;
+ case (int)UserEnum.HEADHUNTERS:
+ wxUser.Type = (int)UserEnum.HEADHUNTERS;
+ await this.Baseuser.UpdateAsync(wxUser);
+ break;
+ case (int)UserEnum.ADVERTISE:
+ wxUser.Type = (int)UserEnum.ADVERTISE;
+ await this.Baseuser.UpdateAsync(wxUser);
+ //获取公司信息
+ company = await this.CompanyRep.FirstOrDefaultAsync(x => x.Id == wxUser.CompanyID);
+ authUserOut.companyDto = company.Adapt();
+ break;
+ default:
+ break;
+ }
- if (wxUser.IsEmpty() || sysUser.IsEmpty())
- throw Oops.Oh(ErrorCode.xg1002);
- //判断是否存在邀请
- if(phoneModel.Scene != null)
- {
- //判断当前用户是否被邀请过
- var invi = await this.invitaitionRey.FirstOrDefaultAsync(x => x.UserID == UserManager.UserId);
- if (invi.IsNullOrZero())
+ if (wxUser.IsEmpty() || sysUser.IsEmpty())
+ throw Oops.Oh(ErrorCode.xg1002);
+ var userc = await this.UserScope.FirstOrDefaultAsync(x => x.BaseUserID == wxUser.Id && x.SysUserID == sysUser.Id);
+ if (userc.IsNullOrZero())
{
- var invres = await this.invitaitionRey.FirstOrDefaultAsync(x => x.InviteID == phoneModel.Scene);
- //未被邀请
- var invrey = await this.invitaitionRey.InsertAsync(new InviteUserPos()
+ await this.UserScope.InsertAsync(new UserScope()
{
- UserID = UserManager.UserId,
- InviteUserID = (long)phoneModel.Scene,
- InviteID = invres.InviteID
-
+ SysUserID = sysUser.Id,
+ BaseUserID = wxUser.Id,
});
- if (invrey > 0)
+
+ }
+
+
+
+ //判断是否存在邀请
+ if (phoneModel.Scene != null)
+ {
+ //判断当前用户是否被邀请过
+ var invi = await this.invitaitionRey.FirstOrDefaultAsync(x => x.UserID == UserManager.UserId);
+ if (invi.IsNullOrZero())
{
- //附加奖励给邀请人
- UtilService utilService = new UtilService(this.rechargeRep);
- utilService.Reward((long)phoneModel.Scene, 1);
+ var invres = await this.invitaitionRey.FirstOrDefaultAsync(x => x.InviteID == phoneModel.Scene);
+ //未被邀请
+ var invrey = await this.invitaitionRey.InsertAsync(new InviteUserPos()
+ {
+ UserID = UserManager.UserId,
+ InviteUserID = (long)phoneModel.Scene,
+ InviteID = invres.InviteID
+
+ });
+ if (invrey > 0)
+ {
+ //附加奖励给邀请人
+ UtilService utilService = new UtilService(this.rechargeRep);
+ utilService.Reward((long)phoneModel.Scene, 1);
+ }
}
+
}
- }
-
- var Self = await this.Self.FirstOrDefaultAsync(x => x.CreatedUserId == sysUser.Id);
+ var Self = await this.Self.FirstOrDefaultAsync(x => x.CreatedUserId == sysUser.Id);
- // 获取加密后的密码
- var encryptPassword = MD5Encryption.Encrypt(sysUser.Password);
+ // 获取加密后的密码
+ var encryptPassword = MD5Encryption.Encrypt(sysUser.Password);
- // 验证账号是否被冻结
- if (sysUser.Status == CommonStatus.DISABLE)
- throw Oops.Oh(ErrorCode.D1017);
- //获取对应租户
- var tenant = this._sysTenantRep.Single(sysUser.TenantId);
+ // 验证账号是否被冻结
+ if (sysUser.Status == CommonStatus.DISABLE)
+ throw Oops.Oh(ErrorCode.D1017);
+ //获取对应租户
+ var tenant = this._sysTenantRep.Single(sysUser.TenantId);
- if (tenant.IsNullOrZero())
- throw Oops.Oh(ErrorCode.F1001);
+ if (tenant.IsNullOrZero())
+ throw Oops.Oh(ErrorCode.F1001);
- // 生成Token令牌
- authUserOut.Token = JWTEncryption.Encrypt(new Dictionary
+ // 生成Token令牌
+ authUserOut.Token = JWTEncryption.Encrypt(new Dictionary
{
{ClaimConst.CLAINM_USERID, sysUser.Id},
{ClaimConst.TENANT_ID, sysUser.TenantId},
@@ -239,31 +254,38 @@ namespace GDZZ.Application.Service.Auth
{ ClaimConst.CLAINM_TENANT_NAME, tenant.Name },
});
- // 设置Swagger自动登录
- _httpContextAccessor.HttpContext.SigninToSwagger(authUserOut.Token);
-
- // 生成刷新Token令牌
- var refreshToken = JWTEncryption.GenerateRefreshToken(authUserOut.Token, 30);
-
- // 设置刷新Token令牌
- _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;
-
- var httpContext = App.HttpContext;
- await _eventPublisher.PublishAsync(new ChannelEventSource("Update:UserLoginInfo",
- new SysUser { Id = sysUser.Id, LastLoginIp = httpContext.GetLocalIpAddressToIPv4(), LastLoginTime = DateTime.Now }));
+ // 设置Swagger自动登录
+ _httpContextAccessor.HttpContext.SigninToSwagger(authUserOut.Token);
+
+ // 生成刷新Token令牌
+ var refreshToken = JWTEncryption.GenerateRefreshToken(authUserOut.Token, 30);
+
+ // 设置刷新Token令牌
+ _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;
+
+ var httpContext = App.HttpContext;
+ await _eventPublisher.PublishAsync(new ChannelEventSource("Update:UserLoginInfo",
+ new SysUser { Id = sysUser.Id, LastLoginIp = httpContext.GetLocalIpAddressToIPv4(), LastLoginTime = DateTime.Now }));
+ authUserOut.Avatar = sysUser.Avatar;
+ authUserOut.Phone = sysUser.Phone;
+ authUserOut.Sex = sysUser.Sex;
+ authUserOut.UserId = sysUser.Id;
+ authUserOut.UserName = sysUser.Name;
+ authUserOut.Self = Self.IsEmpty() ? null : Self.Name;
+ authUserOut.Type = (UserEnum)wxUser.Type;
+ authUserOut.OpenID = tokenModel.OpenId;
+ authUserOut.Tenant = tenant.Adapt();
+ authUserOut.Describe = wxUser.Describe;
+ await this.cacheService.SetUserInfoAsync(authUserOut, authUserOut.UserId);
+ this.UserScope.CurrentCommitTran();
+ }
+ catch (Exception)
+ {
+ this.UserScope.CurrentRollbackTran();
+ throw;
+ }
- authUserOut.Avatar = sysUser.Avatar;
- authUserOut.Phone = sysUser.Phone;
- authUserOut.Sex = sysUser.Sex;
- authUserOut.UserId = sysUser.Id;
- authUserOut.UserName = sysUser.Name;
- authUserOut.Self = Self.IsEmpty() ? null : Self.Name;
- authUserOut.Type = (UserEnum)wxUser.Type;
- authUserOut.OpenID = tokenModel.OpenId;
- authUserOut.Tenant = tenant.Adapt();
- authUserOut.Describe = wxUser.Describe;
- await this.cacheService.SetUserInfoAsync(authUserOut, authUserOut.UserId);
return authUserOut;
}
diff --git a/GDZZ.Application/Service/Auth/DTO/WxRefundInput.cs b/GDZZ.Application/Service/Auth/DTO/WxRefundInput.cs
index 60f9905..675e425 100644
--- a/GDZZ.Application/Service/Auth/DTO/WxRefundInput.cs
+++ b/GDZZ.Application/Service/Auth/DTO/WxRefundInput.cs
@@ -39,11 +39,11 @@ namespace GDZZ.Application
///
/// 商户ID
///
- public string MerchantID { get; set; }
+ public string OpenID { get; set; }
///
/// 转账金额
///
- public dynamic TransferAmount { get; set; }
+ public decimal TransferAmount { get; set; }
}
}
diff --git a/GDZZ.Application/Service/LiveHistoryContacts/Dto/LiveHistoryContactsInput.cs b/GDZZ.Application/Service/LiveHistoryContacts/Dto/LiveHistoryContactsInput.cs
index e6d16bf..46dfd88 100644
--- a/GDZZ.Application/Service/LiveHistoryContacts/Dto/LiveHistoryContactsInput.cs
+++ b/GDZZ.Application/Service/LiveHistoryContacts/Dto/LiveHistoryContactsInput.cs
@@ -133,7 +133,7 @@ namespace GDZZ.Application
///
/// 公司ID
///
- public long CompanyID { get; set; }
+ public long? CompanyID { get; set; }
}
}
diff --git a/GDZZ.Application/Service/LiveHistoryContacts/LiveHistoryContactsService.cs b/GDZZ.Application/Service/LiveHistoryContacts/LiveHistoryContactsService.cs
index b6e1c6b..1e24175 100644
--- a/GDZZ.Application/Service/LiveHistoryContacts/LiveHistoryContactsService.cs
+++ b/GDZZ.Application/Service/LiveHistoryContacts/LiveHistoryContactsService.cs
@@ -80,12 +80,20 @@ namespace GDZZ.Application
public async Task AddLive(AddLiveFriendInput input)
{
- var baseUser = await this.Baseuser.AsQueryable().Filter("TenantId", true).Where(x => x.CompanyID == input.CompanyID).SingleAsync();
- if (baseUser.IsNullOrZero())
- throw Oops.Oh(ErrorCode.B1002);
- var user = await this._sysUserRep.Where(x => x.Id == baseUser.CreatedUserId).SingleAsync();
- if (user.IsNullOrZero())
- throw Oops.Oh(ErrorCode.xg1002);
+ SysUser user = new SysUser();
+ if (input.CompanyID.IsNullOrZero())
+ {
+ user = await this._sysUserRep.FirstOrDefaultAsync(x => x.Id == input.UserId);
+ if (user.IsNullOrZero())
+ throw Oops.Oh(ErrorCode.xg1002);
+ }
+ else
+ {
+ var buser = await this.Baseuser.FirstOrDefaultAsync(x => x.CompanyID == input.CompanyID);
+ user = await this._sysUserRep.Where(x => x.Id == buser.CreatedUserId).SingleAsync();
+ if (user.IsNullOrZero())
+ throw Oops.Oh(ErrorCode.xg1002);
+ }
//判断是是好友
var fends =await this.liveUserFriend.Where(x => x.FriendID == UserManager.UserId && x.CreatedUserId == user.Id).FirstAsync();
@@ -111,7 +119,9 @@ namespace GDZZ.Application
await this.liveUserFriend.InsertAsync(item);
}
}
- await this.cacheService.DelLiveHistoryService(UserManager.UserId);
+
+ if(!await this.cacheService.DelLiveHistoryService(UserManager.UserId))
+ throw Oops.Oh(ErrorCode.B1004);
return user;
}
@@ -186,7 +196,6 @@ namespace GDZZ.Application
Id = item.FriendID,
Index = sysUser.Name.Substring(0, 1),
LastSendTime = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000,
-
};
//查询聊天记录
diff --git a/GDZZ.Application/Service/WXPay/Dto/Merchant.cs b/GDZZ.Application/Service/WXPay/Dto/Merchant.cs
new file mode 100644
index 0000000..bfc6b9d
--- /dev/null
+++ b/GDZZ.Application/Service/WXPay/Dto/Merchant.cs
@@ -0,0 +1,20 @@
+using GDZZ.Application.Enum;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace GDZZ.Application
+{
+ public class Merchant
+ {
+ public string out_batch_no { get; set; }
+ public string batch_id { get; set; }
+ public DateTime create_time { get; set; }
+
+ public string code { get; set; }
+
+ public string message { get; set; }
+ }
+}
diff --git a/GDZZ.Application/Service/WXPay/JsApiPay.cs b/GDZZ.Application/Service/WXPay/JsApiPay.cs
index 483fbb7..00ce4b8 100644
--- a/GDZZ.Application/Service/WXPay/JsApiPay.cs
+++ b/GDZZ.Application/Service/WXPay/JsApiPay.cs
@@ -6,19 +6,31 @@ using System.Runtime.Serialization;
using System.IO;
using System.Text;
using System.Net;
-
+using Flurl;
+using Flurl.Http;
using Furion.Logging;
using SqlSugar;
using Enyim.Caching;
using System.Security.Cryptography;
+using static System.Net.Mime.MediaTypeNames;
+using Microsoft.Extensions.Hosting.Internal;
+using Enyim.Caching.Configuration;
+using Furion.RemoteRequest;
+using Furion.RemoteRequest.Extensions;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Security.Policy;
+
///
///JsApiPay 的摘要说明
///
-public static class JsApiPay
+public class JsApiPay : IHttpDispatchProxy
{
- public static string WithDrawsToWx(string appid, string mchid, string serialNo, string openID, string partnerTradeNo, decimal totalFee)
+ const string PrivateKey = "App_Data/cert/apiclient_key.pem";
+
+ public async Task WithDrawsToWx(string url, string appid, string mchid, string serialNo, string openID, string partnerTradeNo, decimal totalFee, string hostting)
{
SortedDictionary dic = new SortedDictionary();
@@ -39,10 +51,7 @@ public static class JsApiPay
list.Add(dic1);
dic.Add("transfer_detail_list", list);
- var url = "https://api.mch.weixin.qq.com/v3/transfer/batches";
- string transactionsResponse = WxV3PostJson(url, Newtonsoft.Json.JsonConvert.SerializeObject(dic), mchid, serialNo);
- //Log.Info("商户转账到零钱返回:" , transactionsResponse);
- return transactionsResponse; ;
+ return await WxV3PostJson(url, Newtonsoft.Json.JsonConvert.SerializeObject(dic), mchid, serialNo, hostting); ; ;
}
///
/// V3版本请求接口
@@ -50,52 +59,49 @@ public static class JsApiPay
/// 微信的接口地址
/// post请求的数据,json格式
/// apiclient_key.pem中的内容,不要-----BEGIN PRIVATE KEY----- -----END PRIVATE KEY-----
- /// 发起请求的商户(包括直连商户、服务商或渠道商)的商户号 mchid
+ /// 发起请求的商户(包括直连商户、服务商或渠道商)的商户号 mchid
/// 商户证书号
- ///
+ ///
///
- public static string WxV3PostJson(string url, string postData, string mchId, string serialNo)
+ public async Task WxV3PostJson(string url, string postData, string mchId, string serialNo, string hostting)
{
-
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
+ string Authorization = GetAuthorization(url, "POST", postData, mchId, serialNo, hostting);
+ var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/json;charset=UTF-8";
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36";
request.Accept = "application/json";
- //Log.Info("发起开始申请商户转账到零钱请求", "发起请求1");
- string Authorization = GetAuthorization(url, "POST", postData, mchId, serialNo);
request.Headers.Add("Authorization", Authorization);
- //Log.Info("返回申请商户转账到零钱结果", Authorization);
- byte[] paramJsonBytes;
- paramJsonBytes = System.Text.Encoding.UTF8.GetBytes(postData);
- request.ContentLength = paramJsonBytes.Length;
+ byte[] byteData = System.Text.Encoding.UTF8.GetBytes(postData);
+ request.ContentLength = byteData.Length;
Stream writer;
try
{
writer = request.GetRequestStream();
}
- catch (Exception)
+ catch (Exception e)
{
- writer = null;
Console.Write("连接服务器失败!");
+ throw;
}
- writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);
+ writer.Write(byteData, 0, byteData.Length);
writer.Close();
+ string responseString = "";
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
- catch (WebException ex)
+ catch (WebException e)
{
- response = ex.Response as HttpWebResponse;
+ response = e.Response as HttpWebResponse;
}
Stream resStream = response.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
- string text = reader.ReadToEnd();
- return text;
+ responseString = reader.ReadToEnd();
+ return responseString;
}
- private static string GetAuthorization(string url, string method, string jsonParame, string mchId, string serialNo)
+ private string GetAuthorization(string url, string method, string jsonParame, string mchId, string serialNo, string hostting)
{
var uri = new Uri(url);
string urlPath = uri.PathAndQuery;
@@ -107,8 +113,8 @@ public static class JsApiPay
//Log.Info("请求message:", message);
//string signTxt = Sign(message, privateKey);
- string signTxt = Sign(message);
-
+ string signTxt = Sign(message, hostting);
+
//Authorization和格式
string authorzationTxt = string.Format("WECHATPAY2-SHA256-RSA2048 mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"",
@@ -122,17 +128,31 @@ public static class JsApiPay
}
- private static string Sign(string message)
+ private string Sign(string message, string hostting)
{
+
+ string base64X509Cert = "";
+ string pemPublicCert = Path.Combine(hostting, PrivateKey);
+ using (FileStream fs = new FileStream(pemPublicCert, FileMode.Open, FileAccess.Read))
+ {
+ using (StreamReader sr = new StreamReader(fs))
+ {
+ base64X509Cert = sr.ReadToEnd().Trim();
+ }
+ }
+ base64X509Cert = base64X509Cert.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "");
+
// NOTE: 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY-----
// 亦不包括结尾的-----END PRIVATE KEY-----
- string privateKey = "{你的私钥}";
- byte[] keyData = Convert.FromBase64String(privateKey);
+
+ byte[] keyData = Convert.FromBase64String(base64X509Cert);
var rsa = RSA.Create();
rsa.ImportPkcs8PrivateKey(keyData, out _);
byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
- return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
+ var sigdata = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
+ var res = Convert.ToBase64String(sigdata);
+ return res;
}
}
diff --git a/GDZZ.Application/Service/WXPay/WXPayService.cs b/GDZZ.Application/Service/WXPay/WXPayService.cs
index df80216..112db6e 100644
--- a/GDZZ.Application/Service/WXPay/WXPayService.cs
+++ b/GDZZ.Application/Service/WXPay/WXPayService.cs
@@ -27,6 +27,8 @@ using Senparc.CO2NET.Cache.Redis;
using GDZZ.Core.Service;
using System.Linq.Dynamic.Core.Tokenizer;
using System.Diagnostics;
+using Microsoft.AspNetCore.Hosting;
+using Furion.JsonSerialization;
namespace GDZZ.Application.Service.WXPay
{
@@ -35,7 +37,7 @@ namespace GDZZ.Application.Service.WXPay
{
-
+ private readonly IHostingEnvironment hostingEnvironment;
private readonly SqlSugarRepository Baseuser; // wx用户仓储
private readonly SqlSugarRepository _sysUserRep; // 用户表仓储
private readonly SqlSugarRepository _sysTenantRep; //租户仓储
@@ -71,6 +73,7 @@ namespace GDZZ.Application.Service.WXPay
SqlSugarRepository payTakeRep,
SqlSugarRepository refundRep,
WechatOAuth wechatOAuth,
+ IHostingEnvironment hostingEnvironment,
IHttpContextAccessor _httpContextAccessor,
IEventPublisher eventPublisher)
{
@@ -85,6 +88,7 @@ namespace GDZZ.Application.Service.WXPay
this.payTakeRep = payTakeRep;
this._wechatOAuth = wechatOAuth;
this._oauthConfig = options.Value.SenparcWeixin;
+ this.hostingEnvironment = hostingEnvironment;
this._httpContextAccessor = _httpContextAccessor;
}
@@ -128,6 +132,7 @@ namespace GDZZ.Application.Service.WXPay
public async Task UpBalance(decimal Consume,long? ResumeID)
{
+ this.balance.CurrentBeginTran();
var comrep = await this.ComsumeRep.Where(x=>x.ResumeID== ResumeID).FirstAsync();
if(!comrep.IsNullOrZero()) //已经消费过了
return "";
@@ -424,19 +429,21 @@ namespace GDZZ.Application.Service.WXPay
///
///
[HttpPost]
- [Route("Mini/v1/GetBalance")]
+ [Route("Mini/v1/MerchantTransfer")]
public async Task MerchantTransfer(TransferInput wxRefundInput)
{
+ var hostting = this.hostingEnvironment.ContentRootPath;
//读取商户信息
-
var appid = Config.SenparcWeixinSetting.TenPayV3_AppId;
var mchid = Config.SenparcWeixinSetting.TenPayV3_MchId;
var serialno = Config.SenparcWeixinSetting.TenPayV3_SerialNumber;
- string partnerTradeNo = "xcx" + DateTime.Now.ToString("yyyyMMddHHmmfff");
- string result = JsApiPay.WithDrawsToWx(appid, mchid, serialno, wxRefundInput.MerchantID, partnerTradeNo, Convert.ToInt32(wxRefundInput.TransferAmount * 100));
+ string url = string.Format("https://api.mch.weixin.qq.com/v3/transfer/batches");
+ string partnerTradeNo = "tk" + DateTime.Now.ToString("yyyyMMddHHmmfff");
+ JsApiPay jsApiPay = new JsApiPay();
+ string result =await jsApiPay.WithDrawsToWx(url, appid, mchid, serialno, wxRefundInput.OpenID, partnerTradeNo,
+ Convert.ToInt32(wxRefundInput.TransferAmount * 100), hostting);
return result;
-
}
diff --git a/GDZZ.Core/ConfigOption/ConfigOptions.cs b/GDZZ.Core/ConfigOption/ConfigOptions.cs
index b578492..509d03c 100644
--- a/GDZZ.Core/ConfigOption/ConfigOptions.cs
+++ b/GDZZ.Core/ConfigOption/ConfigOptions.cs
@@ -244,6 +244,8 @@ public class SenparcWeixinSetting
public string TenPayV3_PrivateKey { get; set; }
public string TenPayV3_SerialNumber { get; set; }
public string TenPayV3_ApiV3Key { get; set; }
+
+ public string TenPayv3_WxTransfer { get; set; }
}
diff --git a/GDZZ.Core/Enum/ErrorCode.cs b/GDZZ.Core/Enum/ErrorCode.cs
index 854bc8c..9a3cd5c 100644
--- a/GDZZ.Core/Enum/ErrorCode.cs
+++ b/GDZZ.Core/Enum/ErrorCode.cs
@@ -431,4 +431,10 @@ public enum ErrorCode
///
[ErrorCodeItemMetadata("手机已经存在")]
B1003,
+
+ ///
+ /// 数据删除失败
+ ///
+ [ErrorCodeItemMetadata("数据删除失败")]
+ B1004,
}
diff --git a/GDZZ.Core/GDZZ.Core.xml b/GDZZ.Core/GDZZ.Core.xml
index 0164721..e35e13f 100644
--- a/GDZZ.Core/GDZZ.Core.xml
+++ b/GDZZ.Core/GDZZ.Core.xml
@@ -2620,6 +2620,11 @@
手机已经存在
+
+
+ 数据删除失败
+
+
文件扩展枚举
diff --git a/GDZZ.Core/Manager/UserManager.cs b/GDZZ.Core/Manager/UserManager.cs
index 4c905c2..72ec7be 100644
--- a/GDZZ.Core/Manager/UserManager.cs
+++ b/GDZZ.Core/Manager/UserManager.cs
@@ -18,8 +18,6 @@ public static class UserManager
///
public static string Account => App.User.FindFirst(ClaimConst.CLAINM_ACCOUNT)?.Value;
-
-
///
/// 租户ID
///
diff --git a/GDZZ.Web.Core/applicationconfig.json b/GDZZ.Web.Core/applicationconfig.json
index e054e83..2d9da2b 100644
--- a/GDZZ.Web.Core/applicationconfig.json
+++ b/GDZZ.Web.Core/applicationconfig.json
@@ -158,9 +158,9 @@
* 1、支持明文私钥(无换行字符)
* 2、私钥文件路径(如:~/App_Data/cert/apiclient_key.pem),注意:必须放在 App_Data 等受保护的目录下,避免泄露
*/
- "TenPayV3_PrivateKey": "#{TenPayV3_PrivateKey}#", //(新)证书私钥
- "TenPayV3_SerialNumber": "56FA7394CDD74ACB0329480EAB7185BE7A2CB081", //(新)证书序列号
- "TenPayV3_ApiV3Key": "#{TenPayV3_APIv3Key}#", //(新)APIv3 密钥
+ "TenPayV3_PrivateKey": "/App_Data/cert/apiclient_key.pem", //(新)证书私钥
+ "TenPayV3_SerialNumber": "133833F7E1F4083BF191A81938EF25AC659F23D6", //(新)证书序列号
+ "TenPayV3_ApiV3Key": "ZZRZJKvAstv4SJapStuyHhCOzqrrjSUD", //(新)APIv3 密钥
//如果不设置TenPayV3_WxOpenTenpayNotify,默认在 TenPayV3_TenpayNotify 的值最后加上 "WxOpen"
"TenPayV3_WxOpenTenpayNotify": "https://admin.gdzongzhi.com/api/Mini/NotifyUrlWxOpen", //http://YourDomainName/TenpayV3/PayNotifyUrlWxOpen
diff --git a/GDZZ.Web.Entry/App_Data/cert/apiclient_cert.p12 b/GDZZ.Web.Entry/App_Data/cert/apiclient_cert.p12
new file mode 100644
index 0000000000000000000000000000000000000000..049d40892879c751a8afd7322b5337ab32fad0ee
GIT binary patch
literal 2782
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
Z#Lg`q-Brb*Z?hnFplqkxU3#(NzX7oIA_o8f
literal 0
HcmV?d00001
diff --git a/GDZZ.Web.Entry/App_Data/cert/apiclient_cert.pem b/GDZZ.Web.Entry/App_Data/cert/apiclient_cert.pem
new file mode 100644
index 0000000..c41b4b7
--- /dev/null
+++ b/GDZZ.Web.Entry/App_Data/cert/apiclient_cert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEMTCCAxmgAwIBAgIUEzgz9+H0CDvxkagZOO8lrGWfI9YwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
+FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
+Q0EwHhcNMjQwMTIyMDgyMjIyWhcNMjkwMTIwMDgyMjIyWjCBijETMBEGA1UEAwwK
+MTY0MDM2MzE2NzEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTYwNAYDVQQL
+DC3lub/kuJznnIHnurXmmbrkvIHkuJrnrqHnkIblkqjor6LmnInpmZDlhazlj7gx
+CzAJBgNVBAYTAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMGnNPWyzoN6ldrf0B8coEu0naNSCJZvXRYKKOi8VH17
+uNwbuxdYP4G0rWQC1hSbqc7Qz3iFEW5PqKA2ZqoDBdhFNqZTSVMOcw8Dagz0ya1m
+a3EdjXSGp7prHNXRSWQtVGYVPqPmg1qrt+Uptfkd75Z1EmIxDMoN8ERLToOtmfi5
+vTWWS0TZ9xaE99qGVirb4yjDr9qrutSCx/C1xNHssAnT3m2x5bYHiOEcDGtVp6iG
+DqvUBpLaqSa3IxJlQZSZP3mdrV7i2o8tlw8heSQJ+o7VWWrP0V/Y1CgPhsT0HBK4
+PRQRPfpHGv98W5tf+XBPorrjYqBFAc6TpoZHKLTY6BcCAwEAAaOBuTCBtjAJBgNV
+HRMEAjAAMAsGA1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0
+cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIw
+RTUwREJDMDRCMDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0
+MjJFMTJCMjdBOUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUA
+A4IBAQCTh90ch63bv8M0xPwCk31nuM5YZL3TsOxN8ZB+3odVEjY/zWuypSgK2aM7
+VuvroBsivAlLKefqw/U0JXw2oHNGveWW9Bq71K2KJmb8E+8yLzF9jae1mwCQmBo0
++r0D2OWDdXKrJ0eFAu4Ug6LYIu7x//JoUW3e0jY+BgiOZgkOl7LdI0bmGHiQ8LMr
+g0BgUSWc7TDd9r9UH86Rq9E0leA+5ftIN3QDfpIsxcoKXFG1hlFEj6hHQP25aKS2
+ViGl35FrUyOC+/2MAyJqjEpfTGOrX3s5HyXDyM19Qqd+oCiLjc0vblWY0Zk8Y22a
+DIzWjsG1cpBTaRqxkLaquCkyR26G
+-----END CERTIFICATE-----
diff --git a/GDZZ.Web.Entry/App_Data/cert/apiclient_key.pem b/GDZZ.Web.Entry/App_Data/cert/apiclient_key.pem
new file mode 100644
index 0000000..e096e30
--- /dev/null
+++ b/GDZZ.Web.Entry/App_Data/cert/apiclient_key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBpzT1ss6DepXa
+39AfHKBLtJ2jUgiWb10WCijovFR9e7jcG7sXWD+BtK1kAtYUm6nO0M94hRFuT6ig
+NmaqAwXYRTamU0lTDnMPA2oM9MmtZmtxHY10hqe6axzV0UlkLVRmFT6j5oNaq7fl
+KbX5He+WdRJiMQzKDfBES06DrZn4ub01lktE2fcWhPfahlYq2+Mow6/aq7rUgsfw
+tcTR7LAJ095tseW2B4jhHAxrVaeohg6r1AaS2qkmtyMSZUGUmT95na1e4tqPLZcP
+IXkkCfqO1Vlqz9Ff2NQoD4bE9BwSuD0UET36Rxr/fFubX/lwT6K642KgRQHOk6aG
+Ryi02OgXAgMBAAECggEACBBXYzfL46uyG8ggGXuOrThbLBbZZrJCdQ19QJu/BO6m
+9vtsof85vcPxSG3ZzkfhHUySpxkbbbWBdxJs2f2AO84+BVUIg53haqmgu+Nhlofi
+R3aMkmKdD2UwcTLi1HoSvqF510ddBuSJptBC1JnLhT9gwZf7SVqlO6LLJS6Qb8vx
+hMqNlvG3EqBVGSTuE8mTjcga3lmI9eAxz8rL9sZ59lj17k2JTxW6/Q3QjeTRqIpA
+UTm+SOjVYn++2kHB3Ix8RYD5vClsZ7BpMS0f3fko6qt/SuRHS0wZF2RoELia+ohv
+AyON+jKGSGRVivCiMPISDE7UGaA/cxKrolTok63QWQKBgQD8v14vWxZVp15VPosb
+1quBUDajQLBjfNIifoU1Aqc7VD2zLJ79LN7Pngv84p55TAS3+MTcu/elYGeUeZuS
+X/JexTJmSE30FtmGhpCuf/9VXyj7rN6sYbJkj+1ENFFv/qM0NBxagk/aVewM+PHs
+tIetibw+qZ0iiabnSUrqBMMVkwKBgQDEJSm4hkzGdL3I1oOyVbju/gMXcMM3IMxZ
+RpsmUQ8qhjid9KvBvC/AmWJFyDAkAkVownAcvSwoJAMSNUuApghEPDqRvvNnoc72
+lmtbwF5s6veyadZMVnrTc/ipFZdZg9ya+Qs0Kocbnceo2fJ+R5+HBtt+Wd8GE0oc
+24//+C+17QKBgQCFdsxWd2QI4POYUgmFLsur4l6nwG4kavJP0r2mq3sBgk9+gO6H
+xJz3x36PEGAcrz7CozPZV8zC4HBx3/F9zvqefsVJa572aOZ++ioGa4K6YyCyHawM
+HR7lqXbiEDp8yFsIIwhh5vQh2ENo6kBd/Uq0Icps0IYwib2/3l0XzGHzzwKBgEsa
+h70V/3PF451xNgAk/qjULk7daIJFVrmgZWvogcwglLE2rEWETyyKDqz1mClRjU4t
+lUwLy0qbb2mbaouaB3RJM4v297BorpyQwA7ju8QsvCdeiyWzv1gUAdSMZeVqrh/Q
+2E9jMVSLt5WZzlY4CodjQsxAkTr8S9Z848h5OZuJAoGBAKaaRH/9FY7igN5okg6s
+4GkoxvhOtUZ2quMCK79xKnq7SaMXz07qEhBK/a9ajYvzlbOCw9ZcX3pe641IbE+K
+03Fo7Uy/dJEtKE9rqA0lefGR9GpMbb6PdeHh9RvOKftMhrk8p8rL/GwUc2eFzgse
+BfWBXzr2mpCy3arBimmjeyx/
+-----END PRIVATE KEY-----