Wechat_bak.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. <?php
  2. namespace app\api\controller;
  3. use addons\epay\library\Service;
  4. use app\api\model\CoinRecord;
  5. use app\api\model\Delivery;
  6. use app\api\model\DeliveryTrade;
  7. use app\api\model\Order;
  8. use app\api\model\Prizerecord;
  9. use app\api\model\RechargeOrder;
  10. use app\common\controller\Frontend;
  11. use think\Db;
  12. use think\exception\HttpResponseException;
  13. use think\Response;
  14. use traits\controller\Jump;
  15. /**
  16. * 微信支付接口
  17. * Class Wechat
  18. * @package app\api\controller
  19. * @version 1.0
  20. * @author fuyelk <fuyelk@fuyelk.com>
  21. */
  22. class Wechat extends Frontend
  23. {
  24. protected $noNeedLogin = ['notifyx', 'boxpaysuccess', 'rechargesuccess', 'deliverypay'];
  25. protected $noNeedRight = ['*'];
  26. use Jump;
  27. /**
  28. * 盲盒订单支付
  29. * @throws \Exception
  30. * @author fuyelk <fuyelk@fuyelk.com>
  31. */
  32. public function boxpay($orderid = '')
  33. {
  34. if (empty($orderid)) {
  35. $this->error('订单ID不能为空');
  36. }
  37. $user = $this->auth->getUser();
  38. if (empty($user->wechat_openid)) {
  39. throw new HttpResponseException(Response::create(['code' => 403, 'msg' => '请先微信登录', 'data' => null], 'json', 200));
  40. }
  41. $order = Order::where('id', $orderid)->where('user_id', $this->auth->id)->where('status', 'unpay')->find();
  42. if (empty($order)) {
  43. throw new HttpResponseException(Response::create(['code' => 0, 'msg' => '订单有误', 'data' => null], 'json', 200));
  44. }
  45. $params = [
  46. // 'amount' => $order->rmb_amount,
  47. 'amount' => 0.01, // TODO 微信支付金额固定为1分钱
  48. 'openid' => $user->wechat_openid,
  49. 'orderid' => $order->out_trade_no,
  50. 'type' => "wechat",
  51. 'title' => $order->box_name,
  52. 'notifyurl' => $this->request->domain() . '/api/wechat/notifyx/orderfrom/buybox',
  53. 'returnurl' => $this->request->domain() . '/api/wechat/boxpaysuccess',
  54. 'method' => "mp",
  55. ];
  56. $query = input('get.');
  57. if (isset($query['orderid'])) {
  58. unset($query['orderid']);
  59. }
  60. $this->auth->redis->set($order->out_trade_no, $query, 60 * 30); // 将参数存入缓存,30分钟
  61. try {
  62. $payinfo = \addons\epay\library\Service::submitOrder($params);
  63. } catch (\Exception $e) {
  64. throw new HttpResponseException(Response::create(['code' => 0, 'msg' => $e->getMessage(), 'data' => null], 'json', 200));
  65. }
  66. throw new HttpResponseException(Response::create(['code' => 1, 'msg' => '获取支付信息成功', 'data' => $payinfo], 'json', 200));
  67. }
  68. /**
  69. * 充值订单支付
  70. * @throws \Exception
  71. * @author fuyelk <fuyelk@fuyelk.com>
  72. */
  73. public function rechargepay($orderid = '')
  74. {
  75. if (empty($orderid)) {
  76. $this->error('订单ID不能为空');
  77. }
  78. $user = $this->auth->getUser();
  79. if (empty($user->wechat_openid)) {
  80. throw new HttpResponseException(Response::create(['code' => 403, 'msg' => '请先微信登录', 'data' => null], 'json', 200));
  81. }
  82. $order = RechargeOrder::where('id', $orderid)->where('user_id', $this->auth->id)->where('status', 'unpay')->find();
  83. if (empty($order)) {
  84. throw new HttpResponseException(Response::create(['code' => 0, 'msg' => '订单有误', 'data' => null], 'json', 200));
  85. }
  86. $params = [
  87. // 'amount' => $order->rmb_amount,
  88. 'amount' => 0.01, // TODO 微信支付金额固定为1分钱
  89. 'openid' => $user->wechat_openid,
  90. 'orderid' => $order->out_trade_no,
  91. 'type' => "wechat",
  92. 'title' => '充值',
  93. 'notifyurl' => $this->request->domain() . '/api/wechat/notifyx/orderfrom/recharge',
  94. 'returnurl' => $this->request->domain() . '/api/wechat/rechargesuccess',
  95. 'method' => "mp",
  96. ];
  97. $query = input('get.');
  98. if (isset($query['orderid'])) {
  99. unset($query['orderid']);
  100. }
  101. $this->auth->redis->set($order->out_trade_no, $query, 60 * 30); // 将参数存入缓存,30分钟
  102. try {
  103. $payinfo = \addons\epay\library\Service::submitOrder($params);
  104. } catch (\Exception $e) {
  105. throw new HttpResponseException(Response::create(['code' => 0, 'msg' => $e->getMessage(), 'data' => null], 'json', 200));
  106. }
  107. throw new HttpResponseException(Response::create(['code' => 1, 'msg' => '获取支付信息成功', 'data' => $payinfo], 'json', 200));
  108. }
  109. /**
  110. * 发货订单支付
  111. * @throws \Exception
  112. * @author fuyelk <fuyelk@fuyelk.com>
  113. */
  114. public function deliverypay($orderid = '')
  115. {
  116. if (empty($orderid)) {
  117. $this->error('订单ID不能为空');
  118. }
  119. $user = $this->auth->getUser();
  120. if (empty($user->wechat_openid)) {
  121. throw new HttpResponseException(Response::create(['code' => 403, 'msg' => '请先微信登录', 'data' => null], 'json', 200));
  122. }
  123. $order = DeliveryTrade::where('id', $orderid)->where('user_id', $this->auth->id)->where('status', 'unpay')->find();
  124. if (empty($order)) {
  125. throw new HttpResponseException(Response::create(['code' => 0, 'msg' => '订单有误', 'data' => null], 'json', 200));
  126. }
  127. $params = [
  128. // 'amount' => $order->rmb_amount,
  129. 'amount' => 0.01, // TODO 微信支付金额固定为1分钱
  130. 'openid' => $user->wechat_openid,
  131. 'orderid' => $order->out_trade_no,
  132. 'type' => "wechat",
  133. 'title' => '快递费用',
  134. 'notifyurl' => $this->request->domain() . '/api/wechat/notifyx/orderfrom/delivery',
  135. 'returnurl' => $this->request->domain() . '/api/wechat/deliverypaysuccess',
  136. 'method' => "mp",
  137. ];
  138. $query = input('get.');
  139. if (isset($query['orderid'])) {
  140. unset($query['orderid']);
  141. }
  142. $this->auth->redis->set($order->out_trade_no, $query, 60 * 30); // 将参数存入缓存,30分钟
  143. try {
  144. $payinfo = \addons\epay\library\Service::submitOrder($params);
  145. } catch (\Exception $e) {
  146. throw new HttpResponseException(Response::create(['code' => 0, 'msg' => $e->getMessage(), 'data' => null], 'json', 200));
  147. }
  148. throw new HttpResponseException(Response::create(['code' => 1, 'msg' => '获取支付信息成功', 'data' => $payinfo], 'json', 200));
  149. }
  150. /**
  151. * 盲盒、充值支付回调
  152. */
  153. public function notifyx($orderfrom = '')
  154. {
  155. // 回调只能来自于购买盲盒和充值
  156. if (!in_array($orderfrom, ['buybox', 'recharge', 'delivery'])) {
  157. dta(input(), '微信回调有误');
  158. echo '请求有误';
  159. return;
  160. }
  161. $pay = Service::checkNotify('wechat');
  162. if (!$pay) {
  163. dta('微信签名错误', __METHOD__ . ' ' . __LINE__);
  164. echo '签名错误';
  165. return;
  166. }
  167. Db::startTrans();
  168. try {
  169. $data = $pay->verify()->toArray();
  170. $usefulTemplate = array(
  171. 'out_trade_no' => '202107221724365792624',
  172. 'result_code' => 'SUCCESS',
  173. 'total_fee' => '100', // 单位:分
  174. 'transaction_id' => '4200001157202107228405177371',
  175. );
  176. if ('SUCCESS' != strtoupper($data['result_code'])) {
  177. dta(array_intersect_key($data, $usefulTemplate), '微信支付失败');
  178. echo '支付失败';
  179. return;
  180. }
  181. // 购买盲盒订单,更新盲盒订单
  182. if ('buybox' == $orderfrom) {
  183. $order = Order::where('out_trade_no', $data['out_trade_no'])->where('status', 'unpay')->find();
  184. if (empty($order)) {
  185. dta(array_intersect_key($data, $usefulTemplate), '订单有误,支付失败');
  186. echo '支付失败';
  187. return;
  188. }
  189. $order->save([
  190. 'pay_method' => 'wechat',
  191. 'pay_rmb' => round($data['total_fee'] / 100, 2),
  192. 'transaction_id' => $data['transaction_id'],
  193. 'pay_time' => time(),
  194. 'status' => 'unused',
  195. 'backend_read' => 0,
  196. ]);
  197. }
  198. // 充值订单
  199. if ('recharge' == $orderfrom) {
  200. $order = RechargeOrder::where('out_trade_no', $data['out_trade_no'])->where('status', 'unpay')->find();
  201. if (empty($order)) {
  202. dta(array_intersect_key($data, $usefulTemplate), '订单有误,支付失败');
  203. echo '支付失败';
  204. return;
  205. }
  206. $order->save([
  207. 'pay_method' => 'wechat',
  208. 'pay_rmb' => round($data['total_fee'] / 100, 2),
  209. 'transaction_id' => $data['transaction_id'],
  210. 'pay_time' => time(),
  211. 'status' => 'paid',
  212. 'backend_read' => 0,
  213. ]);
  214. $user = \app\common\model\User::where('id', $order->user_id)->find();
  215. // 给账户充值前
  216. $coin_before = $user->coin;
  217. // 增加金币余额
  218. $user->setInc('coin', $order->coin_amount);
  219. // 创建金币记录
  220. CoinRecord::create([
  221. 'user_id' => $user->id,
  222. 'before' => $coin_before,
  223. 'after' => $user->coin,
  224. 'coin' => $order->coin_amount,
  225. 'order_id' => $order->id,
  226. 'type' => 'recharge', // 变更类型:pay_box=支付盲盒,recharge=充值,fromwallet=余额转入,refund=退款
  227. ]);
  228. }
  229. // 发货订单
  230. if ('delivery' == $orderfrom) {
  231. $trade = DeliveryTrade::where('out_trade_no', $data['out_trade_no'])->where('status', 'unpay')->find();
  232. if (empty($trade)) {
  233. dta(array_intersect_key($data, $usefulTemplate), '订单有误,支付失败');
  234. echo '支付失败';
  235. return;
  236. }
  237. // 变更发货交易订单状态
  238. $trade->save([
  239. 'pay_method' => 'wechat',
  240. 'pay_rmb' => round($data['total_fee'] / 100, 2),
  241. 'transaction_id' => $data['transaction_id'],
  242. 'pay_time' => time(),
  243. 'status' => 'paid'
  244. ]);
  245. // 变更发货订单状态
  246. $deliveryOrder = Delivery::where('delivery_trade_id', $trade->id)->select();
  247. $prizeIds = [];
  248. foreach ($deliveryOrder as $order) {
  249. $order->save(['status' => 'undelivered']);
  250. $prizeIds[] = $order->prize_id;
  251. }
  252. // 变更奖品状态
  253. Prizerecord::whereIn('id', $prizeIds)->update(['status' => 'delivery', 'delivery_time' => time()]);
  254. }
  255. } catch (\Exception $e) {
  256. Db::rollback();
  257. dta($e->getMessage(), '微信回调执行出错');
  258. echo '错误';
  259. return;
  260. }
  261. Db::commit();
  262. echo $pay->success();
  263. }
  264. /**
  265. * 盲盒支付成功后用户会被重定向到这里
  266. * @author fuyelk <fuyelk@fuyelk.com>
  267. */
  268. public function boxpaysuccess()
  269. {
  270. $out_trade_no = $this->request->param('out_trade_no');
  271. $pay = Service::checkReturn('wechat');
  272. // 读取缓存里的参数
  273. $query = $this->auth->redis->get($out_trade_no);
  274. if (!$query || !is_array($query)) {
  275. $query = [];
  276. }
  277. $query['status'] = 1;
  278. if (!$pay) {
  279. $query['status'] = 0;
  280. }
  281. $query['out_trade_no'] = $out_trade_no;
  282. $params = http_build_query($query);
  283. // 将用户重定向到前端页面
  284. $this->redirect($this->request->domain() . "/h5/#/pagesA/pages/camera?" . $params);
  285. }
  286. /**
  287. * 充值支付成功后用户会被重定向到这里
  288. * @author fuyelk <fuyelk@fuyelk.com>
  289. */
  290. public function rechargesuccess()
  291. {
  292. $out_trade_no = $this->request->param('out_trade_no');
  293. $pay = Service::checkReturn('wechat');
  294. // 读取缓存里的参数
  295. $query = $this->auth->redis->get($out_trade_no);
  296. if (!$query || !is_array($query)) {
  297. $query = [];
  298. }
  299. $query['status'] = 1;
  300. if (!$pay) {
  301. $query['status'] = 0;
  302. }
  303. $params = http_build_query($query);
  304. // 将用户重定向到前端页面
  305. $this->redirect($this->request->domain() . "/h5/#/pages/me/wallet?" . $params);
  306. }
  307. /**
  308. * 发货订单支付成功后用户会被重定向到这里
  309. * @author fuyelk <fuyelk@fuyelk.com>
  310. */
  311. public function deliverypaysuccess()
  312. {
  313. $out_trade_no = $this->request->param('out_trade_no');
  314. $pay = Service::checkReturn('wechat');
  315. // 读取缓存里的参数
  316. $query = $this->auth->redis->get($out_trade_no);
  317. if (!$query || !is_array($query)) {
  318. $query = [];
  319. }
  320. $query['status'] = 1;
  321. if (!$pay) {
  322. $query['status'] = 0;
  323. }
  324. $params = http_build_query($query);
  325. // 将用户重定向到前端页面
  326. $this->redirect($this->request->domain() . "/h5/#/pages/me/order?type=0?" . $params);
  327. }
  328. }