|
@@ -0,0 +1,352 @@
|
|
|
|
+<?php
|
|
|
|
+
|
|
|
|
+namespace app\api\controller;
|
|
|
|
+
|
|
|
|
+use addons\epay\library\Service;
|
|
|
|
+use app\common\controller\Api;
|
|
|
|
+use app\utils\CurlUtil;
|
|
|
|
+use app\utils\Easywechat\MiniAppService;
|
|
|
|
+use app\utils\JingXiu\JingXiuPayUtil;
|
|
|
|
+use app\utils\LogUtil;
|
|
|
|
+use app\utils\PayUtil;
|
|
|
|
+use think\Cache;
|
|
|
|
+use think\Db;
|
|
|
|
+use think\Exception;
|
|
|
|
+use think\Request;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 通行证
|
|
|
|
+ */
|
|
|
|
+class JingXiuPay extends Api
|
|
|
|
+{
|
|
|
|
+ // 日志模块名称
|
|
|
|
+ const LOG_MODULE = 'JingXiuPay';
|
|
|
|
+ protected $noNeedLogin = ['vip_recharge', 'gold_recharge', 'pay', 'pay_notify'];
|
|
|
|
+ protected $noNeedRight = '*';
|
|
|
|
+
|
|
|
|
+ public function _initialize()
|
|
|
|
+ {
|
|
|
|
+ parent::_initialize();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public function __construct(Request $request = null)
|
|
|
|
+ {
|
|
|
|
+ parent::__construct($request);
|
|
|
|
+ //日志统一写入
|
|
|
|
+ register_shutdown_function([new LogUtil, 'close']);
|
|
|
|
+ LogUtil::getInstance('Api/'); //设置日志存入通道
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 会员充值 (跳转小程序充值)
|
|
|
|
+ * @return void
|
|
|
|
+ */
|
|
|
|
+ public function vip_recharge()
|
|
|
|
+ {
|
|
|
|
+ Db::startTrans();
|
|
|
|
+ try {
|
|
|
|
+ $rc_id = input('rc_id', 0);
|
|
|
|
+ $pay_type = input('pay_type', 'wechat');
|
|
|
|
+ $uid = $this->auth->id;
|
|
|
|
+
|
|
|
|
+ if ($pay_type != 'wechat') {
|
|
|
|
+ throw new Exception('支付类型有误');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!$rc_id) {
|
|
|
|
+ throw new Exception('请选择会员套餐');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //赋值money
|
|
|
|
+ $recharge_config = Db::name('payvip_config')->where('id', $rc_id)->find();
|
|
|
|
+ $money = $recharge_config['money'];
|
|
|
|
+
|
|
|
|
+ if ($money <= 0) {
|
|
|
|
+ throw new Exception('支付金额必须大于0');
|
|
|
|
+ }
|
|
|
|
+ if ($money > 10000) {
|
|
|
|
+ throw new Exception('支付金额太大');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //会员等级冲突
|
|
|
|
+ //当前是会员,但是却要向下级续费,直接提示报错
|
|
|
|
+ //修改等级,向上立刻改,向下不允许
|
|
|
|
+ $wallet_info = model('wallet')->getWallet($this->auth->id);
|
|
|
|
+ if ($wallet_info['vip_endtime'] > time() && $recharge_config['vip_level'] < $wallet_info['vip_level']) {
|
|
|
|
+ throw new Exception('当前会员没有过期,不能续费');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //创建订单
|
|
|
|
+ $data = [];
|
|
|
|
+ $data['status'] = 0;
|
|
|
|
+ $pay_no = createUniqueNo('V', $uid);
|
|
|
|
+ $data['pay_no'] = $pay_no;
|
|
|
|
+ $data['money'] = $money;
|
|
|
|
+ $data['payment_class'] = $pay_type;
|
|
|
|
+ $data['user_id'] = $uid;
|
|
|
|
+ $data['ext_info'] = json_encode(['subject' => '充值vip支付']);
|
|
|
|
+ $data['memo'] = '充值会员支付';
|
|
|
|
+ $data['createtime'] = time();
|
|
|
|
+ //$data['payment'] = 'miniapp';
|
|
|
|
+ $data['payment'] = 'app';
|
|
|
|
+ $pay_order = Db::name('pay_order')->insertGetId($data);
|
|
|
|
+
|
|
|
|
+ //创建回调
|
|
|
|
+ $even_data = [];
|
|
|
|
+ $even_data['event'] = 'success';
|
|
|
|
+ $even_data['class'] = 'app\common\model\Recharge';
|
|
|
|
+ $even_data['method'] = 'vippaysucc';
|
|
|
|
+ $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]);
|
|
|
|
+ $even_data['pay_no'] = $pay_no;
|
|
|
|
+ $pay_event = Db::name('pay_event')->insertGetId($even_data);
|
|
|
|
+
|
|
|
|
+ if (!$pay_order || !$pay_event) {
|
|
|
|
+ throw new Exception('下单失败');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Db::commit();
|
|
|
|
+
|
|
|
|
+ $pay = new JingXiuPayUtil();
|
|
|
|
+ if (!$pay->wxWapPay($pay_no,$money,'充值会员','/api/jing_xiu_pay/pay_notify')){
|
|
|
|
+ $this->error($pay->getMessage());
|
|
|
|
+ }
|
|
|
|
+ $data = $pay->getData();
|
|
|
|
+ $this->success('success', $data);
|
|
|
|
+ } catch (Exception $e) {
|
|
|
|
+ Db::rollback();
|
|
|
|
+ $this->error($e->getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 金币充值
|
|
|
|
+ * @return void
|
|
|
|
+ */
|
|
|
|
+ public function gold_recharge()
|
|
|
|
+ {
|
|
|
|
+ Db::startTrans();
|
|
|
|
+ try {
|
|
|
|
+ $rc_id = input_post('rc_id', 0);
|
|
|
|
+ $pay_type = 'wechat';
|
|
|
|
+ $freemoney = input_post('freemoney', 0, 'intval');
|
|
|
|
+ $uid = $this->auth->id;
|
|
|
|
+
|
|
|
|
+ if (!$rc_id && !$freemoney) {
|
|
|
|
+ throw new Exception('请选择或填写充值金额');
|
|
|
|
+ }
|
|
|
|
+ if (!in_array($pay_type, ['wechat', 'alipay'])) {
|
|
|
|
+ throw new Exception('错误的支付类型');
|
|
|
|
+ }
|
|
|
|
+ //赋值money
|
|
|
|
+ if ($rc_id) {
|
|
|
|
+ $recharge_config = Db::name('paygold_config')->where('id', $rc_id)->find();
|
|
|
|
+ $money = $recharge_config ? $recharge_config['money'] : 0;
|
|
|
|
+ $gold = $recharge_config ? $recharge_config['gold'] : 0;
|
|
|
|
+ $first_gold = $recharge_config ? $recharge_config['first_gold'] : 0;
|
|
|
|
+ $first_vipdays = $recharge_config ? $recharge_config['first_vipdays'] : 0;
|
|
|
|
+ $vip_gold = $recharge_config ? $recharge_config['vip_gold'] : 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //自由输入覆盖
|
|
|
|
+ if (!empty($freemoney)) {
|
|
|
|
+ $rc_id = 0;
|
|
|
|
+ $money = floatval($freemoney);
|
|
|
|
+ $bili = config('site.money_to_gold') ?: 10;
|
|
|
|
+ $gold = bcmul($money, $bili, 0);
|
|
|
|
+ $first_gold = 0;
|
|
|
|
+ $first_vipdays = 0;
|
|
|
|
+ $vip_gold = 0;
|
|
|
|
+ }
|
|
|
|
+ if ($money <= 0) {
|
|
|
|
+ throw new Exception('支付金额必须大于0');
|
|
|
|
+ }
|
|
|
|
+ if ($money > 10000) {
|
|
|
|
+ throw new Exception('支付金额太大');
|
|
|
|
+ }
|
|
|
|
+ //查询是不是会员,若不是则不赠送金币
|
|
|
|
+ $vip_endtime = Db::name('user_wallet')->where('user_id', $this->auth->id)->value('vip_endtime');
|
|
|
|
+ if ($vip_endtime < time()) {
|
|
|
|
+ $vip_gold = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //创建订单
|
|
|
|
+ $data = [];
|
|
|
|
+ $data['status'] = 0;
|
|
|
|
+ $pay_no = createUniqueNo('P', $uid);
|
|
|
|
+ $data['pay_no'] = $pay_no;
|
|
|
|
+ $data['money'] = $money;
|
|
|
|
+ $data['payment_class'] = $pay_type;
|
|
|
|
+ $data['user_id'] = $uid;
|
|
|
|
+ $data['ext_info'] = json_encode(['subject' => '充值金币支付']);
|
|
|
|
+ $data['memo'] = '充值金币支付';
|
|
|
|
+ $data['createtime'] = time();
|
|
|
|
+ $data['payment'] = 'app';
|
|
|
|
+ $pay_order = Db::name('pay_order')->insertGetId($data);
|
|
|
|
+
|
|
|
|
+ //创建回调
|
|
|
|
+ $even_data = [];
|
|
|
|
+ $even_data['event'] = 'success';
|
|
|
|
+ $even_data['class'] = 'app\common\model\Recharge';
|
|
|
|
+ $even_data['method'] = 'goldpaysucc';
|
|
|
|
+ $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]);
|
|
|
|
+ $even_data['pay_no'] = $pay_no;
|
|
|
|
+ $pay_event = Db::name('pay_event')->insertGetId($even_data);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (!$pay_order || !$pay_event) {
|
|
|
|
+ throw new Exception('下单失败');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Db::commit();
|
|
|
|
+ $pay = new JingXiuPayUtil();
|
|
|
|
+ if (!$pay->wxWapPay($pay_no,$money,'充值会员','/api/jing_xiu_pay/pay_notify')){
|
|
|
|
+ $this->error($pay->getMessage());
|
|
|
|
+ }
|
|
|
|
+ $data = $pay->getData();
|
|
|
|
+ $this->success('success', $data);
|
|
|
|
+ } catch (Exception $e) {
|
|
|
|
+ Db::rollback();
|
|
|
|
+ $this->error($e->getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 支付回调
|
|
|
|
+ *
|
|
|
|
+ * @param Request $request
|
|
|
|
+ * @return string
|
|
|
|
+ * @throws \think\db\exception\DataNotFoundException
|
|
|
|
+ * @throws \think\db\exception\ModelNotFoundException
|
|
|
|
+ * @throws \think\exception\DbException
|
|
|
|
+ */
|
|
|
|
+ public function pay_notify(Request $request)
|
|
|
|
+ {
|
|
|
|
+ $params = $request->param();
|
|
|
|
+
|
|
|
|
+ // 消息主体信息
|
|
|
|
+ $resp_data_json = htmlspecialchars_decode($params['resp_data'] ?? '');
|
|
|
|
+ $resp_data = json_decode(stripslashes($resp_data_json), true);
|
|
|
|
+ unset($params['resp_data']);
|
|
|
|
+
|
|
|
|
+ LogUtil::info('支付回调参数', self::LOG_MODULE, __FUNCTION__, [
|
|
|
|
+ 'params' => $params,
|
|
|
|
+ 'resp_data2' => base64_encode($resp_data_json),
|
|
|
|
+ 'resp_data' => $resp_data,
|
|
|
|
+ ]);
|
|
|
|
+
|
|
|
|
+ // 校验回调信息
|
|
|
|
+ if (empty($params['resp_code']) || $params['resp_code'] != '00000000' || empty($resp_data['req_seq_id'])) {
|
|
|
|
+ LogUtil::info('回调信息有误', self::LOG_MODULE, __FUNCTION__, "resp_code error");
|
|
|
|
+ return self::response201('支付信息有误');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 校验签名
|
|
|
|
+ $huiPay = new PayUtil();
|
|
|
|
+ if (!$huiPay->checkSign($params['sign'],$resp_data_json)){
|
|
|
|
+ LogUtil::info('签名校验失败', self::LOG_MODULE, __FUNCTION__);
|
|
|
|
+ return self::response201('签名校验失败');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ($resp_data['resp_code'] != '00000000'){
|
|
|
|
+ LogUtil::info('订单交易失败', self::LOG_MODULE, __FUNCTION__,$resp_data['resp_desc'] ?? '交易失败');
|
|
|
|
+ return self::response201('支付信息有误');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 开始处理业务逻辑
|
|
|
|
+ $pay_no = $resp_data['req_seq_id'];
|
|
|
|
+ LogUtil::info('订单号', self::LOG_MODULE, __FUNCTION__, $pay_no);
|
|
|
|
+ //查询订单信息
|
|
|
|
+ $order_info = Db::name('pay_order')->where('pay_no', $pay_no)->find();
|
|
|
|
+ if (!$order_info) {
|
|
|
|
+ LogUtil::info('订单信息不存在', self::LOG_MODULE, __FUNCTION__);
|
|
|
|
+ return self::response201('订单信息不存在');
|
|
|
|
+ }
|
|
|
|
+ if ($order_info['status'] == 3){
|
|
|
|
+ LogUtil::info('订单信息_已删除', self::LOG_MODULE, __FUNCTION__, [
|
|
|
|
+ 'status' => $order_info['status']
|
|
|
|
+ ]);
|
|
|
|
+ return self::response201('充值入账失败');
|
|
|
|
+ }
|
|
|
|
+ if ($order_info['status'] == 1 || $order_info['status'] == 2) {
|
|
|
|
+ LogUtil::info('充值入账更新余额失败_status已更新过', self::LOG_MODULE, __FUNCTION__, [
|
|
|
|
+ 'status' => $order_info['status']
|
|
|
|
+ ]);
|
|
|
|
+ return self::response201('充值入账失败');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $extendType = '';
|
|
|
|
+ //区分vip 还是 冲金币
|
|
|
|
+ $is_g = stripos($pay_no, 'P');
|
|
|
|
+ if ($is_g !== false) {
|
|
|
|
+ $extendType = 'gold';
|
|
|
|
+ } else {
|
|
|
|
+ $is_v = stripos($pay_no, 'V');
|
|
|
|
+ if ($is_v !== false) {
|
|
|
|
+ $extendType = 'vip';
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //status已更新过
|
|
|
|
+ $result = Db::name('pay_order')->where('pay_no', $pay_no)->setField(['status' => 2]);
|
|
|
|
+
|
|
|
|
+ if (!$result) {
|
|
|
|
+ LogUtil::info('充值入账更新余额失败_status更新状态2不成功', self::LOG_MODULE, __FUNCTION__, [
|
|
|
|
+ 'status' => $order_info['status']
|
|
|
|
+ ]);
|
|
|
|
+ return self::response201('充值入账失败');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //你可以在此编写订单逻辑
|
|
|
|
+ $payEvent = Db::name('pay_event')->where('pay_no', $pay_no)->find();
|
|
|
|
+ $args = json_decode($payEvent['args'] ?? '', true);
|
|
|
|
+ $rechargeM = new \app\common\model\Recharge();
|
|
|
|
+ if ($extendType == 'gold') {
|
|
|
|
+ $payRes = $rechargeM->goldpaysucc($pay_no, $args);
|
|
|
|
+ $payTypeStr = '充值';
|
|
|
|
+ } elseif ($extendType == 'vip') {
|
|
|
|
+ $payRes = $rechargeM->vippaysucc($pay_no, $args);
|
|
|
|
+ $payTypeStr = 'vip';
|
|
|
|
+ } else {
|
|
|
|
+ $payRes = false;
|
|
|
|
+ $payTypeStr = '未知支付类型';
|
|
|
|
+ }
|
|
|
|
+ if (!$payRes) {
|
|
|
|
+ LogUtil::info('更新失败', self::LOG_MODULE, __FUNCTION__, $payTypeStr);
|
|
|
|
+ return self::response201('更新失败');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ LogUtil::info('订单处理成功', self::LOG_MODULE, __FUNCTION__, $payTypeStr);
|
|
|
|
+ return self::response200('success');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 成功返回
|
|
|
|
+ * @param string $message
|
|
|
|
+ * @param $result
|
|
|
|
+ * @return string
|
|
|
|
+ */
|
|
|
|
+ private static function response200(string $message = 'success', $result = null)
|
|
|
|
+ {
|
|
|
|
+ return json_encode([
|
|
|
|
+ 'code' => 200,
|
|
|
|
+ 'message' => $message,
|
|
|
|
+ 'result' => $result,
|
|
|
|
+ ], JSON_UNESCAPED_UNICODE);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 失败返回201
|
|
|
|
+ * @param string $message
|
|
|
|
+ * @param $result
|
|
|
|
+ * @return string json
|
|
|
|
+ */
|
|
|
|
+ private static function response201(string $message = 'error', $result = null)
|
|
|
|
+ {
|
|
|
|
+ return json_encode([
|
|
|
|
+ 'code' => 201,
|
|
|
|
+ 'message' => $message,
|
|
|
|
+ 'result' => $result
|
|
|
|
+ ], JSON_UNESCAPED_UNICODE);
|
|
|
|
+ }
|
|
|
|
+}
|