聚合支付接口设计-ag真人官方网址

大家好!今天让小编来大家介绍下关于聚合支付接口设计的问题,以下是酷知号的小编对此问题的归纳整理,让我们一起来看看吧。

前段时间对接了微信支付,于是乎,从网上找了一下别人写过的一顿copy后,修修改改终于实现完成了。

本以为万事大吉, 但是项目经理review代码时候,发现我写的支付功能和系统业务功能高度耦合, 搅和在一起结果就扣了我一部分绩效(mmp…) 。

为了避免以后扣绩效,所以决定研究一下,怎么设计支付接口比较合理。末尾附上 git传送门代码

1. if 编码方式

支付渠道暂时虽然只有微信,但是保不齐后面再加支付宝,银联啥的。到时候,代码就会像这样

if (paytype.equals ("微信")) {
//dosomething
}else if (paytype.equals ("支付宝")) {
//dosomething
}else if(paytype.equals ("银联")) {
//dosomething
}

每多一个支付渠道,改动的地方包括:支付接口、支付配置、退款、统计业务。

2.聚合支付

万能的百度上搜索了一下对接多个系统的方案(参考末尾的链接),其中聚合支付的方案比较合理。虽然可能用不到其中一部分的功能,比如结算功能。

1) 什么是聚合支付呢?

说白了就是一个项目接入了多个支付渠道,而且能够使用任意一个渠道进行支付、退款等操作,而且任何渠道之间没有任何关系,彼此不会互相干扰。

2) 简单梳理一下聚合支付的业务

  •需要对接多个支付渠道

  • 所有的支付能够兼容任意渠道

  • 所有的退款能够兼容任何渠道

  • 任何渠道都能需要独立进行配置

  • 任何渠道都有统计功能

  • 渠道之间能够无缝进行切换(比如某个渠道奔溃了,能够切换到其他渠道)

如果想满足上面的功能,又不影响原有的业务的情况下,就需要将原有的支付模块独立抽离开来,单独作为一个服务,也就是聚合支付,凡是项目里面的任何支付、退款、查询、统计等都要通过聚合支付来处理。

3) 如何设计

设计模式是面试时候经常问的,那么,大胆地使用合理的设计模式对功能进行设计吧!

工厂模式: 每个支付渠道可以看成一个工厂

适配器模式: 不同的支付渠道使用的api,参数或者返回结果都可能不一样

策略模式: 根据支付类型创建对应的支付通道

3.工厂模式

1) 创建一个支付的统一接口 , 这里列举几个接口

/**
 * 支付接口, 所有支付类的接口,系统所有支付功能类都需要实现它;
 */
public interface pay {
    /**
     * 下单
     */
    doordervo doorder(doorderso so);
    /**
     * 支付或者退款通知
     */
    paynotifyvo paynotify(paynotifyso so);
    /**
     * 查询退款
     */
    queryrefundvo queryrefund(queryrefundso so);
}

2) ag真人官方网址的支付方式枚举类

/**
 * 支付类型枚举类
 * 

* 每增加一种支付渠道,需要同时在工厂类{@link payfactory}里面配置 *

*/ public enum paywayenum { /** * wx_app */ wx_app("wx_app"), /** * wx_native */ wx_native("wx_native"), /** * ali_app */ ali_app("ali_app"), /** * ali_web */ ali_web("ali_web"); paywayenum(string key) { } }

3) 实现类

支付渠道有微信,支付宝,银联或者第三方支付等, 而微信又有native支付,native支付,手机支付等方式....

使用工厂方式可以根据ag真人官方网址的支付方式枚举出来具体实现, 结构如下

 

                                                                           图一 支付接口

 4) 工厂获取实例对象 (又要用if...或者switch....,不过后面再优化....)

@service
public class payfactory {
    //根据类型获取结果处理的实现类
    public pay getpayimpl(paywayenum paywayenum) {
        assert.notnull(paywayenum, "付款渠道不能为空");
        if (paywayenum.equals(paywayenum.wx_app)) {
            return new wxpayappimpl();
        } else if (paywayenum.equals(paywayenum.wx_native)) {
            return new wxpaynativeimpl();
        } else if (paywayenum.equals(paywayenum.ali_app)) {
            return new alipayappimpl();
        } else if (paywayenum.equals(paywayenum.ali_web)) {
            return new alipaywebimpl();
        } else {
            return null;
        }
    }
}

4.适配器模式

1) 多个实现pay接口问题

图一里面,通过观察发现:

①4个实现类都统一实现了pay的接口,如果再在pay接口中增加一个接口void doaction(),那么4个接口都得重新加上

②微信支付的api有些是通用的,比如统一下单,签名和验签,没必要在每个实现类里面都加上

2) 接口适配器模式 (缺省适配器模式)

 适用场景: 当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求。

微信支付抽象类:

/**
 * 微信支付底层抽象类
 * 

为对接第三方支付接口的支付抽象类,需要实现第三方支付接口的所有api交互,为支付功能类提供功能方法

*

每一种支付方法,都可以继承该抽象类,并拥有自己的独立的支付流程,

*/ public abstract class wxpay implements pay { //=============================下面是支付的业务功能接口================== @override public wxdoordervo doorder(doorderso so) { //子类实现 return null; } @override public paynotifyvo paynotify(paynotifyso so) { //子类实现 return null; } @override public queryrefundvo queryrefund(queryrefundso so) { //子类实现 return null; } //=============================下面是微信支付的基础api和相关方法================== /** * 统一下单接口 * * @param so */ public wxunifiedordervo unifiedorder(wxunifiedorderso so) { system.out.println("wxpay->unifiedorder :" so.tostring()); /** * 这里调用微信支付api 发送下单请求,返回二维码链接等信息 , */ // 创建签名 createsign(so.tostring()); //发送请求 string resultxml = paymenutils.dopost("www.weixinpay/unifiedorder", so.tostring()); //解析结果成实体,并返回 wxunifiedordervo wxunifiedordervo = paymenutils.parsewxunifiedorderresult(resultxml); return wxunifiedordervo; } /** * 生成签名 */ public void createsign(string params) { system.out.println("wxpay->createsign :" params); } /** * 验证签名 */ public void checksign(string params) { system.out.println("wxpay->checksign :" params); } }

微信nativeag真人官方网址的支付方式实现类 (假如我只想使用native下单,其他功能不需要,只需要重写一下doorder方法,其他的不需要重写)

@service
public class wxpaynativeimpl extends wxpay {
    @override
    public wxdoordervo doorder(doorderso so) {
        system.out.println("------微信-app方式-------");
        //调用统一下单逻辑
        wxunifiedorderso unifiedorderso = new wxunifiedorderso();
        wxunifiedordervo unifiedordervo = super.unifiedorder(unifiedorderso);
        wxnativedoordervo wxnativedoordervo = new wxnativedoordervo();
        wxnativedoordervo.setnativeflag("------nativeflag------");
        wxnativedoordervo.setwxunifiedordervo(unifiedordervo);
        return wxnativedoordervo;
    }
}

接口设计如下图

5.策略模式

1) 策略模式的定义

策略模式是对算法的包装,把使用算法的责任和算法本身分隔开,委派给不同的对象管理。策略模式通常把一系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。

2)  payfactory 工厂优化

前面工厂类,是根据if判断各种支付类型来new xxxpayimpl() 实例创建对象, 

根据类型来实例化不同的对象,可以看做是多种实现策略,可以使用策略模式来优化一下;

3) 建立ag真人官方网址的支付方式->实现类的对应关系

   /**
     * 具体ag真人官方网址的支付方式的配置
     * key 表示ag真人官方网址的支付方式,
     * value 表示支付具体实现类,** 注意这里类名小写
     */
    public static final map pay_map = new hashmap<>(8);
static {
        pay_map.put(paywayenum.wx_app, "wxpayappimpl");
        pay_map.put(paywayenum.wx_native, "wxpaynativeimpl");
        pay_map.put(paywayenum.ali_app, "alipayappimpl");
        pay_map.put(paywayenum.ali_web, "alipaywebimpl");
       
    }

4) spring实例化bean(而不是手动new xxx)

 spring工具类

/**
 * 直接通过spring 上下文获取springbean,用于多线程环境
 */
@component
public class springcontextutil implements applicationcontextaware {
    // spring应用上下文环境
    private static applicationcontext applicationcontext;
    /**
     * 实现applicationcontextaware接口的回调方法。设置上下文环境
     */
    @override
    public void setapplicationcontext(applicationcontext applicationcontext) {
        springcontextutil.applicationcontext = applicationcontext;
    }
    public static applicationcontext getapplicationcontext() {
        return applicationcontext;
    }
    /**
     * 获取对象
     *
     * @param name
     * @return object
     * @throws beansexception
     */
    public static object getbean(string name) throws beansexception {
        return applicationcontext.getbean(name);
    }
    public static void main(string[] args) {
        //具体使用:
        //   alipay alipayimpl =(alipay) springcontextutil.getbean("alipayimpl");
        //  alipayimpl.pay();
    }
}

根据类型获取支付渠道的实现类

    //根据类型获取结果处理的实现类
    public pay getpay(paywayenum paywayenum) {
        assert.notnull(paywayenum, "付款渠道不能为空");
        return (pay) springcontextutil.getbean(pay_after_map.get(paywayenum));
    }

6.controller调用

1) 请求接口

@autowired
private payfactory payfactory;

@getmapping("/hellopay/{typeenum}") public string hello(@pathvariable("typeenum") string typeenumstr) { paywayenum typeenum = paywayenum.valueof(typeenumstr);       //由工厂获取具体的pay实现类 pay pay = payfactory.getpay(typeenum); system.out.println("pay:" pay); doorderso doorderso = new doorderso(); doorderso.setorderno("下单的单号orderno_00001"); doorderso.settradeno("下单的外部单号tradeno_111111"); //获取处理结果,这里实际转换成了具体的结果实现类 doordervo doordervo = pay.doorder(doorderso); // 这里其实是具体的vo system.out.println("调用doorder返回结果:doordervo :" doordervo); return null; }

说明: 这里的xxxso 表示参数, xxxvo表示返回值, (可以自行定义), so和so之间存在父子关系,vo和vo之间也存在父子关系,

这样设计主要是: 方便支付的api处理逻辑有一个统一的返回,然后再交给系统进行db等业务处理~

2) 测试请求

 http://localhost:8088/demo/testpay/hellopay/wx_native
 http://localhost:8088/demo/testpay/hellopay/zfb_web

请求会看到不同的效果,(zfb_web的实现类需要按照上面那样写一点逻辑就可以看到效果)

7.支付结果后处理

doordervo 是调用支付的api后,统一处理的实体,我们需要根据不同的类型,转发到不同的后处理service的具体业务实现类中,
主要是在系统中记录一些db信息和订单等信息,仿照上面的接口设计,
 //工厂获取支付后处理的实现类
        payafter payafter = payfactory.getpayafter(typeenum);
        system.out.println("payafter:"   payafter);
        payafter.doorderafter(doordervo);
payafter是后处理统一接口,doorderafter是doorder支付接口的后处理逻辑;

8.调用效果

请求: 

          http://localhost:8088/demo/testpay/hellopay/wx_native 

          http://localhost:8088/demo/testpay/hellopay/ali_web

结果: 

git传送门代码:  https://github.com/colozhu/paydemo

 

参考:  

 https://blog.csdn.net/think2017/article/details/79820786?utm_medium=distribute.pc_relevant.none-task-blog-blogcommendfrommachinelearnpai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-blogcommendfrommachinelearnpai2-1.channel_param ,

 https://www.cnblogs.com/lyc94620/p/13055116.html ,

以上就是小编对于聚合支付接口设计问题和相关问题的解答了,聚合支付接口设计的问题希望对你有用!

© ag真人官方网址的版权声明
the end
喜欢就支持一下吧
分享
相关推荐
    木子李的头像-木子李育儿网6秒前
    0
    木子李的头像-木子李育儿网8秒前
    0
    木子李的头像-木子李育儿网8秒前
    0
    木子李的头像-木子李育儿网9秒前
    0
    木子李的头像-木子李育儿网9秒前
    0
    木子李的头像-木子李育儿网12秒前
    0
    木子李的头像-木子李育儿网17秒前
    35
    木子李的头像-木子李育儿网25秒前
    43
    木子李的头像-木子李育儿网33秒前
    44
    木子李的头像-木子李育儿网45秒前
    44
    木子李的头像-木子李育儿网57秒前
    43
    木子李的头像-木子李育儿网1分钟前
    47
    木子李的头像-木子李育儿网1分钟前
    49
    木子李的头像-木子李育儿网1分钟前
    26
    木子李的头像-木子李育儿网1分钟前
    22
    木子李的头像-木子李育儿网2分钟前
    21
    木子李的头像-木子李育儿网2分钟前
    39
    木子李的头像-木子李育儿网2分钟前
    28
    木子李的头像-木子李育儿网2分钟前
    29
    木子李的头像-木子李育儿网3分钟前
    43
    木子李的头像-木子李育儿网3分钟前
    49
    木子李的头像-木子李育儿网3分钟前
    20
    木子李的头像-木子李育儿网3分钟前
    49
    木子李的头像-木子李育儿网4分钟前
    49
    木子李的头像-木子李育儿网4分钟前
    21
    木子李的头像-木子李育儿网4分钟前
    26
    木子李的头像-木子李育儿网4分钟前
    39