GhsRechargeSettleService.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. <?php
  2. namespace bizGhs\custom\services;
  3. use biz\ghs\classes\GhsClass as BizGhsClass;
  4. use bizGhs\custom\classes\AccountMoneyClass;
  5. use bizGhs\custom\classes\CustomBalanceChangeClass;
  6. use bizGhs\custom\classes\CustomClass;
  7. use bizGhs\ghs\classes\GhsBalanceChangeClass;
  8. use bizGhs\order\classes\OrderClearClass;
  9. use bizGhs\order\classes\OrderClass;
  10. use common\components\dict;
  11. use common\components\noticeUtil;
  12. use common\components\util;
  13. /**
  14. * 批发净余额模型:来款、销挂账、流水(对齐 hd RechargeClass::complete)
  15. *
  16. * 规则(仅此一套,无旧三件套):
  17. * 1. 净 balance:正=有余额,负=待结;历史挂账已并入 balance(ensure 幂等)。
  18. * 2. 来款:balance += 金额,记一条充值流水(amount=来款)。
  19. * 3. 销单:仅用「本次资金池」按订单 id FIFO 减少 remainDebtPrice,不再扣 balance。
  20. * 4. 用账面正余额销账:无来款,FIFO 后 balance -= 实销额,可记「结账」流水。
  21. *
  22. * 入口:merchantRechargeWithAutoClear / onlinePayFifoClear / confirmClearBillWithIncoming /
  23. * consumePositiveBalanceFifo
  24. */
  25. class GhsRechargeSettleService
  26. {
  27. /** 结账单掺杂历史正余额时的 payWay(dict balancePay=2) */
  28. const CLEAR_PAY_WAY_BALANCE = 2;
  29. /** 商家帮充 + 按来款 FIFO 销账(CustomController) */
  30. public static function merchantRechargeWithAutoClear($custom, $amount, $shop, $staff, $payWay, $params = [])
  31. {
  32. $pair = self::lockAccountPair($custom, null);
  33. $custom = $pair['custom'];
  34. $ghs = $pair['ghs'];
  35. $pool = self::money($amount);
  36. self::voidAwaitPayClearBills($custom->id ?? 0);
  37. // 入账前净余额:决定结账单线上/线下及 payWay
  38. $balanceBeforeRecharge = bcadd((string)($custom->balance ?? '0'), '0', 2);
  39. $respond = CustomClass::rechargeBalance($custom, $pool, $shop, $staff, $payWay, $params);
  40. $custom = $respond['custom'] ?? $custom;
  41. $ghs = $respond['ghs'] ?? $ghs;
  42. $customRecharge = $respond['customRecharge'] ?? null;
  43. $allocate = self::fifoSettleWithPool($pair, $shop, $staff, $pool, [
  44. 'payWay' => $payWay,
  45. 'balanceBeforeRecharge' => $balanceBeforeRecharge,
  46. 'rechargeSource' => 'merchant',
  47. 'deduct_balance' => false,
  48. ]);
  49. if (!empty($customRecharge) && !empty($allocate['clear'])) {
  50. self::bindRechargeToClear($customRecharge, $respond['ghsRecharge'] ?? null, $allocate, $custom, $ghs);
  51. }
  52. return $respond;
  53. }
  54. /**
  55. * 线上支付已入账后的 FIFO 销账(CustomRechargeClass::thirdPay)。
  56. * $balanceBeforeRecharge 为本次入账前客户净余额,用于 xhClear.onlinePay 判定。
  57. */
  58. public static function onlinePayFifoClear($custom, $ghs, $shop, $amount, $customRecharge, $ghsRecharge = null, $balanceBeforeRecharge = null)
  59. {
  60. $pair = self::lockAccountPair($custom, $ghs);
  61. $pool = self::money($amount);
  62. self::voidAwaitPayClearBills($pair['custom']->id ?? 0);
  63. $payWay = intval(is_object($customRecharge) ? ($customRecharge->payWay ?? dict::getDict('payWay', 'unPay')) : dict::getDict('payWay', 'unPay'));
  64. $thirdNo = is_object($customRecharge) ? (string)($customRecharge->returnCode ?? '') : '';
  65. $allocate = self::fifoSettleWithPool($pair, $shop, null, $pool, [
  66. 'payWay' => $payWay,
  67. 'thirdNo' => $thirdNo,
  68. 'balanceBeforeRecharge' => $balanceBeforeRecharge,
  69. 'rechargeSource' => 'online',
  70. 'deduct_balance' => false,
  71. ]);
  72. if (!empty($customRecharge) && !empty($allocate['clear'])) {
  73. self::bindRechargeToClear($customRecharge, $ghsRecharge, $allocate, $pair['custom'], $pair['ghs']);
  74. }
  75. return $allocate;
  76. }
  77. /** 待付结账单 — 客户已转账:来款入账 + 按本单销订单(OrderClearController) */
  78. public static function confirmClearBillWithIncoming($custom, $ghs, $shop, $staff, $clear, $payWay, $customRecharge = null)
  79. {
  80. $pair = self::lockAccountPair($custom, $ghs);
  81. $custom = $pair['custom'];
  82. $ghs = $pair['ghs'];
  83. $pool = self::money($clear->actPrice ?? 0);
  84. if (bccomp($pool, '0', 2) <= 0) {
  85. util::fail('结账单金额有误');
  86. }
  87. $clearId = intval($clear->id ?? 0);
  88. $clearSn = $clear->orderSn ?? '';
  89. $clearAudit = [
  90. 'clearId' => $clearId,
  91. 'clearSn' => $clearSn,
  92. 'clearAmount' => $pool,
  93. ];
  94. $ghsRecharge = null;
  95. if (empty($customRecharge)) {
  96. $respond = CustomClass::rechargeBalance($custom, $pool, $shop, $staff, $payWay, [
  97. 'remark' => $clear->remark ?? '',
  98. 'clearAudit' => $clearAudit,
  99. ]);
  100. $custom = $respond['custom'];
  101. $ghs = $respond['ghs'];
  102. $customRecharge = $respond['customRecharge'] ?? null;
  103. $ghsRecharge = $respond['ghsRecharge'] ?? null;
  104. }
  105. // 商家「线下已转账」确认:微信/支付宝亦为线下,不得被 confirmClear 兜底标为线上
  106. OrderClearClass::applyNetBalanceClear($clear, $payWay, [
  107. 'skipCashMoney' => true,
  108. 'onlinePay' => intval(dict::getDict('onlinePay', 'not')),
  109. ]);
  110. $settled = self::money(OrderClearClass::sumClearAmountByClearId($clearId));
  111. if (bccomp($settled, $pool, 2) > 0) {
  112. $settled = $pool;
  113. }
  114. $clearAudit['clearAmount'] = $settled;
  115. self::refreshDebtFlags($custom, $ghs);
  116. $allocate = [
  117. 'clear' => $clear,
  118. 'realClearAmount' => $settled,
  119. 'clearId' => $clearId,
  120. 'clearSn' => $clearSn,
  121. 'clearAmount' => $settled,
  122. ];
  123. if (!empty($customRecharge)) {
  124. self::bindRechargeToClear($customRecharge, $ghsRecharge, $allocate, $custom, $ghs);
  125. } else {
  126. self::bindClearToLatestIncomeRow($custom, $ghs, $clear, $settled);
  127. }
  128. return [
  129. 'custom' => $custom,
  130. 'ghs' => $ghs,
  131. 'customRecharge' => $customRecharge,
  132. 'allocate' => $allocate,
  133. ];
  134. }
  135. /** 用当前正余额 FIFO 销挂账(原 useBalanceClear) */
  136. public static function consumePositiveBalanceFifo($custom, $ghs, $shop, $staff)
  137. {
  138. $pair = self::lockAccountPair($custom, $ghs);
  139. $pool = self::money($pair['custom']->balance ?? 0);
  140. if (bccomp($pool, '0', 2) <= 0) {
  141. return true;
  142. }
  143. $balanceBeforeRecharge = self::money($pair['custom']->balance ?? 0);
  144. $allocate = self::fifoSettleWithPool($pair, $shop, $staff, $pool, [
  145. 'deduct_balance' => true,
  146. 'balanceBeforeRecharge' => $balanceBeforeRecharge,
  147. 'rechargeSource' => 'merchant',
  148. ]);
  149. return true;
  150. }
  151. /**
  152. * FIFO 分配计划:按订单 id 升序,资金池用尽即停止。
  153. *
  154. * @return array<int, array{orderId:int, clearAmount:string, orderSn:string}>
  155. */
  156. public static function planFifoByPool($customId, $poolAmount)
  157. {
  158. $pool = self::money($poolAmount);
  159. if (bccomp($pool, '0', 2) <= 0) {
  160. return [];
  161. }
  162. $orderList = OrderClass::getAllByCondition(['customId' => $customId, 'debt' => 1], 'id asc', '*', null, true);
  163. if (empty($orderList)) {
  164. return [];
  165. }
  166. $plan = [];
  167. $used = '0.00';
  168. foreach ($orderList as $order) {
  169. $left = bcsub($pool, $used, 2);
  170. if (bccomp($left, '0', 2) <= 0) {
  171. break;
  172. }
  173. $remain = self::money($order->remainDebtPrice ?? 0);
  174. if (bccomp($remain, '0', 2) <= 0) {
  175. continue;
  176. }
  177. $clearAmount = bccomp($remain, $left, 2) <= 0 ? $remain : $left;
  178. $plan[] = [
  179. 'orderId' => (int)($order->id ?? 0),
  180. 'clearAmount' => $clearAmount,
  181. 'orderSn' => $order->orderSn ?? '',
  182. ];
  183. $used = bcadd($used, $clearAmount, 2);
  184. }
  185. return $plan;
  186. }
  187. /**
  188. * @param array{custom:object, ghs:object} $pair
  189. */
  190. protected static function fifoSettleWithPool(array $pair, $shop, $staff, $poolAmount, $options = [])
  191. {
  192. $custom = $pair['custom'];
  193. $ghs = $pair['ghs'];
  194. $customId = $custom->id ?? 0;
  195. $pool = self::money($poolAmount);
  196. $plan = self::planFifoByPool($customId, $pool);
  197. if (empty($plan)) {
  198. self::refreshDebtFlags($custom, $ghs);
  199. return self::emptyAllocateResult($custom, $ghs);
  200. }
  201. $planTotal = self::sumPlan($plan);
  202. if (bccomp($planTotal, $pool, 2) > 0) {
  203. util::fail('销账计划超过本次可用金额,请联系技术员');
  204. }
  205. self::voidAwaitPayClearBills($customId);
  206. $staffId = $staff->id ?? 0;
  207. $staffName = $staff->name ?? '';
  208. $sjId = $shop->sjId ?? 0;
  209. $shopId = $shop->id ?? 0;
  210. $actualPayWay = isset($options['payWay']) && is_numeric($options['payWay'])
  211. ? intval($options['payWay'])
  212. : intval(dict::getDict('payWay', 'unPay'));
  213. if (array_key_exists('balanceBeforeRecharge', $options)) {
  214. $payMeta = self::resolveClearPayMetaForRechargeFifo(
  215. $options['balanceBeforeRecharge'],
  216. $planTotal,
  217. $pool,
  218. $actualPayWay,
  219. $options['rechargeSource'] ?? 'merchant',
  220. !empty($options['deduct_balance'])
  221. );
  222. $payWay = $payMeta['payWay'];
  223. $onlinePay = $payMeta['onlinePay'];
  224. } elseif (isset($options['onlinePay']) && is_numeric($options['onlinePay'])) {
  225. $payWay = $actualPayWay;
  226. $onlinePay = intval($options['onlinePay']);
  227. } else {
  228. $payWay = $actualPayWay;
  229. $onlinePay = self::resolveOnlinePayByPayWay($payWay);
  230. }
  231. $clear = OrderClearClass::clearWithAmountMap([
  232. 'customId' => $customId,
  233. 'ghsShopAdminId' => $staffId,
  234. 'ghsShopId' => $shopId,
  235. 'ghsShopAdminName' => $staffName,
  236. 'modifyPrice' => $planTotal,
  237. 'payWay' => $payWay,
  238. 'onlinePay' => $onlinePay,
  239. 'complete' => 0,
  240. 'remark' => '',
  241. ], $plan, $sjId, $shopId);
  242. OrderClearClass::applyNetBalanceClear($clear, $payWay, [
  243. 'skipCashMoney' => true,
  244. 'onlinePay' => $onlinePay,
  245. ]);
  246. $clearId = intval($clear->id ?? 0);
  247. if ($clearId > 0 && !empty($options['thirdNo'])) {
  248. $clear = OrderClearClass::getLockById($clearId);
  249. if (!empty($clear) && self::modelHasAttr($clear, 'thirdNo')) {
  250. $clear->thirdNo = (string)$options['thirdNo'];
  251. $clear->save(false, ['thirdNo']);
  252. }
  253. }
  254. $settled = self::money(OrderClearClass::sumClearAmountByClearId($clear->id ?? 0));
  255. if (bccomp($settled, $planTotal, 2) !== 0) {
  256. util::fail('销账结果与计划不一致,请检查订单待结或联系技术员');
  257. }
  258. if (bccomp($settled, $pool, 2) > 0) {
  259. util::fail('销账金额超过本次可用金额' . floatval($pool) . '元,请检查订单待结或联系技术员');
  260. }
  261. if (!empty($options['deduct_balance']) && bccomp($settled, '0', 2) > 0) {
  262. $custom = CustomClass::getLockById($custom->id ?? 0);
  263. $ghs = BizGhsClass::getLockById($ghs->id ?? 0);
  264. CustomClass::clearConsumeBalance($settled, $custom, $ghs, $shop, $staff, $clear);
  265. }
  266. self::refreshDebtFlags($custom, $ghs);
  267. return [
  268. 'clear' => $clear,
  269. 'realClearAmount' => $settled,
  270. 'clearId' => $clear->id ?? 0,
  271. 'clearSn' => $clear->orderSn ?? '',
  272. 'clearAmount' => $settled,
  273. 'custom' => $custom,
  274. 'ghs' => $ghs,
  275. ];
  276. }
  277. /** @return array{custom: object, ghs: object} */
  278. public static function lockAccountPair($custom, $ghs = null)
  279. {
  280. if (empty($custom)) {
  281. util::fail('没有客户信息');
  282. }
  283. $customId = is_object($custom) ? ($custom->id ?? 0) : ($custom['id'] ?? 0);
  284. $custom = CustomClass::getLockById($customId);
  285. if (empty($custom)) {
  286. util::fail('没有找到客户');
  287. }
  288. AccountMoneyClass::ensureCustomMoneyReady($custom, true);
  289. $ghsId = $custom->ghsId ?? 0;
  290. if (empty($ghs)) {
  291. $ghs = BizGhsClass::getLockById($ghsId);
  292. }
  293. if (empty($ghs)) {
  294. util::fail('没有找到供货商');
  295. }
  296. AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
  297. if (bccomp(self::money($custom->balance), self::money($ghs->balance), 2) !== 0) {
  298. noticeUtil::push("客户的余额,和供货商端不一致,客户 ID:" . $custom->id . " 余额:" . $custom->balance . " 供货商 ID:" . $ghsId . ' 余额:' . $ghs->balance, '15280215347');
  299. util::fail('余额有问题,请联系管理员');
  300. }
  301. return ['custom' => $custom, 'ghs' => $ghs];
  302. }
  303. protected static function voidAwaitPayClearBills($customId)
  304. {
  305. OrderClearClass::expireAwaitPayClears(intval($customId));
  306. }
  307. protected static function sumPlan(array $plan)
  308. {
  309. $total = '0.00';
  310. foreach ($plan as $row) {
  311. $total = bcadd($total, self::money($row['clearAmount'] ?? 0), 2);
  312. }
  313. return $total;
  314. }
  315. protected static function refreshDebtFlags($custom, $ghs)
  316. {
  317. $bal = self::money($custom->balance ?? 0);
  318. $custom->isDebt = bccomp($bal, '0', 2) < 0 ? CustomClass::IS_DEBT_YES : CustomClass::IS_DEBT_NO;
  319. $custom->save(false, ['isDebt']);
  320. if (!empty($ghs)) {
  321. $ghs->debt = bccomp($bal, '0', 2) < 0 ? 2 : 1;
  322. $ghs->save(false, ['debt']);
  323. }
  324. }
  325. protected static function emptyAllocateResult($custom, $ghs)
  326. {
  327. return [
  328. 'clear' => null,
  329. 'realClearAmount' => '0.00',
  330. 'clearId' => 0,
  331. 'clearSn' => '',
  332. 'clearAmount' => '0.00',
  333. 'custom' => $custom,
  334. 'ghs' => $ghs,
  335. ];
  336. }
  337. protected static function bindRechargeToClear($customRecharge, $ghsRecharge, $allocate, $custom = null, $ghs = null)
  338. {
  339. $clearId = $allocate['clearId'] ?? 0;
  340. $clearSn = $allocate['clearSn'] ?? '';
  341. $clearAmount = $allocate['clearAmount'] ?? '0.00';
  342. $finalCustomBalance = is_object($custom) ? ($custom->balance ?? null) : null;
  343. $finalGhsBalance = is_object($ghs) ? ($ghs->balance ?? null) : null;
  344. if (!empty($customRecharge) && self::modelHasAttr($customRecharge, 'clearId')) {
  345. $customRecharge->clearId = $clearId;
  346. $customRecharge->clearSn = $clearSn;
  347. $customRecharge->clearAmount = $clearAmount;
  348. if ($finalCustomBalance !== null) {
  349. $customRecharge->balance = $finalCustomBalance;
  350. }
  351. $customRecharge->save(false);
  352. }
  353. $relateId = $customRecharge->id ?? 0;
  354. $customId = is_object($custom) ? intval($custom->id ?? 0) : 0;
  355. if ($customId <= 0 && is_object($customRecharge)) {
  356. $customId = intval($customRecharge->customId ?? 0);
  357. }
  358. CustomBalanceChangeClass::patchClearAuditByRechargeId($customId, $relateId, $clearId, $clearSn, $clearAmount, $finalCustomBalance);
  359. self::patchBalanceChangeRow(CustomBalanceChangeClass::class, $relateId, $clearId, $clearSn, $clearAmount, [
  360. 'customId' => $customId,
  361. ], $finalCustomBalance);
  362. if (!empty($ghsRecharge)) {
  363. $gRelateId = intval($ghsRecharge->id ?? 0);
  364. CustomBalanceChangeClass::patchClearAuditByGhsRechargeId(
  365. $gRelateId,
  366. $clearId,
  367. $clearSn,
  368. $clearAmount,
  369. $finalGhsBalance
  370. );
  371. self::patchBalanceChangeRow(GhsBalanceChangeClass::class, $gRelateId, $clearId, $clearSn, $clearAmount, [], $finalGhsBalance);
  372. $balanceGhsId = intval($ghsRecharge->ghsId ?? 0);
  373. if ($balanceGhsId > 0) {
  374. self::patchBalanceChangeRow(GhsBalanceChangeClass::class, 0, $clearId, $clearSn, $clearAmount, [
  375. 'ghsId' => $balanceGhsId,
  376. 'amount' => self::money($ghsRecharge->amount ?? 0),
  377. ], $finalGhsBalance);
  378. }
  379. if ($finalGhsBalance !== null) {
  380. $ghsRecharge->balance = $finalGhsBalance;
  381. $ghsRecharge->save(false, ['balance']);
  382. }
  383. }
  384. }
  385. protected static function bindClearToLatestIncomeRow($custom, $ghs, $clear, $clearAmount)
  386. {
  387. $clearId = $clear->id ?? 0;
  388. $clearSn = $clear->orderSn ?? '';
  389. self::patchBalanceChangeRow(CustomBalanceChangeClass::class, 0, $clearId, $clearSn, $clearAmount, [
  390. 'customId' => $custom->id ?? 0,
  391. 'io' => 1,
  392. ]);
  393. self::patchBalanceChangeRow(GhsBalanceChangeClass::class, 0, $clearId, $clearSn, $clearAmount, [
  394. 'ghsId' => $ghs->id ?? 0,
  395. 'io' => 1,
  396. ]);
  397. }
  398. protected static function patchBalanceChangeRow($class, $relateId, $clearId, $clearSn, $clearAmount, $extraWhere = [], $finalBalance = null)
  399. {
  400. $where = array_merge(['io' => 1], $extraWhere);
  401. if ($relateId > 0) {
  402. $where['relateId'] = $relateId;
  403. }
  404. $row = $class::getByCondition($where, true, null, 'id DESC');
  405. if (empty($row) || !self::modelHasAttr($row, 'clearId')) {
  406. return;
  407. }
  408. $row->clearId = $clearId;
  409. $row->clearSn = $clearSn;
  410. $row->clearAmount = $clearAmount;
  411. if (self::modelHasAttr($row, 'giveAmount')) {
  412. $row->giveAmount = '0.00';
  413. }
  414. if ($finalBalance !== null && self::modelHasAttr($row, 'balance')) {
  415. $row->balance = $finalBalance;
  416. }
  417. $row->save(false);
  418. }
  419. protected static function modelHasAttr($row, $attr)
  420. {
  421. return is_object($row) && method_exists($row, 'hasAttribute') && $row->hasAttribute($attr);
  422. }
  423. protected static function money($value)
  424. {
  425. return bcadd((string)$value, '0', 2);
  426. }
  427. /** 微信/支付宝视为线上付,其余为线下(非充值销账 FIFO 场景兜底) */
  428. protected static function resolveOnlinePayByPayWay($payWay)
  429. {
  430. $payWay = intval($payWay);
  431. $wxPay = intval(dict::getDict('payWay', 'wxPay'));
  432. $aliPay = intval(dict::getDict('payWay', 'alipay'));
  433. if (in_array($payWay, [$wxPay, $aliPay], true)) {
  434. return intval(dict::getDict('onlinePay', 'yes'));
  435. }
  436. return intval(dict::getDict('onlinePay', 'not'));
  437. }
  438. /**
  439. * 充值 FIFO 结账单 onlinePay / payWay。
  440. * 入账前无正余额:hd 线上充→线上+实付方式;商家手动充→线下+实付方式。
  441. * 入账前仍有正余额:一律线下,payWay=2(余额支付)。
  442. */
  443. protected static function resolveClearPayMetaForRechargeFifo(
  444. $balanceBeforeRecharge,
  445. $settledAmount,
  446. $poolAmount,
  447. $actualPayWay,
  448. $rechargeSource,
  449. $deductBalance = false
  450. )
  451. {
  452. $notOnline = intval(dict::getDict('onlinePay', 'not'));
  453. $yesOnline = intval(dict::getDict('onlinePay', 'yes'));
  454. if ($deductBalance) {
  455. return [
  456. 'onlinePay' => $notOnline,
  457. 'payWay' => self::CLEAR_PAY_WAY_BALANCE,
  458. ];
  459. }
  460. $before = bcadd((string)$balanceBeforeRecharge, '0', 2);
  461. $settled = bcadd((string)$settledAmount, '0', 2);
  462. $pool = bcadd((string)$poolAmount, '0', 2);
  463. $actualPayWay = intval($actualPayWay);
  464. // 客户仍有正余额:掺杂历史余额,线下 + 余额支付
  465. if (bccomp($before, '0', 2) > 0) {
  466. return [
  467. 'onlinePay' => $notOnline,
  468. 'payWay' => self::CLEAR_PAY_WAY_BALANCE,
  469. ];
  470. }
  471. if (bccomp($settled, '0', 2) <= 0 || bccomp($settled, $pool, 2) > 0) {
  472. return [
  473. 'onlinePay' => $notOnline,
  474. 'payWay' => $actualPayWay,
  475. ];
  476. }
  477. // 入账前无余额或负余额:hdApp 线上充值 → 线上 + 微信/支付宝等实付
  478. if ($rechargeSource === 'online') {
  479. $wxPay = intval(dict::getDict('payWay', 'wxPay'));
  480. $aliPay = intval(dict::getDict('payWay', 'alipay'));
  481. if (in_array($actualPayWay, [$wxPay, $aliPay], true)) {
  482. return [
  483. 'onlinePay' => $yesOnline,
  484. 'payWay' => $actualPayWay,
  485. ];
  486. }
  487. return [
  488. 'onlinePay' => $notOnline,
  489. 'payWay' => $actualPayWay,
  490. ];
  491. }
  492. // ghsApp 商家手动充值:线下 + 所选支付方式
  493. return [
  494. 'onlinePay' => $notOnline,
  495. 'payWay' => $actualPayWay,
  496. ];
  497. }
  498. }