Notify.php 16 KB

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