public DefatultAlipayHelper( AlipayF2FService alipayF2FService, AlipayService alipayService, IOptions <FTFConfig> fTFConfigOptions ) { _alipayF2FService = alipayF2FService; _alipayService = alipayService; _fTFConfig = fTFConfigOptions.Value; }
/// <summary> /// FTF渲染二维码 /// </summary> /// <param name="str"></param> /// <returns></returns> private Bitmap RenderQrCode(string str, FTFConfig fTFConfig = null) { var eccLevel = QRCodeGenerator.ECCLevel.L; using (var qrGenerator = new QRCodeGenerator()) { using (var qrCodeData = qrGenerator.CreateQrCode(str, eccLevel)) { using (var qrCode = new QRCode(qrCodeData)) { var bp = qrCode.GetGraphic(20, Color.Black, Color.White, new Bitmap(fTFConfig == null ? this._fTFConfig?.QRCodeIconFullPath : fTFConfig.QRCodeIconFullPath), 15); return(bp); } } } }
/// <summary> /// 面对面支付(轮询),返回生成的图片二维码byte数组 /// </summary> /// <param name="input">支付信息</param> /// <param name="loopQueryAction"></param> /// <param name="fTFConfig">面对面支付配置信息(不填则使用全局配置的)</param> /// <returns></returns> public async Task <FTFOutput> FTFPay(AlipayTradePrecreateContentBuilder input, Action <AlipayF2FPrecreateResult> loopQueryAction, FTFConfig fTFConfig = null) { return(await this.FTFGenQRCode(input, null, loopQueryAction, fTFConfig)); }
/// <summary> /// 面对面支付(异步消息通知),返回生成的图片二维码byte数组 /// </summary> /// <param name="input">支付信息</param> /// <param name="asyncNotifyUrl">异步消息通知地址</param> /// <param name="fTFConfig">面对面支付配置信息(不填则使用全局配置的)</param> /// <returns>二维码图片字节数组</returns> public async Task <FTFOutput> FTFPay(AlipayTradePrecreateContentBuilder input, string asyncNotifyUrl, FTFConfig fTFConfig = null) { return(await this.FTFGenQRCode(input, asyncNotifyUrl, null, fTFConfig)); }
/// <summary> /// 面对面支付生成支付二维码 /// </summary> /// <param name="input">支付数据</param> /// <param name="asyncNotifyUrl">异步通知地址,为空则表示为同步轮询模式</param> /// <param name="loopQueryAction">同步轮询回调函数</param> /// <param name="fTFConfig">面对面支付其它配置</param> /// <returns></returns> private async Task <FTFOutput> FTFGenQRCode(AlipayTradePrecreateContentBuilder input, string asyncNotifyUrl, Action <AlipayF2FPrecreateResult> loopQueryAction, FTFConfig fTFConfig) { // 参数检测 var isAsyncNotify = !asyncNotifyUrl.IsNullOrWhiteSpace(); if (!isAsyncNotify && loopQueryAction == null) { throw new NullReferenceException("轮询模式下 loopQueryAction 不能为空!"); } // 收款账号检测,如果为空则默认填入全局配置的Uid if (input.seller_id.IsNullOrWhiteSpace()) { input.seller_id = this._alipayService.Options.Uid; } Bitmap bitmap = null; MemoryStream memoryStream = null; var message = string.Empty; //推荐使用轮询撤销机制,不推荐使用异步通知,避免单边账问题发生。 AlipayF2FPrecreateResult precreateResult = null; // 异步通知 if (isAsyncNotify) { precreateResult = await _alipayF2FService.TradePrecreateAsync(input, asyncNotifyUrl); }// 同步轮询 else { precreateResult = await _alipayF2FService.TradePrecreateAsync(input); } switch (precreateResult.Status) { case F2FResultEnum.SUCCESS: // 将链接用二维码工具生成二维码打印出来,顾客可以用支付宝钱包扫码支付。 bitmap = RenderQrCode(precreateResult.response.QrCode); // 同步轮询模式,触发轮询回调函数 if (!isAsyncNotify) { loopQueryAction.Invoke(precreateResult); } break; case F2FResultEnum.FAILED: message = $"生成二维码失败: {precreateResult.response.Body}"; break; case F2FResultEnum.UNKNOWN: message = "生成二维码失败:" + (precreateResult.response == null ? "配置或网络异常,请检查后重试" : "系统异常,请更新外部订单后重新发起请求"); break; } // 如果位图为空,则生成错误提示二维码 if (bitmap == null) { bitmap = new Bitmap(fTFConfig == null ? this._fTFConfig?.QRCodeGenErrorImageFullPath : fTFConfig.QRCodeGenErrorImageFullPath); } // 转换成字节数组 memoryStream = new MemoryStream(); bitmap.Save(memoryStream, ImageFormat.Png); var imgBuffer = memoryStream.GetBuffer(); // 释放资源 memoryStream.Dispose(); bitmap.Dispose(); return(new FTFOutput() { QRCodeImageBuffer = imgBuffer, IsSuccess = precreateResult.Status == F2FResultEnum.SUCCESS, Message = message }); }
public IServiceProvider ConfigureServices(IServiceCollection services) { #region 配置MVC与SingalR中间件 //MVC services.AddControllersWithViews(options => { options.Filters.Add(new AbpAutoValidateAntiforgeryTokenAttribute()); }) #if DEBUG .AddRazorRuntimeCompilation() #endif .AddNewtonsoftJson(options => { ////将所有枚举序列化为字符串 options.SerializerSettings.Converters.Add(new StringEnumConverter()); }) ; // Add SingalR services.AddSignalR(options => { options.EnableDetailedErrors = true; }); #endregion 配置MVC与SingalR中间件 #region 配置前后端分离跨域 // 配置前后端分离跨域 services.AddCors( options => options.AddPolicy( _defaultCorsPolicyName, builder => builder .WithOrigins( // 在appsettings.json中可以包含多个跨域地址,由逗号隔开。 _appConfiguration["App:CorsOrigins"] .Split(",", StringSplitOptions.RemoveEmptyEntries) .Select(o => o.RemovePostFix("/")) .ToArray() ) .SetIsOriginAllowedToAllowWildcardSubdomains() .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials() ) ); #endregion 配置前后端分离跨域 #region 配置支付宝 services.AddYoYoAlipay(() => { var res = _appConfiguration.GetSection("Pay:Alipay").Get <AlipayOptions>(); return(res); }, (fTFConfig) => { if (fTFConfig == null) { fTFConfig = new FTFConfig(); } fTFConfig.QRCodeGenErrorImageFullPath = System.IO.Path.Combine(_env.WebRootPath, "imgs", "pay", "alipay_error.png"); fTFConfig.QRCodeIconFullPath = System.IO.Path.Combine(_env.WebRootPath, "imgs", "pay", "alipay.png"); }); #endregion 配置支付宝 services.AddHttpClient(); // Add Wchat SenparcWXConfigurer.AddWechat(services, _appConfiguration); IdentityRegistrar.Register(services); AuthConfigurer.Configure(services, _appConfiguration); // IdentityServer4 配置 if (bool.Parse(_appConfiguration["IdentityServer:IsEnabled"])) { IdentityServerRegistrar.Register(services, _appConfiguration); } #region 配置SwaggerUI if (WebConsts.SwaggerUiEnabled) { //Swagger -启用此行以及Configure方法中的相关行,以启用Swagger UI services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Title = "52ABP-PRO API", Version = "v1", Description = "52ABP-PRO 的动态WEBAPI管理端,可以进行测试和调用API。", TermsOfService = new Uri("https://gitee.com/ABPCN/52abp-pro"), Contact = new OpenApiContact { Name = "52abp.com", Email = "*****@*****.**", Url = new Uri("https://www.52abp.com/") }, }); // 使用 camel case 的枚举 //options.DescribeStringEnumsInCamelCase(); //使用相对路径获取应用程序所在目录 options.DocInclusionPredicate((docName, description) => true); // 支持非body内容中的枚举 options.ParameterFilter <SwaggerEnumParameterFilter>(); // 对应client枚举转为字符串对应值 options.SchemaFilter <SwaggerEnumSchemaFilter>(); options.OperationFilter <SwaggerOperationIdFilter>(); options.OperationFilter <SwaggerOperationFilter>(); options.CustomDefaultSchemaIdSelector(); options.OrderActionsBy(x => x.RelativePath); options.DescribeAllParametersInCamelCase(); ConfigApiDoc(options); }); // 使用 newtonsoft.json 做swagger的序列化工具 services.AddSwaggerGenNewtonsoftSupport(); } #endregion 配置SwaggerUI if (WebConsts.HangfireDashboardEnabled) { // 启用hangfire services.AddHangfire(config => { config.UseSqlServerStorage(_appConfiguration.GetConnectionString("Default")); // config.UseRecurringJob(typeof(RecurringJobService)); //注入Hnagfire的测试服务 }); } #region 配置健康检查服务 //services.AddHealthChecks().AddSqlServer(_appConfiguration["ConnectionStrings:Default"]); //services.AddHealthChecksUI(); if (bool.Parse(_appConfiguration["HealthChecks:HealthChecksEnabled"])) { services.AddYoyoCmsHealthCheck(); var healthCheckUISection = _appConfiguration.GetSection("HealthChecks")?.GetSection("HealthChecksUI"); if (bool.Parse(healthCheckUISection["HealthChecksUIEnabled"])) { services.Configure <HealthChecksUISettings>(settings => { healthCheckUISection.Bind(settings, c => c.BindNonPublicProperties = true); }); services.AddHealthChecksUI().AddInMemoryStorage(); } } #endregion 配置健康检查服务 // 配置abp和依赖注入 return(services.AddAbp <YoyoCmsTemplateWebHostModule>(options => { // 配置log4net options.IocManager.IocContainer.AddFacility <LoggingFacility>( f => f.UseAbpLog4Net().WithConfig("log4net.config")); } )); }