Magicodes.Pay(统一支付库)
Nuget
主要功能
Magicodes.Pay,是心莱科技团队提供的统一支付库,相关库均使用.NET标准库编写,支持.NET
Framework以及.NET Core。目前支持以下支付方式和功能:
支付宝支付
APP支付
Wap支付
支付宝国际支付
支持分账
微信支付
小程序支付
APP支付
订单查询
企业付款(提现)
退款申请
普通红包
统一支付回调处理
支持日志函数注入(不依赖支付库)
支持支付配置函数注入,以便于支持自定义配置获取逻辑,以应用于不同的场景(比如从配置文件、用户设置获取配置,或者多租户支持)
目前此库我们在很多项目上已经进行了验证,由于项目赶工,许多功能我们并没有添加、迁移或者重构过来,在后续的过程中,我们会逐步来完成这些工作。同时,在Magicodes.Admin开源库中,我们也编写了相关的Demo和实现。
Magicodes.Admin开源库地址:https://gitee.com/magicodes/Magicodes.Admin.Core
整个支付实现这块,我们在Magicodes.Admin开源库中已经提供了统一支付的Demo,而且我们将会提供根据请求头来自动调用相关支付的功能。如下图所示:
在各个业务支付场景中,我们可以非常方便的调用此统一支付,如下图所示:
VNext
这是目前的下个版本的规划:
支付宝PC支付
微信H5支付
提供默认的回调管理逻辑,支持回调处理函数的注入
具体功能我们会根据项目的情况来迭代,如果你有好的建议或者意见,可以关注我们的公众号“magiccodes”来提交您的意见或者意见。
如何配置
相关库的配置相对比较简单,一般均使用相关Builder类来配置自定义日志逻辑、配置获取逻辑等,具体可以查阅Builder目录下的代码。
配置参考
部分代码如下所示:
配置界面参考
如下图所示:
Demo
微信支付Demo
if (WeChatPayApi == null)
{
throw new UserFriendlyException(“支付未开放,请联系管理员!”);
}
var appPayInput = new WeChat.Pay.Dto.AppPayInput
{
Body = input.Body,
OutTradeNo = input.OutTradeNo,
Attach = input.CustomData,
TotalFee = input.TotalAmount,
SpbillCreateIp = _clientInfoProvider?.ClientIpAddress
};
try
{
var appPayOutput = WeChatPayApi.AppPay(appPayInput);
return Task.FromResult(appPayOutput);
}
catch (Exception ex)
{
throw new UserFriendlyException(ex.Message);
}
支付宝支付Demo
if (AlipayAppService == null)
{
throw new UserFriendlyException(“支付未开放,请联系管理员!”);
}
var appPayInput = new Alipay.Dto.AppPayInput
{
Body = input.Body,
Subject = input.Subject,
TradeNo = input.OutTradeNo,
PassbackParams = input.CustomData,
TotalAmount = input.TotalAmount
};
try
{
var appPayOutput = await AlipayAppService.AppPay(appPayInput);
return appPayOutput.Response.Body;
}
catch (Exception ex)
{
throw new UserFriendlyException(ex.Message);
}
支付宝国际支付Demo
if (GlobalAlipayAppService == null)
{
throw new UserFriendlyException(“支付未开放,请联系管理员!”);
}
var payInput = new Alipay.Global.Dto.PayInput
{
Body = input.Body,
Subject = input.Subject,
TradeNo = input.OutTradeNo,
//PassbackParams = input.CustomData,
TotalFee = input.TotalAmount,
};
try
{
return await GlobalAlipayAppService.Pay(payInput);
}
catch (Exception ex)
{
throw new UserFriendlyException(ex.Message);
}
国际支付宝分账参考界面
支付回调
目的
统一回调处理逻辑和回调处理地址
代码参考
上图的PayAction参考:
void PayAction(string key, string outTradeNo, string transactionId, int
totalFee, JObject data)
{
using (var paymentCallbackManagerObj =
iocManager.ResolveAsDisposable<PaymentCallbackManager>())
{
var paymentCallbackManager = paymentCallbackManagerObj?.Object;
if (paymentCallbackManager == null)
{
throw new ApplicationException(“支付回调管理器异常,无法执行回调!”);
}
AsyncHelper.RunSync(async () => await
paymentCallbackManager.ExecuteCallback(key, outTradeNo, transactionId, totalFee,
data));
}
}
完整回调代码请参考此代码:https://gitee.com/magicodes/Magicodes.Admin.Core/blob/develop/src/unity/Magicodes.Pay/Startup/PayStartup.cs
回调逻辑参考:
Magicodes.Storage(统一存储库)
说明
Magicodes.Storage,是心莱科技团队提供的统一存储库,相关库均使用.NET标准库(netstandard2.0)编写,支持.NET
Framework以及.NET Core。
我们希望,使用了Magicodes.Storage之后,开发者可以很快的从本地存储切换到云端存储;我们希望,使用了Magicodes.Storage之后,开发者可以快速地从不同的云存储供应商之间切换。
目前主要支持以下存储:
本地存储(本地站点目录)
阿里云存储
腾讯云存储
相关Nuget包
相关实践
我们围绕Magicodes.Admin开源库做了许多实践。如下图所示:
Magicodes.Admin开源库地址:https://gitee.com/magicodes/Magicodes.Admin.Core
VNext
这是目前的下个版本的规划:
支持分块上传
支持存储桶的创建和删除
支持Azure存储
支持亚马逊存储
支持七牛云
阿里云的SDK包更新为官方的包(目前还存在问题)
具体功能我们会根据项目的情况来迭代,如果你有好的建议或者意见,可以关注我们的公众号“magiccodes”来提交您的意见或者意见。
如何配置
相关库的配置相对比较简单,一般均使用相关Builder类来配置自定义日志逻辑、配置获取逻辑等,具体可以查阅Builder目录下的代码。
配置参考
部分代码如下所示:
使用代码可以参考:
单元测试:
Magicodes.WeChat.SDK(微信、小程序SDK)
相关介绍见http://www.cnblogs.com/codelove/p/6061406.html
已添加小程序SDK,具体使用见相关单元测试以及相关框架
Magicodes.Sms(短信支持库)
短信服务核心库。
官方网址:http://xin-lai.com
开源库地址:https://github.com/xin-lai
博客地址:http://www.cnblogs.com/codelove/
交流QQ群:85318032
小店地址:https://shop113059108.taobao.com/
最新框架(完全支持.NET
Core):https://gitee.com/magicodes/Magicodes.Admin.Core
已更新为.NET标准库,支持.NET Core
已编写单元测试,可以自行配置。
配置
AliyunSmsBuilder.Create()
//设置日志记录
.WithLoggerAction((tag, message) =>
{
Console.WriteLine(string.Format(“Tag:{0}\tMessage:{1}”, tag, message));
}).SetSettingsFunc(() =>
{
//TODO:请自行配置自己的配置
//如果是一个项目多个配置,请使用key来获取相关配置
return ConfigHelper.LoadConfig(“aliyun_app”);
}).Build();
阿里云短信发送
[Theory(DisplayName = “短信发送测试”)]
[InlineData(“你的手机号码”, “验证码”)]
public async Task SendCodeAsync_Test(string phone, string code)
{
var smsService = new AliyunSmsService();
var result = await smsService.SendCodeAsync(phone, code);
result.Success.ShouldBeTrue();
}
Magicodes.ExporterAndImporter(导入导出)
特点
封装导入导出业务,目前仅支持Excel,后续将支持CSV以及其他业务
配置特性即可控制相关逻辑和显示结果,无需修改逻辑代码
推荐配合DTO使用
导出支持列头自定义处理以便支持多语言等场景
导出支持文本自定义过滤或处理
导入支持验证逻辑(即将支持)
导入支持自定义过滤或处理(即将支持)
导入支持自动根据DTO生成导入模板(即将支持)
导出Demo
Demo1
普通导出
public class ExportTestData
{
public string Name1 { get; set; }
public string Name2 { get; set; }
public string Name3 { get; set; }
public string Name4 { get; set; }
}
var result = await Exporter.Export(filePath, new List<ExportTestData>()
{
new ExportTestData()
{
Name1 = “1”,
Name2 = “test”,
Name3 = “12”,
Name4 = “11”,
},
new ExportTestData()
{
Name1 = “1”,
Name2 = “test”,
Name3 = “12”,
Name4 = “11”,
}
});
Demo2
特性导出
[ExcelExporter(Name = “测试”, TableStyle = “Light10”)]
public class ExportTestDataWithAttrs
{
[ExporterHeader(DisplayName = “加粗文本”, IsBold = true)]
public string Text { get; set; }
[ExporterHeader(DisplayName = “普通文本”)]
public string Text2 { get; set; }
[ExporterHeader(DisplayName = “忽略”, IsIgnore = true)]
public string Text3 { get; set; }
[ExporterHeader(DisplayName = “数值”, Format = “#,##0”)]
public double Number { get; set; }
[ExporterHeader(DisplayName = “名称”, IsAutoFit = true)]
public string Name { get; set; }
}
var result = await Exporter.Export(filePath, new
List<ExportTestDataWithAttrs>()
{
new ExportTestDataWithAttrs()
{
Text = “啊实打实大苏打撒”,
Name=”aa”,
Number =5000,
Text2 = “w萨达萨达萨达撒”,
Text3 = “sadsad打发打发士大夫的”
},
new ExportTestDataWithAttrs()
{
Text = “啊实打实大苏打撒”,
Name=”啊实打实大苏打撒”,
Number =6000,
Text2 = “w萨达萨达萨达撒”,
Text3 = “sadsad打发打发士大夫的”
},
new ExportTestDataWithAttrs()
{
Text = “啊实打实速度大苏打撒”,
Name=”萨达萨达”,
Number =6000,
Text2 = “突然他也让他人”,
Text3 = “sadsad打发打发士大夫的”
},
});
Demo3
列头处理或者多语言支持
[ExcelExporter(Name = “测试”, TableStyle = “Light10”)]
public class AttrsLocalizationTestData
{
[ExporterHeader(DisplayName = “加粗文本”, IsBold = true)]
public string Text { get; set; }
[ExporterHeader(DisplayName = “普通文本”)]
public string Text2 { get; set; }
[ExporterHeader(DisplayName = “忽略”, IsIgnore = true)]
public string Text3 { get; set; }
[ExporterHeader(DisplayName = “数值”, Format = “#,##0”)]
public double Number { get; set; }
[ExporterHeader(DisplayName = “名称”, IsAutoFit = true)]
public string Name { get; set; }
}
ExcelBuilder.Create().WithLocalStringFunc((key) =>
{
if (key.Contains(“文本”))
{
return “Text”;
}
return “未知语言”;
}).Build();
var filePath = Path.Combine(Directory.GetCurrentDirectory(),
“testAttrsLocalization.xlsx”);
if (File.Exists(filePath)) File.Delete(filePath);
var result = await Exporter.Export(filePath, new
List<AttrsLocalizationTestData>()
{
new AttrsLocalizationTestData()
{
Text = “啊实打实大苏打撒”,
Name=”aa”,
Number =5000,
Text2 = “w萨达萨达萨达撒”,
Text3 = “sadsad打发打发士大夫的”
},
new AttrsLocalizationTestData()
{
Text = “啊实打实大苏打撒”,
Name=”啊实打实大苏打撒”,
Number =6000,
Text2 = “w萨达萨达萨达撒”,
Text3 = “sadsad打发打发士大夫的”
},
new AttrsLocalizationTestData()
{
Text = “啊实打实速度大苏打撒”,
Name=”萨达萨达”,
Number =6000,
Text2 = “突然他也让他人”,
Text3 = “sadsad打发打发士大夫的”
},
});
Magicodes.SwaggerUI(API文档生成)
快速配置和集成SwaggerUI Magicodes SwaggerUI扩展库
配置Demo:
“SwaggerDoc”: {
“IsEnabled”: “true”,
“Title”: “Api Documents”,
“Version”: “v1”,
“Description”: “”,
“Contact”: {
“Name”: “心莱科技”,
“Email”: “xinlai@xin-lai.com”
},
//以便于在界面上显示验证(Authorize)按钮,验证按钮处理逻辑基于
wwwroot/swagger/ui/index.html
“Authorize”: “true”,
“HiddenApi”: {
“IsEnabled”: “false”,
“HiddenUrls”: “”
},
//将枚举值以字符串显示
“DescribeAllEnumsAsStrings”: true,
//设置api首页从嵌入资源中加载
“ManifestResourceAssembly”: “Magicodes.Admin.Web.Host”,
“ManifestResourceUrl”: “Magicodes.Admin.Web.wwwroot.swagger.ui.index.html”
},
注入代码:
//添加自定义API文档生成(支持文档配置) public IServiceProvider
ConfigureServices(IServiceCollection services) {
services.AddCustomSwaggerGen(_appConfiguration, _hostingEnvironment); }
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory) { //启用自定义API文档(支持文档配置)
app.UseCustomSwaggerUI(_appConfiguration); }
Magicodes.Districts(行政区域)
行政区域信息核心库。以便于获取最新的行政区域数据用于自动更新业务数据库等。
官方网址:http://xin-lai.com
开源库地址:https://github.com/xin-lai
博客地址:http://www.cnblogs.com/codelove/
交流QQ群:85318032
小店地址:https://shop113059108.taobao.com/
最新框架(完全支持.NET
Core):https://gitee.com/magicodes/Magicodes.Admin.Core
已更新为.NET标准库,支持.NET Core
已编写单元测试,可以自行配置。
目前只支持通过高德API获取。后续再对接其他服务商。
高德接口配置
请先申请高德的开发者Key。
var districtsProvider = new AmapDistrictsProvider(settings.ApiKey);
获取中国省市区街道信息
var result = await DistrictsProvider.GetDistricts();
具体见单元测试:
[Fact]
public async Task GetDistricts_TestsAsync()
{
var result = await DistrictsProvider.GetDistricts();
result.ShouldNotBeNull();
//一级行政区(省级行政区):34个(23个省、5个自治区、4个直辖市、2个特别行政区)
…台湾
result[0].Children.Count.ShouldBeGreaterThanOrEqualTo(34);
//二级行政区(地级行政区):334个(294个地级市、7个地区、30个自治州、3个盟)
result[0].Children.Sum(p =>
p.Children.Count).ShouldBeGreaterThanOrEqualTo(334);
}
[Fact]
public async Task GetDistrictsByKeywords_TestsAsync()
{
var result = await DistrictsProvider.GetDistricts(“湖南”);
result.ShouldNotBeNull();
//截止2017年9月12日,湖南省共计划分为14个地区(13地级市和1自治州),122个县级行政区包括35个市辖区、17个县级市、63个县和7个自治县
result[0].Children.Count.ShouldBeGreaterThanOrEqualTo(14);
result[0].Children.Sum(p =>
p.Children.Count).ShouldBeGreaterThanOrEqualTo(122);
}
Magicodes.Echarts(基于EChart封装的映射库)
Magicodes.ECharts是心莱团队基于百度EChart封装的开源的.NET类库,以便让用户更快更便捷的上手开发EChart图表。
相关资料请访问我们的官方博客。
使用教程:http://www.cnblogs.com/codelove/p/5969036.html
官方博客:http://www.cnblogs.com/codelove/
相关开源库地址:https://github.com/xin-lai
我们的官网:http://xin-lai.com
在开始之前,您需要了解以下内容:
Magicodes.ECharts是基于百度EChart封装的开源的.NET类库,封装的目的便于使用强类型语言约束后台代码,以便于更好维护和重构代码,并且封装自身业务
Magicodes.EChartsJS是基于knockoutJs封装的组件,结合Magicodes.ECharts能够很方便的利用Ajax加载Echart图表
目前Magicodes.ECharts已经支持大部分图表,但是尚不能支持所有图表和所有情形
本着按需设计的原则,在遇到不支持的情形,希望您能够自行扩展并贡献自己的代码。众人拾材火焰高,Magicodes.ECharts在不断地实践中会更加完善的
在设计上,我们不会过多设计,但是后续版本可能会不断地进行重构
源码中提供了一些Demo,在开始之前,请进行阅读。
Magicodes.Mvc.TrustIP(服务端授信IP中间件)
基于ASP.NET
Core的筛选器和中间件打造的通用授信IP通用库,支持筛选器和中间件配置,支持全局和局部使用.
Nuget
VNext
黑名单
支持内存缓存以及分布式缓存
本地IP是否授信
配置
支持配置多个授信IP,如下”TrustIpList”所示:
{ “TrustIpList”: [ “218.76.8.29”, “::1” ] }
注意:0.0.0.0 表示支持任意Ip
使用
筛选器
启用全局筛选器
services.AddMvc(options =>
options.Filters.Add(typeof(TrustIPFilter))).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
在控制器中使用
// GET api/values
[HttpGet]
//也可以单独配置
[ServiceFilter(typeof(TrustIpFilter))]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { “value1”, “value2” };
}
中间件
启用中间件: app.UseTrustIP(loggerFactory, Configuration);
结果
如当前请求IP未在授信IP列表之内,则返回http状态码403
注意事项
Nginx 代理不能获取IP问题
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto
});