# FINANCE - 财务管理模块 **Repository Path**: inphp-modules/finance ## Basic Information - **Project Name**: FINANCE - 财务管理模块 - **Description**: 简单的财务管理,主要用于账户的资产管理、流水记录、充值记录、提现记录(包含提现绑定)、收银记录、退款记录。支持设定在线支付配置,包括:支付宝、微信。1.x 已停止维护,新版INPHP框架,请使用最新的2.x标签 - **Primary Language**: PHP - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2022-03-13 - **Last Updated**: 2025-05-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 财务模块 适用于 INPHP 框架 > 2023.7.3 面向统一付款调取,支持支付中间键定义,支持第三方支付、支付内置余额、积分支付 ```php // 支付成功通知 const FINANCE_PAYED_NOTIFY = "financePayedNotify"; // 非资产退款时,会使该通知,以便通知使用第三方退款原路退回 const FINANCE_REFUND = "financeRefund"; // 退款成功通知 const FINANCE_REFUND_NOTIFY = "financeRefundNotify"; // 获取外部订单数据 const FINANCE_GET_OUTSIDE_ORDER = "financeGetOutsideOrder"; // 在线支付无法处理时,会使用该通知 const FINANCE_ONLINE_PAY = "financeOnlinePay"; ``` ### 支付使用的第三方库 [PaySDK](https://gitee.com/yurunsoft/PaySDK) ```composer "yurunsoft/pay-sdk": "~3.0" ``` ### 项目开发思路 在自己的订单系统中创建订单后,得到订单号,将订单号(orderId)与订单类型(orderType)传到收银接口,创建收银单据,然后作一系列的支付、退款处理。甚至可以实现搭建独立的支付平台。 ### 支付流程 1. 使用 `orderType` + `orderId` 方式生成预付单据,注意,预付款单据不会生成任何数据,仅做数据判断、返回付款单据信息,关键字段有:`payed`(1=已支付, 2=待支付), `amount`(需要支付的金额) 2. 若 `orderType` 的值并非内部订单类型时,会执行 `FINANCE_GET_OUTSIDE_ORDER` 中间键通知,相关的订单模块添加好该中间键的响应,返回固定格式的二维数组即可。 3. 使用 `orderType` + `orderId` 提交生成付款单据,成功将取得单据的`id` 4. 使用单据的`id` + 支付方式`payment` + 自定义参数`params`,进行在线支付时,系统会自动调用 `FINANCE_ONLINE_PAY` 中间键通知,相应的在线支付模块会自动处理,结果会返回支付参数、付款URL,客户端按需使用唤起支付即可。 5. 付款成功时,系统收到第三方平台的支付异步通知时,会执行 `FINANCE_PAYED_NOTIFY` 中间键通知,相关的订单模块添加好该中间键的响应处理,每次通知,会计一次计数 6. 在接收到异步通知时,记得输出正确的信息,系统会自动累计通知完成次数 7. 严格上系统在通知成功后,不会再执行中间键通知,但不排除有手动调试通知的情况,所以相关订单请务必做好防重复通知的处理 ### 退款流程 1. 使用单据 `id` + 退款金额 `amount` + 原因 `reason` 提到交退款接口。 2. 退款接口将自动判断可退款金额与需要退款金额是否足够,在足够的情况下才会进行下一步。 3. 生成退款订单,并且更新收银单据为已退款(`refund`=1),同时累计已退款金额(`refundAmount`+) 4. 等待审核(可设置为无需审核) 5. 审核通过,将款项原路退回 6. 账户内置资产(如:余额、积分)退款时,实时退款成功,非资产退款,调用 `FINANCE_REFUND` 中间键通知,等待第三方代码处理和成功回调 7. 退款成功时,执行 `FINANCE_REFUND_NOTIFY` 中间键通知 8. 请每个订单类型添加好 `FINANCE_REFUND_NOTIFY` 中间键,以判断处理 9. 严格上系统在通知成功后,不会再执行中间键通知,但不排除有手动调试通知的情况,所以相关订单请务必做好防重复通知的处理 ### 内置第三方支付,配置即可使用 - [x] 支付宝 - [x] 微信 ### 内置微信支付接口,支持客户端 - [x] 微信公众号网页支付 - [x] 微信小程序 - [x] APP ### 内置的支付宝支付,支持客户端 - [x] 网页 ### 配置 ```php // 参考配置文件 config.php // 1. 将您想使用该模板的订单类型添加进去 [ "cashier" => [ //订单类型名称解析 "orderTypes" => [ "myOrderType" => "订单类型名称" ], //允许API接口创建收银单的订单类型 "generateOrderTypes" => ["myOrderType"], //需要使用中间键去处理获取订单数据的订单类型 "outsideOrderTypes" => ["myOrderType"] ] ] // 2. 定义中间键,完成订单数据获取、支付完成处理、退款处理 // 订单获取 \Inphp\Core\Middlewares::push(FINANCE_GET_OUTSIDE_ORDER, function (...$args) { //订单类型 $orderType = $args["orderType"] ?? null; //订单号 $orderId = $args["orderId"] ?? 0; $orderId = is_numeric($orderId) && $orderId > 0 ? ceil($orderId) : 0; //必须增加这个判断,因为系统中可能存在很多种订单类型,都会执行同样名称的中间键 if ($orderType === "myOrderType" && $orderId > 0) { //从数据库中查询订单数据 $order = \Inphp\Core\Db\Db::from("myOrderType")->where("orderId", $orderId)->first(); if (!empty($order)) { //计算剩余未支付的金额 $amount = bcsub($order["amount"], $order["payedAmount"], 2); //返回固定格式的数组 return [ //订单号 "orderId" => $orderId, //订单类型 "orderType" => "recharge_order", //原订单总金额 "payAmount" => $order["amount"], //已支付的金额 "payedAmount" => $order["payedAmount"], //剩余未付款金额 "amount" => $amount, //是否已支付完成 "payed" => $amount > 0 ? 0 : 1, //订单信息说明,也会提交到第三方支付接口 "info" => "iPhone 16 1台" ]; } } }); //订单支付成功 \Inphp\Core\Middlewares::push(FINANCE_PAYED_NOTIFY, function (...$args) { //订单类型 $orderType = $args["orderType"] ?? null; //订单号,订单号格式不一定是数字,请自行判断处理 $orderId = $args["orderId"] ?? 0; $orderId = is_numeric($orderId) && $orderId > 0 ? ceil($orderId) : 0; //本次支付成功的金额 $payedAmount = $args["payedAmount"] ?? 0; //支付方式 $payment = $args["payment"] ?? "unknown"; //收银ID $cashierId = $args["cashierId"] ?? 0; if ($orderType === "myOrderType" && $orderId > 0 && $payedAmount > 0) { //处理支付成功... } }); //订单发生退款 \Inphp\Core\Middlewares::push(FINANCE_REFUND_NOTIFY, function (...$args) { //订单类型 $orderType = $args["orderType"] ?? null; //订单号,订单号格式不一定是数字,请自行判断处理 $orderId = $args["orderId"] ?? 0; $orderId = is_numeric($orderId) && $orderId > 0 ? ceil($orderId) : 0; //本次退款成功的金额 $refundAmount = $args["refundAmount"] ?? 0; //退款ID $refundId = $args["refundId"]; if ($orderType === "myOrderType" && $orderId > 0 && $refundAmount > 0) { //处理退款 ... } }); ``` ### 支付配置 ```php // 具体请参考 config.php //在线支付方式 [ "onlinePayments" => [ //微信 "wechat" => [ //名称 "name" => "微信", //是否开通该支付通道 "enable" => true, //appid "appList" => [ //key 为APPID "应用APPID" => [ // "appId" => "应用APPID", //app secret "secret" => "应用APP密钥", //商户ID "mchId" => "微信商户ID", //API V3 密钥 "apiKey" => "", //证书内容 "cert" => "", //证书SN "certSN" => "", //证书key内容 "certKey" => "", //是否开启调试模式,开启后,会变成支付金额为1分钱,退款也是退1分钱 "dev" => false, //提交到支付时的订单号附加前缀 "outTradeNoPrefix" => "" ] ] ], //支付宝 "alipay" => [ //名称 "name" => "支付宝", //是否开通该支付通道 "enable" => true, //appid "appList" => [ //key: 应用ID "应用APPID" => [ //应用ID "appId" => "", //接口网关 "gatewayUrl" => "https://openapi.alipay.com/gateway.do", //私钥,请使用RSA2加密方式,在支付宝工具中取得 "privateKey" => "", //支付宝公钥,在应用配置网页中取得 "publicKey" => "", //异步通知地址 "notifyUrl" => null, //同步地址 "returnUrl" => "https://xxxx.com/finance/pay/return", //是否开启调试模式,开启后,会变成支付金额为1分钱,退款也是退1分钱 "dev" => false, //提交到支付时的订单号附加前缀 "outTradeNoPrefix" => "" ] ] ], //其余在线支付自行配置 ] ] ``` ### 调用支付配置 ```php // 获取在线支付 onlinePayments 配置数组 $payments = \app\finance\model\CashierModel::onlinePayments(); // 获取订单类型名称 $orderName = \app\finance\model\CashierModel::orderName("myOrderType"); ``` ### 调用退款 ```php // 首先从您的订单数据中,获取到收银单据ID,一个订单多次付款会产生多个收银单据ID,请注意处理 $cashierId = $order["cashierId"]; //调用退款 $res = \app\finance\model\CashierModel::refundByCashierId($cashierId); if ($res->error === 0) { //退款处理成功 //退款记录ID $refundId = $res->data["refundId"]; //实际退款金额 $refundAmount = $res->data["refundAmount"]; //处理其它逻辑... } ```