Notify.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\controller\Api;
  4. use app\common\service\UserService;
  5. use kjpay\kjpay;
  6. use think\Request;
  7. use think\Db;
  8. use addons\epay\library\Service;
  9. /**
  10. * 支付回调
  11. */
  12. class Notify extends Api
  13. {
  14. protected $noNeedLogin = ['wechatnotify', 'alipaynotify', 'wechatkjnotify'];
  15. protected $noNeedRight = ['*'];
  16. /**
  17. * 支付回调
  18. */
  19. public function wechatnotify()
  20. {
  21. $paytype = "wechat";
  22. $pay = Service::checkNotify($paytype);
  23. if (!$pay) {
  24. echo '签名错误';
  25. return;
  26. }
  27. $data = $pay->verify();
  28. Db::startTrans();
  29. try {
  30. /*$orderModel = new \app\common\model\RecharOrder();
  31. $out_trade_no = $data['out_trade_no'];
  32. $orderinfo = $orderModel->where(["order_no" => $out_trade_no])->find();
  33. if(empty($orderinfo)){
  34. Db::rollback();
  35. echo $pay->success();
  36. exit;
  37. }
  38. if($orderinfo['status'] != 0)
  39. {
  40. Db::rollback();
  41. echo $pay->success();
  42. exit;
  43. }*/
  44. $this->payhandel($data);
  45. Db::commit();
  46. } catch (ValidateException $e) {
  47. Db::rollback();
  48. $this->error($e->getMessage());
  49. } catch (PDOException $e) {
  50. Db::rollback();
  51. $this->error($e->getMessage());
  52. } catch (Exception $e) {
  53. Db::rollback();
  54. $this->error($e->getMessage());
  55. }
  56. echo $pay->success();
  57. }
  58. /**
  59. * 支付回调
  60. */
  61. public function alipaynotify()
  62. {
  63. $paytype = "alipay";
  64. $notify_file = $this->notify_log_start($paytype);
  65. $pay = Service::checkNotify($paytype);
  66. if (!$pay) {
  67. echo '签名错误';
  68. return;
  69. }
  70. $data = $pay->verify();
  71. /*$dataStr = '{
  72. "s": "\/api\/notify\/alipaynotify",
  73. "gmt_create": "2023-07-12 09:37:14",
  74. "charset": "utf-8",
  75. "seller_email": "ixiaoqiuqiu@qq.com",
  76. "subject": "充值钻石",
  77. "sign": "SzP5OgA9Z+qD8mSzMbAbKFsYOyB6fiH\/8itILn6YqX0Aloa5FnOxUHXEKCFlv5k3ya+OORjZPDq5mt7eZ3FvwJUasSWnMgDlSa6zWLGhlkKE3HXVAe777tkM5UgnVw53uJEr\/Ur2UsLpI+qEcrZAXhNAhA2nNNWhwkvrA1Fyc3iZERnbtJ3XNT\/8nnxGMBjhS3TWlr3VDZ\/bb26fvC1qHQ9Y6GGz8gvj3z30Fo7\/DlLFvH2HFSi6wky+33vWEtgug+klsqh6ziOWaVJhJKvnt2H+ltINiKLCshYVhu8ZBc856sV8noEwMmxPoFTW4CoG7ut\/3PKLjglygSOZblyf4Q==",
  78. "buyer_id": "2088702050034935",
  79. "invoice_amount": "0.01",
  80. "notify_id": "2023071201222093714034931493558779",
  81. "fund_bill_list": "[{&quot;amount&quot;:&quot;0.01&quot;,&quot;fundChannel&quot;:&quot;ALIPAYACCOUNT&quot;}]",
  82. "notify_type": "trade_status_sync",
  83. "trade_status": "TRADE_SUCCESS",
  84. "receipt_amount": "0.01",
  85. "app_id": "2021004103620776",
  86. "buyer_pay_amount": "0.01",
  87. "sign_type": "RSA2",
  88. "seller_id": "2088641467220712",
  89. "gmt_payment": "2023-07-12 09:37:14",
  90. "notify_time": "2023-07-12 09:37:14",
  91. "version": "1.0",
  92. "out_trade_no": "20230712093707239053",
  93. "total_amount": "0.01",
  94. "trade_no": "2023071222001434931415906799",
  95. "auth_app_id": "2021004103620776",
  96. "buyer_logon_id": "136****5934",
  97. "point_amount": "0.00"
  98. }';
  99. $data = json_decode($dataStr,true);*/
  100. Db::startTrans();
  101. try {
  102. $orderModel = new \app\common\model\RecharOrder();
  103. $out_trade_no = $data['out_trade_no'];
  104. $orderinfo = $orderModel->where(["order_no" => $out_trade_no])->find();
  105. if(empty($orderinfo)){
  106. Db::rollback();
  107. echo $pay->success();
  108. exit;
  109. }
  110. if($orderinfo['status'] != 0)
  111. {
  112. Db::rollback();
  113. echo $pay->success();
  114. exit;
  115. }
  116. $this->payhandel($data);
  117. Db::commit();
  118. } catch (ValidateException $e) {
  119. Db::rollback();
  120. $this->error($e->getMessage());
  121. } catch (PDOException $e) {
  122. Db::rollback();
  123. $this->error($e->getMessage());
  124. } catch (Exception $e) {
  125. Db::rollback();
  126. $this->error($e->getMessage());
  127. }
  128. echo $pay->success();
  129. }
  130. /**
  131. * 支付处理方法
  132. * @return void
  133. */
  134. private function payhandel($params = [])
  135. {
  136. $payamount = $params['total_amount'];
  137. $out_trade_no = $params['out_trade_no'];
  138. $trade_no = $params['trade_no'];
  139. $orderModel = new \app\common\model\RecharOrder();
  140. $userModel = new \app\common\model\User();
  141. $jewellogModel = new \app\common\model\UserJewelLog();
  142. $rechargelogModel = new \app\common\model\UserRechargeLog();
  143. $orderInfo = $orderModel->where(["order_no" => $out_trade_no])->find();
  144. $userInfo = $userModel->where(["id" => $orderInfo["user_id"]])->find();
  145. $userwallet = Db::name('user_wallet')->where('user_id',$orderInfo["user_id"])->find();
  146. $time = time();
  147. // 修改订单状态
  148. $res1 = $orderModel->update(["status" => 1,'transaction_id' => $trade_no,'paytime'=>$time], ["order_no" => $out_trade_no]);
  149. // 修改用户钻石余额
  150. $res2 = true;
  151. //判断是否首充
  152. $jewellogWhere['user_id'] = $orderInfo["user_id"];
  153. $jewellogWhere['type'] = 1;
  154. $userJewelLog = $jewellogModel->where($jewellogWhere)->find();
  155. $isFirst = 1;
  156. if (!empty($userJewelLog)) {
  157. $isFirst = 0;
  158. }
  159. $preUserId = $userInfo['pre_userid'];
  160. // 添加钻石流水记录
  161. $detail = "钻石充值";
  162. $res3 = true;
  163. //增加用户钻石余额
  164. $rs_wallet = model('wallet')->lockChangeAccountRemain($userInfo["id"], $orderInfo["jewel"], "+", 0, $detail, 1,'jewel');
  165. if($rs_wallet['status'] == false){
  166. Db::rollback();
  167. $this->error($rs_wallet['msg']);
  168. }
  169. // 添加充值记录
  170. $res4 = $rechargelogModel->addRecord($userInfo["id"], $orderInfo["jewel"], $payamount, bcadd($userwallet["jewel"], $orderInfo["jewel"], 2), $userInfo["money"], $orderInfo["platform"], 2,$isFirst,$preUserId);
  171. if ($res1 && $res2 && $res3 && $res4) {
  172. // 添加统计
  173. $userInfo->chargecount = $userInfo->chargecount + $payamount;
  174. $userInfo->chargetime = time();
  175. $userInfo->save();
  176. $userService = new UserService();//邀请赠送奖励
  177. $userService->inviteMoney(['user_id'=>$orderInfo["user_id"]]);
  178. // +EXP 充值任意金额
  179. \app\common\model\TaskLog::tofinish($orderInfo["user_id"], "5EMwg7la", 1);
  180. // 查询今日充值记录
  181. $today = strtotime(date("Y-m-d 00:00:00"));
  182. $rechargeMoney = \app\common\model\RecharOrder::where(["user_id" => $orderInfo["user_id"], "createtime" => ["gt", $today]])->sum("money");
  183. if ($rechargeMoney >= 100) {
  184. // +EXP 充值超过100
  185. \app\common\model\TaskLog::tofinish($orderInfo["user_id"], "DaCVgOLu", 1);
  186. }
  187. } else {
  188. $res1 = $orderModel->update(["status" => -1], ["order_no" => $out_trade_no]);
  189. if (!$res1) {
  190. throw new Exception('更新充值状态失败:'.$out_trade_no);
  191. }
  192. }
  193. }
  194. /**
  195. * 支付回调
  196. */
  197. public function wechatkjnotify()
  198. {
  199. $input = file_get_contents("php://input"); // 主题信息
  200. $dataArr = explode("&", urldecode($input));
  201. $data = [];
  202. if ($dataArr) foreach ($dataArr as $k => $v) {
  203. $vv = explode("=", $v);
  204. $data[$vv[0]] = $vv[1];
  205. }
  206. // 实例化支付类
  207. $kjpay = new kjpay();
  208. // 获取公共参数
  209. $config = config("kjPay");
  210. //密钥
  211. $key = $config["key"];
  212. $sign = $data['sign'];
  213. unset($data['sign']);
  214. if ($kjpay->local_sign($data, $key) == $sign) {
  215. //验签成功后,开始业务逻辑
  216. try {
  217. $payamount = $data['amount'];
  218. $out_trade_no = $data['merchant_order_no'];
  219. $pay_channel = $data['pay_channel'];
  220. Db::startTrans();
  221. try {
  222. $orderModel = new \app\common\model\RecharOrder();
  223. $userModel = new \app\common\model\User();
  224. $rechargelogModel = new \app\common\model\UserRechargeLog();
  225. $orderInfo = $orderModel->where(["order_no" => $out_trade_no])->find();
  226. $userInfo = $userModel->where(["id" => $orderInfo["user_id"]])->find();
  227. $userwallet = Db::name('user_wallet')->where('user_id',$orderInfo["user_id"])->find();
  228. // 修改订单状态
  229. $res1 = $orderModel->update(["status" => 1], ["order_no" => $out_trade_no]);
  230. // 修改用户钻石余额
  231. $res2 = true;
  232. // 添加钻石流水记录
  233. $detail = "钻石充值";
  234. $res3 = true;
  235. //增加用户钻石余额
  236. $rs_wallet = model('wallet')->lockChangeAccountRemain($userInfo["id"], $orderInfo["jewel"], "+", 0, $detail, 1,'jewel');
  237. if($rs_wallet['status'] == false){
  238. Db::rollback();
  239. $this->error($rs_wallet['msg']);
  240. }
  241. // 添加充值记录
  242. $rechargeCount = $rechargelogModel->where('user_id',$orderInfo["user_id"])->count();
  243. $isFirstRecharge = $rechargeCount > 0 ? 0 : 1;
  244. $platformArr = ["wx_app_pay" => 1, "ali_wap_pay" => 2, "wx_public_pay" => 3];
  245. $res4 = $rechargelogModel->addRecord($userInfo["id"], $orderInfo["jewel"], $payamount, bcadd($userwallet["jewel"], $orderInfo["jewel"], 2), $userInfo["money"], $orderInfo["platform"], $platformArr[$pay_channel], $isFirstRecharge, $userInfo["pre_userid"]);
  246. if ($res1 && $res2 && $res3 && $res4) {
  247. // 添加统计
  248. $time = time();
  249. (new \app\common\model\User)->execute("update hx_user set chargecount = chargecount + $payamount,chargetime = $time where id = " . $userInfo["id"]);
  250. // \app\common\model\Test::update(["content"=>"update hx_user set chargecount = chargecount + $payamount,chargetime = $time where id = ".$userInfo["id"]],["id"=>1]);
  251. // 首充赠送
  252. $userInfo = \app\common\model\User::get($orderInfo["user_id"]);
  253. if ($userInfo->is_recharge == 0) { // 首充
  254. Db::startTrans();
  255. try {
  256. // 赠送消息尾灯
  257. $res1 = \app\common\model\AttireBack::addToMyBack(15, $orderInfo["user_id"]);
  258. $userInfo->is_recharge = 1;
  259. $res2 = $userInfo->save();
  260. if ($res1 && $res2) Db::commit();
  261. } catch (ValidateException $e) {
  262. Db::rollback();
  263. $this->error($e->getMessage());
  264. }
  265. }
  266. $this->rebate($orderInfo["user_id"], $data['amount']);
  267. // +EXP
  268. \app\common\model\TaskLog::tofinish($orderInfo["user_id"], "5EMwg7la", 1);
  269. // 查询今日充值记录
  270. $today = strtotime(date("Y-m-d 00:00:00"));
  271. $rechargeMoney = \app\common\model\RecharOrder::where(["user_id" => $orderInfo["user_id"], "createtime" => ["gt", $today]])->sum("money");
  272. if ($rechargeMoney >= 100) {
  273. // +EXP
  274. \app\common\model\TaskLog::tofinish($orderInfo["user_id"], "DaCVgOLu", 1);
  275. }
  276. // 查询新人礼包
  277. $this->addBagGift($orderInfo["user_id"], $data['amount']);
  278. Db::commit();
  279. echo "success";
  280. exit;
  281. }
  282. } catch (ValidateException $e) {
  283. Db::rollback();
  284. $this->error($e->getMessage());
  285. } catch (PDOException $e) {
  286. Db::rollback();
  287. $this->error($e->getMessage());
  288. } catch (Exception $e) {
  289. Db::rollback();
  290. $this->error($e->getMessage());
  291. }
  292. //你可以在此编写订单逻辑
  293. } catch (Exception $e) {
  294. }
  295. }
  296. }
  297. /**
  298. * 银联提现回调
  299. */
  300. public function cashoutNotify()
  301. {
  302. }
  303. /**
  304. * 更新新人礼包
  305. */
  306. private function addBagGift($user_id, $amount)
  307. {
  308. if (!$user_id || !$amount) return false;
  309. // 先看该用户是否有新人礼包特权
  310. $have = \app\common\model\NewBagHave::where(["user_id" => $user_id])->find();
  311. // print_r($have);exit;
  312. if ($have && time() - $have->createtime <= 7 * 86400) {
  313. $where = [];
  314. $where["value"] = ["elt", $amount];
  315. $bagInfo = \app\common\model\NewBag::where($where)->order("value", "desc")->select();
  316. if (!$bagInfo) return false;
  317. $res1 = false;
  318. foreach ($bagInfo as $k => $v) {
  319. // 查询完成情况
  320. $bagfinish = \app\common\model\NewBagFinish::where(["user_id" => $user_id, "bag_id" => $v["id"]])->find();
  321. if (!$bagfinish || $bagfinish->status <= 0) {
  322. if ($bagfinish) {
  323. $bagfinish->status = 1;
  324. $bagfinish->updatetime = time();
  325. $res1 = $bagfinish->save();
  326. } else {
  327. $res1 = \app\common\model\NewBagFinish::insert(["user_id" => $user_id, "bag_id" => $v["id"], "status" => 1, "updatetime" => time()]);
  328. }
  329. break;
  330. }
  331. }
  332. return $res1;
  333. }
  334. }
  335. /**
  336. * 充值返利
  337. */
  338. private function rebate($user_id, $money)
  339. {
  340. // // 获取配置信息
  341. // $config = \app\common\model\RebateConfig::where(["recharge"=>$money])->find();
  342. // if(!$config) return true;
  343. // 找到当前用户的上级和上上级
  344. $userInfo = \app\common\model\User::get($user_id);
  345. if ($userInfo->pre_userid > 0) {
  346. $preUserInfo = \app\common\model\User::where(["id" => $userInfo->pre_userid])->find();// 上一级用户
  347. $this->addRebateMoney($preUserInfo->id, $user_id, $money, 1);
  348. if ($preUserInfo->pre_userid > 0) {
  349. $this->addRebateMoney($preUserInfo->pre_userid, $user_id, $money, 2);
  350. } else {
  351. return true;
  352. }
  353. } else {
  354. return true;
  355. }
  356. }
  357. /**
  358. * 添加返利金额
  359. */
  360. private function addRebateMoney($preUserId, $user_id, $money, $type)
  361. {
  362. Db::startTrans();
  363. try {
  364. // 添加返利记录表
  365. $data = [];
  366. $data["user_id"] = $preUserId;
  367. $data["by_user_id"] = $user_id;
  368. $data["money"] = $money;
  369. $data["rebate_money"] = 0.00;
  370. $data["rebate_type"] = $type;
  371. $data["createtime"] = time();
  372. $res1 = \app\common\model\RebateLog::insertGetId($data);
  373. // $res2 = (new \app\common\model\RebateLog)->execute("update hx_rebate_log set rebate_money = $rebatemoney where id = $res1");
  374. if ($res1) {
  375. Db::commit();
  376. }
  377. } catch (ValidateException $e) {
  378. Db::rollback();
  379. $this->error($e->getMessage());
  380. } catch (PDOException $e) {
  381. Db::rollback();
  382. $this->error($e->getMessage());
  383. } catch (Exception $e) {
  384. Db::rollback();
  385. $this->error($e->getMessage());
  386. }
  387. }
  388. //异步日志
  389. private function notify_log_start($paytype = 'wechat'){
  390. //记录支付回调数据
  391. ignore_user_abort(); // run script in background
  392. set_time_limit(30);
  393. // 日志文件 start
  394. $log_base_dir = '../paylog/'.$paytype.'/';
  395. if (!is_dir($log_base_dir))
  396. {
  397. mkdir($log_base_dir, 0770, true);
  398. @chmod($log_base_dir, 0770);
  399. }
  400. $notify_file = $log_base_dir.'notify.txt';
  401. if(!file_exists($notify_file)) {
  402. @touch($notify_file);
  403. @chmod($notify_file, 0770);
  404. }
  405. if(filesize($notify_file)>5242880)//大于5M自动切换
  406. {
  407. rename($notify_file, $log_base_dir.'notify_'.date('Y_m_d_H_i_s').'.txt');
  408. }
  409. if(!file_exists($notify_file)) {
  410. @touch($notify_file);
  411. @chmod($notify_file, 0770);
  412. }
  413. // 日志文件 end
  414. //开始写入
  415. $_REQUEST = isset($_REQUEST) ? $_REQUEST : array();
  416. if($_REQUEST && $paytype == 'alipay') {
  417. file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收request]".json_encode($_REQUEST), FILE_APPEND);
  418. } else {
  419. $xml = file_get_contents("php://input");
  420. file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收php://input流原始数据] \n".$xml, FILE_APPEND);
  421. $xmlObj = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
  422. file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收php://input流] ".json_encode($xmlObj), FILE_APPEND);
  423. }
  424. ini_set('display_errors','On');
  425. return $notify_file;
  426. }
  427. }