Notifynew.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\controller\Api;
  4. use think\Db;
  5. use addons\epay\library\Service;
  6. /**
  7. * 订单支付回调
  8. */
  9. class Notifynew extends Api
  10. {
  11. protected $noNeedLogin = ['*'];
  12. protected $noNeedRight = ['*'];
  13. public function index(){
  14. }
  15. //充值金币 异步回调对外方法
  16. public function recharge_notify_base(){
  17. //验签
  18. $paytype = input('paytype','wechat');
  19. $notify_file = $this->notify_log_start($paytype);
  20. $pay = Service::checkNotify($paytype);
  21. if (!$pay) {
  22. echo '签名错误';
  23. exit;
  24. }
  25. //验证,拿订单号等信息
  26. $data = $pay->verify();
  27. $out_trade_no = $data['out_trade_no'];
  28. //订单查询
  29. $info = Db::name('pay_order')->where('out_trade_no',$out_trade_no)->find();
  30. if(empty($info)){
  31. echo $pay->success();
  32. exit;
  33. }
  34. if($info['order_status'] != 0)
  35. {
  36. echo $pay->success();
  37. exit;
  38. }
  39. //你可以在此编写订单逻辑
  40. $rs = $this->recharge_notify_do($out_trade_no);
  41. if($rs === false){
  42. //不论结果都应返回success
  43. echo $pay->success();
  44. exit;
  45. }else{
  46. //不论结果都应返回success
  47. echo $pay->success();
  48. exit;
  49. }
  50. //默认
  51. echo $pay->success();
  52. exit;
  53. }
  54. //充值金币 逻辑
  55. private function recharge_notify_do($out_trade_no){
  56. Db::startTrans();
  57. $orderInfo = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->lock(true)->find();
  58. if (empty($orderInfo)) {
  59. Db::rollback();
  60. return false;
  61. }
  62. if($orderInfo['order_status'] != 0){
  63. Db::rollback();
  64. return false;
  65. }
  66. //逻辑开始
  67. //加钱
  68. $args = json_decode($orderInfo['args'],true);
  69. $extend = [
  70. 'cityname' => $args['cityname']
  71. ];
  72. $result = model('Wallet')->lockChangeAccountRemain($orderInfo['user_id'],$args['jewel'],'+',0,'金币充值',1,'jewel',$extend);
  73. if($result['status']===false)
  74. {
  75. Db::rollback();
  76. return false;
  77. }
  78. //找到上级用户并加钱
  79. $userinfo = Db::name('user')->where('id',$orderInfo['user_id'])->field('id,nickname,pre_userid')->find();
  80. if($userinfo['pre_userid']){
  81. $bili = config('site.introsite_recharge_intro_bili') ?: 3;
  82. $jewel = bcdiv(bcmul($args['jewel'],$bili,0),100,0);
  83. if($jewel > 0){
  84. $result = model('Wallet')->lockChangeAccountRemain($userinfo['pre_userid'],$jewel,'+',0,$userinfo['nickname'].'充值金币返奖励',2,'jewel');
  85. if($result['status']===false)
  86. {
  87. Db::rollback();
  88. return false;
  89. }
  90. }
  91. }
  92. //逻辑结束
  93. //状态
  94. $ros = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->update(['order_status'=>1,'notifytime'=>time()]);
  95. if($ros === false) {
  96. Db::rollback();
  97. return false;
  98. }
  99. //默认提交
  100. Db::commit();
  101. return true;
  102. }
  103. //充值VIP 异步回调对外方法
  104. public function vip_notify_base(){
  105. //验签
  106. $paytype = input('paytype','wechat');
  107. $notify_file = $this->notify_log_start($paytype);
  108. $pay = Service::checkNotify($paytype);
  109. if (!$pay) {
  110. echo '签名错误';
  111. exit;
  112. }
  113. //验证,拿订单号等信息
  114. $data = $pay->verify();
  115. $out_trade_no = $data['out_trade_no'];
  116. //订单查询
  117. $info = Db::name('pay_order')->where('out_trade_no',$out_trade_no)->find();
  118. if(empty($info)){
  119. echo $pay->success();
  120. exit;
  121. }
  122. if($info['order_status'] != 0)
  123. {
  124. echo $pay->success();
  125. exit;
  126. }
  127. //你可以在此编写订单逻辑
  128. $rs = $this->vip_notify_do($out_trade_no);
  129. if($rs === false){
  130. //不论结果都应返回success
  131. echo $pay->success();
  132. exit;
  133. }else{
  134. //不论结果都应返回success
  135. echo $pay->success();
  136. exit;
  137. }
  138. //默认
  139. echo $pay->success();
  140. exit;
  141. }
  142. //充值金币 逻辑
  143. private function vip_notify_do($out_trade_no){
  144. Db::startTrans();
  145. $orderInfo = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->lock(true)->find();
  146. if (empty($orderInfo)) {
  147. Db::rollback();
  148. return false;
  149. }
  150. if($orderInfo['order_status'] != 0){
  151. Db::rollback();
  152. return false;
  153. }
  154. //逻辑开始
  155. //先充值
  156. $args = json_decode($orderInfo['args'],true);
  157. $user_info = Db::name('user_wallet')->where('user_id',$orderInfo['user_id'])->lock(true)->find();
  158. if($user_info['vip_endtime'] < time()){
  159. //过期了
  160. $vip_endtime = time() + (intval($args['days']) * 86400);
  161. }else{
  162. //追加vip
  163. $vip_endtime = $user_info['vip_endtime'] + (intval($args['days']) * 86400);
  164. }
  165. $update_data = [
  166. 'vip_endtime'=>$vip_endtime,
  167. ];
  168. $result = Db::name('user_wallet')->where('user_id',$orderInfo['user_id'])->update($update_data);
  169. if($result === false)
  170. {
  171. Db::rollback();
  172. return false;
  173. }
  174. //逻辑结束
  175. //状态
  176. $ros = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->update(['order_status'=>1,'notifytime'=>time()]);
  177. if($ros === false) {
  178. Db::rollback();
  179. return false;
  180. }
  181. //默认提交
  182. Db::commit();
  183. return true;
  184. }
  185. //异步日志
  186. private function notify_log_start($paytype = 'wechat'){
  187. //记录支付回调数据
  188. ignore_user_abort(); // run script in background
  189. set_time_limit(30);
  190. // 日志文件 start
  191. $log_base_dir = '../paylog/'.$paytype.'/';
  192. if (!is_dir($log_base_dir))
  193. {
  194. mkdir($log_base_dir, 0770, true);
  195. @chmod($log_base_dir, 0770);
  196. }
  197. $notify_file = $log_base_dir.'notify.txt';
  198. if(!file_exists($notify_file)) {
  199. @touch($notify_file);
  200. @chmod($notify_file, 0770);
  201. }
  202. if(filesize($notify_file)>5242880)//大于5M自动切换
  203. {
  204. rename($notify_file, $log_base_dir.'notify_'.date('Y_m_d_H_i_s').'.txt');
  205. }
  206. if(!file_exists($notify_file)) {
  207. @touch($notify_file);
  208. @chmod($notify_file, 0770);
  209. }
  210. // 日志文件 end
  211. //开始写入
  212. $_REQUEST = isset($_REQUEST) ? $_REQUEST : array();
  213. if($_REQUEST && $paytype == 'alipay') {
  214. file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收request]".json_encode($_REQUEST), FILE_APPEND);
  215. } else {
  216. $xml = file_get_contents("php://input");
  217. file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收php://input流原始数据] \n".$xml, FILE_APPEND);
  218. $xmlObj = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
  219. file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收php://input流] ".json_encode($xmlObj), FILE_APPEND);
  220. }
  221. ini_set('display_errors','On');
  222. return $notify_file;
  223. }
  224. }