Notify.php 7.6 KB

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