Activity.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <?php
  2. namespace app\common\service;
  3. use app\common\model\ActivityApply;
  4. use app\common\model\ActivityApplyItem;
  5. use app\common\model\GoodsOrderRefund;
  6. use app\common\model\StoreOrderRefund;
  7. use app\api\controller\Alipay;
  8. use app\common\model\UserMessage;
  9. use EasyWeChat\Factory;
  10. use library\tools\Data;
  11. use think\Db;
  12. use think\Exception;
  13. /**
  14. * 活动管理
  15. * Class Activity
  16. */
  17. class Activity extends SerBase
  18. {
  19. /**
  20. * 订单申请退款【按票整个订单退款】
  21. * @param $order_id 订单id
  22. * @param $source 1用户申请2后台操作
  23. * @param $is_refund 是否立即退款
  24. */
  25. public static function orderRefundApply($order_id,$source = 1,$is_refund = 0,$message='')
  26. {
  27. $order_info = ActivityApply::where('id',$order_id)->with('itemList')->find()->toArray();
  28. if(!$order_info['pay_state']) return ['code'=>201,'msg' => '订单未支付'];
  29. if($order_info['money'] <= 0) return ['code'=>201,'msg' => '免费门票不支持退款'];
  30. if(in_array($order_info['refund_state'],[1,2,4,5])) return ['code'=>201,'msg' => '订单已申请退款'];
  31. $refund_money = StoreOrderRefund::getRefundMoney($order_id);
  32. if($refund_money >= $order_info['money']) return ['code'=>201,'msg' => '订单已全额退款'];
  33. Db::startTrans();
  34. try {
  35. foreach ($order_info['item_list'] as $item_info) {
  36. if($item_info['money'] <= 0) continue;
  37. if($item_info['is_hx'] || $item_info['ticket_status']) throw new Exception('门票已审核无法退款');
  38. $refund_info = StoreOrderRefund::where(['order_id'=>$order_id,'item_id'=>$item_info['id'],'order_type'=>1])->find();
  39. if(!empty($refund_info) && in_array($refund_info->status,[0,1,3,4])) continue;
  40. Data::save('StoreOrderRefund',[
  41. 'user_id' => $order_info['user_id'],
  42. 'order_id' => $order_id,
  43. 'item_id' => $item_info['id'],
  44. 'order_type' => 1,
  45. 'is_deleted' => 0,
  46. 'sell_price' => $item_info['total_money'],
  47. 'refund_money' => $item_info['money'],//优惠后价格
  48. 'refund_no' =>$order_info['pay_no'].'_'.$item_info['id'],
  49. 'status' => 0,
  50. 'source' => $source,
  51. ],'order_id',['order_id'=>$order_id,'item_id'=> $item_info['id'],'order_type'=>1]);
  52. }
  53. ActivityApply::where('id',$order_id)->update(['refund_state'=>1]);
  54. // UserMessage::sendUserMessage($order_info['user_id'],'activity',4,1,0,$order_info['id'],$message,$order_info['id']);
  55. UserMessage::sendUserMessage($order_info['user_id'],'apply',4,1,0,$order_info['id'],$message,$order_info['id']);
  56. Db::commit();
  57. }catch (\Exception $e){
  58. Db::rollback();
  59. return ['code'=>201,'msg' => $e->getMessage() ];
  60. }
  61. return ['code'=>200,'msg' => '申请成功'];
  62. }
  63. /**
  64. * 订单退款【按整个订单退款】
  65. * @param $order_id 订单id
  66. */
  67. public static function orderRefundMoney($order_id,$message = '')
  68. {
  69. $order_info = ActivityApply::where('id',$order_id)->with('itemList')->find()->toArray();
  70. if(!$order_info['pay_state']) return ['code'=>201,'msg' => '订单未支付'];
  71. if($order_info['money'] <= 0) return ['code'=>201,'msg' => '免费门票不支持退款'];
  72. if(!in_array($order_info['refund_state'],[2,4])) return ['code'=>201,'msg' => '退款状态有误'];
  73. $refund_money = StoreOrderRefund::getHasRefund($order_id);
  74. if($refund_money >= $order_info['money']) return ['code'=>201,'msg' => '订单已全额退款'];
  75. // (1.h5微信,2.h5支付宝,3.app微信,4.app支付宝,5.h5微信内支付,9线下支付)
  76. $apply_refund = StoreOrderRefund::where('order_id',$order_id)->where('order_type',1)->where('status','in','0,1,4')->select()->toArray();
  77. if(empty($apply_refund)) return ['code'=>201,'msg' => '没有退款记录'];
  78. $total_money = array_sum(array_column($apply_refund,'refund_money'));// 需要退款金额
  79. Db::startTrans();
  80. try {
  81. $refund_no = $order_info['pay_no'].'_'.$order_id.'_'.$order_info['act_id'];
  82. if(in_array($order_info['pay_type'],[1,3,5])){ // h5
  83. $app = $order_info['pay_type'] == 3 ? Factory::payment(config('app.app_wx')) : Factory::payment(config('app.wx_pay'));
  84. $result = $app->refund->byOutTradeNumber($order_info['pay_no'], $refund_no, $order_info['money'] * 100, $total_money *100, ['refund_desc' => '订单退款']);
  85. if($result['return_code'] != 'SUCCESS') throw new Exception('微信退款异常');
  86. if($result['result_code'] != 'SUCCESS') throw new Exception($result['err_code_des']);
  87. }
  88. // 支付宝退款
  89. if(in_array($order_info['pay_type'],[2,4,7]))
  90. {
  91. $result = Alipay::aliRefund($order_info['pay_no'], $total_money,$order_info['pay_type'] == 2 ?'H5':'APP');
  92. if(!$result) throw new Exception('支付宝退款异常');
  93. }
  94. GoodsOrderRefund::where('id','in',array_column($apply_refund,'id'))->update(['status'=>3]);
  95. ActivityApply::where('id',$order_id)->update(['refund_state'=>5]);
  96. //UserMessage::sendUserMessage($order_info['user_id'],'activity',4,2,0,$order_info['id'],$message,$order_info['id']);
  97. UserMessage::sendUserMessage($order_info['user_id'],'apply',4,1,0,$order_info['id'],$message,$order_info['id']);
  98. Db::commit();
  99. }catch (\Exception $e){
  100. Db::rollback();
  101. GoodsOrderRefund::where('id','in',array_column($apply_refund,'id'))->update(['status'=>4]);
  102. ActivityApply::where('id',$order_id)->update(['refund_state'=>4]);
  103. return ['code'=>201 ,'msg'=>$e->getMessage()];
  104. }
  105. return ['code'=>200,'msg'=>'退款成功'];
  106. }
  107. /**
  108. * 订单申请退款【按票退款】
  109. * @param $order_id 订单id
  110. * @param $item_id 票id
  111. * @param $source 1用户申请2后台操作
  112. * @param $is_refund 是否立即退款
  113. */
  114. public static function orderApplyRefund($order_id,$item_id,$source,$is_refund = 0)
  115. {
  116. //$ret_val = static::$ret_val;// ['code' => 200 , 'msg'=>'ok','extend'=>''];
  117. $order_info = ActivityApply::where('id',$order_id)->find()->toArray();
  118. $item_info = ActivityApplyItem::where('id',$item_id)->find()->toArray();
  119. if(!$order_info['pay_state']) return ['code'=>201,'msg' => '订单未支付'];
  120. if($item_info['money'] <= 0) return ['code'=>201,'msg' => '免费门票不支持退款'];
  121. $refund_money = StoreOrderRefund::getRefundMoney($order_id);
  122. if($refund_money >= $order_info['money'])return ['code'=>201,'msg' => '订单已全额退款'];
  123. $refund_info = StoreOrderRefund::where(['order_id'=>$order_id,'item_id'=>$item_id,'order_type'=>1])->find();
  124. if(!empty($refund_info) && in_array($refund_info->status,[0,1,3,4])) return ['code'=>201,'msg' => '订单已申请退款'];
  125. if($item_info['is_hx'] || $item_info['ticket_status'])return ['code'=>201,'msg' => '票已核销无法申请'];
  126. // 申请记录详情
  127. Data::save('StoreOrderRefund',[
  128. 'user_id' => $order_info['user_id'],
  129. 'order_id' => $order_id,
  130. 'item_id' => $item_id,
  131. 'order_type' => 1,
  132. 'is_deleted' => 0,
  133. 'sell_price' => $item_info['total_money'],
  134. 'refund_money' => $item_info['money'],//优惠后价格
  135. 'refund_no' => $order_info['pay_no'].'_'.$item_info['id'],
  136. 'status' => 0,
  137. 'source' => $source,
  138. ],'order_id',['order_id'=>$order_id,'item_id'=>$item_id,'order_type'=>1]);
  139. if($is_refund) {
  140. $refund_id = StoreOrderRefund::where(['order_id'=>$order_id,'item_id'=>$item_id,'order_type'=>1])->value('id');
  141. $refund_res = static::orderRefund($refund_id);
  142. return $refund_res;
  143. }
  144. return ['code'=>200,'msg' => '申请成功'];
  145. }
  146. /**
  147. * 确定退款
  148. * @param $refund_id 退款记录id
  149. */
  150. public static function orderRefund($refund_id)
  151. {
  152. $refund_info = StoreOrderRefund::where('id',$refund_id)->find()->toArray();
  153. if(in_array($refund_info['status'],[2,3,5]) || $refund_info['is_deleted']) return ['code'=>201,'msg' => '退款记录异常'];
  154. $order_info = ActivityApply::where('id',$refund_info['order_id'])->find()->toArray();
  155. $item_info = ActivityApplyItem::where('id',$refund_info['item_id'])->find()->toArray();
  156. if($item_info['is_hx'] || $item_info['ticket_status'])return ['code'=>201,'msg' => '票已核销无法退款'];
  157. // (1.h5微信,2.h5支付宝,3.app微信,4.app支付宝,5.h5微信内支付,9线下支付)
  158. if($refund_info['refund_money'] <= 0 || $refund_info['refund_money'] > $order_info['money']) return ['code'=>201,'订单退款金额有误'];
  159. Db::startTrans();
  160. try {
  161. $refund_no = $refund_info['refund_no'] ? $refund_info['refund_no'] : get_order_sn();
  162. //微信退款
  163. if(in_array($order_info['pay_type'],[1,3,5,6])){ // h5
  164. $app = $order_info['pay_type'] == 3 ? Factory::payment(config('app.app_wx')) : Factory::payment(config('app.wx_pay'));
  165. $result = $app->refund->byOutTradeNumber($order_info['pay_no'], $refund_no, $order_info['money'] * 100, $refund_info['refund_money']*100, ['refund_desc' => '订单退款']);
  166. // var_dump($result);
  167. if($result['return_code'] != 'SUCCESS') throw new Exception('微信退款异常');
  168. if($result['result_code'] != 'SUCCESS') throw new Exception($result['err_code_des']);
  169. // 修改退款记录状态
  170. GoodsOrderRefund::where(['id'=>$refund_info['id']])->update(['refund_no'=>$refund_no,'status'=>3]);
  171. }
  172. // 支付宝退款
  173. if(in_array($order_info['pay_type'],[2,4,7]))
  174. {
  175. $result = Alipay::aliRefund($order_info['pay_no'], $refund_info['refund_money'],$order_info['pay_type'] == 2 ?'H5':'APP');
  176. if(!$result) throw new Exception('支付宝退款异常');
  177. // 修改退款记录状态
  178. GoodsOrderRefund::where(['id'=>$refund_info['id']])->update(['refund_no'=>$refund_no,'status'=>3]);
  179. }
  180. if(in_array($order_info['pay_type'],[9])) {
  181. // 修改退款记录状态
  182. GoodsOrderRefund::where(['id'=>$refund_info['id']])->update(['refund_no'=>$refund_no,'status'=>3]);
  183. }
  184. Db::commit();
  185. }catch (\Exception $e){
  186. Db::rollback();
  187. GoodsOrderRefund::where(['id'=>$refund_info['id']])->update(['status'=>4]);
  188. return ['code'=>201 ,'msg'=>$e->getMessage()];
  189. }
  190. return ['code'=>200,'msg'=>'退款成功'];
  191. }
  192. // 活动变更消息推送
  193. public static function activityChange($act_id)
  194. {
  195. $where = [];
  196. $where[] = ['a.pay_state','=',1];
  197. $where[] = ['a.refund_state','=',0];
  198. $act_info = \app\common\model\Activity::where('id',$act_id)->find()->toArray();
  199. $act_title = $act_info['title'];
  200. $list = ActivityApplyItem::field('i.id,i.apply_id,i.phone,i.email,i.user_id,i.act_id')
  201. ->alias('i')->where($where)
  202. ->leftJoin('ActivityApply a','i.apply_id = a.id')
  203. ->leftJoin('StoreOrderRefund r','r.item_id = i.id')
  204. ->group('i.user_id')
  205. ->select()->toArray();
  206. $message = '由于不可抗因素,您报名的《'.$act_title.'》活动,参会地点及时间变更为:'.$act_info['start_time'].',';
  207. $message.=$act_info['province'].$act_info['city'].$act_info['county'].$act_info['address'].',请悉知,跟您带来的不便,敬请谅解!期待与您再次相遇';
  208. foreach ($list as $item_info) {
  209. $refund_info = StoreOrderRefund::getRefundInfo($item_info['apply_id'],$item_info['id'],1);
  210. if(!empty($refund_info && in_array($refund_info['status'],[0,1,3,5])))continue;
  211. // 站内信 && 极光
  212. // UserMessage::sendUserMessage($item_info['user_id'],'activity',2,0,0,$item_info['act_id'],$message,$item_info['id']);
  213. UserMessage::sendUserMessage($item_info['user_id'],'activity',2,0,0,$item_info['act_id'],$message,$item_info['act_id']);
  214. // 短信推送
  215. // 邮箱提示
  216. $content = '您报名的活动:'.$act_title.'已发生变更';
  217. if($item_info['email'] && strpos ('@', $item_info['email'])) send_email($item_info['email'],$content);
  218. }
  219. }
  220. }