历经1年多,沐雪.NetCore版本的多租户商城系统终于研发成功。全新的技术,全新的界面!我们将采用新的产品名称 -- 多租宝,并且以后都将全部精力致力于该平台的升级研发。
《多租宝》功能简介:
SaaS模式的多租户/多商户小程序商城系统,可以同时支持多个租户/商户, 每个商户又可以创建多个店铺,每个店铺对应一个小程序商城系统,各个店铺管理各自的店铺功能。
自带平台管理系统,可以查看和管理所有商户和所有店铺信息,可以给商户的店铺充值续费,可对所有店铺里的商品和订单进行管理,以及数据统计。
一、平台方管理系统
1、平台概览:今日新增租户数,今日新增店铺数,今日付款金额,待处理事项(待付款订单,待发货订单,待续费店铺数等),商城信息统计(会员总数,商品总数,订单总数等)
2、租户管理:租户账号管理,租户店铺管理,租户店铺续费,店铺禁用,店铺资料修改等;
3、所有店铺的商品信息管理;
4、所有店铺订单管理;
5、所有店铺的会员管理;
6、所有店铺的交易流水记录;
7、系统功能:站点设置(短信设置,交易设置,租户设置等), 管理员管理, 菜单设置, 权限设置,消息模板设置,自动代码生成器
二、租户/商户平台
支持商户自己注册账号,自行创建店铺,试用店铺里的功能;
1、租户注册账号,登录,修改密码/找回密码,修改资料等;
2、免费创建店铺,管理店铺;
3、店铺概览:今日新增会员数,今日订单数,今日付款金额,交易统计,快捷入口
待处理事项(商品库存报警,待付款订单,备货中订单,待待收货订单,待回复评价,仓库中商品),
商城信息统计(会员总数,商品总,近七天评价数,近七天订单数,近7天销售额(元)),
4、店铺管理:信息设置,小程序设置,意见反馈
5、图片库:图片分类,图片上传,图片管理;
6、商品管理:商品发布,分组,标签,规格,评价,商品管理等;
7、订单管理:订单管理(所有订单,待付款,待发货,已完成),发货,批量发货,备注,订单详细查看,物流信息,运费模板,交易设置等;
8、会员管理:会员查看,会员下单记录;
9、店铺的交易流水;
10、营销管理:优惠券,满额减;
11、广告管理,文章管理;
三、小程序端
1、手机号注册,微信号授权登录,修改资料,上传头像等;
2、首页广告位,banner,商品列表,商品分类,商品查询,商品详情,电话客服
3、优惠券领取,满额减;
4、商品加入购物车,购物车管理;
5、商品收藏,收藏管理;
6、下单,创建订单,选择收货地址,选择支付方式(支持微信支付和货到付款),微信支付;
7、用户中心:订单概览,我的优惠券列表,订单管理(查看,取消订单,订单列表,订单详情,确认收货,物流信息,订单重新付款,删除订单,评价,联系客服),商品浏览历史,地址管理,我的收藏,意见反馈,设置
《多租宝》技术概览:
.NetCore是大势所趋,是时候技术升级了。我们的系统不仅仅是一套成熟的多租户商城系统源码!
购买我们的源码,您将很容易掌握所有常用的.NetCore的技术框架,组件和开发思想,以及微服务架构的搭建。
我们的源码,会从.NetCore3.1---> .Net 6 ---> ....一直不断升级技术架构;
我们的源码,会从SaaS商城的常用功能,逐渐完美,强大,更加通用,最终做成一艘技术框架的航母,可以承载更多的功能。
后端开发语言:.Net Core 3.1
数据库:mysql 5.7
小程序前端:uni-app,跨平台
后台:asp.net core mvc 3.1 +bootstrap4
接口:asp.net core 3.1 webapi
Job: HangFire
缓存:Redis
ORM:采用EFCore ,集成 Helper类
DDD领域驱动设计;
DI:采用微软自带的容器,部分采用Autoface;大量使用依赖注入;
自带代码生长器,免去写实体层,仓储层,和单表的增删改查等功能;
全异步方式执行,高性能,易扩展;全局日志跟踪,异步捕获;
接口采用JWT鉴权,安全有保障;
短信通知:阿里云短信通道;
SaaS模式的多租户商城系统,各店铺完全隔离,从数据库层面开始隔离;
app小程序端可以支持多平台的小程序,微信小程序,支付宝小程序,百度小程序,qq小程序,ios,Andriod等等,目前微信小程序已经全面测试通过,其他端待测试。
后端代码和接口,可以部署在windows服务器和Linux服务器,支持Docker部署。
租户的测试地址: http://shop.duozubao.cn/Login 可以自行注册账号,创建店铺使用。
---------------------------------------------------------------------------------------------------
欢迎前来购买整套源码!
购买后全部代码都是源码形式。
购买后获得授权,可以用于商业用途。
购买源码,另外包括1年的免费升级和1年的售后服务,免费安装一次。
赠送一套精美的asp.net core mvc 3.1版本的后台管理系统。
购买请联系官方qq: 23002807
手机(微信):13816330315
-------------------------------------------------------------------------------------------------------
小程序段界面:
(可以扫码二维码查看)
超级管理员后台界面:
Tenant租户后台:
代码展示:
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using MuXue.Extensions.DependencyInjection; using MuXue.WeTao.Mall.Domain.Model; using MuXue.WeTao.Mall.Repository; using MuXue.WeTao.Mall.Service.WxOpenMessageHandler; using MuXue.WeTao.Mall.WebApi.Extensions; using MuXue.WeTao.Mall.WebApi.Filter; using Senparc.CO2NET; using Senparc.CO2NET.AspNet; using Senparc.NeuChar.MessageHandlers; using Senparc.Weixin; using Senparc.Weixin.Cache.Redis; using Senparc.Weixin.Entities; using Senparc.Weixin.WxOpen.MessageHandlers.Middleware; using StackExchange.Redis.Extensions.Newtonsoft; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace MuXue.WeTao.Mall.WebApi { /// <summary> /// 沐雪-多租宝StartUp类 /// </summary> public class Startup { private const string ApiName = "MuXue.WeTao.Mall"; readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; /// <summary> /// 运行环境 /// </summary> public IWebHostEnvironment Env { get; set; } /// <summary> /// 配置 /// </summary> public IConfiguration Configuration { get; } public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { #if DEBUG builder.AddConsole(); #endif }); /// <summary> /// 构造函数 /// </summary> /// <param name="configuration"></param> /// <param name="env"></param> public Startup(IConfiguration configuration, IWebHostEnvironment env) { Configuration = configuration; Env = env; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMuXueMVC(Env) // .AddMuXueDbContext(Configuration) .AddInjection() .AddSwagger() .AddRedisExtensions<NewtonsoftSerializer>(Configuration.GetSection("Redis")) .AddCors(options => { options.AddPolicy(MyAllowSpecificOrigins, builder => builder.AllowAnyOrigin() // .AllowAnyHeader() // .AllowCredentials() .WithMethods("GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS") .WithHeaders("x-requested-with", "Authorization", "token", "content-type") ); }) .AddWeixin(Configuration) .AddControllers(); //配置jwt services.ConfigureJwt(Configuration); //注入JWT配置文件 // services.Configure<JwtConfig>(Configuration.GetSection("JwtConfig")); // 添加mysql的dbcontext上下文 services.AddDbContextPool<IDbContext, ApplicationDbContext>(options => { options.UseMySql(Configuration.GetConnectionString("Default"), sqlOptions => { sqlOptions.EnableRetryOnFailure(3, TimeSpan.FromSeconds(30), new[] { 2 }); }).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking).UseLoggerFactory(MyLoggerFactory); }, 128); services.AddHttpClient(); services.Configure<ApiBehaviorOptions>(opts => opts.SuppressModelStateInvalidFilter = true); services.AddControllers(options => { options.Filters.Add<LogstashFilter>(); options.Filters.Add<PrivilegeFilter>(); options.Filters.Add<XcActionFilter>(); options.Filters.Add<GlobalExceptions>(); }).AddNewtonsoftJson(option => { option.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; option.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IOptions<SenparcSetting> senparcSetting, IOptions<SenparcWeixinSetting> senparcWeixinSetting) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } string OpenSwagger = Configuration.GetSection("AppSettingConfig:OpenSwagger").Value;//是否开启swagger if (OpenSwagger == "1") { app.UseSwagger().UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", $"{ApiName} V1"); }); } app.UseRouting(); app.UseCors(MyAllowSpecificOrigins); // 启动 CO2NET 全局注册,必须! // 关于 UseSenparcGlobal() 的更多用法见 CO2NET Demo:https://github.com/Senparc/Senparc.CO2NET/blob/master/Sample/Senparc.CO2NET.Sample.netcore3/Startup.cs var registerService = app.UseSenparcGlobal(env, senparcSetting.Value, globalRegister => { #region CO2NET 全局配置 #region 全局缓存配置(按需)配置和使用 Redis if (UseRedis(senparcSetting.Value, out string redisConfigurationStr))//这里为了方便不同环境的开发者进行配置,做成了判断的方式,实际开发环境一般是确定的,这里的if条件可以忽略 { Senparc.CO2NET.Cache.Redis.Register.SetConfigurationOption(redisConfigurationStr); Senparc.CO2NET.Cache.Redis.Register.UseKeyValueRedisNow();//键值对缓存策略(推荐) } #endregion #region 注册日志(按需,建议) globalRegister.RegisterTraceLog(ConfigTraceLog);//配置TraceLog #endregion #region APM 系统运行状态统计记录配置 //测试APM缓存过期时间(默认情况下可以不用设置) Senparc.CO2NET.APM.Config.EnableAPM = true;//默认已经为开启,如果需要关闭,则设置为 false Senparc.CO2NET.APM.Config.DataExpire = TimeSpan.FromMinutes(60); #endregion #endregion }, true) .UseSenparcWeixin(senparcWeixinSetting.Value, weixinRegister => { if (UseRedis(senparcSetting.Value, out _)) { weixinRegister.UseSenparcWeixinCacheRedis();//StackExchange.Redis } }) ; //使用 小程序 MessageHandler 中间件 // -- DPBMARK MiniProgram app.UseMessageHandlerForWxOpen("/WxOpenAsync", CustomWxOpenMessageHandler.GenerateMessageHandler, options => { options.DefaultMessageHandlerAsyncEvent = DefaultMessageHandlerAsyncEvent.SelfSynicMethod; options.AccountSettingFunc = context => senparcWeixinSetting.Value; } ); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } // -- DPBMARK Redis /// <summary> /// 判断当前配置是否满足使用 Redis(根据是否已经修改了默认配置字符串判断) /// </summary> /// <param name="senparcSetting"></param> /// <param name="redisConfigurationStr">redis地址</param> /// <returns></returns> private bool UseRedis(SenparcSetting senparcSetting, out string redisConfigurationStr) { redisConfigurationStr = senparcSetting.Cache_Redis_Configuration; var useRedis = !string.IsNullOrEmpty(redisConfigurationStr) && redisConfigurationStr != "#{Cache_Redis_Configuration}#"/*默认值,不启用*/; return useRedis; } /// <summary> /// 配置微信跟踪日志(演示,按需) /// </summary> private void ConfigTraceLog() { //这里设为Debug状态时,/App_Data/WeixinTraceLog/目录下会生成日志文件记录所有的API请求日志,正式发布版本建议关闭 //如果全局的IsDebug(Senparc.CO2NET.Config.IsDebug)为false,此处可以单独设置true,否则自动为true Senparc.CO2NET.Trace.SenparcTrace.SendCustomLog("系统日志", "系统启动");//只在Senparc.Weixin.Config.IsDebug = true的情况下生效 //全局自定义日志记录回调 Senparc.CO2NET.Trace.SenparcTrace.OnLogFunc = () => { //加入每次触发Log后需要执行的代码 }; } } }
using MuXue.WeTao.Mall.IRepository; using MuXue.WeTao.Mall.Repository; using System; using System.Collections.Generic; using Microsoft.Extensions.Logging; using System.Threading.Tasks; using MuXue.WeTao.Mall.Domain.Model; using MuXue.WeTao.Mall.Domain.Model.Request; using MuXue.WeTao.Mall.Domain.Entity; using MuXue.WeTao.Mall.Common; using MuXue.WeTao.Mall.Domain.Model.response; using System.Linq; using System.Linq.Expressions; using MuXue.WeTao.Mall.Domain.Model.Common; using System.Transactions; using Microsoft.AspNetCore.Mvc.Formatters; using System.Text; using MySql.Data.MySqlClient; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using MuXue.WeTao.Mall.Domain.Model.MXEnum; using Senparc.Weixin.TenPay.V3; using static MuXue.WeTao.Mall.Domain.Model.MXEnum.TenantOrderSomeEnum; using Senparc.Weixin.TenPay; using MuXue.WeTao.Mall.Core.Http; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using System.Text.Encodings.Web; using System.Web; using Senparc.CO2NET.Extensions; namespace MuXue.WeTao.Mall.Service.Impl { public class PaymentService : IPaymentService { private ILogger _logger; private IDbContext _dbContext; private IUnitOfWork _unitOfWork; private IConfiguration _config; private Itenant_orderRepository _orderRepository; private Itenant_order_itemRepository _order_itemRepository; private IMemberService _memberService; private ITenantGoodsService _goodsService; private ITenantShopBaseService _shopBaseService; private IWxOpenUserInfoServie _wxOpenUserInfoServie; private ITenantAppBaseinfoService _appBaseinfoService; public PaymentService(IDbContext dbContext, ILogger<PaymentService> logger, IConfiguration config, IMemberService memberService, ITenantShopBaseService shopBaseService, IWxOpenUserInfoServie wxOpenUserInfoServie, ITenantAppBaseinfoService appBaseinfoService) { _dbContext = dbContext; _unitOfWork = new UnitOfWork(_dbContext); _config = config; _orderRepository = new tenant_orderRepository(_dbContext); _order_itemRepository = new tenant_order_itemRepository(_dbContext); _logger = logger; _memberService = memberService; _shopBaseService = shopBaseService; _wxOpenUserInfoServie = wxOpenUserInfoServie; _appBaseinfoService = appBaseinfoService; } /// <summary> /// 订单查询 /// </summary> /// <param name="shop_code"></param> /// <param name="appBaseInfo">可以为null</param> /// <param name="transaction_id"></param> /// <param name="out_trade_no"></param> /// <returns></returns> public async Task<OrderQueryResult> OrderQuery(string shop_code, tenant_app_baseinfo appBaseInfo, string transaction_id, string out_trade_no) { try { if (appBaseInfo == null) { appBaseInfo = new tenant_app_baseinfo(); appBaseInfo = await _appBaseinfoService.GetModel(shop_code, AppChannelEnum.wxminapp); } string nonceStr = TenPayV3Util.GetNoncestr(); TenPayV3OrderQueryRequestData queryData = new TenPayV3OrderQueryRequestData(appBaseInfo.AppId, appBaseInfo.MchId, transaction_id, nonceStr, out_trade_no, appBaseInfo.PayKey32); OrderQueryResult result = await TenPayV3.OrderQueryAsync(queryData); return result; } catch (Exception ex) { _logger.LogError(ex, $"查询订单异常:{ex.Message}"); return null; } } } }
/** *┌──────────────────────────────────────────────────────────────┐ *│ 描 述:沐雪-多租宝-快递100物流信息查询帮助类 *│ 作 者:多租户商城系统 *│ 版 本:muxue.wetao.saas.v1 沐雪微信商城系列产品-模板代码自动生成 *│ 创建时间:2020-10-01 16:46:46 *│ 上海沐雪网络技术有限公司 版权所有 http://www.uweixin.com/ *│ 警告:本计算机程序受著作权法和国际公约的保护, *│ 未经授权擅自复制传播本程序的部分或全部,可能受到严厉的民事及刑事制裁,并在法律的许可范围内受到可能的起诉。 *└──────────────────────────────────────────────────────────────┘ *┌──────────────────────────────────────────────────────────────┐ *│ 命名空间: MuXue.WeTao.Mall.Core.kuaidi100 *│ 类 名: KuaiDi100Helper *└──────────────────────────────────────────────────────────────┘ */ using Microsoft.Extensions.Logging; using MuXue.WeTao.Mall.Core.Http; using MuXue.WeTao.Mall.Core.kuaidi100.Common; using MuXue.WeTao.Mall.Core.kuaidi100.Model; using MuXue.WeTao.Mall.Core.kuaidi100.Utils; using MuXue.WeTao.Mall.Core.System; using MuXue.WeTao.Mall.Domain.Model; using MuXue.WeTao.Mall.Domain.Model.Common; using MuXue.WeTao.Mall.Domain.Model.Request; using MuXue.WeTao.Mall.IRepository; using MuXue.WeTao.Mall.Repository; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace MuXue.WeTao.Mall.Core.kuaidi100 { public class KuaiDi100Helper { private ILogger _logger; private MuXueConfigHelper _configHelper; HttpClient _client; /// <summary> /// 沐雪-多租宝-快递100物流信息查询帮助类 /// </summary> /// <param name="logger"></param> /// <param name="configHelper"></param> public KuaiDi100Helper(ILogger<KuaiDi100Helper> logger, HttpClient client, MuXueConfigHelper configHelper) { _configHelper = configHelper; _logger = logger; _client = client; } /// <summary> /// 实时快递查询接口 /// </summary> /// <param name="tenant_id"></param> /// <param name="shop_code"></param> /// <param name="com">查询的快递公司的编码, 一律用小写字母</param> /// <param name="num">查询的快递单号, 单号的最大长度是32个字符</param> /// <param name="phone">收、寄件人的电话号码(手机和固定电话均可,只能填写一个,顺丰单号必填,其他快递公司选填。如座机号码有分机号,分机号无需上传。)</param> /// <returns></returns> public async Task<QueryTackResult> QueryTrack(string shop_code,string com,string num,string phone="13816330315") { QueryTackResult result = new QueryTackResult(); try { TenantConfig config = await _configHelper.GetTenantAllAsync(shop_code); QueryTrackParam queryTrackParam = new QueryTrackParam(); if (com== "shunfeng") { queryTrackParam = new QueryTrackParam() { com = com, num = num, phone = phone }; } else { queryTrackParam = new QueryTrackParam() { com = com, num = num, }; } QueryTrackReq query = new QueryTrackReq() { customer = config.KuaiDi100CustomerID, sign = SignUtils.GetMD5(queryTrackParam.ToString() + config.KuaiDi100Key + config.KuaiDi100CustomerID), param = queryTrackParam }; var requestParam = ObjectToDictionaryUtils.ObjectToMap(query); if (requestParam == null) { return null; } result = await HttpClientHelper.PostFormAsync<QueryTackResult>(_client, ApiInfoConstant.QUERY_URL, requestParam); } catch (Exception ex) { _logger.LogError(ex, $"快递100实时快递查询接口异常:{ex.Message}"); return null; } return result; } } }
购买请联系官方qq: 23002807
手机(微信):13816330315
请发表评论