上一篇文章引来不少非议,笔者并非对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" />

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

财付通:

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

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

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

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

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

    上一篇博文中讲述了使用EF开发电商项目的代码基础篇,提到EF后,一语激起千层浪.不少园友纷纷表示:EF不适合增长速度飞快的互联网项目,EF只适合企业级应用等等. 也有部分高手提到了分布式,确实,性能优 ...

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

    经过几个月的忙碌,我厂最近的电商平台项目终于上线,期间遇到的问题以及解决方案,也可以拿来和大家多做交流了. 我厂的项目大多采用C#.net,使用逐渐发展并流行起来的EF(Entity Framewor ...

  3. Spark大型电商项目实战-及其改良之番外(1)-将spark前端页面效果高效拷贝至博客

    Spark大型电商项目实战-及其改良这个系列的时间轴展示图一直在变....1-3篇是用图直接表示时间轴,用一段简陋的html代码表示时间表.第4篇开始才是用比较完整的前端效果,能移动.缩放时间轴,鼠标 ...

  4. vue大型电商项目尚品汇(前台篇)day01

    学完vue2还是决定先做一个比较经典,也比较大的项目来练练手好一点,vue3的知识不用那么着急,先把vue2用熟练了,vue3随时都能学. 这个项目确实很经典包含了登录注册.购物车电商网站该有的都有, ...

  5. Spark大型电商项目实战-及其改良(2) RDD优化效果不稳定的真正原因

    首先看没有map join的第2任务: 时间线如下 接着是对应id的算子计算时间表 Stage Id Description Submitted Duration Tasks: Succeeded/T ...

  6. Spark大型电商项目实战-及其改良(1) 比对sparkSQL和纯RDD实现的结果

    代码存在码云:https://coding.net/u/funcfans/p/sparkProject/git 代码主要学习https://blog.csdn.net/u012318074/artic ...

  7. vue大型电商项目尚品汇(前台篇)day02

    现在正式回归,开始好好做项目了,正好这一个项目也开始慢慢的开始起色了,前面的准备工作都做的差不多了. 而且我现在也开始慢慢了解到了一些项目才开始需要的一些什么东西了,vuex.router这些都是必备 ...

  8. vue大型电商项目尚品汇(前台篇)day04

    这几天一直都在做项目,只是没有上传上来,即将把前台项目完结了.现在开始更新整个前台的部分 一.面包屑处理 1.分类操作 点击三级联动进入搜索产生面包屑,直接取参数中的name即可 点击x怎么干掉这个面 ...

  9. vue大型电商项目尚品汇(前台篇)day05

    紧急更新第二弹,然后就剩下最后一弹,也就是整个前台的项目 一.购物车 1.加入购物车(新知识点) 加入到购物车是需要接口操作的,因为我们需要将用户的加入到购物车的保存到服务器数据库,你的账号后面才会在 ...

随机推荐

  1. 【HANA系列】SAP HANA XS使用服务器JavaScript Libraries详解

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA XS使用服务器 ...

  2. exec 动态脚本 里面的参数和sp_executesql (注意引号,否则容易异常)

    @indexCt int@DemographicName nvarchar(500)INSERT INTO #finalTemp EXEC('SELECT a.QuestionId,a.AnswerI ...

  3. centos6.9设置桥接网络模式方法

    第一步:设置 VMware 在 VMware 中打开[编辑]->[虚拟网络编辑器],添加 VMnet0,并选择桥接模式.需要注意的是,需要选择“桥接到”的网卡,使用无线网卡就选无线网卡,使用有线 ...

  4. 手把手教你搭建WEB服务器和FTP服务器

    注:本次教程的环境是在“Windows 10 PC中远程控制的Windows Server 2012 R2服务器”,你可以自己在自己电脑中安装虚拟机再安装Windows Server 2012 R2服 ...

  5. 百度、高德、谷歌、火星、wgs84(2000)地图坐标相互转换的JS实现

    一.调用例子: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  6. Visual studio 2010 OpenGL配置

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/niuxiunan/article/details/24557935 题记:今天同学问我关于OpenG ...

  7. Mashmokh and Numbers CodeForces - 415C

    题意:就是n个数和k,每次按顺序那两个数,最大公约数的和为k. 思路:注意:当n=1,k>0时一定不存在,还有n=1,k=0时为1即可. 然后再正常情况下,第一组的最大公约数为k-n/2+1即可 ...

  8. cmd 监控网络状况

    提示:如果提示curl不是内部命令,请自行百度 windows 安装curl @echo off color 1f title 正在监控 echo 正在监控http://ioscheck.duapp. ...

  9. 简单使用metamascara

    package.json 配置文件信息 { "name": "test-mascara", "version": "1.0.0&q ...

  10. ethereum/EIPs-1078 Universal login / signup using ENS subdomains

    https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1078.md eip title author discussions-to status ...