C#大型电商项目优化(三)——扩展性与支付

上一篇文章引来不少非议,笔者并非对EF有看法,而是针对不同的业务场景和框架背景,挑选不同的方案。每个方案都有其优势劣势,挑选最快速,最简单的方案,是笔者的初衷。

看评论也是学习的过程,然而有些只做评价,却不道明原委的评论,也确实让笔者感受到了些许来自世界的恶意^_^

开个玩笑,下面进入正题,之前系统的支付部分只需要支持支付宝和财付通,且支付代码是写在一个页面文件里的,也就是说,这个页面文件包含了支付宝和财付通的支付请求、支付同步回调和异步回调。且不说代码混乱可读性差,其可扩展性也实在不敢恭维。其功能像这样:

可将来需要支持其他支付平台呢,类似于快钱等支付平台,我们预期的是这样甚至更多:

难道这些将来亟待扩展的功能还一一写在页面里吗?当然不能。在扩展支付功能之前,必须对原来的代码做重构。

重构前我们需要对目前的支付做分析:支付需要哪些方法?哪些是公共的?经过总结,我们发现支付宝和财付通支付最主要的就是这三个方法:

1.提交支付请求

2.支付同步回调(重定向)

3.异步回调

当然,有些支付平台可能有不同,比如支付宝的退款接口,是没有同步回调的。如果有更多的场景,我们可以扩展接口。

我们定义了这样一个接口类:

public interface IPayment
    {
        /// <summary>
        /// 支付
        /// </summary>
        void GoToPay(PaymentParameter parameters);
        /// <summary>
        /// 支付同步回调
        /// </summary>
        void PayReturn();
        /// <summary>
        /// 支付异步回调
        /// </summary>
        void PayNotify();
    }

接下来构建基础类,类名为PaymentBase,让它继承我们的接口类。基础类中,我们定义各种平台支付所需要调用的公共方法,声明支付所必需的对象,代码如下:

        protected string _orderId = string.Empty;
        protected string _orderNum = string.Empty;
        protected MerchantPayInfo _merchantPayInfo = null;
        protected string _orderPrice;
        protected string _productName = string.Empty;
        protected string _orderType = string.Empty;
        protected HttpResponse Response;
        protected HttpRequest Request;
        log4net.ILog log = log4net.LogManager.GetLogger("myDemo");

        /// <summary>
        /// 去支付
        /// </summary>
        public abstract void GoToPay(PaymentParameter parameters);
        /// <summary>
        /// 支付同步回调
        /// </summary>
        public abstract void PayReturn();
        /// <summary>
        /// 支付异步回调
        /// </summary>
        public abstract void PayNotify();
        /// <summary>
        /// 支付前的初始化
        /// </summary>
        /// <param name="parameters"></param>
        protected void PaymentInitial(PaymentParameter parameters)
        {...}

在PaymentInitial中为部分对象做初始化,这里不做赘述。

准备工作就绪,接下来我们开始调用支付接口,首先是支付宝,我们定义一个类,可以叫作AliPayment,在其构造函数中为支付商家账号对象赋值,然后开始为我们的三个最重要的方法编写实现:     

        public override void GoToPay(PaymentParameter parameters)
        {
            base.PaymentInitial(parameters);

            ......var submit = new Submit(_merchantPayInfo.Akey);
            //建立请求
            string sHtmlText = submit.BuildRequest(sParaTemp, "get", "确认");
            Response.ContentType = "text/html";
            Response.Write(sHtmlText);
            Response.End();
        }
        /// <summary>
        /// 支付后同步调用
        /// </summary>
        public override void PayReturn()
        {
            ......
        }
        /// <summary>
        /// 支付后异步调用
        /// </summary>
        public override void PayNotify()
        {       ......
        }

这三个方法的实现在支付宝接口文档的demo里有提供,大家可以参考。考虑到篇幅问题,这部分代码就不贴出来了。

支付类型和方法都定义且实现完成,接下来就是调用了。考虑到可扩展性,我们希望调用部分的代码在以后扩展时,都不需要修改,这里我们可以通过配置实现。类似于我们所熟知的“控制反转,依赖注入”:调用者不构造被调用者的实例,由容器构造被调用者的实例,再注入到调用者。当前的系统框架并没有引入控制反转策略,没关系,框架里没有,我们可以自己写个类似的。

这里可以通过反射来构造支付类型的实例,创建类型实例的代码如下:

     /// <summary>
        /// 创建对象实例
        /// </summary>
        /// <typeparam name="T">要创建对象的类型</typeparam>
        /// <param name="assemblyName">类型所在程序集名称</param>
        /// <param name="nameSpace">类型所在命名空间</param>
        /// <param name="className">类型名</param>
        /// <returns></returns>
        public static T CreateInstance<T>(string assemblyName, string nameSpace, string className)
        {
            try
            {
                string fullName = nameSpace + "." + className;//命名空间.类型名
                //此为第一种写法
                object ect = Assembly.Load(assemblyName).CreateInstance(fullName);//加载程序集,创建程序集里面的 命名空间.类型名 实例
                return (T)ect;//类型转换并返回
                //下面是第二种写法
                //string path = fullName + "," + assemblyName;//命名空间.类型名,程序集
                //Type o = Type.GetType(path);//加载类型
                //object obj = Activator.CreateInstance(o, true);//根据类型创建实例
                //return (T)obj;//类型转换并返回
            }
            catch
            {
                //发生异常,返回类型的默认值
                return default(T);
            }
        }

这里需要注意:我们所创建的支付类型必须要自己写构造函数,否则无法通过此方法创建实例。

在辅助方案都完成之后,实际调用的地方代码量是非常少的,我们看调用的代码:

            string className = ConfigurationManager.AppSettings[payCode];
                    payment = ReflectionHelper.CreateInstance<IPayment>("MyTestAssembly", "MyTestAssembly.Payment", className);

                    PaymentParameter parameter = new PaymentParameter();
                    parameter.LocalPath = "/Pay/Payment";
                    parameter.OrderId = OrderId;
                    parameter.OrderType = OrderType;
                    payment.GoToPay(parameter);

配置的内容如下:

<!--支付宝支付方案类型配置,用于反射 Leon-->
    <add key="0" value="AliPayment" />

    <!--财付通支付方案类型配置,用于反射 Leon-->
    <add key="1" value="TecentPayment" />

以上,我们完成了支付模块的重构,当给到不同的参数时,能够通过不同的支付平台进行支付,如支付宝:

财付通:

后续需要扩展支付平台时,这套方案也能轻松应对:只需添加支付类型并增加该类型的配置即可。

本篇文章重点描述可扩展性,其实归根结底是降低模块间的藕合度。系统开发初期追求效率,未必能考虑到系统后续的发展需求,此时适当的代码重构是很必要的。“高内聚,低耦合”的思想应贯穿设计到开发的始终。其他模块也可以按这套思路进行重构,增加代码的可读性、可维护性和健壮性。

曾有一位前辈和我说过:“重构的过程,是程序员进步最快的过程。”这句话分享给大家。

时间: 2024-08-07 08:40:08

C#大型电商项目优化(三)——扩展性与支付的相关文章

C#大型电商项目优化(二)——嫌弃EF与抛弃EF

上一篇博文中讲述了使用EF开发电商项目的代码基础篇,提到EF后,一语激起千层浪.不少园友纷纷表示:EF不适合增长速度飞快的互联网项目,EF只适合企业级应用等等. 也有部分高手提到了分布式,确实,性能优化从数据库出发,初期就加索引,然后垂直拆分,水平拆分,读写分离,甚至是分布式事务,阳春白雪,格局很高.然而笔者希望通过渐进的过程来优化这个项目,我们缩小格局,从细节查看不同方案的优劣. 之前提过,使用EF最主要的原因是项目时间紧迫,EF搭建速度快,熟悉的同事也多,使用方便.这个决策确实帮助我们挺过了

C# 大型电商项目性能优化(一)

经过几个月的忙碌,我厂最近的电商平台项目终于上线,期间遇到的问题以及解决方案,也可以拿来和大家多做交流了. 我厂的项目大多采用C#.net,使用逐渐发展并流行起来的EF(Entity Framework)框架,并搭配使用丹麦的一款主打CMS, DMS的.net web应用程序sitecore. 本篇为基础篇,侧重于阐述编码规范和一些编码技巧对系统性能的影响.不规范的编码方式,可能对单个方法或模块产生的性能影响是微不足道的,但在大型电商项目中,高并发的场景随处可见,欠妥的编码方式,可能会对整个系统

java架构师课程、性能调优、高并发、tomcat负载均衡、大型电商项目实战、高可用、高可扩展、数据库架构设计、Solr集群与应用、分布式实战、主从复制、高可用集群、大数据

15套Java架构师详情 * { font-family: "Microsoft YaHei" !important } h1 { background-color: #006; color: #FF0 } 15套java架构师.集群.高可用.高可扩展.高性能.高并发.性能优化.Spring boot.Redis.ActiveMQ.Nginx.Mycat.Netty.Jvm大型分布式项目实战视频教程 视频课程包含: 高级Java架构师包含:Spring boot.Spring  clo

Java从入门到架构师|高并发|高性能|高可用|分布式|性能调优|设计模式|大型电商项目

没有设计的思想,你就不能成为一名架构师.架构师是一个能撸的了一手好代码,画的了一个漂亮的UML/原型,写的了一篇技术文档,更加能解决好项目关键技术的综合人才.架构师=前端工程师+后端程序员+系统分析师+关键技术解决+各种技术搭配+设计模式+部署调优+其他,可见架构师是多面手,在项目当中起到连接管理与项目成员的重要角色.因此,在通往大神级的架构师的道路上,你需要懂需求.设计.代码.部署.架构.服务器.运维.调优等等. 简单系统架构图 一个能担负起企业级应用的架构师,脑海里常出现的词会是这些:负载均

16套java架构师,高并发,高可用,高性能,集群,大型分布式电商项目实战视频教程

16套Java架构师,集群,高可用,高可扩展,高性能,高并发,性能优化,设计模式,数据结构,虚拟机,微服务架构,日志分析,工作流,Jvm,Dubbo ,Spring boot,Spring cloud, Redis,ActiveMQ,Nginx,Mycat,Netty,Jvm,Mecached,Nosql,Spring,大型分布式项目实战视频教程 视频课程包含: 高级Java架构师包含:架构师,高并发,分布式,集群,高可用,高可扩展,高性能,设计模式,数据结构算法,虚拟机,微服务架构,日志分析,

企业级电商项目P2P金融项目实战,企业架构师培训视频课程

15套java架构师.集群.高可用.高可扩 展.高性能.高并发.性能优化.Spring boot.Redis.ActiveMQ.Nginx.Mycat.Netty.Jvm大型分布 式项目实战视频教程 视频课程包含: 高级Java架构师包含:Spring boot.Spring  cloud.Dubbo.Redis.ActiveMQ.Nginx.Mycat. Spring.MongoDB.ZeroMQ.Git.Nosql.Jvm.Mecached.Netty.Nio.Mina.性能调优.高并发.

大型电商分布式网站架构设计与实践,Java分布式架构,Java事务分布式高并发-视频教程

15套java架构师.集群.高可用.高可扩 展.高性能.高并发.性能优化.Spring boot.Redis.ActiveMQ.Nginx.Mycat.Netty.Jvm大型分布 式项目实战视频教程 视频课程包含: 高级Java架构师包含:Spring boot.Spring  cloud.Dubbo.Redis.ActiveMQ.Nginx.Mycat. Spring.MongoDB.ZeroMQ.Git.Nosql.Jvm.Mecached.Netty.Nio.Mina.性能调优.高并发.

柯南君:教你如何对待大型电商平台的性能优化?之 一 (方法、指标、工具、定位)

柯南君:教你如何对待大型电商平台的性能优化?之 一 (方法.指标.工具.定位) 柯南君的朋友"闲哥"最近遇到了点困扰---"大型网站平台如何对待性能优化,以及如何针对性调优?",柯南君今天,想谈一下性能优化的战略,主要是一些企业架构级别的技术和方法.柯南君将自己的个人经验和各家公司大咖的经验一起汇总给大家,如有瑕疵,请大家及时指正. 柯南君有句自律的口头语"如果你不能成为一个追求性能的疯子,那么性能将会把你变成疯子"        序曲: 如何评

大型电商互联网性能优化案例

大型电商互联网性能优化案例 理论基础 The Theory 平台设计 Platform Design 业务结果 Business Impact 双11优化 架构思考 Architecture Takeaways   ----------------------------------------------------------------------------------------------------------------------------------------------