HdRefundService.php 13 KB

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