|
|
@@ -1,8 +1,8 @@
|
|
|
<?php
|
|
|
/**
|
|
|
- * 隔天售后(冲销)辅助服务
|
|
|
- * 用途:资格校验、资金方式解析、隔天通过后的金额缓存与返余额;不建独立冲销表。
|
|
|
- * 对应:xhRefund/xhCgRefund.sameDay=0,订单 nextDayTkPrice 累计且不改 actPrice。
|
|
|
+ * 售后资金/隔天冲销辅助服务
|
|
|
+ * 用途:资格校验、资金快照(fundType/onlinePay/payWay)、隔天通过后的金额与返余额。
|
|
|
+ * 字段:sameDay 区分当天/隔天;fundType 当天隔天通用;onlinePay/payWay 落在售后单上。
|
|
|
*/
|
|
|
namespace bizGhs\order\services;
|
|
|
|
|
|
@@ -25,10 +25,16 @@ class NextDayRefundService
|
|
|
const SAME_DAY_YES = 1;
|
|
|
const SAME_DAY_NO = 0;
|
|
|
|
|
|
+ /** 资金未确认 */
|
|
|
const FUND_UNUSED = 0;
|
|
|
+ /** 原路退回 */
|
|
|
const FUND_ORIGINAL = 1;
|
|
|
+ /** 返充到余额 */
|
|
|
const FUND_BALANCE = 2;
|
|
|
+ /** 线下自行转账(原「仅记账」) */
|
|
|
const FUND_NONE = 3;
|
|
|
+ /** 与 FUND_NONE 同义,便于语义阅读 */
|
|
|
+ const FUND_OFFLINE = 3;
|
|
|
|
|
|
/**
|
|
|
* 是否有有效支付时间(售后唯一时间依据;无支付时间不能售后)
|
|
|
@@ -134,7 +140,6 @@ class NextDayRefundService
|
|
|
|
|
|
/**
|
|
|
* 隔天售后未选手选资金时的默认值:线上默认原路,其它默认返余额。
|
|
|
- * 最终仍须经 resolveFundType 收敛(挂账/余额强制返余额)。
|
|
|
*/
|
|
|
public static function defaultNextDayFundType($order)
|
|
|
{
|
|
|
@@ -142,13 +147,30 @@ class NextDayRefundService
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 解析隔天资金方式:挂账/余额强制返余额;线上可选原路/返余额/仅记账。
|
|
|
- * $hasRelateOrder=false 表示无原单退款(工作台「退款」),不可原路退。
|
|
|
+ * 当天售后未选手选资金时的默认值:线上原路;余额/挂账返余额;线下默认线下转账。
|
|
|
+ */
|
|
|
+ public static function defaultSameDayFundType($order)
|
|
|
+ {
|
|
|
+ if (self::isOnlinePayOrder($order)) {
|
|
|
+ return self::FUND_ORIGINAL;
|
|
|
+ }
|
|
|
+ $payWay = intval($order->payWay ?? 0);
|
|
|
+ $balancePay = dict::getDict('payWay', 'balancePay');
|
|
|
+ $debtPay = dict::getDict('payWay', 'debtPay');
|
|
|
+ if ($payWay === $balancePay || $payWay === $debtPay) {
|
|
|
+ return self::FUND_BALANCE;
|
|
|
+ }
|
|
|
+ return self::FUND_NONE;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析资金方式(当天/隔天通用):挂账/余额强制返余额;线上可选原路/返余额/线下转账。
|
|
|
+ * $hasRelateOrder=false 表示无原单退款,不可原路退。
|
|
|
*/
|
|
|
public static function resolveFundType($fundType, $order, $hasRelateOrder = true)
|
|
|
{
|
|
|
$fundType = intval($fundType);
|
|
|
- // 无原单:只能返余额或仅记账
|
|
|
+ // 无原单:只能返余额或线下自行转账
|
|
|
if (!$hasRelateOrder || empty($order)) {
|
|
|
if ($fundType === self::FUND_ORIGINAL) {
|
|
|
util::fail('无原单退款不能原路退回');
|
|
|
@@ -161,23 +183,115 @@ class NextDayRefundService
|
|
|
$payWay = intval($order->payWay ?? 0);
|
|
|
$debtPay = dict::getDict('payWay', 'debtPay');
|
|
|
$balancePay = dict::getDict('payWay', 'balancePay');
|
|
|
- // 挂账/余额付款:隔天只能返余额
|
|
|
+ // 挂账/余额付款:资金落到返充余额
|
|
|
if ($payWay === $debtPay || $payWay === $balancePay) {
|
|
|
return self::FUND_BALANCE;
|
|
|
}
|
|
|
- // 线上付款:隔天也允许原路退回(与当天售后一致)
|
|
|
+ // 线上付款:可选原路 / 返余额 / 线下转账
|
|
|
if (self::isOnlinePayOrder($order)) {
|
|
|
if (!in_array($fundType, [self::FUND_ORIGINAL, self::FUND_BALANCE, self::FUND_NONE], true)) {
|
|
|
util::fail('请选择资金处理方式');
|
|
|
}
|
|
|
return $fundType;
|
|
|
}
|
|
|
+ // 线下付款:返余额或线下自行转账
|
|
|
if (!in_array($fundType, [self::FUND_BALANCE, self::FUND_NONE], true)) {
|
|
|
return self::FUND_BALANCE;
|
|
|
}
|
|
|
return $fundType;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 生成写入售后单的资金快照:fundType + onlinePay + payWay(落 xhRefund/xhCgRefund)。
|
|
|
+ * onlinePay:原路且走线上通道为 2,否则 1;payWay:原路/线下转账的具体渠道。
|
|
|
+ *
|
|
|
+ * @param int $fundTypeInput 前端/上游传入,0 表示按 sameDay 自动默认
|
|
|
+ * @param object|null $order 原销售单;无原单传 null
|
|
|
+ * @param bool $hasRelateOrder 是否有关联原单
|
|
|
+ * @param array $options sameDay、payWay(线下转账选手选渠道)
|
|
|
+ * @return array{fundType:int,onlinePay:int,payWay:int}
|
|
|
+ */
|
|
|
+ public static function buildRefundFundSnapshot($fundTypeInput, $order = null, $hasRelateOrder = true, $options = [])
|
|
|
+ {
|
|
|
+ $fundTypeInput = intval($fundTypeInput);
|
|
|
+ $sameDay = intval($options['sameDay'] ?? self::SAME_DAY_YES);
|
|
|
+ $onlineNot = intval(dict::getDict('onlinePay', 'not'));
|
|
|
+ $onlineYes = intval(dict::getDict('onlinePay', 'yes'));
|
|
|
+
|
|
|
+ if ($fundTypeInput === self::FUND_UNUSED && $hasRelateOrder && !empty($order)) {
|
|
|
+ $fundTypeInput = ($sameDay === self::SAME_DAY_NO)
|
|
|
+ ? self::defaultNextDayFundType($order)
|
|
|
+ : self::defaultSameDayFundType($order);
|
|
|
+ }
|
|
|
+
|
|
|
+ $fundType = self::resolveFundType($fundTypeInput, $order, $hasRelateOrder);
|
|
|
+
|
|
|
+ // 返充余额:渠道固定为余额,非线上原路
|
|
|
+ if ($fundType === self::FUND_BALANCE) {
|
|
|
+ return [
|
|
|
+ 'fundType' => self::FUND_BALANCE,
|
|
|
+ 'onlinePay' => $onlineNot,
|
|
|
+ 'payWay' => intval(dict::getDict('payWay', 'balancePay')),
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 线下自行转账:优先用选手选 payWay(微信/支付宝/现金/银行卡)
|
|
|
+ if ($fundType === self::FUND_NONE) {
|
|
|
+ $payWay = self::normalizeOfflinePayWay($options['payWay'] ?? null, $order);
|
|
|
+ return [
|
|
|
+ 'fundType' => self::FUND_NONE,
|
|
|
+ 'onlinePay' => $onlineNot,
|
|
|
+ 'payWay' => $payWay,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 原路退回:线上微信/支付宝标记 onlinePay=2;否则记线下原路渠道
|
|
|
+ if ($fundType === self::FUND_ORIGINAL && !empty($order)) {
|
|
|
+ $orderPayWay = intval($order->payWay ?? 0);
|
|
|
+ if (self::isOnlinePayOrder($order)) {
|
|
|
+ return [
|
|
|
+ 'fundType' => self::FUND_ORIGINAL,
|
|
|
+ 'onlinePay' => $onlineYes,
|
|
|
+ 'payWay' => $orderPayWay,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ return [
|
|
|
+ 'fundType' => self::FUND_ORIGINAL,
|
|
|
+ 'onlinePay' => $onlineNot,
|
|
|
+ 'payWay' => $orderPayWay,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'fundType' => self::FUND_UNUSED,
|
|
|
+ 'onlinePay' => $onlineNot,
|
|
|
+ 'payWay' => 0,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 线下转账渠道:允许 0微信/1支付宝/4现金/5银行卡;非法则回落原单或现金
|
|
|
+ */
|
|
|
+ protected static function normalizeOfflinePayWay($payWay, $order = null)
|
|
|
+ {
|
|
|
+ $allowed = [
|
|
|
+ intval(dict::getDict('payWay', 'wxPay')),
|
|
|
+ intval(dict::getDict('payWay', 'alipay')),
|
|
|
+ intval(dict::getDict('payWay', 'cash')),
|
|
|
+ intval(dict::getDict('payWay', 'bankCard')),
|
|
|
+ ];
|
|
|
+ if ($payWay !== null && $payWay !== '' && in_array(intval($payWay), $allowed, true)) {
|
|
|
+ return intval($payWay);
|
|
|
+ }
|
|
|
+ if (!empty($order)) {
|
|
|
+ $orderPayWay = intval($order->payWay ?? -1);
|
|
|
+ if (in_array($orderPayWay, $allowed, true)) {
|
|
|
+ return $orderPayWay;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return intval(dict::getDict('payWay', 'cash'));
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* GHS 侧隔天通过:累计 nextDayTkPrice,按 fundType 处理资金,不改 actPrice。
|
|
|
* @return string 返余额后的客户余额(非返余额则为当前余额)
|
|
|
@@ -209,7 +323,7 @@ class NextDayRefundService
|
|
|
$custom = CustomClass::getById($customId, true);
|
|
|
$balance = bcadd((string)($custom->balance ?? '0'), '0', 2);
|
|
|
}
|
|
|
- // FUND_ORIGINAL:网关退款在采购侧 CgRefundClass 执行;FUND_NONE:仅记账
|
|
|
+ // FUND_ORIGINAL:网关退款在采购侧执行;FUND_NONE:线下自行转账(只记账)
|
|
|
return $balance;
|
|
|
}
|
|
|
|