HdRefundService.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. <?php
  2. namespace bizHd\refund\services;
  3. use biz\product\classes\ProductClass;
  4. use biz\shop\classes\MainClass;
  5. use biz\shop\classes\ShopCapitalClass;
  6. use biz\stat\classes\StatOutClass;
  7. use biz\stat\classes\StatRefundClass;
  8. use biz\stock\classes\GoodsStockRecordClass;
  9. use bizHd\base\services\BaseService;
  10. use bizHd\custom\classes\CustomClass;
  11. use bizHd\goods\classes\GoodsClass;
  12. use bizHd\merchant\classes\ShopClass;
  13. use bizHd\order\classes\OrderClass;
  14. use bizHd\order\classes\OrderGoodsClass;
  15. use bizHd\order\classes\OrderItemClass;
  16. use bizHd\refund\classes\HdRefundClass;
  17. use bizHd\refund\classes\HdRefundGoodsClass;
  18. use bizHd\refund\classes\HdRefundItemClass;
  19. use bizGhs\shop\classes\ShopMoneyClass;
  20. use bizHd\wx\classes\WxOpenClass;
  21. use common\components\dict;
  22. use common\components\noticeUtil;
  23. use common\components\orderSn;
  24. use common\components\util;
  25. use Yii;
  26. use common\components\lakala\Lakala;
  27. class HdRefundService extends BaseService
  28. {
  29. public static $baseFile = '\bizHd\refund\classes\HdRefundClass';
  30. //新增退款
  31. public static function addRefund($post, $order)
  32. {
  33. $refundPrice = $post['price'] ?? 0;
  34. if ($refundPrice <= 0) {
  35. util::fail('请填写退款金额');
  36. }
  37. //记录总的退款金额
  38. $order->refundPrice = $refundPrice;
  39. $currentTkPrice = bcadd($order->tkPrice, $refundPrice, 2);
  40. if ($currentTkPrice > $order->mainPay) {
  41. util::fail('可退款金额不足');
  42. }
  43. $order->tkPrice = $currentTkPrice;
  44. $order->refund = OrderClass::REFUND_YES;
  45. $currentActPrice = bcsub($order->actPrice, $refundPrice, 2);
  46. if ($currentActPrice < 0) {
  47. util::fail('可退款金额不足!');
  48. }
  49. $order->actPrice = $currentActPrice;
  50. $order->realPrice = $currentActPrice;
  51. $order->save();
  52. $refundType = $post['refundType'] ?? 1;
  53. $post['orderId'] = $order->id ?? 0;
  54. $data = [];
  55. $data['status'] = HdRefundClass::STATUS_COMPLETE;
  56. $refundSn = orderSn::getHdRefundSn();
  57. $data['refundSn'] = $refundSn;
  58. $data['orderSn'] = $order->orderSn ?? '';
  59. $data['orderId'] = $order->id ?? 0;
  60. $sjId = $post['sjId'] ?? 0;
  61. $shopId = $post['shopId'] ?? 0;
  62. $mainId = $post['mainId'] ?? 0;
  63. $myOrderSn = $order->orderSn ?? '';
  64. $thirdNo = $order->thirdNo ?? '';
  65. $data['sjId'] = $sjId;
  66. $data['shopId'] = $shopId;
  67. $data['mainId'] = $mainId;
  68. $data['shopAdminId'] = $post['shopAdminId'] ?? 0;
  69. $data['shopAdminName'] = $post['shopAdminName'] ?? '';
  70. $postProduct = $post['product'] ?? '';
  71. if ($refundType == 1) {
  72. //商品花材结构 property 0商品 1花材
  73. //[{productId:0,num:1,unitType:0,unitPrice:12,unitName:'扎',property:1}]
  74. if (empty($postProduct)) {
  75. util::fail('没有退款商品');
  76. }
  77. $goodsInfoList = [];
  78. $itemInfoList = [];
  79. $calcAmount = 0;
  80. foreach ($postProduct as $current) {
  81. $property = $current['property'] ?? 0;
  82. if ($property == 0) {
  83. $goodsInfoList[] = $current;
  84. } else {
  85. $itemInfoList[] = $current;
  86. }
  87. $calcNum = $current['num'] ?? 0;
  88. $calcUnitPrice = $current['unitPrice'] ?? 0;
  89. $calcPrice = bcmul($calcNum, $calcUnitPrice, 2);
  90. $calcAmount = bcadd($calcAmount, $calcPrice, 2);
  91. }
  92. if (floatval($refundPrice) < floatval($calcAmount)) {
  93. //util::fail('退款金额要大于商品金额总和');
  94. }
  95. if (!empty($itemInfoList)) {
  96. $ids = array_column($itemInfoList, 'productId');
  97. $productInfo = ProductClass::getByids($ids, null, 'id');
  98. $orderItemData = OrderItemClass::getAllByCondition(['orderSn' => $myOrderSn], null, '*', 'itemId', true);
  99. if (empty($orderItemData)) {
  100. util::fail('没有找到商品');
  101. }
  102. foreach ($itemInfoList as $currentProduct) {
  103. $id = $currentProduct['productId'] ?? 0;
  104. $unitPrice = $currentProduct['unitPrice'] ?? 0;
  105. $unitType = $currentProduct['unitType'] ?? 0;
  106. $unitName = $currentProduct['unitName'] ?? '';
  107. $currentRefundNum = $currentProduct['num'] ?? 0;
  108. $price = bcmul($currentRefundNum, $unitPrice, 2);
  109. $name = $productInfo[$id]['name'] ?? '';
  110. $ptItemId = $productInfo[$id]['itemId'] ?? 0;
  111. $cover = $productInfo[$id]['cover'] ?? '';
  112. $ratio = $productInfo[$id]['ratio'] ?? '';
  113. $bigUnit = $productInfo[$id]['bigUnit'] ?? '';
  114. $smallUnit = $productInfo[$id]['smallUnit'] ?? '';
  115. $currentOrderItem = $orderItemData[$id] ?? null;
  116. if (empty($currentOrderItem)) {
  117. util::fail('没有找到退款的花材');
  118. }
  119. $orderItemNum = $currentOrderItem->num ?? 0;
  120. //已退货数
  121. $hasRefundNum = $currentOrderItem->refundNum ?? 0;
  122. $remainNum = bcsub($orderItemNum, $hasRefundNum);
  123. if ($currentRefundNum > $remainNum) {
  124. util::fail("{$name}超过可退数量");
  125. }
  126. $currentOrderItem->refundNum = bcadd($hasRefundNum, $currentRefundNum);
  127. $currentOrderItem->save();
  128. $thisItemData = [
  129. 'refundSn' => $refundSn,
  130. 'mainId' => $mainId,
  131. 'sjId' => $sjId,
  132. 'shopId' => $shopId,
  133. 'name' => $name,
  134. 'itemId' => $id,
  135. 'ptItemId' => $ptItemId,
  136. 'num' => $currentRefundNum,
  137. 'unitName' => $unitName,
  138. 'unitType' => $unitType,
  139. 'cover' => $cover,
  140. 'ratio' => $ratio,
  141. 'bigUnit' => $bigUnit,
  142. 'smallUnit' => $smallUnit,
  143. 'unitPrice' => $unitPrice,
  144. 'price' => $price,
  145. ];
  146. HdRefundItemClass::addData($thisItemData, $refundSn, $post);
  147. }
  148. }
  149. if (!empty($goodsInfoList)) {
  150. $ids = array_column($goodsInfoList, 'productId');
  151. $goodsData = GoodsClass::getByIds($ids, null, 'id');
  152. $orderGoodsData = OrderGoodsClass::getAllByCondition(['orderSn' => $myOrderSn], null, '*', 'goodsId', true);
  153. foreach ($goodsInfoList as $currentGoods) {
  154. $goodsId = $currentGoods['productId'] ?? 0;
  155. $unitPrice = $currentGoods['unitPrice'] ?? 0;
  156. $name = $goodsData[$goodsId]['name'] ?? '';
  157. $currentRefundNum = $currentGoods['num'] ?? 0;
  158. $price = bcmul($currentRefundNum, $unitPrice, 2);
  159. $currentOrderGoods = $orderGoodsData[$goodsId] ?? [];
  160. if (empty($currentOrderGoods)) {
  161. util::fail('没有找到商品呢');
  162. }
  163. $totalNum = $currentOrderGoods->num ?? 0;
  164. $hasRefundNum = $currentOrderGoods->refundNum ?? 0;
  165. $remainNum = bcsub($totalNum, $hasRefundNum);
  166. if ($currentRefundNum > $remainNum) {
  167. util::fail("{$name}超过可退数量");
  168. }
  169. $currentOrderGoods->refundNum = bcadd($hasRefundNum, $currentRefundNum);
  170. $currentOrderGoods->save();
  171. $cover = $goodsData[$goodsId]['cover'] ?? '';
  172. $num = $currentGoods['num'] ?? 0;
  173. $saveGoods = [
  174. 'refundSn' => $refundSn,
  175. 'mainId' => $mainId,
  176. 'sjId' => $sjId,
  177. 'shopId' => $shopId,
  178. 'name' => $name,
  179. 'cover' => $cover,
  180. 'goodsId' => $goodsId,
  181. 'num' => $num,
  182. 'unitPrice' => $unitPrice,
  183. 'price' => $price,
  184. ];
  185. HdRefundGoodsClass::addData($saveGoods, $refundSn, $post);
  186. }
  187. }
  188. }
  189. $data['customId'] = $order->customId ?? 0;
  190. $data['remark'] = $post['remark'] ?? '';
  191. $data['refundPrice'] = $refundPrice;
  192. $data['refundType'] = $post['refundType'] ?? 0;
  193. //写入订单表
  194. $refund = HdRefundClass::add($data, true);
  195. $payWay = $order->payWay;
  196. $shopId = $order->shopId;
  197. $onlinePay = $order->onlinePay ?? 1;
  198. $main = MainClass::getLockById($mainId);
  199. $shop = ShopClass::getLockById($shopId);
  200. if (empty($main)) {
  201. util::fail('main信息缺失呢');
  202. }
  203. if (empty($shop)) {
  204. util::fail('没有找到门店,编号15860');
  205. }
  206. //总支出增加
  207. $currentTotalExpend = bcadd($main->totalExpend, $refundPrice, 2);
  208. $main->totalExpend = $currentTotalExpend;
  209. $totalRefund = bcadd($main->totalRefund, $refundPrice, 2);
  210. $main->totalRefund = $totalRefund;
  211. $main->save();
  212. //支出流水
  213. $thisType = dict::getDict('capitalType', 'hdOrderRefund', 'id');
  214. $sjId = $order->sjId ?? 0;
  215. $event = '销售退款';
  216. $capitalData = [
  217. 'capitalType' => $thisType,
  218. 'io' => 0,
  219. 'totalExpend' => $currentTotalExpend,
  220. 'payWay' => 0,
  221. 'amount' => $refundPrice,
  222. 'sjId' => $sjId,
  223. 'shopId' => $shopId,
  224. 'event' => $event,
  225. 'mainId' => $mainId,
  226. ];
  227. ShopCapitalClass::addCapital($capitalData);
  228. //当天和当月支出统计
  229. //StatOutClass::updateOrInsert($main, $shop, $refundPrice);
  230. //退款统计
  231. //StatRefundClass::replace($main, $shop, $payWay, $refundPrice);
  232. if ($onlinePay == dict::getDict('onlinePay', 'yes')) {
  233. //退款流程
  234. if ($payWay == dict::getDict('payWay', 'wxPay') || $payWay == dict::getDict('payWay', 'alipay')) {
  235. //门店余额减少
  236. \biz\shop\classes\ShopClass::hdSaleRefundReduceBalance($main, $shop, $refund, $refundPrice);
  237. $refundFee = bcmul($refundPrice, 100);
  238. $merchantPrivateKeyPath = Yii::getAlias("@vendor/lakala") . '/production/api_private_key.pem';
  239. $lklCertificatePath = Yii::getAlias("@vendor/lakala") . '/production/lkl-apigw-v1.cer';
  240. $params = [
  241. 'appid' => 'OP00002119',
  242. 'serial_no' => '018b08cfddbd',
  243. 'merchant_no' => $shop->lklSjNo,
  244. 'term_no' => $shop->lklScanTermNo,
  245. 'merchantPrivateKeyPath' => $merchantPrivateKeyPath,
  246. 'lklCertificatePath' => $lklCertificatePath,
  247. ];
  248. $laResource = new Lakala($params);
  249. $refundReason = '';
  250. $refundParams = [
  251. 'refundSn' => $refundSn,
  252. 'orderSn' => $myOrderSn,
  253. 'refundAmount' => $refundFee,
  254. 'refundReason' => $refundReason,
  255. 'thirdNo' => $thirdNo,//这个参数必传,不然聚合收银合支付宝付款的退款不会成功
  256. ];
  257. $response = $laResource->refund($refundParams);
  258. if (!isset($response['code']) || $response['code'] != 'BBS00000') {
  259. $errMsg = $response['msg'] ?? '';
  260. noticeUtil::push('散客订单,支付宝,退款失败,原因:' . $errMsg . ' refundSn:' . $refundSn . ' orderSn:' . $myOrderSn, '15280215347');
  261. util::fail('退款失败');
  262. }
  263. $wxRefundId = isset($response['resp_data']['trade_no']) ? $response['resp_data']['trade_no'] : '';
  264. $refund->thirdRefundNo = $wxRefundId;
  265. $refund->save();
  266. }
  267. } else {
  268. $customId = $order->customId ?? 0;
  269. $custom = CustomClass::getLockById($customId);
  270. if (empty($custom)) {
  271. util::fail('没有找到客户');
  272. }
  273. if ($payWay == dict::getDict('payWay', 'debtPay')) {
  274. //如果欠款支付,减掉欠款,其实就是增加余额
  275. $currentRemain = bcsub($order->remainDebtPrice, $refundPrice, 2);
  276. if ($currentRemain < 0) {
  277. util::fail('剩余欠款不足售后金额');
  278. }
  279. $order->remainDebtPrice = $currentRemain;
  280. if ($currentRemain <= 0) {
  281. $order->debt = 0;
  282. }
  283. $order->save();
  284. CustomClass::skRefundDebtAmountReduce($custom, $refundPrice, $refund, $payWay);
  285. }
  286. if ($payWay == dict::getDict('payWay', 'cash')) {
  287. //如果现金支付
  288. $moneyData = [
  289. 'shopId' => $shopId,
  290. 'amount' => $refundPrice,
  291. 'orderSn' => $order->orderSn,
  292. 'mainId' => $mainId,
  293. ];
  294. ShopMoneyClass::hdRefundSkOutAmount($moneyData, $main);
  295. }
  296. if ($payWay == dict::getDict('payWay', 'balancePay')) {
  297. //如果是余额支付,客户的余额要增加
  298. CustomClass::skRefundDebtAmountReduce($custom, $refundPrice, $refund, $payWay);
  299. }
  300. }
  301. return $refund;
  302. }
  303. }