OrderRefund.php 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830
  1. <?php
  2. /**
  3. * Niushop商城系统 - 团队十年电商经验汇集巨献!
  4. * =========================================================
  5. * Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
  6. * ----------------------------------------------
  7. * 官方网址: https://www.niushop.com
  8. * =========================================================
  9. */
  10. namespace app\model\order;
  11. use addon\cardservice\model\MemberCard;
  12. use addon\presale\model\PresaleOrder;
  13. use app\model\goods\GoodsStock;
  14. use app\model\member\Member;
  15. use app\model\member\MemberAccount;
  16. use app\model\shop\Shop;
  17. use app\model\shop\SiteAddress;
  18. use app\model\system\Pay;
  19. use app\model\BaseModel;
  20. use app\model\message\Message;
  21. use addon\coupon\model\Coupon;
  22. use app\model\order\Order as OrderModel;
  23. use app\model\system\Stat;
  24. use app\model\verify\Verify as VerifyModel;
  25. use addon\shopcomponent\model\Weapp;
  26. /**
  27. * 订单退款
  28. *
  29. * @author Administrator
  30. *
  31. */
  32. class OrderRefund extends BaseModel
  33. {
  34. /*********************************************************************************订单退款状态*****************************************************/
  35. //未申请退款
  36. const REFUND_NOT_APPLY = 0;
  37. //已申请退款
  38. const REFUND_APPLY = 1;
  39. // 已确认
  40. const REFUND_CONFIRM = 2;
  41. //已完成
  42. const REFUND_COMPLETE = 3;
  43. //等待买家发货
  44. const REFUND_WAIT_DELIVERY = 4;
  45. //等待卖家收货
  46. const REFUND_WAIT_TAKEDELIVERY = 5;
  47. //卖家确认收货
  48. const REFUND_TAKEDELIVERY = 6;
  49. // 卖家拒绝退款
  50. const REFUND_DIEAGREE = -1;
  51. // 卖家关闭退款
  52. const REFUND_CLOSE = -2;
  53. //退款方式
  54. const ONLY_REFUNDS = 1;//仅退款
  55. const A_REFUND_RETURN = 2;//退款退货
  56. const SHOP_ACTIVE_REFUND = 3;//店铺主动退款
  57. /**
  58. * 订单退款状态
  59. * @var unknown
  60. */
  61. public $order_refund_status = [
  62. 0 => [
  63. 'status' => 0,
  64. 'name' => '',
  65. 'action' => [
  66. ],
  67. 'member_action' => [
  68. [
  69. 'event' => 'orderRefundApply',
  70. 'title' => '申请维权',
  71. 'color' => ''
  72. ],
  73. ]
  74. ],
  75. self::REFUND_APPLY => [
  76. 'status' => self::REFUND_APPLY,
  77. 'name' => '申请维权',
  78. 'action' => [
  79. [
  80. 'event' => 'orderRefundAgree',
  81. 'title' => '同意',
  82. 'color' => ''
  83. ],
  84. [
  85. 'event' => 'orderRefundRefuse',
  86. 'title' => '拒绝',
  87. 'color' => ''
  88. ],
  89. [
  90. 'event' => 'orderRefundClose',
  91. 'title' => '关闭维权',
  92. 'color' => ''
  93. ]
  94. ],
  95. 'member_action' => [
  96. [
  97. 'event' => 'orderRefundCancel',
  98. 'title' => '撤销维权',
  99. 'color' => ''
  100. ],
  101. ]
  102. ],
  103. self::REFUND_CONFIRM => [
  104. 'status' => self::REFUND_CONFIRM,
  105. 'name' => '待转账',
  106. 'action' => [
  107. [
  108. 'event' => 'orderRefundTransfer',
  109. 'title' => '转账',
  110. 'color' => ''
  111. ],
  112. [
  113. 'event' => 'orderRefundClose',
  114. 'title' => '关闭维权',
  115. 'color' => ''
  116. ]
  117. ],
  118. 'member_action' => [
  119. ]
  120. ],
  121. self::REFUND_COMPLETE => [
  122. 'status' => self::REFUND_COMPLETE,
  123. 'name' => '维权结束',
  124. 'action' => [
  125. ],
  126. 'member_action' => [
  127. ]
  128. ],
  129. self::REFUND_WAIT_DELIVERY => [
  130. 'status' => self::REFUND_WAIT_DELIVERY,
  131. 'name' => '买家待退货',
  132. 'action' => [
  133. [
  134. 'event' => 'orderRefundClose',
  135. 'title' => '关闭维权',
  136. 'color' => ''
  137. ]
  138. ],
  139. 'member_action' => [
  140. [
  141. 'event' => 'orderRefundDelivery',
  142. 'title' => '填写发货物流',
  143. 'color' => ''
  144. ],
  145. ]
  146. ],
  147. self::REFUND_WAIT_TAKEDELIVERY => [
  148. 'status' => self::REFUND_WAIT_TAKEDELIVERY,
  149. 'name' => '卖家待收货',
  150. 'action' => [
  151. [
  152. 'event' => 'orderRefundTakeDelivery',
  153. 'title' => '收货',
  154. 'color' => ''
  155. ],
  156. [
  157. 'event' => 'orderRefundRefuse',
  158. 'title' => '拒绝',
  159. 'color' => ''
  160. ],
  161. [
  162. 'event' => 'orderRefundClose',
  163. 'title' => '关闭维权',
  164. 'color' => ''
  165. ]
  166. ],
  167. 'member_action' => [
  168. ]
  169. ],
  170. self::REFUND_TAKEDELIVERY => [
  171. 'status' => self::REFUND_TAKEDELIVERY,
  172. 'name' => '卖家已收货',
  173. 'action' => [
  174. [
  175. 'event' => 'orderRefundTransfer',
  176. 'title' => '转账',
  177. 'color' => ''
  178. ],
  179. [
  180. 'event' => 'orderRefundClose',
  181. 'title' => '关闭维权',
  182. 'color' => ''
  183. ]
  184. ],
  185. 'member_action' => [
  186. ]
  187. ],
  188. self::REFUND_DIEAGREE => [
  189. 'status' => self::REFUND_DIEAGREE,
  190. 'name' => '卖家拒绝',
  191. 'action' => [
  192. [
  193. 'event' => 'orderRefundClose',
  194. 'title' => '关闭维权',
  195. 'color' => ''
  196. ]
  197. ],
  198. 'member_action' => [
  199. [
  200. 'event' => 'orderRefundCancel',
  201. 'title' => '撤销维权',
  202. 'color' => ''
  203. ],
  204. [
  205. 'event' => 'orderRefundAsk',
  206. 'title' => '修改申请',
  207. 'color' => ''
  208. ],
  209. ]
  210. ]
  211. ];
  212. /**
  213. * 退款方式
  214. * @var unknown
  215. */
  216. public $refund_type = [
  217. self::ONLY_REFUNDS => '仅退款',
  218. self::A_REFUND_RETURN => '退货退款',
  219. ];
  220. /**
  221. * 退款方式
  222. * @var unknown
  223. */
  224. public $refund_reason_type = [
  225. '未按约定时间发货',
  226. '拍错/多拍/不喜欢',
  227. '协商一致退款',
  228. '其他',
  229. ];
  230. /****************************************************************************订单退款相关操作(开始)**********************************/
  231. /**
  232. * 获取退款金额
  233. * @param string $order_goods_ids
  234. */
  235. public function getOrderRefundMoney($order_goods_ids)
  236. {
  237. //订单商品项
  238. $order_goods_ids = (string) $order_goods_ids;
  239. $order_goods_lists = model('order_goods')->getList([ [
  240. 'order_goods_id', 'in', is_array($order_goods_ids) ? $order_goods_ids : (string) $order_goods_ids
  241. ] ]);
  242. if (empty($order_goods_lists)) return $this->error(null, '未查询到订单商品');
  243. $order_id = $order_goods_lists[ 0 ][ 'order_id' ];
  244. //退款状态检测 只有未申请的可以发起退款
  245. foreach ($order_goods_lists as $val) {
  246. if (!in_array($val[ 'refund_status' ], [ 0, self::REFUND_NOT_APPLY, self::REFUND_DIEAGREE ])) {
  247. return $this->error(null, '订单商品退款状态有误');
  248. }
  249. }
  250. //剩余未申请退款的订单商品统计
  251. $not_apply_count = model('order_goods')->getCount([
  252. [ 'order_id', '=', $order_id ],
  253. [ 'order_goods_id', 'not in', $order_goods_ids ],
  254. [ 'refund_status', 'in', [ 0, self::REFUND_NOT_APPLY, self::REFUND_DIEAGREE ] ],
  255. ], 'order_goods_id');
  256. //有退过运费的订单商品统计
  257. $refund_delivery_count = model('order_goods')->getCount([
  258. [ 'order_id', '=', $order_id ],
  259. [ 'order_goods_id', 'not in', $order_goods_ids ],
  260. [ 'refund_delivery_money', '>', 0 ],
  261. ], 'order_goods_id');
  262. //如果还有未申请退款的商品就不退运费 发票 和发票运费
  263. if ($not_apply_count > 0) {
  264. $delivery_money = 0;
  265. $invoice_delivery_money = 0;
  266. $invoice_money = 0;
  267. } else {
  268. $order_info = model('order')->getInfo([
  269. [ 'order_id', '=', $order_id ],
  270. ], 'delivery_money, invoice_delivery_money, invoice_money');
  271. if ($refund_delivery_count == 0) {
  272. $delivery_money = $order_info[ 'delivery_money' ];
  273. } else {
  274. $delivery_money = 0;
  275. }
  276. $invoice_delivery_money = $order_info[ 'invoice_delivery_money' ];
  277. $invoice_money = $order_info[ 'invoice_money' ];
  278. }
  279. //计算实际退款金额
  280. $refund_money = 0;
  281. foreach ($order_goods_lists as $item) {
  282. $refund_money += $item[ 'real_goods_money' ];
  283. }
  284. $refund_money += $delivery_money + $invoice_delivery_money + $invoice_money;
  285. $data = array (
  286. 'refund_money' => round($refund_money, 2),
  287. 'refund_delivery_money' => round($delivery_money, 2)
  288. );
  289. return $data;
  290. }
  291. /**
  292. * 订单退回余额
  293. * @param int $order_goods_id
  294. */
  295. public function getOrderRefundBalance($order_goods_id)
  296. {
  297. //订单商品项
  298. $order_goods_info = model('order_goods')->getInfo([
  299. 'order_goods_id' => $order_goods_id
  300. ], 'order_id, goods_money');
  301. //订单整体项
  302. $order_info = model('order')->getInfo([
  303. 'order_id' => $order_goods_info[ 'order_id' ]
  304. ], 'goods_money, balance_money');
  305. if ($order_info[ 'balance_money' ] != 0) {
  306. if ($order_info[ 'goods_money' ] != 0) {
  307. return $this->success($order_info[ 'balance_money' ] * $order_goods_info[ 'goods_money' ] / $order_info[ 'goods_money' ]);
  308. } else {
  309. return $this->success(0);
  310. }
  311. }
  312. return $this->success(0);
  313. }
  314. /**
  315. * 添加退款操作日志
  316. * @param int $order_goods_id
  317. * @param int $refund_status
  318. * @param string $action
  319. * @param int $action_way
  320. * @param int $action_userid
  321. * @param string $action_username
  322. */
  323. public function addOrderRefundLog($order_goods_id, $refund_status, $action, $action_way, $action_userid, $action_username, $desc = '')
  324. {
  325. $data = [
  326. 'order_goods_id' => $order_goods_id,
  327. 'refund_status' => $refund_status,
  328. 'action' => $action,
  329. 'action_way' => $action_way,
  330. 'action_userid' => $action_userid,
  331. 'username' => $action_username,
  332. 'action_time' => time(),
  333. 'desc' => $desc
  334. ];
  335. $res = model('order_refund_log')->add($data);
  336. // 维权状态变更
  337. event('RefundStatusChange', $data);
  338. return $res;
  339. }
  340. /**
  341. * 会员申请退款
  342. * @param array $data
  343. * @param array $member_info
  344. * @return multitype:string mixed
  345. */
  346. public function orderRefundApply($data, $member_info, $log_data = [])
  347. {
  348. $order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $data[ 'order_goods_id' ] ], 'order_id,refund_status,delivery_status,is_virtual,site_id,order_no,order_goods_id');
  349. if (empty($order_goods_info))
  350. return $this->error();
  351. if ($order_goods_info[ 'refund_status' ] != 0 && $order_goods_info[ 'refund_status' ] != -1)
  352. return $this->error();
  353. $refund_type_list = $this->getRefundType($order_goods_info);
  354. //防止退款方式越权
  355. if (!in_array($data[ 'refund_type' ], $refund_type_list))
  356. return $this->error();
  357. $order_info = model('order')->getInfo([ 'order_id' => $order_goods_info[ 'order_id' ] ]);
  358. //判断是否允许申请退款
  359. if ($order_info[ 'is_enable_refund' ] == 0) {
  360. if ($order_info[ 'promotion_type' ] == 'pinfan') {
  361. return $this->error('', '拼团活动正在进行中,待拼成功后可发起退款');
  362. }
  363. return $this->error();
  364. }
  365. model('order_goods')->startTrans();
  366. try {
  367. $data[ 'refund_status' ] = self::REFUND_APPLY;
  368. $data[ 'refund_status_name' ] = $this->order_refund_status[ self::REFUND_APPLY ][ 'name' ];
  369. $data[ 'refund_status_action' ] = json_encode($this->order_refund_status[ self::REFUND_APPLY ], JSON_UNESCAPED_UNICODE);
  370. $data[ 'refund_mode' ] = $order_info[ 'order_status' ] == Order::ORDER_COMPLETE ? 2 : 1;
  371. $pay_model = new Pay();
  372. $data[ 'refund_no' ] = $pay_model->createRefundNo();
  373. $data[ 'refund_action_time' ] = time();
  374. $refund_apply_money_array = $this->getOrderRefundMoney($data[ 'order_goods_id' ]);//可退款金额 通过计算获得
  375. $refund_apply_money = $refund_apply_money_array[ 'refund_money' ];
  376. $refund_delivery_money = $refund_apply_money_array[ 'refund_delivery_money' ];
  377. $data[ 'refund_apply_money' ] = $refund_apply_money;//申请的总退款
  378. $data[ 'refund_delivery_money' ] = $refund_delivery_money;//退的运费
  379. //生成视频号订单ID
  380. $data[ 'out_aftersale_id' ] = $order_goods_info[ 'order_no' ] . time() . $order_goods_info[ 'order_goods_id' ];
  381. $res = model('order_goods')->update($data, [ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  382. //验证订单锁定状态
  383. $local_result = $this->verifyOrderLock($order_goods_info[ 'order_id' ]);
  384. $this->addOrderRefundLog($data[ 'order_goods_id' ], self::REFUND_APPLY, '买家申请退款', 1, $member_info[ 'member_id' ], $member_info[ 'nickname' ]);
  385. event('orderRefundApply', $data);//传入订单类型以及订单项id
  386. model('order_goods')->commit();
  387. //订单会员申请退款消息
  388. $message_model = new Message();
  389. $message_model->sendMessage([ 'keywords' => 'BUYER_REFUND', 'order_goods_id' => $data[ 'order_goods_id' ], 'site_id' => $order_goods_info[ 'site_id' ] ]);
  390. // 发起维权 关闭订单评价
  391. model('order')->update([ 'is_evaluate' => 0 ], [ 'order_id' => $order_goods_info[ 'order_id' ] ]);
  392. //记录订单日志 start
  393. if ($log_data) {
  394. $order_common_model = new OrderCommon();
  395. $log_data = array_merge($log_data, [
  396. 'order_id' => $order_goods_info[ 'order_id' ],
  397. 'order_status' => $order_info[ 'order_status' ],
  398. 'order_status_name' => $order_info[ 'order_status_name' ]
  399. ]);
  400. $order_common_model->addOrderLog($log_data);
  401. }
  402. //记录订单日志 end
  403. return $this->success($res);
  404. } catch (\Exception $e) {
  405. model('order_goods')->rollback();
  406. return $this->error('', $e->getMessage());
  407. }
  408. }
  409. /**
  410. * 用户撤销退款申请
  411. * @param array $data
  412. * @param array $member_info
  413. * @return string[]|mixed[]
  414. */
  415. public function memberCancelRefund($data, $member_info, $log_data = [])
  416. {
  417. $order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  418. if (empty($order_goods_info)) {
  419. return $this->error();
  420. }
  421. model('order_goods')->startTrans();
  422. try {
  423. //
  424. $data[ 'refund_status' ] = 0;
  425. $data[ 'refund_status_name' ] = $this->order_refund_status[ 0 ][ 'name' ];
  426. $data[ 'refund_status_action' ] = json_encode($this->order_refund_status[ 0 ], JSON_UNESCAPED_UNICODE);
  427. $data[ 'refund_type' ] = 0;
  428. //重置部分字段
  429. $data[ 'refund_address' ] = '';
  430. $data[ 'refund_delivery_remark' ] = '';
  431. $data[ 'refund_remark' ] = '';
  432. $data[ 'refund_delivery_name' ] = '';
  433. $data[ 'refund_delivery_no' ] = '';
  434. $data[ 'refund_reason' ] = '';
  435. $res = model('order_goods')->update($data, [ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  436. //验证订单锁定状态
  437. $lock_result = $this->verifyOrderLock($order_goods_info[ 'order_id' ]);
  438. // 维权拒绝 评价锁定放开
  439. $order_info = model('order')->getInfo([ 'order_id' => $order_goods_info[ 'order_id' ] ]);
  440. if ($order_info[ 'evaluate_status' ] != 2) {
  441. model('order')->update([ 'is_evaluate' => 1 ], [ [ 'order_id', '=', $order_goods_info[ 'order_id' ] ], [ 'order_status', 'in', [ OrderModel::ORDER_TAKE_DELIVERY, OrderModel::ORDER_COMPLETE ] ] ]);
  442. }
  443. //记录订单日志 start
  444. if ($log_data) {
  445. $order_common_model = new OrderCommon();
  446. $order_info = model('order')->getInfo([ 'order_id' => $order_goods_info[ 'order_id' ] ], 'order_status,order_status_name,member_id,site_id,is_video_number');
  447. $log_data = array_merge($log_data, [
  448. 'order_id' => $order_goods_info[ 'order_id' ],
  449. 'order_status' => $order_info[ 'order_status' ],
  450. 'order_status_name' => $order_info[ 'order_status_name' ]
  451. ]);
  452. $order_common_model->addOrderLog($log_data);
  453. if ($order_info[ 'is_video_number' ] == 1) {
  454. $weapp_model = new Weapp($order_info[ 'site_id' ]);
  455. $member = model('member')->getInfo([ [ 'member_id', '=', $order_info[ 'member_id' ] ] ]);
  456. $res = $weapp_model->cancel([
  457. 'out_aftersale_id' => $order_goods_info[ 'out_aftersale_id' ],
  458. 'openid' => $member[ 'weapp_openid' ]
  459. ]);
  460. if ($res[ 'code' ] < 0) {
  461. model('order_goods')->rollback();
  462. return $this->error('', $res[ 'message' ]);
  463. }
  464. }
  465. }
  466. //记录订单日志 end
  467. $this->addOrderRefundLog($data[ 'order_goods_id' ], 0, '买家撤销退款申请', 1, $member_info[ 'member_id' ], $member_info[ 'nickname' ]);
  468. event('memberCancelRefund', $data);//传入订单类型以及订单项id
  469. model('order_goods')->commit();
  470. return $this->success();
  471. } catch (\Exception $e) {
  472. model('order_goods')->rollback();
  473. return $this->error('', $e->getMessage());
  474. }
  475. }
  476. /**
  477. * 卖家确认退款
  478. * @param array $data
  479. * @param array $user_info
  480. */
  481. public function orderRefundConfirm($data, $user_info)
  482. {
  483. $order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  484. if (empty($order_goods_info)) {
  485. return $this->error();
  486. }
  487. if ($order_goods_info[ 'refund_status' ] != self::REFUND_APPLY) {
  488. return $this->error();
  489. }
  490. model('order_goods')->startTrans();
  491. try {
  492. if ($order_goods_info[ 'refund_type' ] == 1) {
  493. $data[ 'refund_status' ] = self::REFUND_CONFIRM; //确认等待转账
  494. } else {
  495. $data[ 'refund_status' ] = self::REFUND_WAIT_DELIVERY; //确认等待买家发货
  496. }
  497. $data[ 'refund_status_name' ] = $this->order_refund_status[ $data[ 'refund_status' ] ][ 'name' ];
  498. $data[ 'refund_status_action' ] = json_encode($this->order_refund_status[ $data[ 'refund_status' ] ], JSON_UNESCAPED_UNICODE);
  499. $res = model('order_goods')->update($data, [ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  500. //记录订单日志 start
  501. $order_common_model = new OrderCommon();
  502. $order_info = model('order')->getInfo([ 'order_id' => $order_goods_info[ 'order_id' ] ], 'order_status,order_status_name,is_video_number,site_id');
  503. $log_data = [
  504. 'uid' => $user_info[ 'uid' ],
  505. 'nick_name' => $user_info[ 'username' ],
  506. 'action' => '商家同意了退款申请,等待转账',
  507. 'action_way' => 2,
  508. 'order_id' => $order_goods_info[ 'order_id' ],
  509. 'order_status' => $order_info[ 'order_status' ],
  510. 'order_status_name' => $order_info[ 'order_status_name' ]
  511. ];
  512. $order_common_model->addOrderLog($log_data);
  513. //记录订单日志 end
  514. if ($order_goods_info[ 'refund_type' ] != 1) {
  515. if ($order_info[ 'is_video_number' ] == 1) {
  516. // $shop_info = model('shop')->getInfo([['site_id', '=',$order_info['site_id'] ]]);
  517. $refund_address = $this->getRefundAddress($order_goods_info[ 'site_id' ]);
  518. $weapp_model = new Weapp($order_info[ 'site_id' ]);
  519. $res = $weapp_model->aceptreturn([
  520. 'out_aftersale_id' => $order_goods_info[ 'out_aftersale_id' ],
  521. 'address_info' => [
  522. 'receiver_name' => $refund_address[ 'shop_contacts' ],
  523. 'detailed_address' => $refund_address[ 'shop_address' ],
  524. 'tel_number' => $refund_address[ 'shop_mobile' ],
  525. 'country' => '',
  526. 'province' => $refund_address[ 'province_name' ] ?? '无',
  527. 'city' => $refund_address[ 'city_name' ] ?? '无',
  528. 'town' => $refund_address[ 'district_name' ] ?? '无',
  529. ]
  530. ]);
  531. if ($res[ 'code' ] < 0) {
  532. model('order_goods')->rollback();
  533. return $this->error('', $res[ 'message' ]);
  534. }
  535. }
  536. }
  537. $this->addOrderRefundLog($data[ 'order_goods_id' ], $data[ 'refund_status' ], '卖家确认退款', 2, $user_info[ 'uid' ], $user_info[ 'username' ]);
  538. model('order_goods')->commit();
  539. //订单退款同意消息
  540. $message_model = new Message();
  541. $message_model->sendMessage([ 'keywords' => 'ORDER_REFUND_AGREE', 'order_id' => $order_goods_info[ 'order_id' ], 'order_goods_id' => $data[ 'order_goods_id' ], 'site_id' => $order_goods_info[ 'site_id' ] ]);
  542. return $this->success($res);
  543. } catch (\Exception $e) {
  544. model('order_goods')->rollback();
  545. return $this->error('', $e->getMessage());
  546. }
  547. }
  548. /**
  549. * 卖家拒绝退款
  550. * @param array $data
  551. * @param array $user_info
  552. */
  553. public function orderRefundRefuse($data, $user_info, $refund_refuse_reason, $log_data = [])
  554. {
  555. $order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  556. if (empty($order_goods_info)) {
  557. return $this->error();
  558. }
  559. if ($order_goods_info[ 'refund_status' ] != self::REFUND_APPLY && $order_goods_info[ 'refund_status' ] != self::REFUND_WAIT_TAKEDELIVERY) {
  560. return $this->error();
  561. }
  562. model('order_goods')->startTrans();
  563. try {
  564. $data[ 'refund_status' ] = self::REFUND_DIEAGREE;
  565. $data[ 'refund_status_name' ] = $this->order_refund_status[ self::REFUND_DIEAGREE ][ 'name' ];
  566. $data[ 'refund_status_action' ] = json_encode($this->order_refund_status[ self::REFUND_DIEAGREE ], JSON_UNESCAPED_UNICODE);
  567. $data[ 'refund_refuse_reason' ] = $refund_refuse_reason;
  568. $data[ 'refund_action_time' ] = time();
  569. $res = model('order_goods')->update($data, [ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  570. //验证订单锁定状态
  571. $lock_result = $this->verifyOrderLock($order_goods_info[ 'order_id' ]);
  572. $log_desc = empty($refund_refuse_reason) ? '' : '拒绝原因:' . $refund_refuse_reason;
  573. $this->addOrderRefundLog($data[ 'order_goods_id' ], $data[ 'refund_status' ], '卖家拒绝退款', 2, $user_info[ 'uid' ], $user_info[ 'username' ], $log_desc);
  574. event('OrderRefundRefuse', $data);
  575. //记录订单日志 start
  576. $order_info = model('order')->getInfo([ 'order_id' => $order_goods_info[ 'order_id' ] ], 'order_status,order_status_name,is_video_number,site_id');
  577. if ($log_data) {
  578. $order_common_model = new OrderCommon();
  579. $log_data = array_merge($log_data, [
  580. 'order_id' => $order_goods_info[ 'order_id' ],
  581. 'order_status' => $order_info[ 'order_status' ],
  582. 'order_status_name' => $order_info[ 'order_status_name' ]
  583. ]);
  584. $order_common_model->addOrderLog($log_data);
  585. }
  586. if ($order_info[ 'is_video_number' ] == 1) {
  587. $weapp_model = new Weapp($order_info[ 'site_id' ]);
  588. $res = $weapp_model->orderNoRefund([ 'out_aftersale_id' => $order_goods_info[ 'out_aftersale_id' ] ]);
  589. if ($res[ 'code' ] < 0) {
  590. model('order_goods')->rollback();
  591. return $this->error('', $res[ 'message' ]);
  592. }
  593. }
  594. //记录订单日志 end
  595. // 维权拒绝 评价锁定放开
  596. model('order')->update([ 'is_evaluate' => 1 ], [ [ 'order_id', '=', $order_goods_info[ 'order_id' ] ], [ 'order_status', 'in', [ OrderModel::ORDER_TAKE_DELIVERY, OrderModel::ORDER_COMPLETE ] ] ]);
  597. //订单退款拒绝消息
  598. $message_model = new Message();
  599. $message_model->sendMessage([ 'keywords' => 'ORDER_REFUND_REFUSE', 'order_id' => $order_goods_info[ 'order_id' ], 'order_goods_id' => $data[ 'order_goods_id' ], 'site_id' => $order_goods_info[ 'site_id' ] ]);
  600. model('order_goods')->commit();
  601. return $this->success();
  602. } catch (\Exception $e) {
  603. model('order_goods')->rollback();
  604. return $this->error('', $e->getMessage());
  605. }
  606. }
  607. /**
  608. * 买家退货
  609. * @param array $data 退货信息
  610. * @param array $member_info 会员信息
  611. */
  612. public function orderRefundDelivery($data, $member_info)
  613. {
  614. $order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  615. if (empty($order_goods_info)) {
  616. return $this->error();
  617. }
  618. if ($order_goods_info[ 'refund_status' ] != self::REFUND_WAIT_DELIVERY) {
  619. return $this->error();
  620. }
  621. model('order_goods')->startTrans();
  622. try {
  623. $data[ 'refund_status' ] = self::REFUND_WAIT_TAKEDELIVERY;
  624. $data[ 'refund_status_name' ] = $this->order_refund_status[ self::REFUND_WAIT_TAKEDELIVERY ][ 'name' ];
  625. $data[ 'refund_status_action' ] = json_encode($this->order_refund_status[ self::REFUND_WAIT_TAKEDELIVERY ], JSON_UNESCAPED_UNICODE);
  626. // $shop_model = new Shop();
  627. // $shop_info_result = $shop_model->getShopInfo([ [ 'site_id', '=', $order_goods_info[ 'site_id' ] ] ], 'full_address');
  628. // $shop_info = $shop_info_result[ 'data' ];
  629. $refund_address = $this->getRefundAddress($order_goods_info[ 'site_id' ]);
  630. $data[ 'refund_address' ] = $refund_address[ 'shop_address' ];
  631. $res = model('order_goods')->update($data, [ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  632. $this->addOrderRefundLog($data[ 'order_goods_id' ], $data[ 'refund_status' ], $data[ 'refund_delivery_name' ] . ':' . $data[ 'refund_delivery_no' ], 1, $member_info[ 'member_id' ], $member_info[ 'nickname' ]);
  633. $order_info = model('order')->getInfo([ 'order_id' => $order_goods_info[ 'order_id' ] ], 'order_status,order_status_name,is_video_number,site_id,member_id');
  634. if ($order_info[ 'is_video_number' ] == 1) {
  635. $member_info = model('member')->getInfo([ [ 'member_id', '=', $order_info[ 'member_id' ] ] ]);
  636. $weapp_model = new Weapp($order_info[ 'site_id' ]);
  637. $res = $weapp_model->uploadreturninfo([
  638. 'out_aftersale_id' => $order_goods_info[ 'out_aftersale_id' ],
  639. 'openid' => $member_info[ 'weapp_openid' ],
  640. 'delivery_id' => '',
  641. 'waybill_id' => $order_goods_info[ 'refund_delivery_no' ],
  642. 'delivery_name' => $order_goods_info[ 'refund_delivery_name' ]
  643. ]);
  644. if ($res[ 'code' ] < 0) {
  645. model('order_goods')->rollback();
  646. return $this->error('', $res[ 'message' ]);
  647. }
  648. }
  649. model('order_goods')->commit();
  650. //买家已退货提醒
  651. $message_model = new Message();
  652. $message_model->sendMessage([ 'keywords' => 'BUYER_DELIVERY_REFUND', 'order_goods_info' => $order_goods_info, 'site_id' => $order_goods_info[ 'site_id' ] ]);
  653. return $this->success();
  654. } catch (\Exception $e) {
  655. model('order_goods')->rollback();
  656. return $this->error('', $e->getMessage());
  657. }
  658. }
  659. /**
  660. * 卖家确认收到退货
  661. * @param array $data 退货信息
  662. * @param array $member_info 会员信息
  663. */
  664. public function orderRefundTakeDelivery($data, $user_info)
  665. {
  666. $order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  667. if (empty($order_goods_info)) {
  668. return $this->error();
  669. }
  670. if ($order_goods_info[ 'refund_status' ] != self::REFUND_WAIT_TAKEDELIVERY) {
  671. return $this->error();
  672. }
  673. model('order_goods')->startTrans();
  674. try {
  675. $data[ 'refund_status' ] = self::REFUND_TAKEDELIVERY;
  676. $data[ 'refund_status_name' ] = $this->order_refund_status[ self::REFUND_TAKEDELIVERY ][ 'name' ];
  677. $data[ 'refund_status_action' ] = json_encode($this->order_refund_status[ self::REFUND_TAKEDELIVERY ], JSON_UNESCAPED_UNICODE);
  678. $res = model('order_goods')->update($data, [ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  679. $this->addOrderRefundLog($data[ 'order_goods_id' ], $data[ 'refund_status' ], '卖家确认收到退货', 2, $user_info[ 'uid' ], $user_info[ 'username' ]);
  680. model('order_goods')->commit();
  681. return $this->success();
  682. } catch (\Exception $e) {
  683. model('order_goods')->rollback();
  684. return $this->error('', $e->getMessage());
  685. }
  686. }
  687. /**
  688. * 退货完成
  689. * @param array $data
  690. * @param array $user_info
  691. * @return multitype:string mixed
  692. */
  693. public function orderRefundFinish($data, $user_info, $log_data = [])
  694. {
  695. $order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  696. if (empty($order_goods_info))
  697. return $this->error([], '不存在的退款项');
  698. $order_id = $order_goods_info[ 'order_id' ];
  699. $order_info = model('order')->getInfo([ [ 'order_id', '=', $order_id ] ]);
  700. if (empty($order_info))
  701. return $this->error([], '不存在的退款项');
  702. $refund_apply_money = $order_goods_info[ 'refund_apply_money' ];
  703. $shop_active_refund = $data[ 'shop_active_refund' ] ?? 0;
  704. $update_data = array (
  705. 'refund_time' => time(),
  706. 'shop_active_refund' => $shop_active_refund,
  707. );
  708. if ($shop_active_refund == 1) {//商家主动退款
  709. //查询发货状态(已发货的不能主动退款)
  710. if ($order_info[ 'order_scene' ] == 'online') {//todo 只有非收银订单受限
  711. if ($order_goods_info[ 'delivery_status' ] != OrderModel::DELIVERY_WAIT) {
  712. return $this->error([], '已发货的订单不能发起主动退款');
  713. }
  714. }
  715. //获取可退金额
  716. $do_refund_money = $data[ 'do_refund_money' ] ?? 0;
  717. $refund_apply_money_arr = $this->getOrderRefundMoney($data[ 'order_goods_id' ]);
  718. // $refund_apply_money = $refund_apply_money_arr['refund_money'];
  719. $refund_apply_money = $do_refund_money;
  720. $refund_delivery_money = $refund_apply_money_arr[ 'refund_delivery_money' ];
  721. $data[ 'refund_real_money' ] = $refund_apply_money;
  722. $data[ 'refund_delivery_money' ] = $refund_delivery_money;
  723. $update_data[ 'refund_no' ] = ( new Pay() )->createRefundNo();
  724. $update_data[ 'refund_action_time' ] = time();
  725. } else {
  726. if ($order_goods_info[ 'refund_status' ] != self::REFUND_TAKEDELIVERY && $order_goods_info[ 'refund_status' ] != self::REFUND_CONFIRM) {
  727. return $this->error();
  728. }
  729. }
  730. if ($data[ 'refund_real_money' ] > $refund_apply_money) return $this->error('', '退款金额超出最大可退金额');
  731. model('order_goods')->startTrans();
  732. try {
  733. $update_data[ 'refund_apply_money' ] = $refund_apply_money;
  734. $update_data[ 'refund_money_type' ] = $data[ 'refund_money_type' ];
  735. $update_data[ 'refund_real_money' ] = $data[ 'refund_real_money' ];
  736. $update_data[ 'shop_refund_remark' ] = $data[ 'shop_refund_remark' ];
  737. $update_data[ 'refund_delivery_money' ] = $data[ 'refund_delivery_money' ] ?? 0.00;
  738. $update_data[ 'refund_status' ] = self::REFUND_COMPLETE;
  739. $update_data[ 'refund_status_name' ] = $this->order_refund_status[ self::REFUND_COMPLETE ][ 'name' ];
  740. $update_data[ 'refund_status_action' ] = json_encode($this->order_refund_status[ self::REFUND_COMPLETE ], JSON_UNESCAPED_UNICODE);
  741. if (!empty($data[ 'out_aftersale_id' ])) {
  742. $update_data[ 'out_aftersale_id' ] = $data[ 'out_aftersale_id' ];
  743. }
  744. $res = model('order_goods')->update($update_data, [ [ 'order_goods_id', '=', $data[ 'order_goods_id' ] ] ]);
  745. $result = $this->finishAction($data[ 'order_goods_id' ], $log_data, $data[ 'is_deposit_back' ] ?? 0);
  746. if ($result[ 'code' ] < 0) {
  747. model('order_goods')->rollback();
  748. return $result;
  749. }
  750. //退货日志
  751. $this->addOrderRefundLog($data[ 'order_goods_id' ], self::REFUND_COMPLETE, '维权完成', 2, $user_info[ 'uid' ], $user_info[ 'username' ], '维权完成,退款金额:¥' . $data[ 'refund_real_money' ] ?? 0);
  752. $order_goods_info = model('order_goods')->getInfo([ [ 'order_goods_id', '=', $data[ 'order_goods_id' ] ] ]);
  753. $this->orderGoodsRefund($order_goods_info);
  754. //同时修改用户的order_money
  755. model('member')->setDec([ [ 'member_id', '=', $order_goods_info[ 'member_id' ] ] ], 'order_money', $order_goods_info[ 'refund_real_money' ]);
  756. // event('OrderRefundFinish', $order_goods_info);//传入订单类型以及订单项id
  757. model('order_goods')->commit();
  758. return $this->success();
  759. } catch (\Exception $e) {
  760. model('order_goods')->rollback();
  761. return $this->error('', $e->getMessage() . $e->getFile() . $e->getLine());
  762. }
  763. }
  764. /**
  765. * 退款完成操作
  766. * @param $order_goods_id
  767. * @param $refund_money_type
  768. * @return array
  769. */
  770. public function finishAction($order_goods_id, $log_data = [], $is_deposit_back = 1, $is_active_refund = false)
  771. {
  772. $order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $order_goods_id ]);
  773. $order_id = $order_goods_info[ 'order_id' ];
  774. $site_id = $order_goods_info[ 'site_id' ];
  775. model('order_goods')->startTrans();
  776. try {
  777. $order_info = model('order')->getInfo([ 'order_id' => $order_id ]);
  778. //验证订单是否全部退款完毕
  779. $order_goods_count = model('order_goods')->getCount([ [ 'order_id', '=', $order_id ] ], 'order_goods_id');
  780. $refund_count = model('order_goods')->getCount([ [ 'order_id', '=', $order_id ], [ 'refund_status', '=', self::REFUND_COMPLETE ] ], 'order_goods_id');
  781. $refund_total_real_money = model('order_goods')->getSum([ [ 'order_id', '=', $order_id ], [ 'refund_status', '=', self::REFUND_COMPLETE ] ], 'refund_real_money');
  782. if ($refund_total_real_money > $order_info[ 'order_money' ]) {
  783. model('order_goods')->rollback();
  784. return $this->error([], '退款金额不能大于订单总金额');
  785. }
  786. //todo 退还创建订单时使用的次卡
  787. //实际执行转账 (存在余额支付的话 退款一部分余额 退还一部分实际金额) //订单退款退回余额积分等操作
  788. if ($order_info[ 'balance_money' ] > 0 && $order_goods_info[ 'refund_real_money' ] > 0) {
  789. $balance_rate = $order_info[ 'balance_money' ] / $order_info[ 'order_money' ];
  790. $refund_balance_money = $order_goods_info[ 'refund_real_money' ] * $balance_rate;
  791. $refund_pay_money = $order_goods_info[ 'refund_real_money' ] - $refund_balance_money;
  792. } else {
  793. $refund_balance_money = 0;
  794. $refund_pay_money = $order_goods_info[ 'refund_real_money' ];
  795. }
  796. model('order_goods')->update([ 'refund_pay_money' => $refund_pay_money ], [ 'order_goods_id' => $order_goods_id ]);
  797. $addon_result = event('AddonOrderRefund', [ 'order_no' => $order_info[ 'order_no' ], 'promotion_type' => $order_info[ 'promotion_type' ], 'is_deposit_back' => $is_deposit_back, 'refund_money_type' => $order_goods_info[ 'refund_money_type' ] ], true);
  798. if (empty($addon_result)) {
  799. //原路退回的时候退还余额 + 支付金额
  800. if ($order_goods_info[ 'refund_money_type' ] == 1) {
  801. //退还直接支付的金额
  802. if ($refund_pay_money > 0) {
  803. $pay_model = new Pay();
  804. if ($order_goods_info[ 'refund_no' ] == '') {
  805. $refund_no = $pay_model->createRefundNo();
  806. } else {
  807. $refund_no = $order_goods_info[ 'refund_no' ];
  808. }
  809. $refund_result = $pay_model->refund($refund_no, $refund_pay_money, $order_info[ 'out_trade_no' ], '', $order_info[ 'pay_money' ], $order_info[ 'site_id' ], 1, $order_goods_id, $order_info[ 'is_video_number' ]);
  810. if ($refund_result[ 'code' ] < 0) {
  811. model('order_goods')->rollback();
  812. return $refund_result;
  813. }
  814. //支付时超卖,主动退款的话,不计入统计数据
  815. if (!$is_active_refund) {
  816. $stat_model = new Stat();
  817. $stat_model->switchStat([ 'type' => 'order_refund', 'data' => [ 'order_goods_id' => $order_goods_id, 'refund_pay_money' => $refund_pay_money, 'site_id' => $site_id ] ]);
  818. }
  819. }
  820. //退款余额
  821. if ($refund_balance_money > 0) {
  822. $member_account_model = new MemberAccount();
  823. // 查询该订单使用的现金余额
  824. $order_use_balance_money = abs($member_account_model->getMemberAccountSum([ [ 'account_type', '=', 'balance_money' ], [ 'type_tag', '=', $order_id ], [ 'from_type', '=', 'order' ] ], 'account_data')[ 'data' ]);
  825. // 查询该订单已退回的现金余额
  826. $refunded_balance_money = $member_account_model->getMemberAccountSum([ [ 'account_type', '=', 'balance_money' ], [ 'type_tag', '=', $order_id ], [ 'from_type', '=', 'refund' ] ], 'account_data')[ 'data' ];
  827. if ($order_use_balance_money > $refunded_balance_money) {
  828. $refundable_balance_money = $order_use_balance_money - $refunded_balance_money;
  829. $refundable_balance_money = $refundable_balance_money > $refund_balance_money ? $refund_balance_money : $refundable_balance_money;
  830. $refund_balance_money -= $refundable_balance_money;
  831. $balance_result = $member_account_model->addMemberAccount($order_info[ 'site_id' ], $order_info[ 'member_id' ], 'balance_money', $refundable_balance_money, 'refund', $order_id, '订单退款返还');
  832. if ($balance_result[ 'code' ] < 0) {
  833. model('order_goods')->rollback();
  834. return $balance_result;
  835. }
  836. }
  837. if ($refund_balance_money > 0) {
  838. $balance_result = $member_account_model->addMemberAccount($order_info[ 'site_id' ], $order_info[ 'member_id' ], 'balance', $refund_balance_money, 'refund', $order_id, '订单退款返还');
  839. if ($balance_result[ 'code' ] < 0) {
  840. model('order_goods')->rollback();
  841. return $balance_result;
  842. }
  843. }
  844. }
  845. } else if ($order_goods_info[ 'refund_money_type' ] == 3) { //退款到余额
  846. $member_account_model = new MemberAccount();
  847. $refund_result = $member_account_model->addMemberAccount($order_info[ 'site_id' ], $order_info[ 'member_id' ], 'balance', $refund_total_real_money, 'refund', $order_id, '订单退款返还');
  848. if ($refund_result[ 'code' ] < 0) {
  849. model('order_goods')->rollback();
  850. return $refund_result;
  851. }
  852. } else if ($order_goods_info[ 'refund_money_type' ] == 2) {//线下退款
  853. //支付时超卖,主动退款的话,不计入统计数据
  854. if (!$is_active_refund) {
  855. $stat_model = new Stat();
  856. $stat_model->switchStat([ 'type' => 'order_refund', 'data' => [ 'order_goods_id' => $order_goods_id, 'refund_pay_money' => $refund_pay_money, 'site_id' => $site_id ] ]);
  857. }
  858. }
  859. } else {
  860. if ($addon_result[ 'code' ] < 0) {
  861. model('order_goods')->rollback();
  862. return $addon_result;
  863. }
  864. }
  865. //虚拟商品 退款 修改核销码状态
  866. if ($order_goods_info[ 'refund_mode' ] == 1 && $order_goods_info[ 'goods_class' ] == 2) {
  867. $verify_goods_condition = [
  868. [ 'order_no', '=', $order_info[ 'order_no' ] ],
  869. [ 'site_id', '=', $order_info[ 'site_id' ] ]
  870. ];
  871. $virtual_goods_res = model('goods_virtual')->update([ 'is_veirfy' => 2 ], $verify_goods_condition);
  872. $verify_model = new VerifyModel();
  873. $verify_condition = [
  874. [ 'verify_code', '=', $order_info[ 'virtual_code' ] ],
  875. [ 'site_id', '=', $order_info[ 'site_id' ] ]
  876. ];
  877. $verify_res = $verify_model->editVerify([ 'is_verify' => 2 ], $verify_condition);
  878. }
  879. // 退还积分 只有退款时返还 售后不返还
  880. if ($order_goods_info[ 'refund_mode' ] == 1 && $order_goods_info[ 'use_point' ] > 0) {
  881. $member_account_model = new MemberAccount();
  882. $point_result = $member_account_model->addMemberAccount($order_info[ 'site_id' ], $order_info[ 'member_id' ], 'point', $order_goods_info[ 'use_point' ], 'refund', $order_id, '订单退款返还');
  883. if ($point_result[ 'code' ] < 0) {
  884. model('order_goods')->rollback();
  885. return $point_result;
  886. }
  887. }
  888. // 退还次卡
  889. if (!empty($order_goods_info[ 'card_item_id' ]) && addon_is_exit('cardservice', $order_goods_info[ 'site_id' ])) {
  890. ( new MemberCard() )->refund([ [ 'type' => 'order', 'relation_id' => $order_goods_info[ 'order_goods_id' ] ] ]);
  891. }
  892. //验证订单锁定状态
  893. $lock_result = $this->verifyOrderLock($order_id);
  894. //验证订单是否全部退款完毕 订单如果全部退款完毕,订单关闭
  895. if ($order_goods_count == $refund_count) {
  896. //将订单设置为不可退款
  897. $order_common_model = new OrderCommon();
  898. $order_common_model->orderUpdate([ 'is_enable_refund' => 0 ], [ [ 'order_id', '=', $order_id ] ]);
  899. if ($order_info[ 'order_status' ] != Order::ORDER_COMPLETE) {
  900. $order_common_model = new OrderCommon();
  901. //记录订单日志 start
  902. if (!empty($log_data)) {
  903. $log_data = array_merge($log_data, [
  904. 'order_id' => $order_id,
  905. 'order_status' => -1,
  906. 'order_status_name' => '已关闭'
  907. ]);
  908. $order_common_model->addOrderLog($log_data);
  909. }
  910. $close_result = $order_common_model->orderClose($order_id, [], '退款完成,订单关闭');
  911. if ($close_result[ 'code' ] < 0) {
  912. model('order_goods')->rollback();
  913. return $close_result;
  914. }
  915. } else {
  916. if (!empty($log_data)) {
  917. $order_common_model = new OrderCommon();
  918. $log_data = array_merge($log_data, [
  919. 'order_id' => $order_id,
  920. 'order_status' => $order_info[ 'order_status' ],
  921. 'order_status_name' => $order_info[ 'order_status_name' ]
  922. ]);
  923. $order_common_model->addOrderLog($log_data);
  924. }
  925. }
  926. } else {
  927. //记录订单日志 start
  928. if (!empty($log_data)) {
  929. $order_common_model = new OrderCommon();
  930. $log_data = array_merge($log_data, [
  931. 'order_id' => $order_id,
  932. 'order_status' => $order_info[ 'order_status' ],
  933. 'order_status_name' => $order_info[ 'order_status_name' ]
  934. ]);
  935. $order_common_model->addOrderLog($log_data);
  936. }
  937. //记录订单日志 end
  938. }
  939. // 如果售后完成关闭订单评价
  940. if ($order_goods_count == $refund_count && $order_info[ 'order_status' ] == Order::ORDER_COMPLETE) {
  941. $order_common_model = new OrderCommon();
  942. $order_common_model->orderUpdate([ 'is_evaluate' => 0 ], [ [ 'order_id', '=', $order_id ] ]);
  943. } else if ($order_info[ 'order_status' ] == Order::ORDER_COMPLETE || $order_info[ 'order_status' ] == Order::ORDER_TAKE_DELIVERY) {
  944. $order_common_model = new OrderCommon();
  945. if ($order_info[ 'evaluate_status' ] != 2) {
  946. $order_common_model->orderUpdate([ 'is_evaluate' => 1 ], [ [ 'order_id', '=', $order_id ] ]);
  947. }
  948. }
  949. //订单累加 退款
  950. model('order')->update([ 'refund_money' => $refund_total_real_money ], [ [ 'order_id', '=', $order_id ] ]);
  951. event('OrderRefundFinish', $order_goods_info);//传入订单类型以及订单项id
  952. model('order_goods')->commit();
  953. return $this->success();
  954. } catch (\Exception $e) {
  955. model('order_goods')->rollback();
  956. return $this->error('', $e->getMessage() . $e->getFile() . $e->getLine());
  957. }
  958. }
  959. /**
  960. * 获取订单售后操作列表
  961. * @param array $condition
  962. * @param string $field
  963. * @return array
  964. */
  965. public function getOrderRefundLogList($condition = [], $field = '*', $order = '', $limit = null)
  966. {
  967. $list = model('order_refund_log')->getList($condition, $field, $order, '', '', '', $limit);
  968. return $this->success($list);
  969. }
  970. /**
  971. * 获取退款维权订单列表
  972. * @param array $condition
  973. * @param number $page
  974. * @param string $page_size
  975. * @param string $order
  976. * @param string $field
  977. */
  978. public function getRefundOrderGoodsPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = 'nop.*,no.order_no,no.site_id,no.site_name,no.name,m.nickname')
  979. {
  980. $join = [
  981. [
  982. 'order no',
  983. 'nop.order_id = no.order_id',
  984. 'left'
  985. ],
  986. [
  987. 'member m',
  988. 'm.member_id = no.member_id',
  989. 'left'
  990. ],
  991. ];
  992. $list = model('order_goods')->pageList($condition, $field, $order, $page, $page_size, 'nop', $join);
  993. if (!empty($list[ 'list' ])) {
  994. foreach ($list[ 'list' ] as $k => $v) {
  995. $refund_action = empty($v[ 'refund_status_action' ]) ? [] : json_decode($v[ 'refund_status_action' ], true);
  996. $refund_member_action = $refund_action[ 'member_action' ] ?? [];
  997. $list[ 'list' ][ $k ][ 'refund_action' ] = $refund_member_action;
  998. if (isset($v[ 'goods_num' ])) {
  999. $list[ 'list' ][ $k ][ 'goods_num' ] = numberFormat($list[ 'list' ][ $k ][ 'goods_num' ]);
  1000. }
  1001. if (isset($v[ 'num' ])) {
  1002. $list[ 'list' ][ $k ][ 'num' ] = numberFormat($list[ 'list' ][ $k ][ 'num' ]);
  1003. }
  1004. }
  1005. }
  1006. return $this->success($list);
  1007. }
  1008. /**
  1009. * 获取退款维权订单数量
  1010. * @param array $condition
  1011. */
  1012. public function getRefundOrderGoodsCount($condition = [])
  1013. {
  1014. $count = model('order_goods')->getCount($condition);
  1015. return $this->success($count);
  1016. }
  1017. /**
  1018. * 初始化订单项退款操作
  1019. * @param $order_id
  1020. */
  1021. public function initOrderGoodsRefundAction($condition)
  1022. {
  1023. //订单项增加可退款操作
  1024. $data = array (
  1025. 'refund_status_action' => json_encode($this->order_refund_status[ 0 ], JSON_UNESCAPED_UNICODE)
  1026. );
  1027. $result = model('order_goods')->update($data, $condition);
  1028. return $this->success($result);
  1029. }
  1030. /**
  1031. * 移除订单项退款操作
  1032. * @param $order_id
  1033. */
  1034. public function removeOrderGoodsRefundAction($condition)
  1035. {
  1036. //订单项增加可退款操作
  1037. $data = array (
  1038. 'refund_status_action' => ''
  1039. );
  1040. $result = model('order_goods')->update($data, $condition);
  1041. return $this->success($result);
  1042. }
  1043. /**
  1044. * 会员维权详情
  1045. * @param $order_goods_id
  1046. */
  1047. public function getMemberRefundDetail($order_goods_id, $member_id)
  1048. {
  1049. $condition = array (
  1050. [ 'order_goods_id', '=', $order_goods_id ]
  1051. );
  1052. $condition[] = [ 'member_id', '=', $member_id ];
  1053. $info = model('order_goods')->getInfo($condition);
  1054. $refund_action = empty($info[ 'refund_status_action' ]) ? [] : json_decode($info[ 'refund_status_action' ], true);
  1055. $refund_member_action = $refund_action[ 'member_action' ] ?? [];
  1056. $info[ 'refund_action' ] = $refund_member_action;
  1057. $info[ 'num' ] = numberFormat($info[ 'num' ]);
  1058. //将售后日志引入
  1059. $refund_log_list = model('order_refund_log')->getList([ [ 'order_goods_id', '=', $order_goods_id ] ], '*', 'action_time desc');
  1060. $info[ 'refund_log_list' ] = $refund_log_list;
  1061. return $this->success($info);
  1062. }
  1063. /**
  1064. * 会员维权详情
  1065. * @param $order_goods_id
  1066. */
  1067. public function getRefundDetail($order_goods_id, $site_id = 0, $store_id = 0)
  1068. {
  1069. $condition = array (
  1070. [ 'order_goods_id', '=', $order_goods_id ]
  1071. );
  1072. if ($site_id > 0) {
  1073. $condition[] = [ 'site_id', '=', $site_id ];
  1074. }
  1075. if ($store_id > 0) {
  1076. $condition[] = [ 'store_id', '=', $store_id ];
  1077. }
  1078. $info = model('order_goods')->getInfo($condition);
  1079. if (empty($info)) return $this->error('', '');
  1080. $order_common_model = new OrderCommon();
  1081. $order_info = $order_common_model->getOrderDetail($info[ "order_id" ])[ 'data' ];
  1082. $info[ 'pay_type' ] = $order_info[ 'pay_type' ];
  1083. $coupon_info = [];
  1084. if ($order_info[ 'coupon_id' ] > 0) {
  1085. $order_goods_count = model('order_goods')->getCount([ [ 'order_id', '=', $info[ 'order_id' ] ] ], 'order_goods_id');
  1086. $refund_count = model('order_goods')->getCount([ [ 'order_id', '=', $info[ 'order_id' ] ], [ 'refund_status', '=', self::REFUND_COMPLETE ] ], 'order_goods_id');
  1087. if (( $order_goods_count - $refund_count ) == 1) {
  1088. //查询优惠劵信息
  1089. $coupon_model = new Coupon();
  1090. $coupon_info = $coupon_model->getCouponInfo([ [ 'coupon_id', '=', $order_info[ 'coupon_id' ] ] ], 'coupon_id,coupon_name,type,at_least,money,discount,discount_limit');
  1091. $coupon_info = $coupon_info[ 'data' ];
  1092. }
  1093. }
  1094. $info[ 'coupon_info' ] = $coupon_info;
  1095. //添加会员昵称
  1096. $member = new Member();
  1097. $member_info = $member->getMemberInfo([ [ "member_id", '=', $info[ 'member_id' ] ] ], 'nickname')[ 'data' ] ?? [];
  1098. $info[ 'nickname' ] = $member_info[ 'nickname' ] ?? '';
  1099. if ($info[ 'refund_status' ] == 0) {
  1100. $refund_apply_arr = $this->getOrderRefundMoney($order_goods_id);
  1101. $info[ 'refund_apply_money' ] = round($refund_apply_arr[ 'refund_money' ], 2);
  1102. $info[ 'refund_delivery_money' ] = $refund_apply_arr[ 'refund_delivery_money' ];
  1103. }
  1104. $refund_action = empty($info[ 'refund_status_action' ]) ? [] : json_decode($info[ 'refund_status_action' ], true);
  1105. $refund_action = $refund_action[ 'action' ] ?? [];
  1106. $info[ 'refund_action' ] = $refund_action;
  1107. //将售后日志引入
  1108. $refund_log_list = model('order_refund_log')->getList([ [ 'order_goods_id', '=', $order_goods_id ] ], '*', 'action_time desc');
  1109. $info[ 'refund_log_list' ] = $refund_log_list;
  1110. $info[ 'num' ] = numberFormat($info[ 'num' ]);
  1111. return $this->success($info);
  1112. }
  1113. /**
  1114. * 根据配送状态获取退款方式
  1115. * @param $refund_status
  1116. */
  1117. public function getRefundType($order_goods_info)
  1118. {
  1119. if ($order_goods_info[ 'is_virtual' ] == 1) {
  1120. return [ self::ONLY_REFUNDS ];
  1121. } else {
  1122. if ($order_goods_info[ 'delivery_status' ] == 0) {
  1123. return [ self::ONLY_REFUNDS ];
  1124. } else {
  1125. return [ self::ONLY_REFUNDS, self::A_REFUND_RETURN ];
  1126. }
  1127. }
  1128. }
  1129. /**
  1130. * 根据配送状态获取退款方式
  1131. */
  1132. public function getRefundOrderType($order_id)
  1133. {
  1134. $status = model('order')->getInfo([ [ 'order_id', '=', $order_id ] ], 'delivery_status');
  1135. if ($status[ 'delivery_status' ] == 0) {
  1136. return [ self::ONLY_REFUNDS ];
  1137. } else {
  1138. return [ self::ONLY_REFUNDS, self::A_REFUND_RETURN ];
  1139. }
  1140. }
  1141. /****************************************************************************订单退款相关操作(结束)**********************************/
  1142. /********************************************************************** 主动退款 ********************************************************************/
  1143. /**
  1144. * 主动完成退款流程
  1145. * @param $order_id
  1146. */
  1147. public function activeRefund($order_id, $remark, $refund_reason)
  1148. {
  1149. $order_info = model('order')->getInfo([ [ 'order_id', '=', $order_id ] ], 'order_money, out_trade_no, site_id, delivery_money');
  1150. if ($order_info[ 'order_money' ] > 0) {
  1151. $pay_model = new Pay();
  1152. //遍历订单项
  1153. $order_goods_list = model('order_goods')->getList([ [ 'order_id', '=', $order_id ] ]);
  1154. if (!empty($order_goods_list)) {
  1155. $count = count($order_goods_list);
  1156. foreach ($order_goods_list as $k => $v) {
  1157. $item_refund_money = $v[ 'real_goods_money' ];
  1158. if ($count == ( $k + 1 )) {
  1159. $item_refund_money += $order_info[ 'delivery_money' ];
  1160. }
  1161. $item_result = $this->activeOrderGoodsRefund($v[ 'order_goods_id' ], $item_refund_money, $remark, $refund_reason);
  1162. if ($item_result[ 'code' ] < 0) {
  1163. return $item_result;
  1164. }
  1165. }
  1166. }
  1167. //订单整体退款
  1168. // $refund_result = $pay_model->refund($refund_no, $order_info['pay_money'], $order_info['out_trade_no'], '', $order_info['pay_money'], $order_info['site_id'], 1);
  1169. return $this->success();
  1170. } else {
  1171. return $this->success();
  1172. }
  1173. }
  1174. /**
  1175. * 订单项主动退款
  1176. * @param $order_goods_id
  1177. * @param $refund_money
  1178. * @return array|mixed|void
  1179. */
  1180. public function activeOrderGoodsRefund($order_goods_id, $refund_money, $remark = '', $refund_reason = '')
  1181. {
  1182. model('order_goods')->startTrans();
  1183. try {
  1184. //判断是否退款完毕
  1185. $order_goods_info = model('order_goods')->getInfo([ [ 'order_goods_id', '=', $order_goods_id ] ]);
  1186. if ($order_goods_info[ 'refund_status' ] == self::REFUND_COMPLETE) {
  1187. model('order_goods')->rollback();
  1188. return $this->error('', '订单不能重复维权');
  1189. }
  1190. $pay_model = new Pay();
  1191. $refund_no = $pay_model->createRefundNo();
  1192. $update_data = array (
  1193. 'refund_no' => $refund_no,
  1194. 'refund_time' => time(),
  1195. 'refund_reason' => $refund_reason,
  1196. 'refund_apply_money' => $refund_money,
  1197. 'refund_real_money' => $refund_money,
  1198. 'refund_action_time' => time()
  1199. );
  1200. $update_data[ 'refund_status' ] = self::REFUND_COMPLETE;
  1201. $update_data[ 'refund_status_name' ] = $this->order_refund_status[ self::REFUND_COMPLETE ][ 'name' ];
  1202. $update_data[ 'refund_status_action' ] = json_encode($this->order_refund_status[ self::REFUND_COMPLETE ], JSON_UNESCAPED_UNICODE);
  1203. $res = model('order_goods')->update($update_data, [ [ 'order_goods_id', '=', $order_goods_id ] ]);
  1204. if ($res === false) {
  1205. model('order_goods')->rollback();
  1206. return $this->error();
  1207. }
  1208. $refund_result = $this->finishAction($order_goods_id, [], 1, true);
  1209. if ($refund_result[ 'code' ] < 0) {
  1210. model('order_goods')->rollback();
  1211. return $refund_result;
  1212. }
  1213. //退货日志
  1214. $this->addOrderRefundLog($order_goods_id, self::REFUND_COMPLETE, $remark . ',维权完成', 3, 0, '平台');
  1215. model('order_goods')->commit();
  1216. return $this->success();
  1217. } catch (\Exception $e) {
  1218. model('order_goods')->rollback();
  1219. return $this->error('', $e->getMessage());
  1220. }
  1221. }
  1222. /********************************************************************** 主动退款 ********************************************************************/
  1223. /**
  1224. * 判断订单的锁定状态
  1225. * @param $order_goods_id
  1226. */
  1227. public function verifyOrderLock($order_id)
  1228. {
  1229. $condition = array (
  1230. [ 'order_id', '=', $order_id ],
  1231. [ 'refund_status', 'not in', [ 0, 3 ] ],
  1232. );
  1233. $count = model('order_goods')->getCount($condition, 'order_goods_id');
  1234. $order_common_model = new OrderCommon();
  1235. if ($count > 0) {
  1236. $res = $order_common_model->orderLock($order_id);
  1237. } else {
  1238. $res = $order_common_model->orderUnlock($order_id);
  1239. }
  1240. return $res;
  1241. }
  1242. /**
  1243. * 关闭退款
  1244. * @param $order_goods_id
  1245. * @param $site_id
  1246. */
  1247. public function orderRefundClose($order_goods_id, $site_id, $user_info)
  1248. {
  1249. $order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $order_goods_id, 'site_id' => $site_id ]);
  1250. if (empty($order_goods_info)) {
  1251. return $this->error();
  1252. }
  1253. model('order_goods')->startTrans();
  1254. try {
  1255. $data = [
  1256. 'order_goods_id' => $order_goods_id,
  1257. 'refund_status' => 0,
  1258. 'refund_status_name' => $this->order_refund_status[ 0 ][ 'name' ],
  1259. 'refund_status_action' => json_encode($this->order_refund_status[ 0 ], JSON_UNESCAPED_UNICODE),
  1260. 'refund_type' => 0,
  1261. 'refund_address' => '',
  1262. 'refund_delivery_remark' => '',
  1263. 'refund_remark' => '',
  1264. 'refund_delivery_name' => '',
  1265. 'refund_delivery_no' => '',
  1266. 'refund_reason' => ''
  1267. ];
  1268. $res = model('order_goods')->update($data, [ 'order_goods_id' => $order_goods_id ]);
  1269. //验证订单锁定状态
  1270. $lock_result = $this->verifyOrderLock($order_goods_info[ 'order_id' ]);
  1271. //记录订单日志 start
  1272. $order_common_model = new OrderCommon();
  1273. $order_info = model('order')->getInfo([ 'order_id' => $order_goods_info[ 'order_id' ] ], 'order_status,order_status_name,is_video_number,site_id,member_id');
  1274. $log_data = [
  1275. 'uid' => $user_info[ 'uid' ],
  1276. 'nick_name' => $user_info[ 'username' ],
  1277. 'action' => '商家关闭了维权',
  1278. 'action_way' => 2,
  1279. 'order_id' => $order_goods_info[ 'order_id' ],
  1280. 'order_status' => $order_info[ 'order_status' ],
  1281. 'order_status_name' => $order_info[ 'order_status_name' ]
  1282. ];
  1283. $order_common_model->addOrderLog($log_data);
  1284. //记录订单日志 end
  1285. if ($order_info[ 'is_video_number' ] == 1) {
  1286. $weapp_model = new Weapp($order_info[ 'site_id' ]);
  1287. $member = model('member')->getInfo([ [ 'member_id', '=', $order_info[ 'member_id' ] ] ]);
  1288. $res = $weapp_model->orderNoRefund([
  1289. 'out_aftersale_id' => $order_goods_info[ 'out_aftersale_id' ]
  1290. ]);
  1291. if ($res[ 'code' ] < 0) {
  1292. model('order_goods')->rollback();
  1293. return $this->error('', $res[ 'message' ]);
  1294. }
  1295. }
  1296. $this->addOrderRefundLog($data[ 'order_goods_id' ], 0, '卖家关闭本次维权', 2, $user_info[ 'uid' ], $user_info[ 'username' ]);
  1297. event('memberCancelRefund', $data);//传入订单类型以及订单项id
  1298. model('order_goods')->commit();
  1299. return $this->success();
  1300. } catch (\Exception $e) {
  1301. model('order_goods')->rollback();
  1302. return $this->error('', $e->getMessage());
  1303. }
  1304. }
  1305. /**
  1306. * 获取订单项退款信息
  1307. * @param $order_goods_id
  1308. * @param $site_id
  1309. * @return array
  1310. */
  1311. public function getOrderGoodsRefundInfo($order_goods_id, $site_id = 0, $store_id = 0)
  1312. {
  1313. $order_goods_condition = array (
  1314. [ 'order_goods_id', '=', $order_goods_id ]
  1315. );
  1316. if ($site_id > 0) {
  1317. $order_goods_condition[] = [ 'site_id', '=', $site_id ];
  1318. }
  1319. if ($store_id > 0) {
  1320. $order_goods_condition[] = [ 'store_id', '=', $store_id ];
  1321. }
  1322. $order_goods_info = model('order_goods')->getInfo($order_goods_condition);
  1323. if (empty($order_goods_info)) {
  1324. return $this->error('', '该订单项不存在');
  1325. }
  1326. if ($order_goods_info[ 'refund_status' ] == self::REFUND_COMPLETE) {
  1327. return $this->error('该订单项已维权结束');
  1328. }
  1329. $order_goods_info[ 'num' ] = numberFormat($order_goods_info[ 'num' ]);
  1330. if ($order_goods_info[ 'refund_status' ] == 0) {
  1331. $refund_apply_arr = $this->getOrderRefundMoney($order_goods_id);
  1332. $order_goods_info[ 'refund_apply_money' ] = round($refund_apply_arr[ 'refund_money' ], 2);
  1333. $order_goods_info[ 'refund_delivery_money' ] = $refund_apply_arr[ 'refund_delivery_money' ];
  1334. }
  1335. //获取订单信息
  1336. $order_info = model('order')->getInfo([ [ 'order_id', '=', $order_goods_info[ 'order_id' ] ] ]);
  1337. $coupon_info = [];
  1338. if ($order_info[ 'coupon_id' ] > 0) {
  1339. $order_goods_count = model('order_goods')->getCount([ [ 'order_id', '=', $order_goods_info[ 'order_id' ] ] ], 'order_goods_id');
  1340. $refund_count = model('order_goods')->getCount([ [ 'order_id', '=', $order_goods_info[ 'order_id' ] ], [ 'refund_status', '=', self::REFUND_COMPLETE ] ], 'order_goods_id');
  1341. if (( $order_goods_count - $refund_count ) == 1) {
  1342. //查询优惠劵信息
  1343. $coupon_model = new Coupon();
  1344. $coupon_info = $coupon_model->getCouponInfo([ [ 'coupon_id', '=', $order_info[ 'coupon_id' ] ] ], 'coupon_id,coupon_name,type,at_least,money,discount,discount_limit');
  1345. $coupon_info = $coupon_info[ 'data' ];
  1346. }
  1347. }
  1348. $data = [
  1349. 'order_goods_info' => $order_goods_info,
  1350. 'order_info' => $order_info,
  1351. 'coupon_info' => $coupon_info
  1352. ];
  1353. //预售订单
  1354. if ($order_info[ 'promotion_type' ] == 'presale') {
  1355. $presale_order_model = new PresaleOrder();
  1356. $presale_order_info = $presale_order_model->getPresaleOrderInfo([ [ 'order_no', '=', $order_info[ 'order_no' ] ] ], 'presale_deposit_money,final_money');
  1357. $data[ 'presale_order_info' ] = $presale_order_info[ 'data' ];
  1358. }
  1359. return $this->success($data);
  1360. }
  1361. public function addshopcomponent($data)
  1362. {
  1363. $order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  1364. if (empty($order_goods_info)) {
  1365. return $this->error();
  1366. }
  1367. $refund_apply_money = $order_goods_info[ 'refund_apply_money' ];
  1368. $shop_active_refund = $data[ 'shop_active_refund' ] ?? 0;
  1369. if ($shop_active_refund == 1) {//商家主动退款
  1370. //查询发货状态(已发货的不能主动退款)
  1371. if ($order_goods_info[ 'delivery_status' ] != OrderModel::DELIVERY_WAIT) {
  1372. return $this->error();
  1373. }
  1374. //获取可退金额
  1375. $refund_apply_money_arr = $this->getOrderRefundMoney($data[ 'order_goods_id' ]);
  1376. $refund_apply_money = $refund_apply_money_arr[ 'refund_money' ];
  1377. $refund_delivery_money = $refund_apply_money_arr[ 'refund_delivery_money' ];
  1378. $data[ 'refund_real_money' ] = $refund_apply_money;
  1379. $data[ 'refund_delivery_money' ] = $refund_delivery_money;
  1380. } else {
  1381. if ($order_goods_info[ 'refund_status' ] != self::REFUND_TAKEDELIVERY && $order_goods_info[ 'refund_status' ] != self::REFUND_CONFIRM) {
  1382. return $this->error();
  1383. }
  1384. }
  1385. if ($data[ 'refund_real_money' ] > $refund_apply_money) return $this->error('', '退款金额超出最大可退金额');
  1386. //视频号订单创建订单
  1387. $order_info = model('order')->getInfo([ [ 'order_id', '=', $order_goods_info[ 'order_id' ] ] ]);
  1388. if ($order_info[ 'is_video_number' ] == 1) {
  1389. $member = model('member')->getInfo([ [ 'member_id', '=', $order_info[ 'member_id' ] ] ]);
  1390. $data = [
  1391. 'out_order_id' => (string) $order_info[ 'order_id' ],
  1392. 'out_aftersale_id' => $data[ 'out_aftersale_id' ],
  1393. 'openid' => $member[ 'weapp_openid' ],
  1394. 'type' => 1,
  1395. 'product_info' => [
  1396. 'out_product_id' => (string) $order_goods_info[ 'goods_id' ],
  1397. 'out_sku_id' => (string) $order_goods_info[ 'sku_id' ],
  1398. 'product_cnt' => (int) $order_goods_info[ 'num' ],//注意:这儿不支持称重商品
  1399. ],
  1400. 'refund_reason' => '无',
  1401. 'refund_reason_type' => 12,
  1402. 'orderamt' => round($refund_apply_money * 100)
  1403. ];
  1404. $weapp = new Weapp($order_info[ 'site_id' ]);
  1405. $res = $weapp->addAftersale($data);
  1406. if ($res[ 'code' ] < 0) {
  1407. return $this->error('', $res[ 'message' ]);
  1408. }
  1409. }
  1410. }
  1411. /******************************************************************************** 主动退款(商家) **********************************************/
  1412. /**
  1413. * 商家主动退款
  1414. * @param $params
  1415. */
  1416. public function doOrderOrderRefund($params)
  1417. {
  1418. $site_id = $params[ 'site_id' ] ?? 0;
  1419. $app_module = $params[ 'app_module' ];
  1420. $refund_money_type = $params[ 'refund_money_type' ];
  1421. $shop_refund_remark = $params[ 'shop_refund_remark' ];
  1422. $do_refund_money = $params[ 'do_refund_money' ] ?? 0;
  1423. $user_info = $params[ 'user_info' ];
  1424. $order_goods_id = $params[ 'order_goods_id' ];
  1425. $config_model = new Config();
  1426. $config_info = $config_model->getOrderEventTimeConfig($site_id, $app_module)[ 'data' ][ 'value' ] ?? [];
  1427. $do_refund = $config_info[ 'do_refund' ] ?? 1;
  1428. $order_commnn_model = new OrderCommon();
  1429. $order_goods_info = $order_commnn_model->getOrderGoodsInfo([ [ 'order_goods_id', '=', $order_goods_id ] ]);
  1430. $out_aftersale_id = $order_goods_info[ 'data' ][ 'order_no' ] . time() . $order_goods_id;
  1431. $data = array (
  1432. 'order_goods_id' => $order_goods_id,
  1433. 'refund_money_type' => $refund_money_type,
  1434. 'shop_refund_remark' => $shop_refund_remark,
  1435. 'shop_active_refund' => 1,
  1436. 'out_aftersale_id' => $out_aftersale_id,
  1437. 'do_refund_money' => $do_refund_money
  1438. );
  1439. $log_data = [
  1440. 'uid' => $user_info[ 'uid' ],
  1441. 'nick_name' => $user_info[ 'username' ],
  1442. 'action' => '商家对订单进行了主动退款',
  1443. 'action_way' => 2
  1444. ];
  1445. if ($do_refund == 1) {//直接完成退款
  1446. //创建视频号售后订单
  1447. $res = $this->addshopcomponent($data);
  1448. if ($res) {
  1449. return $res;
  1450. }
  1451. $result = $this->orderRefundFinish($data, $user_info, $log_data);
  1452. } else {
  1453. //发起申请,需要审核通过转账(仅退款)
  1454. //主动模拟退款申请和退款通过
  1455. $apply_data = array (
  1456. 'order_goods_id' => $order_goods_id,
  1457. 'refund_type' => self::ONLY_REFUNDS,
  1458. 'refund_reason' => '商家对订单进行了主动退款',
  1459. 'refund_remark' => '商家对订单进行了主动退款',
  1460. );
  1461. $refund_data = array (
  1462. 'data' => $apply_data,
  1463. 'user_info' => $user_info,
  1464. 'log_data' => $log_data,
  1465. 'do_refund_money' => $do_refund_money
  1466. );
  1467. $result = $this->doOrderOrderRefundApply($refund_data);
  1468. }
  1469. return $result;
  1470. }
  1471. /**
  1472. * 店家主动申请退款
  1473. * @param $params
  1474. * @return array
  1475. */
  1476. public function doOrderOrderRefundApply($params)
  1477. {
  1478. $data = $params[ 'data' ];
  1479. $user_info = $params[ 'user_info' ];
  1480. $log_data = $params[ 'log_data' ] ?? [];
  1481. $do_refund_money = $params[ 'do_refund_money' ];
  1482. $order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $data[ 'order_goods_id' ] ], 'order_id,refund_status,delivery_status,is_virtual,site_id,order_no,order_goods_id');
  1483. if (empty($order_goods_info))
  1484. return $this->error();
  1485. if ($order_goods_info[ 'refund_status' ] != 0 && $order_goods_info[ 'refund_status' ] != -1)
  1486. return $this->error([], '存在进行中的退款');
  1487. // $refund_type_list = $this->getRefundType($order_goods_info);
  1488. // //防止退款方式越权
  1489. // if (!in_array($data[ 'refund_type' ], $refund_type_list))
  1490. // return $this->error();
  1491. $order_info = model('order')->getInfo([ 'order_id' => $order_goods_info[ 'order_id' ] ]);
  1492. //判断是否允许申请退款
  1493. if ($order_info[ 'is_enable_refund' ] == 0) {
  1494. if ($order_info[ 'promotion_type' ] == 'pinfan') {
  1495. return $this->error('', '拼团活动正在进行中,待拼成功后可发起退款');
  1496. }
  1497. return $this->error();
  1498. }
  1499. model('order_goods')->startTrans();
  1500. try {
  1501. $data[ 'refund_status' ] = self::REFUND_APPLY;
  1502. $data[ 'refund_status_name' ] = $this->order_refund_status[ self::REFUND_APPLY ][ 'name' ];
  1503. $data[ 'refund_status_action' ] = json_encode($this->order_refund_status[ self::REFUND_APPLY ], JSON_UNESCAPED_UNICODE);
  1504. $data[ 'refund_mode' ] = $order_info[ 'order_status' ] == Order::ORDER_COMPLETE ? 2 : 1;
  1505. $pay_model = new Pay();
  1506. $data[ 'refund_no' ] = $pay_model->createRefundNo();
  1507. $data[ 'refund_action_time' ] = time();
  1508. $refund_apply_money_array = $this->getOrderRefundMoney($data[ 'order_goods_id' ]);//可退款金额 通过计算获得
  1509. $refund_apply_money = $refund_apply_money_array[ 'refund_money' ];
  1510. if ($do_refund_money > $refund_apply_money) {
  1511. model('order_goods')->rollback();
  1512. return $this->error('', '主动退款金额不能大于可退款总额');
  1513. }
  1514. $refund_apply_money = $do_refund_money;
  1515. $refund_delivery_money = $refund_apply_money_array[ 'refund_delivery_money' ];
  1516. $data[ 'refund_apply_money' ] = $refund_apply_money;//申请的总退款
  1517. $data[ 'refund_delivery_money' ] = $refund_delivery_money;//退的运费
  1518. //生成视频号订单ID
  1519. $data[ 'out_aftersale_id' ] = $order_goods_info[ 'order_no' ] . time() . $order_goods_info[ 'order_goods_id' ];
  1520. $res = model('order_goods')->update($data, [ 'order_goods_id' => $data[ 'order_goods_id' ] ]);
  1521. //验证订单锁定状态
  1522. $local_result = $this->verifyOrderLock($order_goods_info[ 'order_id' ]);
  1523. $this->addOrderRefundLog($data[ 'order_goods_id' ], self::REFUND_APPLY, '商家主动退款', 2, $user_info[ 'uid' ], $user_info[ 'username' ]);
  1524. event('orderRefundApply', $data);//传入订单类型以及订单项id
  1525. model('order_goods')->commit();
  1526. //订单会员申请退款消息
  1527. // $message_model = new Message();
  1528. // $message_model->sendMessage([ 'keywords' => 'BUYER_REFUND', 'order_goods_id' => $data[ 'order_goods_id' ], 'site_id' => $order_goods_info[ 'site_id' ] ]);
  1529. // 发起维权 关闭订单评价
  1530. model('order')->update([ 'is_evaluate' => 0 ], [ 'order_id' => $order_goods_info[ 'order_id' ] ]);
  1531. //记录订单日志 start
  1532. if ($log_data) {
  1533. $order_common_model = new OrderCommon();
  1534. $log_data = array_merge($log_data, [
  1535. 'order_id' => $order_goods_info[ 'order_id' ],
  1536. 'order_status' => $order_info[ 'order_status' ],
  1537. 'order_status_name' => $order_info[ 'order_status_name' ]
  1538. ]);
  1539. $order_common_model->addOrderLog($log_data);
  1540. }
  1541. //记录订单日志 end
  1542. return $this->success($res);
  1543. } catch (\Exception $e) {
  1544. model('order_goods')->rollback();
  1545. return $this->error('', $e->getMessage());
  1546. }
  1547. }
  1548. /**
  1549. * 查询退货地址
  1550. * @param $site_id
  1551. * @return array
  1552. */
  1553. public function getRefundAddress($site_id, $refund_address_id = 0)
  1554. {
  1555. $address = [];
  1556. $site_address_model = new SiteAddress();
  1557. $site_address_condition = array (
  1558. [ 'site_id', '=', $site_id ],
  1559. [ 'is_return', '=', 1 ],
  1560. );
  1561. if ($refund_address_id > 0) {
  1562. $site_address_condition[] = [ 'id', '=', $refund_address_id ];
  1563. } else {
  1564. $site_address_condition[] = [ 'is_return_default', '=', 1 ];
  1565. }
  1566. $site_address_info = $site_address_model->getAddressInfo($site_address_condition)[ 'data' ] ?? [];
  1567. if (empty($site_address_info)) {
  1568. unset($site_address_condition[ 2 ]);
  1569. $site_address_info = $site_address_model->getAddressInfo($site_address_condition)[ 'data' ] ?? [];
  1570. }
  1571. if (empty($site_address_info)) {
  1572. $shop_model = new Shop();
  1573. $shop_info_result = $shop_model->getShopInfo([ [ 'site_id', '=', $site_id ] ], 'full_address,address,name,mobile');
  1574. $shop_info = $shop_info_result[ 'data' ];
  1575. $address[ 'shop_contacts' ] = $shop_info[ 'name' ];
  1576. $address[ 'shop_mobile' ] = $shop_info[ 'mobile' ];
  1577. $address[ 'shop_address' ] = $shop_info[ 'full_address' ] . $shop_info[ 'address' ];
  1578. }
  1579. if (!empty($site_address_info)) {
  1580. $address[ 'shop_contacts' ] = $site_address_info[ 'contact_name' ];
  1581. $address[ 'shop_mobile' ] = $site_address_info[ 'mobile' ];
  1582. $address[ 'shop_address' ] = $site_address_info[ 'full_address' ];
  1583. }
  1584. return $address;
  1585. }
  1586. /**
  1587. * 求和
  1588. * @param array $where
  1589. * @param string $field
  1590. * @param string $alias
  1591. * @param null $join
  1592. * @return array
  1593. */
  1594. public function getRefundSum($where = [], $field = '', $alias = 'a', $join = null)
  1595. {
  1596. $data = model('order_goods')->getSum($where, $field, $alias, $join);
  1597. return $this->success($data);
  1598. }
  1599. /**
  1600. * 订单项退款
  1601. * @param $order_goods_info
  1602. * @return mixed|void
  1603. */
  1604. public function orderGoodsRefund($order_goods_info)
  1605. {
  1606. $order_info = model('order')->getInfo([ 'order_id' => $order_goods_info[ 'order_id' ] ]);
  1607. if (!empty($order_info)) {
  1608. $order_info[ 'goods_num' ] = numberFormat($order_info[ 'goods_num' ]);
  1609. }
  1610. $order_goods_info[ 'order_info' ] = $order_info;
  1611. $result = event('OrderGoodsRefund', $order_goods_info, true);
  1612. if (empty($result)) {
  1613. $order_common_model = new OrderCommon();
  1614. $order_model = $order_common_model->getOrderModel($order_info);
  1615. $result = $order_model->refund($order_goods_info);
  1616. }
  1617. return $result;
  1618. }
  1619. }