( 最佳答案 奖励芙蓉王香烟1.5条)[0.2版本]碰到了个变态的项目,我如何进行代码优化,跪求各位出个思路!!!!

总需求 : 如何设计程序更加合理,代码写起来要爽 逻辑看起来也爽 如果是您写这个代码会怎么写?

当前问题版本0.2 时间 7月2号 礼拜二下午5点30

问题版本 描述
0.1 问题问的模糊都是文字,不方便大家观看
0.2 采用思维导图的方式把整个程序流程进行了图片方式展示,奖励由1条变成1.5条芙蓉王
  1. 需求很复杂,很变态,内容较多,我知道1条(随着版本叠加可能变成2条3条 初始1条)芙蓉王根本不算什么,花时间去看题目的浪费的时间就不止了。所以我提前说下,最佳答案我邮寄或是直接转账均可。我也是为了找下思路。目前代码我虽然上线了,但是总感觉写的很恶心。
  2. 项目之前是thinkphp的因为是用的fastadmin的后台,目前因为做的实在恶心,我就转到laravel了,用dcat重构。

项目总描述 :
目前有抖音小程序 快手小程序 和 微信小程序 小程序是电影类型的,用户下单然后出票。
目前程序的流程

已经写完
1.分别封装了3个小程序的服务,可以下单 退款 登录等 其中抖音小程序的服务还封装了同步订单的方法。
2.封装了猫眼出票的服务

7月2日晚11点记:
整理了一份新的脑图
1.所有的订单同步都放在ob中
2.单独一个退款的服务这个服务调用小程序的工厂的退款方法 1.保存订单状态退款中 2.去调用工厂的退款方法

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 52

你选择dcat就是个错误

2个月前 评论
liuhaiqiang999 (楼主) 2个月前
PHP布道者 (作者) 2个月前
liuhaiqiang999 (楼主) 2个月前
周小云 2个月前
lovewei 2个月前

你选择dcat就是个错误

2个月前 评论
liuhaiqiang999 (楼主) 2个月前
PHP布道者 (作者) 2个月前
liuhaiqiang999 (楼主) 2个月前
周小云 2个月前
lovewei 2个月前

不同的回调处理不同订单就可以了,但是支付和登录可以使用一个路由解决。根据前端标识在服务里面分开处理就行。各个小程序不通用的字段直接冗余到表里。可以加一个json类型字段存储各个不同小程序的下单快照。如果像第三方订单号可以使用out_trande_no这种统一存储或者直接冗余成wechat_transaction_id(微信),tiktok_trade_no(抖音)。快手小程序没接过不太清楚,如果需要订单每个状态执行流程结果,可以在关联一个订单流程表,存储订单进行的过程。

2个月前 评论
liuhaiqiang999 (楼主) 2个月前

你的代码都写在控制器? 无论是抖音小程序 快手小程序 和 微信小程序下单和退款都有共同点,把共同点抽出来。用于多个控制器调用。所以你需要需要一个service层去承载你的业务逻辑。

namespace App\Services;

use App\Models\Order;

class OrderService
{
    public function createOrder($data)
    {
        // 创建订单并保存到数据库
        $order = Order::create($data);
        return $order;
    }

    public function updateOrderStatus(Order $order, $status)
    {
        // 更新订单状态
        $order->status = $status;
        $order->save();
    }

    public function handlePaymentCallback(Order $order, $status)
    {
        // 处理支付回调
        $this->updateOrderStatus($order, $status);
        // 其他通用逻辑
    }

    public function handleRefund(Order $order)
    {
        // 处理退款逻辑
        $this->updateOrderStatus($order, 'refunding');
        // 其他通用逻辑
    }
}

DouyinService:

namespace App\Services;

use App\Models\Order;

class DouyinService extends OrderService
{
    public function syncOrderToDouyin(Order $order)
    {
        // 同步订单到抖音服务器的逻辑
    }

    public function handlePaymentCallback(Order $order, $status)
    {
        parent::handlePaymentCallback($order, $status);
        $this->syncOrderToDouyin($order);
    }

    public function handleRefund(Order $order)
    {
        parent::handleRefund($order);
        $this->syncOrderToDouyin($order);
    }
}

WeixinService:

namespace App\Services;

use App\Models\Order;

class WeixinService extends OrderService
{
    // 实现微信小程序特定逻辑
}

DouyinOrderController :

namespace App\Http\Controllers;

use App\Services\DouyinService;
use Illuminate\Http\Request;

class DouyinOrderController extends Controller
{
    protected $douyinService;

    public function __construct(DouyinService $douyinService)
    {
        $this->douyinService = $douyinService;
    }

    public function createOrder(Request $request)
    {
        $data = $request->all();
        $order = $this->douyinService->createOrder($data);
        return response()->json($order, 201);
    }

    public function handlePaymentCallback(Request $request)
    {
        $data = $request->all();
        $order = Order::find($data['order_id']);
        $status = $data['status'];
        $this->douyinService->handlePaymentCallback($order, $status);
        return response()->json(['message' => 'Payment callback handled'], 200);
    }

    public function handleRefund(Request $request)
    {
        $data = $request->all();
        $order = Order::find($data['order_id']);
        $this->douyinService->handleRefund($order);
        return response()->json(['message' => 'Refund handled'], 200);
    }
}
2个月前 评论
springlee (作者) 2个月前
liuhaiqiang999 (楼主) 2个月前
kolin 2个月前
springlee (作者) 2个月前
kolin 2个月前

初步的看了一下,你这个项目依赖外部接口,而且还不只是一个平台,我们抛开微服务这种终极解决方案,你这个要写的爽就必须上异步队列,所有依赖外部接口的都在异步队列中处理,自己系统中只关注数据状态,是什么状态就走什么流程,其余的操作全部封装好,当然并不是上了队列就万事大吉,要有基本的容错机制,也就是失败重试机制,将一个任务丢给队列前,要先把这个任务中的数据先保存到数据库中,具体类型,格式自己按需求来,这样做的目的是为了外部平台出现错误时保留好了案发现场,(任务队列有重试机制)那我们后台就能看到哪些出错了,可以手动重试,重试不行也可以自己调试找出问题所在,随后完善系统解决bug,回调逻辑同理可得,注意,不要把下单和回调结合在一起来看,在开发的眼中,回调是回调,回调的最终目的是把订单数据修改了,至于成功和失败,都会有一套逻辑来处理,成功有上报,失败有上报和退款

2个月前 评论
liuhaiqiang999 (楼主) 2个月前
liuhaiqiang999 (楼主) 2个月前
稻草人AQA (作者) 2个月前

重构后端逻辑

file

2个月前 评论

把逻辑一样的抽象出来,小程序那块用工厂模式封装,因为抖音会多一步,封装的时候也多一个方法。 退款就丢队列,用户发起退款后让他等待退款成功

2个月前 评论

不建议用Observers监听,容易套娃,建议用事件event监听不同的事件,然后根据不同的渠道策略进行不同的操作,定义接口,实现具体逻辑,不需要的就留空~

2个月前 评论

看到你整理的需求文档分为几块内容:

  1. 本系统的订单处理:入库、修改状态
  2. 订单同步抖音,包括创建和修改状态
  3. 第三方服务的支付相关:发起支付,支付回调,发起退款
  4. 第三方服务的出票

将上述的内容 封装成多个相应的 service ,service 中每个函数的功能单一,然后组合式调用…

剩下的无非是技术方案:是否要用异步的方式:采用队列,消息生成和消费的方式等….

2个月前 评论
liuhaiqiang999 (楼主) 2个月前
zhy (作者) 2个月前
liuhaiqiang999 (楼主) 2个月前
zhy (作者) 2个月前

这种回调地狱就不要想着重构了,写到哪算哪吧,遇到问题解决问题。

2个月前 评论
liuhaiqiang999 (楼主) 2个月前
MArtian (作者) 2个月前
994914376

搞个工厂方法,暴露的api一致就行,后续只需要增加不同的渠道入口即可

2个月前 评论
liuhaiqiang999 (楼主) 2个月前

分好层级就好了,你就是把业务和服务搞到一起了 ,想规范还想各种兼容。
我们的是 各种的业务订单表和订单总表
第三方-》平台业务(处理第三方和记录业务订单数据,转化为内部统一的订单格式) -> 同步到订单服务
运营后台查看的是订单总表数据

2个月前 评论
liuhaiqiang999 (楼主) 2个月前
yourself

事件驱动,业务订阅对应事件,定时任务窗口期检查兜底。

2个月前 评论
liuhaiqiang999 (楼主) 2个月前
巅峰互联
     回答的各位,都很认真,建议订单逻辑,整一个思维导图,根据思维导图设计 服务层,业务层。逻辑层。然后串联起来,完美解决。你自己开发功能是,用到哪儿,修改哪儿。结果修改完全乱了!。修改功能,比新开发功能累,但是自己挖的坑,含泪也的修改完!
2个月前 评论
巅峰互联 (作者) 2个月前
liuhaiqiang999 (楼主) 2个月前

根据老夫多年的撸码经验,没看出来难点在哪里啊,搞个参数一一对应就行了啊,幸苦你问个问题撸那么多字

2个月前 评论
liuhaiqiang999 (楼主) 2个月前

我的意见是这样的:

1、接口层面。那就对相关的接口采用服务模式,也就是service,例如针对于不同的三方API初始化、鉴权以及调用,封装成service。通过调用不同的service来组成具体的业务,例如支付,需要调用不同地方的API获取状态,那就调用不同的service下的不同的函数;

2、业务流程方面。因为涉及到多个回调,正常情况下是可以完成一个操作,但是如果请求量多了以后,是会存在问题的,因此有的小伙伴提出异步队列是很好的解决办法。然后队列的消费者的代码也是调用不同的service去完成队列的消费;

3、数据库层面。由于涉及到金钱的业务,需要确保数据的准确性和一致性,那就考虑上数据库事务,确保数据库的订单状态等的操作。

4、关于选择的是dcat还是前后分离的问题。如果需要大量的各种异步操作、事务等,并且开发周期足够,那就最好前后分离,后端专注于做API的事。但是如果开发周期比较紧张,那么dcat也不失为一个好的选择,关键就在于一些自定义的操作对于API的调用的地方处理好就可以。

5、其他。可以做好相关的日志记录,后续可以很好的做数据和发生异常时的溯源。

2个月前 评论

既然这么注重质量,说明有足够的时间开发,那或许你可以从单元测试入手。拆分成可单独测试的小单元,再怎么组合起来就不难了。

2个月前 评论

异步队列吧,每个队列都做好记录,配合horzion进行查看重发

2个月前 评论

你可以用事件来拆分支。

protected $listen = [
    \App\Events\CreateOrder::class => [ # 下单
     SaveOrderListener::class, # 保存订单信息,
    GeantePayInfoListen::class, # 生成订单信息并保存
    ....
    延迟队列
    同步状态
    ],
    PaySuccess => [ # 用户支付完成
        SaveOrder...
        SyncOrder # 同步
        Request猫眼Listener.php  -> 
     -> 成功: 同步抖音订单信息
    -> 失败: 调用 退款接口,成功再调用退款事件
    ],
    退款事件 => 
    ... 
];



测试:
$order = Order::find(x)
event(
 new \App\Events\CreateOrder($order)
)
event(
 new \App\Events\PaySuccess($order)
)
....
2个月前 评论

回调一定是每个平台都是一个单独的控制器是最简单的,只要他们最终能走到同一个工厂方法就可以了。

还有一个问题,一般来说,如果前台拿不到支付状态,但是他的手里一定有个订单号,你是可以通过订单去对应的平台查询订单状态的,从支付宝或者微信一类的跳回到支付页面,你要让前端拿订单号去找你查询是否支付成功,这里的代码其实和上一步的回调几乎一模一样,只需要更新订单状态的时候增加一个where条件,必须订单状态是未支付的时候才去更新,如果更新影响行数是0,则回滚之前的sql(如果有),防止重复更新。

一味的依赖异步回调去更新订单,用户可能会遇到前台订单显示异常。

2个月前 评论
liuhaiqiang999 (楼主) 2个月前
Adachi (作者) 2个月前

作者你抖音支付用的是担保支付 还是 支付系统2.0 ?

2个月前 评论
liuhaiqiang999 (楼主) 2个月前

最终目标是分成三块
1、第三方SDK: 「处理第三接口数据 参考WechatPaySdk做好抽象处理」
2、业务处理层:处理第三方业务逻辑和三方业务订单数据
3、订单服务:汇中订单数据 (用于运营后台等)
file

2个月前 评论

封装 service 这些并不会降低业务复杂度,代码层面边写边封装就行,不可能一开始就能把这些业务都抽象好的。

2个月前 评论

我感觉主要是维护好状态扭转,可以看看这篇文章,用状态机去维护状态的变更 blog.csdn.net/dreamdiary/article/d...

1个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!