JingXiuPay.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <?php
  2. namespace app\api\controller;
  3. use addons\epay\library\Service;
  4. use app\common\controller\Api;
  5. use app\utils\CurlUtil;
  6. use app\utils\Easywechat\MiniAppService;
  7. use app\utils\JingXiu\JingXiuPayUtil;
  8. use app\utils\LogUtil;
  9. use app\utils\PayUtil;
  10. use think\Cache;
  11. use think\Db;
  12. use think\Exception;
  13. use think\Request;
  14. /**
  15. * 通行证
  16. */
  17. class JingXiuPay extends Api
  18. {
  19. // 日志模块名称
  20. const LOG_MODULE = 'JingXiuPay';
  21. protected $noNeedLogin = ['vip_recharge', 'gold_recharge', 'pay', 'pay_notify'];
  22. protected $noNeedRight = '*';
  23. public function _initialize()
  24. {
  25. parent::_initialize();
  26. }
  27. public function __construct(Request $request = null)
  28. {
  29. parent::__construct($request);
  30. //日志统一写入
  31. register_shutdown_function([new LogUtil, 'close']);
  32. LogUtil::getInstance('Api/'); //设置日志存入通道
  33. }
  34. /**
  35. * 会员充值 (跳转小程序充值)
  36. * @return void
  37. */
  38. public function vip_recharge()
  39. {
  40. Db::startTrans();
  41. try {
  42. $rc_id = input('rc_id', 0);
  43. $pay_type = input('pay_type', 'wechat');
  44. $uid = $this->auth->id;
  45. if ($pay_type != 'wechat') {
  46. throw new Exception('支付类型有误');
  47. }
  48. if (!$rc_id) {
  49. throw new Exception('请选择会员套餐');
  50. }
  51. //赋值money
  52. $recharge_config = Db::name('payvip_config')->where('id', $rc_id)->find();
  53. $money = $recharge_config['money'];
  54. if ($money <= 0) {
  55. throw new Exception('支付金额必须大于0');
  56. }
  57. if ($money > 10000) {
  58. throw new Exception('支付金额太大');
  59. }
  60. //会员等级冲突
  61. //当前是会员,但是却要向下级续费,直接提示报错
  62. //修改等级,向上立刻改,向下不允许
  63. $wallet_info = model('wallet')->getWallet($this->auth->id);
  64. if ($wallet_info['vip_endtime'] > time() && $recharge_config['vip_level'] < $wallet_info['vip_level']) {
  65. throw new Exception('当前会员没有过期,不能续费');
  66. }
  67. //创建订单
  68. $data = [];
  69. $data['status'] = 0;
  70. $pay_no = createUniqueNo('V', $uid);
  71. $data['pay_no'] = $pay_no;
  72. $data['money'] = $money;
  73. $data['payment_class'] = $pay_type;
  74. $data['user_id'] = $uid;
  75. $data['ext_info'] = json_encode(['subject' => '充值vip支付']);
  76. $data['memo'] = '充值会员支付';
  77. $data['createtime'] = time();
  78. //$data['payment'] = 'miniapp';
  79. $data['payment'] = 'app';
  80. $pay_order = Db::name('pay_order')->insertGetId($data);
  81. //创建回调
  82. $even_data = [];
  83. $even_data['event'] = 'success';
  84. $even_data['class'] = 'app\common\model\Recharge';
  85. $even_data['method'] = 'vippaysucc';
  86. $even_data['args'] = json_encode(['user_id' => $uid, 'days' => $recharge_config['days'], 'vip_level' => $recharge_config['vip_level'], 'gold_num' => $recharge_config['gold_num'], 'money' => $money]);
  87. $even_data['pay_no'] = $pay_no;
  88. $pay_event = Db::name('pay_event')->insertGetId($even_data);
  89. if (!$pay_order || !$pay_event) {
  90. throw new Exception('下单失败');
  91. }
  92. Db::commit();
  93. $pay = new JingXiuPayUtil();
  94. if (!$pay->wxWapPay($pay_no,$money,'充值会员','/api/jing_xiu_pay/pay_notify')){
  95. $this->error($pay->getMessage());
  96. }
  97. $data = $pay->getData();
  98. $this->success('success', $data);
  99. } catch (Exception $e) {
  100. Db::rollback();
  101. $this->error($e->getMessage());
  102. }
  103. }
  104. /**
  105. * 金币充值
  106. * @return void
  107. */
  108. public function gold_recharge()
  109. {
  110. Db::startTrans();
  111. try {
  112. $rc_id = input_post('rc_id', 0);
  113. $pay_type = 'wechat';
  114. $freemoney = input_post('freemoney', 0, 'intval');
  115. $uid = $this->auth->id;
  116. if (!$rc_id && !$freemoney) {
  117. throw new Exception('请选择或填写充值金额');
  118. }
  119. if (!in_array($pay_type, ['wechat', 'alipay'])) {
  120. throw new Exception('错误的支付类型');
  121. }
  122. //赋值money
  123. if ($rc_id) {
  124. $recharge_config = Db::name('paygold_config')->where('id', $rc_id)->find();
  125. $money = $recharge_config ? $recharge_config['money'] : 0;
  126. $gold = $recharge_config ? $recharge_config['gold'] : 0;
  127. $first_gold = $recharge_config ? $recharge_config['first_gold'] : 0;
  128. $first_vipdays = $recharge_config ? $recharge_config['first_vipdays'] : 0;
  129. $vip_gold = $recharge_config ? $recharge_config['vip_gold'] : 0;
  130. }
  131. //自由输入覆盖
  132. if (!empty($freemoney)) {
  133. $rc_id = 0;
  134. $money = floatval($freemoney);
  135. $bili = config('site.money_to_gold') ?: 10;
  136. $gold = bcmul($money, $bili, 0);
  137. $first_gold = 0;
  138. $first_vipdays = 0;
  139. $vip_gold = 0;
  140. }
  141. if ($money <= 0) {
  142. throw new Exception('支付金额必须大于0');
  143. }
  144. if ($money > 10000) {
  145. throw new Exception('支付金额太大');
  146. }
  147. //查询是不是会员,若不是则不赠送金币
  148. $vip_endtime = Db::name('user_wallet')->where('user_id', $this->auth->id)->value('vip_endtime');
  149. if ($vip_endtime < time()) {
  150. $vip_gold = 0;
  151. }
  152. //创建订单
  153. $data = [];
  154. $data['status'] = 0;
  155. $pay_no = createUniqueNo('P', $uid);
  156. $data['pay_no'] = $pay_no;
  157. $data['money'] = $money;
  158. $data['payment_class'] = $pay_type;
  159. $data['user_id'] = $uid;
  160. $data['ext_info'] = json_encode(['subject' => '充值金币支付']);
  161. $data['memo'] = '充值金币支付';
  162. $data['createtime'] = time();
  163. $data['payment'] = 'app';
  164. $pay_order = Db::name('pay_order')->insertGetId($data);
  165. //创建回调
  166. $even_data = [];
  167. $even_data['event'] = 'success';
  168. $even_data['class'] = 'app\common\model\Recharge';
  169. $even_data['method'] = 'goldpaysucc';
  170. $even_data['args'] = json_encode(['user_id' => $uid, 'gold' => $gold, 'money' => $money, 'pg_id' => $rc_id, 'first_gold' => $first_gold, 'first_vipdays' => $first_vipdays, 'intro_uid' => $this->auth->intro_uid, 'vip_gold' => $vip_gold]);
  171. $even_data['pay_no'] = $pay_no;
  172. $pay_event = Db::name('pay_event')->insertGetId($even_data);
  173. if (!$pay_order || !$pay_event) {
  174. throw new Exception('下单失败');
  175. }
  176. Db::commit();
  177. $pay = new JingXiuPayUtil();
  178. if (!$pay->wxWapPay($pay_no,$money,'充值会员','/api/jing_xiu_pay/pay_notify')){
  179. $this->error($pay->getMessage());
  180. }
  181. $data = $pay->getData();
  182. $this->success('success', $data);
  183. } catch (Exception $e) {
  184. Db::rollback();
  185. $this->error($e->getMessage());
  186. }
  187. }
  188. /**
  189. * 支付回调
  190. *
  191. * @param Request $request
  192. * @return string
  193. * @throws \think\db\exception\DataNotFoundException
  194. * @throws \think\db\exception\ModelNotFoundException
  195. * @throws \think\exception\DbException
  196. */
  197. public function pay_notify(Request $request)
  198. {
  199. $params = $request->param();
  200. // 消息主体信息
  201. $resp_data_json = htmlspecialchars_decode($params['resp_data'] ?? '');
  202. $resp_data = json_decode(stripslashes($resp_data_json), true);
  203. unset($params['resp_data']);
  204. LogUtil::info('支付回调参数', self::LOG_MODULE, __FUNCTION__, [
  205. 'params' => $params,
  206. 'resp_data2' => base64_encode($resp_data_json),
  207. 'resp_data' => $resp_data,
  208. ]);
  209. // 校验回调信息
  210. if (empty($params['resp_code']) || $params['resp_code'] != '00000000' || empty($resp_data['req_seq_id'])) {
  211. LogUtil::info('回调信息有误', self::LOG_MODULE, __FUNCTION__, "resp_code error");
  212. return self::response201('支付信息有误');
  213. }
  214. // 校验签名
  215. $huiPay = new PayUtil();
  216. if (!$huiPay->checkSign($params['sign'],$resp_data_json)){
  217. LogUtil::info('签名校验失败', self::LOG_MODULE, __FUNCTION__);
  218. return self::response201('签名校验失败');
  219. }
  220. if ($resp_data['resp_code'] != '00000000'){
  221. LogUtil::info('订单交易失败', self::LOG_MODULE, __FUNCTION__,$resp_data['resp_desc'] ?? '交易失败');
  222. return self::response201('支付信息有误');
  223. }
  224. // 开始处理业务逻辑
  225. $pay_no = $resp_data['req_seq_id'];
  226. LogUtil::info('订单号', self::LOG_MODULE, __FUNCTION__, $pay_no);
  227. //查询订单信息
  228. $order_info = Db::name('pay_order')->where('pay_no', $pay_no)->find();
  229. if (!$order_info) {
  230. LogUtil::info('订单信息不存在', self::LOG_MODULE, __FUNCTION__);
  231. return self::response201('订单信息不存在');
  232. }
  233. if ($order_info['status'] == 3){
  234. LogUtil::info('订单信息_已删除', self::LOG_MODULE, __FUNCTION__, [
  235. 'status' => $order_info['status']
  236. ]);
  237. return self::response201('充值入账失败');
  238. }
  239. if ($order_info['status'] == 1 || $order_info['status'] == 2) {
  240. LogUtil::info('充值入账更新余额失败_status已更新过', self::LOG_MODULE, __FUNCTION__, [
  241. 'status' => $order_info['status']
  242. ]);
  243. return self::response201('充值入账失败');
  244. }
  245. $extendType = '';
  246. //区分vip 还是 冲金币
  247. $is_g = stripos($pay_no, 'P');
  248. if ($is_g !== false) {
  249. $extendType = 'gold';
  250. } else {
  251. $is_v = stripos($pay_no, 'V');
  252. if ($is_v !== false) {
  253. $extendType = 'vip';
  254. }
  255. }
  256. //status已更新过
  257. $result = Db::name('pay_order')->where('pay_no', $pay_no)->setField(['status' => 2]);
  258. if (!$result) {
  259. LogUtil::info('充值入账更新余额失败_status更新状态2不成功', self::LOG_MODULE, __FUNCTION__, [
  260. 'status' => $order_info['status']
  261. ]);
  262. return self::response201('充值入账失败');
  263. }
  264. //你可以在此编写订单逻辑
  265. $payEvent = Db::name('pay_event')->where('pay_no', $pay_no)->find();
  266. $args = json_decode($payEvent['args'] ?? '', true);
  267. $rechargeM = new \app\common\model\Recharge();
  268. if ($extendType == 'gold') {
  269. $payRes = $rechargeM->goldpaysucc($pay_no, $args);
  270. $payTypeStr = '充值';
  271. } elseif ($extendType == 'vip') {
  272. $payRes = $rechargeM->vippaysucc($pay_no, $args);
  273. $payTypeStr = 'vip';
  274. } else {
  275. $payRes = false;
  276. $payTypeStr = '未知支付类型';
  277. }
  278. if (!$payRes) {
  279. LogUtil::info('更新失败', self::LOG_MODULE, __FUNCTION__, $payTypeStr);
  280. return self::response201('更新失败');
  281. }
  282. LogUtil::info('订单处理成功', self::LOG_MODULE, __FUNCTION__, $payTypeStr);
  283. return self::response200('success');
  284. }
  285. /**
  286. * 成功返回
  287. * @param string $message
  288. * @param $result
  289. * @return string
  290. */
  291. private static function response200(string $message = 'success', $result = null)
  292. {
  293. return json_encode([
  294. 'code' => 200,
  295. 'message' => $message,
  296. 'result' => $result,
  297. ], JSON_UNESCAPED_UNICODE);
  298. }
  299. /**
  300. * 失败返回201
  301. * @param string $message
  302. * @param $result
  303. * @return string json
  304. */
  305. private static function response201(string $message = 'error', $result = null)
  306. {
  307. return json_encode([
  308. 'code' => 201,
  309. 'message' => $message,
  310. 'result' => $result
  311. ], JSON_UNESCAPED_UNICODE);
  312. }
  313. }