Activity.php 12 KB

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