Notify.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. <?php
  2. namespace app\controller\api;
  3. use app\extra\basic\Base;
  4. use app\extra\jhfPay\Utils;
  5. use app\model\saas\SaasCart;
  6. use app\model\saas\SaasOrder;
  7. use app\model\saas\SaasOrderDetail;
  8. use app\model\saas\SaasShop;
  9. use app\model\saas\SaasShopLog;
  10. use app\model\saas\SaasUser;
  11. use app\model\saas\SaasUserBuy;
  12. use app\model\saas\SaasUserLog;
  13. use app\model\system\SystemUserMoney;
  14. use LinFly\Annotation\Route\Controller;
  15. use LinFly\Annotation\Route\Route;
  16. use support\Request;
  17. use support\Response;
  18. use think\facade\Db;
  19. use WeChat\Contracts\Tools;
  20. #[Controller(prefix: "/notify")]
  21. class Notify extends Base
  22. {
  23. /**
  24. * 提现银行卡回调
  25. */
  26. #[Route(path: "withdraw",methods: "post")]
  27. public function notifyWithdraw(Request $request): Response
  28. {
  29. try {
  30. echo getDateFull() . "===>提现银行卡异步返回\n";
  31. $data = $this->jhfReturn($request->all(),"withdraw.succeeded");
  32. if (empty($data)) return error("提现失败");
  33. if ($data['status'] == "succeeded") // 成功了
  34. {
  35. $day = date("Y-m-d",strtotime("-1 day"));
  36. $todayMoney = (new SystemUserMoney)->where("member_id",$data['member_id'])->where("day",$day)->select();
  37. if ($todayMoney->count() > 0) {
  38. $state = (new SystemUserMoney)->where("member_id",$data['member_id'])->where("day",$day)->update(['status' => 1,"withdraw_id" => $data['withdraw_id']]);
  39. }
  40. }
  41. return success("ok");
  42. } catch (\Throwable $throwable) {
  43. return error($throwable->getMessage());
  44. }
  45. }
  46. /**
  47. * 退款回调
  48. * @param Request $request
  49. */
  50. #[Route(path: "refund",methods: "post")]
  51. public function notifyRefund(Request $request)
  52. {
  53. try {
  54. echo getDateFull() . "===>退款申请返回\n";
  55. $data = $this->jhfReturn($request->all(),"refund.succeeded");
  56. if (empty($data)) return error("支付失败");
  57. // $payResp = $request->rawBody();
  58. // $wechat = new \WePay\Refund($this->getWxConfig());
  59. // if (empty($payResp)) return $wechat->getNotifySuccessReply();
  60. // $data = $wechat->getNotify($payResp);
  61. // if (empty($data)) return $wechat->getNotifySuccessReply();
  62. // $orderSn = explode("-",$data['attach']);
  63. $order = (new SaasOrder)->where("order_sn",$data['attach'])->with(['shop' => function($query){
  64. $query->field('shop_id,shop_name,shop_address');
  65. }])->findOrEmpty();
  66. if ($order->isEmpty()) return $this->getNotifySuccessReply();
  67. if ($order['status'] <> 4) return $this->getNotifySuccessReply();
  68. $order->status = 6;
  69. $order->refund_at = getDateFull();
  70. $order->save();
  71. (new SaasOrderDetail)->where("order_sn",$order['order_sn'])->update(['status' => 6]);
  72. $orderMoney = (($order['money'] > $order['discount']) ? $order['discount'] : $order['money']);
  73. // 商家账户额度退款
  74. $shop = (new SaasShop)->where("shop_id",$order['shop_id'])->with(['wx' => function($query){
  75. $query->field("shop_id,openid,is_msg");
  76. }])->findOrEmpty();
  77. if ($shop->isEmpty()) return $this->getNotifySuccessReply();
  78. $shop->balance = $shop['balance'] - $orderMoney;
  79. $shop->total_balance = $shop['total_balance'] - $orderMoney;
  80. $shop->save();
  81. (new SaasShopLog)->insertGetId([
  82. "shop_id" => $order['shop_id'],
  83. "money" => $orderMoney,
  84. "balance" => $shop->balance,
  85. "remark" => "订单退款【{$order['order_sn']}】",
  86. "type" => 2
  87. ]);// 推送消息-公众号
  88. if (!empty($shop['wx'])) {
  89. $obj = \We::WeChatTemplate([
  90. "appid" => sConf("wechat.appid"),
  91. "appsecret" => sConf("wechat.secret"),
  92. "token" => sConf("wechat.token"),
  93. "encodingaeskey" => sConf("wechat.aeskey")
  94. ]);
  95. foreach ($shop['wx'] as $val) {
  96. if ($val['is_msg'] == 1) {
  97. $obj->send([
  98. "touser" => $val['openid'],
  99. "template_id" => "WboxN-32rdHORBQHzaVvQb9kPN7rLaXAPS_BL2yfb5w",
  100. "data" => [
  101. "amount3" => ["value" => format_money($order['money']/100)],
  102. "character_string1" => ["value" => $order['old_order']],
  103. "time4" => ["value" => date('Y-m-d H:i')]
  104. ]
  105. ]);
  106. }
  107. }
  108. }
  109. } catch (\Throwable $throwable) {
  110. return error($throwable->getMessage());
  111. }
  112. }
  113. /**
  114. * 订单支付
  115. */
  116. #[Route(path: "wx",methods: "post")]
  117. public function notifyWx(Request $request)
  118. {
  119. try {
  120. echo getDateFull()."===>支付返回\n";
  121. $data = $this->jhfReturn($request->all());
  122. if (empty($data)) return error("支付失败");
  123. // $payResp = $request->rawBody();
  124. // $data = $this->payReturn($payResp);
  125. $order = (new SaasOrder)->where("order_sn",$data['attach'])->with(['shop' => function($query){
  126. $query->field('shop_id,shop_name,shop_address');
  127. }])->findOrEmpty();
  128. if ($order->isEmpty()) return "success";
  129. if ($order['status'] <> 0) return "success"; // 已支付或者是其他状态
  130. $order->status = 1;
  131. $order->pay_at = getDateFull();
  132. $order->transaction_id = $data['transaction_id']??'';
  133. $order->payment_id = $data['payment_id']??'';
  134. $order->notify_status = 1;
  135. $order->pay_type = 1;
  136. $order->save();
  137. $shop = (new SaasShop)->where("shop_id",$order['shop_id'])->with(['wx' => function($query){
  138. $query->field("shop_id,openid,is_msg");
  139. }])->findOrEmpty();
  140. if ($shop->isEmpty()) return "success";
  141. $shop->balance = Db::raw("balance+".$order['money']);
  142. $shop->total_balance = Db::raw("total_balance+".$order['money']);
  143. $shop->save();
  144. (new SaasShopLog)->insertGetId([
  145. "shop_id" => $order['shop_id'],
  146. "money" => $order['money'],
  147. "balance" => $shop->balance,
  148. "remark" => "新订单【{$order['order_sn']}】"
  149. ]);
  150. events("create-order",['shop' => $order['shop_id'],'print' => $order['print_id'],'openid' => $order['openid'],"order" => $order['order_sn']]);
  151. // 推送消息-公众号
  152. if (!empty($shop['wx'])) {
  153. $obj = \We::WeChatTemplate([
  154. "appid" => sConf("wechat.appid"),
  155. "appsecret" => sConf("wechat.secret"),
  156. "token" => sConf("wechat.token"),
  157. "encodingaeskey" => sConf("wechat.aeskey")
  158. ]);
  159. foreach ($shop['wx'] as $val) {
  160. if ($val['is_msg'] == 1) {
  161. $obj->send([
  162. "touser" => $val['openid'],
  163. "template_id" => "D20ZEWmUNmXMHLwiTOzaEateX5NvM9zoCbp2YwbIHsI",
  164. "data" => [
  165. "thing20" => ["value" => $val['shop_name']],
  166. "character_string1" => ["value" => $order['order_sn']],
  167. "amount16" => ["value" => format_money($order['money'] / 100)],
  168. "time2" => ["value" => date('Y-m-d H:i')]
  169. ],
  170. "url" => "https://inmei.yunenv.cn/weixin/order/detail?id=" . $order['id']
  171. ]);
  172. }
  173. }
  174. }
  175. return "success";
  176. } catch (\Throwable $throwable) {
  177. return "success";
  178. }
  179. }
  180. /**
  181. * 充值并支付
  182. */
  183. #[Route(path: "recharge",methods: "post")]
  184. public function notifyPayRecharge(Request $request)
  185. {
  186. try {
  187. echo getDateFull()."===>充值并支付支付返回\n";
  188. $data = $this->jhfReturn($request->all());
  189. if (empty($data)) return error("支付失败");
  190. $orderBuy = (new SaasUserBuy)->where("order_sn",$data['attach'])->with(['orders'])->findOrEmpty();
  191. if ($orderBuy->isEmpty()) return "success";
  192. if ($orderBuy['status'] <> 0) return "success"; // 已支付或者是其他状态
  193. $orderMoney = 0;
  194. $logData[0] = [
  195. "openid" => $orderBuy['openid'],
  196. "card_no" => $orderBuy['card_no'],
  197. "shop_id" => $orderBuy['shop_id'],
  198. "money" => $orderBuy['total_money'],
  199. "order_sn" => $orderBuy['order_sn'],
  200. "type" => 2,
  201. "remark" => "充值",
  202. "balance" => $orderBuy['total_money']
  203. ];
  204. if (!empty($orderBuy['orders']))
  205. {
  206. $orderMoney = $orderBuy['orders']['money'];
  207. $logData[1] = [
  208. "openid" => $orderBuy['openid'],
  209. "card_no" => $orderBuy['card_no'],
  210. "shop_id" => $orderBuy['shop_id'],
  211. "order_sn" => $orderBuy['order_sn'],
  212. "money" => $orderMoney,
  213. "type" => 1,
  214. "remark" => "订单付款",
  215. "balance" => $orderBuy['total_money'] - $orderMoney
  216. ];
  217. };
  218. $orderBuy->status = 1;
  219. $orderBuy->pay_at = getDateFull();
  220. $orderBuy->payment_id = $data['payment_id']??'';
  221. $orderBuy->transaction_id = $data['transaction_id']??'';
  222. $orderBuy->save();
  223. $shop = (new SaasShop)->where("shop_id",$orderBuy['shop_id'])->with(['wx' => function($query){
  224. $query->field("shop_id,openid,is_msg");
  225. }])->findOrEmpty();
  226. if ($shop->isEmpty()) return "success";
  227. // 开通vip账户
  228. $card = (new SaasUser)->where("card_no",$orderBuy['card_no'])->findOrEmpty();
  229. $balanceMoney = $orderBuy['total_money'] - $orderMoney;
  230. if ($card->isEmpty()) {
  231. $card->insertGetId([
  232. "openid" => $orderBuy['openid'],
  233. "shop_id" => $orderBuy['shop_id'],
  234. "card_no" => $orderBuy['card_no'],
  235. "balance" => $balanceMoney, // 余额
  236. "total_balance" => $orderBuy['money'], // 累计充值
  237. "total_consume" => $orderMoney // 累计消费
  238. ]);
  239. } else {
  240. $card->total_consume = Db::raw("total_consume+{$orderMoney}");
  241. $card->total_balance = Db::raw("total_balance+{$orderBuy['money']}");
  242. $card->balance = Db::raw("balance+{$balanceMoney}");
  243. $card->save();
  244. }
  245. if (!empty($orderBuy['orders']))
  246. {
  247. $order = (new SaasOrder)->where("order_sn",$orderBuy['order_sn'])->findOrEmpty();
  248. if ($order->isEmpty()) return "success";
  249. if ($order['status'] <> 0) return "success"; // 已支付或者是其他状态
  250. $order->status = 1;
  251. $order->pay_at = getDateFull();
  252. $order->transaction_id = $data['transaction_id']??'';
  253. $order->notify_status = 1;
  254. $order->pay_type = 2;
  255. $order->save();
  256. events("create-order",['shop' => $order['shop_id'],'print' => $order['print_id'],'openid' => $order['openid'],"order" => $order['order_sn']]);
  257. }
  258. $shop->balance = Db::raw("balance+".$orderBuy['money']);
  259. $shop->total_balance = Db::raw("total_balance+".$orderBuy['money']);
  260. $shop->save();
  261. (new SaasShopLog)->insertGetId([
  262. "shop_id" => $orderBuy['shop_id'],
  263. "money" => $orderBuy['money'],
  264. "balance" => $shop->balance,
  265. "type" => 1,
  266. "remark" => "会员卡充值",
  267. "status" => 1
  268. ]);
  269. // 推送消息-公众号
  270. if (!empty($shop['wx'])) {
  271. $obj = \We::WeChatTemplate([
  272. "appid" => sConf("wechat.appid"),
  273. "appsecret" => sConf("wechat.secret"),
  274. "token" => sConf("wechat.token"),
  275. "encodingaeskey" => sConf("wechat.aeskey")
  276. ]);
  277. foreach ($shop['wx'] as $val) {
  278. if ($val['is_msg'] == 1) {
  279. $obj->send([
  280. "touser" => $val['openid'],
  281. "template_id" => "v1TVHflG9h5BPRLb2hH10r8oOV5OFMKD2cmqIw1nH-w",
  282. "data" => [
  283. "thing1" => ["value" => '微信用户'.$orderBuy['openid']],
  284. "thing6" => ["value" => $val['shop_name']],
  285. "amount3" => ["value" => format_money($orderBuy['money'] / 100)],
  286. "character_string9" => ["value" => $orderBuy['order_sn']],
  287. "time4" => ["time5" => date('Y-m-d H:i')]
  288. ]
  289. ]);
  290. }
  291. }
  292. }
  293. (new SaasUserLog)->insertAll($logData);
  294. return "success";
  295. } catch (\Throwable $throwable) {
  296. return error($throwable->getMessage());
  297. }
  298. }
  299. /**
  300. * 会员卡充值
  301. */
  302. #[Route(path: "recharges",methods: "post")]
  303. public function notifyDataRecharge(Request $request)
  304. {
  305. try {
  306. echo getDateFull()."===>会员卡支付返回\n";
  307. $data = $this->jhfReturn($request->all());
  308. if (empty($data)) return error("支付失败");
  309. } catch (\Throwable $throwable) {
  310. return error($throwable->getMessage());
  311. }
  312. }
  313. /**
  314. * 第三方支付返回
  315. * @param array $respData
  316. * @return array
  317. */
  318. protected function jhfReturn(array $respData = [],string $return = "payment.succeeded"): array
  319. {
  320. if ($respData['type'] <> $return) return [];
  321. $resCipher = Utils::aes_decrypt($respData['resCipher'], sConf("wechat.jhf_aeskey"));
  322. $data = json_decode($resCipher,true);
  323. if ($return == "withdraw.succeeded") {
  324. print_r($data);
  325. }
  326. $data['attach'] = $data['order_no'];
  327. $data['transaction_id'] = $data['out_trans_id']??'';
  328. $data['payment_id'] = $data['payment_id']??'';
  329. $data['withdraw_id'] = $data['withdraw_id']??'';
  330. $data['member_id'] = $data['member_id']??'';
  331. $data['status'] = $data['status']??'';
  332. return $data;
  333. }
  334. protected function payReturn($payResp)
  335. {
  336. $wechat = new \WeChat\Pay($this->getWxConfig());
  337. if (empty($payResp)) return $this->getNotifySuccessReply();
  338. $data = Tools::xml2arr($payResp);
  339. if (empty($data)) return $this->getNotifySuccessReply();
  340. return $data;
  341. }
  342. /**
  343. * 获取微信支付通知成功回复 XML
  344. * @return string
  345. */
  346. protected function getNotifySuccessReply(): string
  347. {
  348. // return Tools::arr2xml(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
  349. return json(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
  350. }
  351. /**
  352. * 小程序配置
  353. * @return array
  354. */
  355. protected function getWxConfig(): array
  356. {
  357. return [
  358. 'token' => 'test',
  359. 'appid' => sConf("wechat.mini_appid"),
  360. 'appsecret' => sConf("wechat.mini_secret"),
  361. 'encodingaeskey' => 'BJIUzE0gqlWy0GxfPp4J1oPTBmOrNDIGPNav1YFH5Z5',
  362. // 配置商户支付参数(可选,在使用支付功能时需要)
  363. 'mch_id' => sConf("wechat.mch_id"),
  364. 'mch_key' => sConf("wechat.mch_key")
  365. ];
  366. }
  367. }