public async Task InvokeAsync(HttpContext context) { try { var serviceProvider = context.RequestServices; var tenantInfoService = serviceProvider.GetRequiredService <TenantInfoService>(); var requestTenantInfo = await tenantInfoService.SetScopedRequestTenantInfoAsync(context);//设置当前 Request 的 RequestTenantInfo 参数 } catch (NcfUninstallException unInstallEx) { Console.WriteLine("\t NcfUninstallException from TenantMiddleware"); context.Items["NcfUninstallException"] = true; } catch (Exception ex) { Console.WriteLine("\t Exception from TenantMiddleware"); //如果数据库出错 SenparcTrace.BaseExceptionLog(ex); throw; } //Console.WriteLine($"\tTenantMiddleware requestTenantInfo({requestTenantInfo.GetHashCode()}):" + requestTenantInfo.ToJson()); await _next(context); //Console.WriteLine("TenantMiddleware finished"); }
/// <summary> /// 自动注册所有 Area /// </summary> /// <param name="builder"></param> /// <param name="env"></param> /// <param name="eachRegsiterAction">遍历到每一个 Register 额外的操作</param> /// <returns></returns> public static IMvcBuilder AddNcfAreas(this IMvcBuilder builder, Microsoft.Extensions.Hosting.IHostEnvironment /*IWebHostEnvironment*/ env, Action <IAreaRegister> eachRegsiterAction = null) { AssembleScanHelper.AddAssembleScanItem(assembly => { try { var areaRegisterTypes = assembly.GetTypes() .Where(z => z.GetInterface(nameof(IAreaRegister)) != null) .ToArray(); foreach (var registerType in areaRegisterTypes) { var register = Activator.CreateInstance(registerType, true) as IAreaRegister; if (register != null) { register.AuthorizeConfig(builder, env); //进行注册 eachRegsiterAction?.Invoke(register); //执行额外的操作 } else { SenparcTrace.BaseExceptionLog(new BaseException($"{registerType.Name} 类型没有实现接口 IAreaRegister!")); } } } catch (Exception ex) { SenparcTrace.SendCustomLog("AddNcfAreas() 自动扫描程序集报告(非程序异常):" + assembly.FullName, ex.ToString()); } }, false); return(builder); }
internal void Build(IApplicationBuilder app, IXncfRegister register) { var threadRegister = register as IXncfThread; if (threadRegister == null) { return; } var i = 0; //遍历单个 XNCF 内所有线程配置 foreach (var threadInfo in _threadInfoList) { if (threadInfo.Task == null) { continue; } try { i++; //定义线程 Thread thread = new Thread(async() => { SenparcTrace.SendCustomLog("启动线程", $"{register.Name}-{threadInfo.Name}"); await Task.Delay(TimeSpan.FromSeconds(i)); while (true) { try { await threadInfo.Task.Invoke(app, threadInfo); // 建议开发者自己在内部做好线程内的异常处理 } catch (Exception ex) { if (threadInfo.ExceptionHandler != null) { await threadInfo.ExceptionHandler.Invoke(ex); } else { SenparcTrace.BaseExceptionLog(ex); } } finally { //进行延迟 await Task.Delay(threadInfo.IntervalTime); } } }); thread.Name = $"{register.Uid}-{threadInfo.Name ?? Guid.NewGuid().ToString()}"; thread.Start();//启动 Register.ThreadCollection[threadInfo] = thread; } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); } } }
/// <summary> /// 创建对象实例 /// </summary> /// <typeparam name="T">要创建对象的类型</typeparam> /// <param name="assemblyName">类型所在程序集名称</param> /// <param name="nameSpace">类型所在命名空间</param> /// <param name="className">类型名</param> /// <param name="recordLog">是否记录日志</param> /// <returns></returns> public static T CreateInstance <T>(string assemblyName, string nameSpace, string className, bool recordLog = false) { try { string fullName = nameSpace + "." + className; //命名空间.类型名 //此为第一种写法 #if !NET45 //object ect = Assembly.Load(new AssemblyName(assemblyName)).CreateInstance(fullName);//加载程序集,创建程序集里面的 命名空间.类型名 实例s //.net core 2.1这种方法也已经支持 object ect = Assembly.Load(assemblyName).CreateInstance(fullName); //加载程序集,创建程序集里面的 命名空间.类型名 实例s #else object ect = Assembly.Load(assemblyName).CreateInstance(fullName); //加载程序集,创建程序集里面的 命名空间.类型名 实例 #endif return((T)ect); //类型转换并返回 //下面是第二种写法 //string path = fullName + "," + assemblyName;//命名空间.类型名,程序集 //Type o = Type.GetType(path);//加载类型 //object obj = Activator.CreateInstance(o, true);//根据类型创建实例 //return (T)obj;//类型转换并返回 } catch (Exception ex) { if (recordLog) { SenparcTrace.BaseExceptionLog(ex); } //发生异常,返回类型的默认值 return(default(T)); } }
// TODO: 待测试 /// <summary> /// JSAPI合单支付下单接口 /// <para>在微信支付服务后台生成JSAPI合单预支付交易单,返回预支付交易会话标识</para> /// <para>https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_3.shtml</para> /// </summary> /// <param name="data">微信支付需要POST的Data数据</param> /// <param name="timeOut">超时时间,单位为ms </param> /// <returns></returns> public async Task <JsApiReturnJson> JsApiCombineAsync(CombineTransactionsRequestData data, int timeOut = Config.TIME_OUT) { try { if (data.sub_orders.Count() is not >= 2 or not <= 10) { throw new TenpayApiRequestException("sub_orders 参数必须在 2 到 10 之间!"); } var url = ReurnPayApiUrl("https://api.mch.weixin.qq.com/{0}v3/combine-transactions/jsapi"); TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); return(await tenPayApiRequest.RequestAsync <JsApiReturnJson>(url, data, timeOut)); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new JsApiReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }
/// <summary> /// BaseException /// </summary> /// <param name="message">异常消息</param> /// <param name="inner">内部异常信息</param> /// <param name="logged">是否已经使用WeixinTrace记录日志,如果没有,BaseException会进行概要记录</param> public BaseException(string message, Exception inner, bool logged = false) : base(message, inner) { if (!logged) { //SenparcTrace.Log(string.Format("BaseException({0}):{1}", this.GetType().Name, message)); SenparcTrace.BaseExceptionLog(this); } }
public void BaseExceptionLogTest() { var keyword = Guid.NewGuid().ToString();//随机字符串 var ex = new BaseException("测试异常:" + keyword); //Log会记录两次,第一次是在BaseException初始化的时候会调用此方法 SenparcTrace.BaseExceptionLog(ex); Assert.IsTrue(UnitTestHelper.CheckKeywordsExist(LogFilePath, "测试异常", keyword)); }
/// <summary> /// 构造函数 /// </summary> /// <param name="message"></param> /// <param name="typeOfDatabaseConfiguration">DatabaseConfiguration 类型</param> /// <param name="typeOfDbContext">DbContext 类型,如:SenparcEntities</param> /// <param name="inner"></param> public NcfDatabaseException(string message, Type typeOfDatabaseConfiguration, Type typeOfDbContext = null, Exception inner = null) : base(message, inner, true) { message += @$ " DatabaseConfiguration 类型:{(typeOfDatabaseConfiguration == null ? " 未提供 " : typeOfDatabaseConfiguration.Name)} DbContext 类型:{(typeOfDbContext == null ? " 未提供 " : typeOfDbContext.Name)} "; SenparcTrace.BaseExceptionLog(this); }
/// <summary> /// 获取单个公钥 /// </summary> /// <param name="serialNumber"></param> /// <returns></returns> public async Task <string> GetPublicKeyAsync(string serialNumber, ISenparcWeixinSettingForTenpayV3 tenpayV3Setting) { var keys = await GetPublicKeysAsync(tenpayV3Setting); if (keys.TryGetValue(serialNumber, out string publicKey)) { return(publicKey); } SenparcTrace.BaseExceptionLog(new TenpaySecurityException($"公钥序列号不存在!serialNumber:{serialNumber},TenPayV3Info:{this.ToJson(true)}")); throw new TenpaySecurityException("公钥序列号不存在!请查看日志!", true); }
/// <summary> /// 运行 /// </summary> /// <param name="param"></param> /// <returns></returns> public override FunctionResult Run(IFunctionParameter param) { /* 这里是处理文字选项(单选)的一个示例 */ return(FunctionHelper.RunFunction <UpdateDocs_Parameters>(param, (typeParam, sb, result) => { var wwwrootDir = Path.Combine(Senparc.CO2NET.Config.RootDictionaryPath, "wwwroot"); var copyDir = Path.Combine(wwwrootDir, "NcfDocs"); //创建目录 FileHelper.TryCreateDirectory(wwwrootDir); FileHelper.TryCreateDirectory(copyDir); var gitUrl = "https://gitee.com/NeuCharFramework/NcfDocs"; try { Repository.Clone(gitUrl, copyDir, new CloneOptions() { IsBare = false }); } catch (Exception) { try { var mergeResult = LibGit2Sharp.Commands.Pull( new Repository(copyDir), new Signature("*****@*****.**", "*****@*****.**", SystemTime.Now), new PullOptions()); sb.AppendLine("已有文件存在,开始 pull 更新"); sb.AppendLine(mergeResult.Status.ToString()); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); } } sb.AppendLine($"仓库创建于 {copyDir}"); UpdateDocs_Version versionData = null; var versionFile = Path.Combine(copyDir, "version.json"); using (var fs = new FileStream(versionFile, FileMode.Open)) { using (var sr = new StreamReader(fs)) { var versionJson = sr.ReadToEnd(); versionData = versionJson.GetObject <UpdateDocs_Version>(); } } result.Message = $"更新成功,当前版本:{versionData.Version},更新时间:{versionData.UpdateTime.ToShortDateString()},What's New:{versionData.WhatsNew ?? "无"}"; })); }
/// <summary> /// 原生支付 模式一 /// </summary> /// <returns></returns> public ActionResult Native() { try { RequestHandler nativeHandler = new RequestHandler(null); string timeStamp = TenPayV3Util.GetTimestamp(); string nonceStr = TenPayV3Util.GetNoncestr(); //商品Id,用户自行定义 string productId = SystemTime.Now.ToString("yyyyMMddHHmmss"); nativeHandler.SetParameter("appid", TenPayV3Info.AppId); nativeHandler.SetParameter("mch_id", TenPayV3Info.MchId); nativeHandler.SetParameter("time_stamp", timeStamp); nativeHandler.SetParameter("nonce_str", nonceStr); nativeHandler.SetParameter("product_id", productId); string sign = nativeHandler.CreateMd5Sign("key", TenPayV3Info.Key); var url = TenPayOldV3.NativePay(TenPayV3Info.AppId, timeStamp, TenPayV3Info.MchId, nonceStr, productId, sign); BitMatrix bitMatrix; bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 600, 600); var bw = new ZXing.BarcodeWriterPixelData(); var pixelData = bw.Write(bitMatrix); var bitmap = new System.Drawing.Bitmap(pixelData.Width, pixelData.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb); var fileStream = new MemoryStream(); var bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, pixelData.Width, pixelData.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb); try { // we assume that the row stride of the bitmap is aligned to 4 byte multiplied by the width of the image System.Runtime.InteropServices.Marshal.Copy(pixelData.Pixels, 0, bitmapData.Scan0, pixelData.Pixels.Length); } finally { bitmap.UnlockBits(bitmapData); } bitmap.Save(_fileStream, System.Drawing.Imaging.ImageFormat.Png); _fileStream.Seek(0, SeekOrigin.Begin); return(File(_fileStream, "image/png")); } catch (Exception ex) { SenparcTrace.SendCustomLog("TenPayV3.Native 执行出错", ex.Message); SenparcTrace.BaseExceptionLog(ex); throw; } }
/// <summary> /// 扫描自动依赖注入的接口 /// </summary> public static IServiceCollection ScanAssamblesForAutoDI(this IServiceCollection services) { //遍历所有程序集进行注册 AssembleScanHelper.AddAssembleScanItem(assembly => { var areaRegisterTypes = assembly.GetTypes() //.GetExportedTypes() .Where(z => !z.IsAbstract && !z.IsInterface && z.GetInterface(nameof(IAutoDI)) != null) .ToArray(); DILifecycleType dILifecycleType = DILifecycleType.Scoped; foreach (var registerType in areaRegisterTypes) { try { //判断特性标签 var attrs = System.Attribute.GetCustomAttributes(registerType, false).Where(z => z is AutoDITypeAttribute); if (attrs.Count() > 0) { var attr = attrs.First() as AutoDITypeAttribute; dILifecycleType = attr.DILifecycleType;//使用指定的方式 } //针对不同的类型进行不同生命周期的 DI 设置 switch (dILifecycleType) { case DILifecycleType.Scoped: services.AddScoped(registerType); break; case DILifecycleType.Singleton: services.AddSingleton(registerType); break; case DILifecycleType.Transient: services.AddTransient(registerType); break; default: throw new NotImplementedException($"未处理此 DILifecycleType 类型:{dILifecycleType.ToString()}"); } } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); } } }, false); return(services); }
public void OnBaseExceptionFuncTest() { var onlogCount = 0; SenparcTrace.OnLogFunc = () => onlogCount++; var keyword = Guid.NewGuid().ToString();//随机字符串 var ex = new BaseException("测试异常:" + keyword); //Log会记录两次,第一次是在BaseException初始化的时候会调用此方法 SenparcTrace.BaseExceptionLog(ex); Assert.IsTrue(UnitTestHelper.CheckKeywordsExist(LogFilePath, keyword)); Assert.AreEqual(2, onlogCount); }
/// <summary> /// 申请资金账单接口 /// 获得微信支付按天提供的微信支付账户资金流水账单文件 /// </summary> /// <param name="bill_date">账单日期 格式YYYY-MM-DD 仅支持三个月内的账单下载申请</param> /// <param name="account_type">不填则默认是BASIC 枚举值:BASIC:基本账户 OPERATION:运营账户 FEES:手续费账户</param> /// <param name="tar_type"> 不填则默认是数据流 枚举值:GZIP:返回格式为.gzip的压缩包账单</param> /// <returns></returns> public async Task <BillReturnJson> FundflowBillQueryAsync(string bill_date, Stream fileStream, string account_type = "BASIC", string tar_type = null, int timeOut = Config.TIME_OUT) { try { var url = ReurnPayApiUrl($"https://api.mch.weixin.qq.com/{{0}}v3/bill/fundflowbill?bill_date={bill_date}&account_type={account_type}"); if (tar_type != null) { url += $"&tar_type={tar_type}"; } TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); var result = await tenPayApiRequest.RequestAsync <BillReturnJson>(url, null, timeOut, ApiRequestMethod.GET); //下载资金账单 if (result.VerifySignSuccess == true) { var responseMessage = await tenPayApiRequest.GetHttpResponseMessageAsync(result.download_url, null, requestMethod : ApiRequestMethod.GET); fileStream.Seek(0, SeekOrigin.Begin); await responseMessage.Content.CopyToAsync(fileStream); fileStream.Seek(0, SeekOrigin.Begin); //校验文件Hash var fileHash = FileHelper.GetFileHash(fileStream, result.hash_type); var fileVerify = fileHash.Equals(result.hash_value, StringComparison.OrdinalIgnoreCase); if (!fileVerify) { result.VerifySignSuccess = false; result.ResultCode.Additional += "请求成功,但文件校验错误。请查看日志!"; SenparcTrace.BaseExceptionLog(new TenpayApiRequestException($"TradeBillQueryAsync 下载文件成功,但校验失败,正确值:{result.hash_value},实际值:{fileHash}(忽略大小写)")); } } return(result); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new BillReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }
/// <summary> /// 获取 Entity SetKey 集合 /// </summary> /// <param name="dbContextType">DbContext 类型</param> /// <returns></returns> public static EntitySetKeysDictionary GetEntitySetInfo(Type dbContextType) { EntitySetKeysDictionary dic = new EntitySetKeysDictionary(); foreach (var setKeyInfo in AllKeys.Values.Where(z => z.SenparcEntityTypes.Contains(dbContextType))) { if (!dic.ContainsKey(setKeyInfo.DbSetType)) { var addSuccess = dic.TryAdd(setKeyInfo.DbSetType, setKeyInfo); if (!addSuccess) { SenparcTrace.BaseExceptionLog(new NcfDatabaseException($"GetEntitySetInfo 发生异常,DbSetType:{setKeyInfo.DbSetType.Name},setKeyInfo:{setKeyInfo.ToJson()}", null, dbContextType)); } } } return(dic); }
/// <summary> /// 获取静态类属性 /// </summary> /// <param name="type">类型</param> /// <param name="memberName">属性名称(忽略大小写)</param> /// <param name="recordLog">是否记录日志</param> /// <returns></returns> public static object GetStaticMember(Type type, string memberName, bool recordLog = false) { try { PropertyInfo[] props = type.GetProperties(); var prop = props.FirstOrDefault(z => z.Name.Equals(memberName, StringComparison.OrdinalIgnoreCase)); return(prop.GetValue(null, null)); } catch (Exception ex) { if (recordLog) { SenparcTrace.BaseExceptionLog(ex); } return(null); } }
public void BaseExceptionLogTest() { var keyword = Guid.NewGuid().ToString();//随机字符串 var ex = new BaseException("测试异常:" + keyword); //Log会记录两次,第一次是在BaseException初始化的时候会调用此方法 SenparcTrace.BaseExceptionLog(ex); var dt1 = SystemTime.Now; while (SystemTime.DiffTotalMS(dt1) < 800) { //等待队列执行 } Assert.IsTrue(UnitTestHelper.CheckKeywordsExist(LogFilePath, "测试异常", keyword)); }
/// <summary> /// 下载批次退款明细 /// 可获取到某批次的退款明细数据,包括订单号、单品信息、银行流水号等,用于对账/数据分析 /// <para>https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_11.shtml</para> /// </summary> /// <param name="stock_id">批次号</param> /// <param name="fileStream">fileStream</param> /// <param name="timeOut">超时时间,单位为ms</param> /// <returns></returns> public async Task <DownloadStockRefundFlowReturnJson> DownloadStockRefundFlowAsync(string stock_id, Stream fileStream, int timeOut = Config.TIME_OUT) { try { var url = ReurnPayApiUrl($"{Senparc.Weixin.Config.TenPayV3Host}/{{0}}v3/marketing/favor/stocks/{stock_id}/refund-flow"); TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); var result = await tenPayApiRequest.RequestAsync <DownloadStockRefundFlowReturnJson>(url, null, timeOut, ApiRequestMethod.GET); //下载交易账单 if (result.VerifySignSuccess == true) { var responseMessage = await tenPayApiRequest.GetHttpResponseMessageAsync(result.url, null, requestMethod : ApiRequestMethod.GET); fileStream.Seek(0, SeekOrigin.Begin); await responseMessage.Content.CopyToAsync(fileStream); fileStream.Seek(0, SeekOrigin.Begin); //校验文件Hash var fileHash = FileHelper.GetFileHash(fileStream, result.hash_type, false); Console.WriteLine("fileHash: " + fileHash); var fileVerify = fileHash.Equals(result.hash_value, StringComparison.OrdinalIgnoreCase); if (!fileVerify) { result.VerifySignSuccess = false; result.ResultCode.Additional += "请求成功,但文件校验错误。请查看日志!"; SenparcTrace.BaseExceptionLog(new TenpayApiRequestException($"TradeBillQueryAsync 下载文件成功,但校验失败,正确值:{result.hash_value},实际值:{fileHash}(忽略大小写)")); } } return(result); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new DownloadStockRefundFlowReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }
public override async Task InstallOrUpdateAsync(IServiceProvider serviceProvider, InstallOrUpdate installOrUpdate) { //TODO:DI注入注册时候,根据指定数据库进行绑定 XncfModuleServiceExtension xncfModuleServiceExtension = serviceProvider.GetService <XncfModuleServiceExtension>(); //SenparcEntities senparcEntities = (SenparcEntities)xncfModuleServiceExtension.BaseData.BaseDB.BaseDataContext; SenparcEntities senparcEntities = (SenparcEntities)xncfModuleServiceExtension.BaseData.BaseDB.BaseDataContext; //更新数据库 var pendingMigs = await senparcEntities.Database.GetPendingMigrationsAsync(); if (pendingMigs.Count() > 0) { senparcEntities.ResetMigrate();//重置合并状态 try { var script = senparcEntities.Database.GenerateCreateScript(); SenparcTrace.SendCustomLog("senparcEntities.Database.GenerateCreateScript", script); senparcEntities.Migrate();//进行合并 } catch (Exception ex) { var currentDatabaseConfiguration = DatabaseConfigurationFactory.Instance.Current; SenparcTrace.BaseExceptionLog(new NcfDatabaseException(ex.Message, currentDatabaseConfiguration.GetType(), senparcEntities.GetType(), ex)); } } //更新数据库(目前不使用 SystemServiceEntities 存放数据库模型) //await base.MigrateDatabaseAsync<SystemServiceEntities>(serviceProvider); var systemModule = xncfModuleServiceExtension.GetObject(z => z.Uid == this.Uid); if (systemModule == null) { //只在未安装的情况下进行安装,InstallModuleAsync会访问到此方法,不做判断可能会引发死循环。 //常规模块中请勿在此方法中自动安装模块! await xncfModuleServiceExtension.InstallModuleAsync(this.Uid).ConfigureAwait(false); } await base.InstallOrUpdateAsync(serviceProvider, installOrUpdate); }
/// <summary> /// 获取领域缓存(指定特定 的IBaseObjectCacheStrategy 缓存策略对象) /// </summary> /// <param name="baseObjectCacheStrategy">IBaseObjectCacheStrategy 缓存策略对象</param> /// <param name="cacheStrategyDomain">缓存领域</param> /// <returns></returns> public static IDomainExtensionCacheStrategy GetDomainExtensionCacheStrategy(IBaseObjectCacheStrategy baseObjectCacheStrategy, ICacheStrategyDomain cacheStrategyDomain) { var identityName = cacheStrategyDomain.IdentityName; var mappingCollection = GetMappingCollection(identityName);//当前扩展缓存可能已经注册的所有基础缓存 if (mappingCollection.ContainsKey(baseObjectCacheStrategy)) { var item = mappingCollection[baseObjectCacheStrategy]; return(item.DomainExtensionCacheStrategy); } else { //未注册,默认情况下使用本地缓存策略(应急) var ex = new Exceptions.UnregisteredDomainCacheStrategyException(cacheStrategyDomain.GetType(), baseObjectCacheStrategy.GetType()); SenparcTrace.BaseExceptionLog(ex); throw ex; } }
// TODO: 待测试 /// <summary> /// 查询单笔退款接口 /// </summary> /// <param name="out_refund_no">商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。示例值:1217752501201407033233368018</param> /// <param name="timeOut">超时时间,单位为ms</param> /// <returns></returns> public async Task <RefundReturnJson> RefundQueryAsync(string out_refund_no, int timeOut = Config.TIME_OUT) { try { var url = ReurnPayApiUrl($"https://api.mch.weixin.qq.com/{{0}}v3/refund/domestic/refunds{out_refund_no}"); TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); return(await tenPayApiRequest.RequestAsync <RefundReturnJson>(url, null, timeOut, ApiRequestMethod.GET)); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new RefundReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }
// TODO: 待测试 /// <summary> /// Native支付下单接口 /// <para>在微信支付服务后台生成Native支付预支付交易单,返回预支付交易会话标识</para> /// </summary> /// <param name="data">微信支付需要POST的Data数据</param> /// <param name="timeOut">超时时间,单位为ms </param> /// <returns></returns> public async Task <NativeReturnJson> NativeAsync(TransactionsRequestData data, int timeOut = Config.TIME_OUT) { try { var url = ReurnPayApiUrl(Senparc.Weixin.Config.TenPayV3Host + "/{0}v3/pay/transactions/native"); TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); return(await tenPayApiRequest.RequestAsync <NativeReturnJson>(url, data, timeOut)); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new NativeReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }
// TODO: 待测试 /// <summary> /// 商户订单号查询 /// <para>https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_2.shtml</para> /// </summary> /// <param name="out_trade_no"> 微信支付系统生成的订单号 示例值:1217752501201407033233368018</param> /// <param name="mchid">直连商户的商户号,由微信支付生成并下发。 示例值:1230000109</param> /// <param name="timeOut">超时时间,单位为ms</param> /// <returns></returns> public async Task <OrderReturnJson> OrderQueryByOutTradeNoAsync(string out_trade_no, string mchid, int timeOut = Config.TIME_OUT) { try { var url = ReurnPayApiUrl($"{Senparc.Weixin.Config.TenPayV3Host}/{{0}}v3/pay/transactions/out-trade-no/{out_trade_no}?mchid={mchid}"); TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); return(await tenPayApiRequest.RequestAsync <OrderReturnJson>(url, null, timeOut, ApiRequestMethod.GET)); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new OrderReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }
/// <summary> /// 获取静态类属性 /// </summary> /// <param name="assemblyName">类型所在程序集名称</param> /// <param name="nameSpace">类型所在命名空间</param> /// <param name="className">类型名</param> /// <param name="memberName">属性名称(忽略大小写)</param> /// <param name="recordLog">是否记录日志</param> /// <returns></returns> public static object GetStaticMember(string assemblyName, string nameSpace, string className, string memberName, bool recordLog = false) { try { string fullName = nameSpace + "." + className; //命名空间.类型名 string path = fullName + "," + assemblyName; //命名空间.类型名,程序集 var type = Type.GetType(path); PropertyInfo[] props = type.GetProperties(); var prop = props.FirstOrDefault(z => z.Name.Equals(memberName, StringComparison.OrdinalIgnoreCase)); return(prop.GetValue(null, null)); } catch (Exception ex) { if (recordLog) { SenparcTrace.BaseExceptionLog(ex); } return(null); } }
// TODO: 待测试 /// <summary> /// 关闭订单接口 /// </summary> /// <param name="out_trade_no">商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 示例值:1217752501201407033233368018</param> /// <param name="mchid">直连商户的商户号,由微信支付生成并下发。 示例值:1230000109</param> /// <param name="timeOut">超时时间,单位为ms</param> /// <returns></returns> public async Task <ReturnJsonBase> CloseOrderAsync(string out_trade_no, string mchid, int timeOut = Config.TIME_OUT) { try { var url = ReurnPayApiUrl($"{Senparc.Weixin.Config.TenPayV3Host}/{{0}}v3/pay/transactions/out-trade-no/{out_trade_no}/close"); TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); return(await tenPayApiRequest.RequestAsync <ReturnJsonBase>(url, mchid, timeOut)); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new ReturnJsonBase() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }
// TODO: 待测试 /// <summary> /// 申请退款接口 /// </summary> /// <param name="data">请求数据</param> /// <param name="timeOut">超时时间,单位为ms</param> /// <returns></returns> public async Task <RefundReturnJson> RefundAsync(RefundRequsetData data, int timeOut = Config.TIME_OUT) { try { var url = ReurnPayApiUrl($"https://api.mch.weixin.qq.com/{{0}}v3/refund/domestic/refunds"); TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); return(await tenPayApiRequest.RequestAsync <RefundReturnJson>(url, data, timeOut)); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new RefundReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }
// TODO: 待测试 /// <summary> /// 合单关闭订单接口 /// </summary> /// <param name="combine_out_trade_no">合单支付总订单号 示例值:P20150806125346</param> /// <param name="data">合单关闭订单请求数据</param> /// <param name="timeOut">超时时间,单位为ms</param> /// <returns></returns> public async Task <ReturnJsonBase> CloseCombineOrderAsync(string combine_out_trade_no, CloseCombineOrderRequestData data, int timeOut = Config.TIME_OUT) { try { var url = ReurnPayApiUrl($"https://api.mch.weixin.qq.com/{{0}}v3/combine-transactions/out-trade-no/{combine_out_trade_no}/close"); TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); return(await tenPayApiRequest.RequestAsync <ReturnJsonBase>(url, data, timeOut)); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new ReturnJsonBase() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }
// TODO: 待测试 /// <summary> /// 合单查询订单接口 /// </summary> /// <param name="combine_out_trade_no">合单支付总订单号 示例值:P20150806125346</param> /// <param name="timeOut">超时时间,单位为ms</param> /// <returns></returns> public async Task <CombineOrderReturnJson> CombineOrderQueryAsync(string combine_out_trade_no, int timeOut = Config.TIME_OUT) { try { var url = ReurnPayApiUrl($"https://api.mch.weixin.qq.com/{{0}}v3/combine-transactions/out-trade-no/{combine_out_trade_no}"); TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); return(await tenPayApiRequest.RequestAsync <CombineOrderReturnJson>(url, null, timeOut, ApiRequestMethod.GET)); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new CombineOrderReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }
// TODO: 待测试 /// <summary> /// 微信支付订单号查询 /// </summary> /// <param name="transaction_id"> 微信支付系统生成的订单号 示例值:1217752501201407033233368018</param> /// <param name="mchid">直连商户的商户号,由微信支付生成并下发。 示例值:1230000109</param> /// <param name="timeOut">超时时间,单位为ms</param> /// <returns></returns> public async Task <OrderReturnJson> OrderQueryByTransactionIdAsync(string transaction_id, string mchid, int timeOut = Config.TIME_OUT) { try { var url = ReurnPayApiUrl($"https://api.mch.weixin.qq.com/{{0}}v3/pay/transactions/id/{transaction_id}?mchid={mchid}"); TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); return(await tenPayApiRequest.RequestAsync <OrderReturnJson>(url, null, timeOut, ApiRequestMethod.GET)); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new OrderReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }
// TODO: 待测试 /// <summary> /// Native合单支付下单接口 /// <para>在微信支付服务后台生成Native合单支付预支付交易单,返回预支付交易会话标识</para> /// </summary> /// <param name="data">微信支付需要POST的Data数据</param> /// <param name="timeOut">超时时间,单位为ms </param> /// <returns></returns> public async Task <NativeReturnJson> NativeCombineAsync(CombineTransactionsRequestData data, int timeOut = Config.TIME_OUT) { try { var url = ReurnPayApiUrl("https://api.mch.weixin.qq.com/{0}v3/combine-transactions/native"); TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting); return(await tenPayApiRequest.RequestAsync <NativeReturnJson>(url, data, timeOut)); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); return(new NativeReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } }); } }