request->get(), true), JSON_UNESCAPED_UNICODE)); Log::info('[ WeChat ] [ PAY ] [ CALLBACK ] INPUT: ' . json_encode(var_export($this->request->getInput(), true), JSON_UNESCAPED_UNICODE)); $goods_id = $this->request->request('id'); // 商品id $admin_id = UserService::instance()->getAdminId()->data; // 渠道商/代理商id $channel_id = UserService::instance()->getUserChannelId()->data; //渠道商id $adminExtend = AdminService::instance()->getAdminExtendModel()->getInfo($admin_id); if ($adminExtend['distribute'] == '1') { //代理商配置信息 $adminConfig = AdminService::instance()->getAdminConfigModel()->getAdminInfoAll($admin_id); } else { //渠道商配置信息 $adminConfig = AdminService::instance()->getAdminConfigModel()->getAdminInfoAll($channel_id); } if (!$goods_id || !$admin_id) { $this->error('缺少参数'); } $goodsCategory = $this->request->request('category'); //商品分类 nickname $activityId = $this->request->request('activityId', 0); //活动id $group = model('AuthGroupAccess')->where('uid', $admin_id)->find(); $group_id = $group->group_id; if (!$goodsInfo = model('Goods')->getGoodsInfoById($goods_id)) { $this->error('商品不存在'); } $goodsInfo['activity_id'] = $activityId; if ($this->request->param('buyMore')) { $configBuyMore = PayConstants::getBuyMore(UserService::instance()->getUserInfo()->id); if ($goodsInfo['money'] >= 1) { $goodsInfo['money'] = (int)$goodsInfo['money']; } $goodsInfo['money'] = (string)($goodsInfo['money'] * 100 / 100); if (array_key_exists($goodsInfo['money'], $configBuyMore)) { $goodsInfo['buy_id'] = $configBuyMore[$goodsInfo['money']]['id']; $goodsInfo['money'] += $configBuyMore[$goodsInfo['money']]['money']; } } /** * 未登录的逻辑处理 */ if (!$this->user->isLogin()) { $this->error('登录信息获取失败'); } /** * 获取渠道商/代理商资料 */ if (!$adminExtend) { $this->error('管理员信息获取失败'); } $channelExtend = $adminExtend; if ($group_id == 4) { //代理 获取渠道信息 $channelExtend = AdminService::instance()->getAdminExtendModel()->where(['admin_id' => $channel_id])->find(); } return [$goodsCategory, $goods_id, $admin_id, $goodsInfo, $adminExtend, $channel_id, $adminConfig, $group_id, $channelExtend]; } /** * @param $payment 支付方式 0 微信;1 四方平台 * @param $adminId * @param $adminExtend * @param $row * @param $goodsCategory * @param $pdOrderId * @param $out_trade_no * @param $goodsId * @param $payInfo * @param $channelId * @param $prepay_id * @param $groupId * @param $pay_json * @param $kl_admin_info * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ private function _createOrderInfo( $payment, $adminId, $adminExtend, $row, $goodsCategory, $pdOrderId, $out_trade_no, $goodsId, $payInfo, $channelId, $prepay_id, $groupId, $pay_json, $kl_admin_info, $channelExtend ) { $user_id = UserService::instance()->getUserInfo()->id; if ($this->request->param('buyMore')) { LogService::info('PAYMOREORDER:' . $user_id . ':' . $out_trade_no); if (array_key_exists('buy_id', $row)) { Redis::instance()->set(CacheConstants::getBuyMoreOrderCache($out_trade_no), $row['buy_id'], 600); } } if ($this->request->param('single_push')) { LogService::info("SinglePush:" . $user_id . ":" . $out_trade_no); $sbookId = $this->request->param('book_id'); Redis::instance()->set(CacheConstants::getSinglePushOrderCache($out_trade_no), $sbookId, 600); } $insertData = [ 'user_id' => $user_id, 'admin_id' => $adminId, 'benefit' => $adminExtend['benefit'], 'money' => $row['money'], 'money_benefit' => round($row['money'] * $adminExtend['benefit'], 2), 'category' => $goodsCategory, 'payid' => $prepay_id, 'out_trade_no' => $out_trade_no, 'ip' => Ip::ip(), 'referral_id' => UrlService::instance()->getUserReferralId()->data, 'referral_id_permanent' => UserService::instance()->getUserInfo()->referral_id_permanent, 'book_id' => $this->request->request('book_id'), 'chapter_id' => $this->request->request('chapter_id'), 'goods_id' => $goodsId, 'kandian' => $row['kandian'], 'free_kandian' => $row['free_kandian'], 'day' => $row['day'], 'type' => $row['type'], 'state' => 0, 'business_line' => $this->request->param('business') ?? 0, 'pay_json' => $pay_json, 'activity_id' => $row['activity_id'], 'payment_method' => $payment, 'wxpay_id' => $payInfo['id'], 'ext' => UserService::instance()->getUserInfo()->ext && json_decode(UserService::instance()->getUserInfo()->ext) ? UserService::instance()->getUserInfo()->ext : json_encode(new \stdClass()), 'createtime' => time(), 'updatetime' => time(), 'channel_id' => $channelId, 'channel_benefit' => $channelExtend['benefit'], 'group' => $groupId, ]; if ($payment == ApiConstants::PAYMENT_METHOD_PALM) { $insertData['pdorderid'] = $pdOrderId; //四方平台订单号 } try { if ($kl_admin_info) { if ($kl_admin_info['admin_id'] != $channelId) { $insertData['deduct'] = 1; } $insertData['benefit'] = $kl_admin_info['benefit']; $insertData['money_benefit'] = round($row['money'] * $kl_admin_info['benefit'], 2); $insertData['admin_id'] = $kl_admin_info['admin_id']; $insertData['resource_id'] = $adminId; $adminId = $kl_admin_info->admin_id; $groupId = 3; $insertData['group'] = $groupId; } } catch (\Exception $e) { Log::error('订单扣量失败, Error:' . $e->getMessage()); } //转移订单结束 //如果订单没有扣量也没有转移,判断订单是否有赏金 if (empty($insertData['deduct']) && empty($insertData['resource_id']) && $groupId == 4 && !empty($adminExtend['invite_id'])) { $invite_admin = model('AdminExtend')->where(['admin_id' => $adminExtend['invite_id']])->find(); $admin_agent = model('Admin')->where('id', $adminExtend['invite_id'])->find(); if ($invite_admin && $admin_agent['status'] == 'normal') { $insertData['reward_money'] = round($row['money'] * $invite_admin['reward_benefit'], 2); $insertData['reward_admin_id'] = $adminExtend['invite_id']; $insertData['reward_benefit'] = $invite_admin['reward_benefit']; } } $ordersId = model('Orders')->insertGetId($insertData); if (empty($insertData['deduct']) && $this->request->request('float_id')) { Redis::instance()->set(CacheConstants::getFloatTipsOrderId($ordersId), $this->request->request('float_id')); } if (!$ordersId) { $this->error('订单创建失败'); } else {//如果订单存在 插入订单关联表 if ($this->request->has('orderExtendType')) {//消耗活动 $order_extend['order_id'] = $ordersId; $order_extend['type'] = $this->request->request('orderExtendType'); $order_extend['created_at'] = date('Y-m-d H:i:s', time()); $campaignArr = []; if ($order_extend['type'] == 1) { $campaignArr['campaign']['match_date'] = $this->request->request('campMatchDate'); $campaignArr['campaign']['kandian'] = $this->request->request('campKandian'); } elseif ($order_extend['type'] == 2) { $campaignArr['act_id'] = $this->request->request('actId'); $campaignArr['sub_code'] = $this->request->request('subCode', 0); } $order_extend['json'] = json_encode($campaignArr); model('ordersExtend')->insert($order_extend); } } #region 快分app订单 KuaifenService::instance()->createKuaifenOrders($ordersId, $insertData['admin_id'], $user_id, $insertData['book_id'], $insertData['money'], $insertData['out_trade_no']); #endregion //判断是充值vip还是充值书币 $isVip = false; if (!empty($row['day'])) { $isVip = true; } $isActivity = !empty($row['activity_id']); if (empty($insertData['deduct'])) { //如果不是KL $channel_id = UserService::instance()->getUserChannelId()->data; OrderCollectService::instance()->addCreateOrderCollect($user_id, $adminId, $isVip, $channel_id, $groupId, PayConstants::BUSINESS_WECHAT, $isActivity); if ($isActivity) { $oAna = new AnalysisObject(); $oAna->type = KafkaDotConstants::TYPE_ACTIVITY; $oAna->user_from = [ 'activity_id' => $row['activity_id'] ]; $oAna->data = [ 'stage' => 'start' ]; KafkaDotService::instance()->sendMsg($user_id, $oAna); } } else { OrderCollectService::instance()->addCreateOrderCollect($user_id, $kl_admin_info['admin_id'], $isVip, $kl_admin_info['admin_id'], $groupId, PayConstants::BUSINESS_WECHAT, $isActivity); } } /** * 支付下单总入口 */ public function pay() { //默认官方支付 $payment_method = 0; //根据域名进行匹配 $host = get_host_no_port(); $payHosts = model('Wxpay')->getHosts(); if (in_array($host, $payHosts)) { //支付域名匹配成功 $pay_hosts = model('Wxpay')->getInfoByHost($host); $payInfo = model('Wxpay')->getInfo($pay_hosts['platform_id'], $pay_hosts['id']); if (isset($payInfo['payment_method']) && $payInfo['payment_method'] > 0) { $payment_method = $payInfo['payment_method']; } } else { //支付域名匹配失败,从Cookie获取渠道默认支付方式 $adminId = UserService::instance()->getAdminId()->data; // 渠道商/代理商ID $channel_id = UserService::instance()->getUserChannelId()->data; $adminExtend = AdminService::instance()->getAdminExtendModel()->where(['admin_id' => $adminId])->find(); if ($adminExtend['distribute'] == '1') { //代理商配置信息 $adminConfig = AdminService::instance()->getAdminConfigModel()->getAdminInfoAll($adminId); } else { //渠道商配置信息 $adminConfig = AdminService::instance()->getAdminConfigModel()->getAdminInfoAll($channel_id); } // $adminConfig = AdminService::instance()->getAdminConfigModel()->getAdminInfoAll($adminId); if (isset($adminConfig['payment_method']) && $adminConfig['payment_method'] > 0) { $payment_method = $adminConfig['payment_method']; } } if ($this->request->has('url_id')) { $url_id = $this->request->request('url_id'); $user_id = UserService::instance()->getUserInfo()->id; $canPay = SpecialPayService::instance()->canPay($url_id, $user_id); if ($canPay['code'] != 200) { $this->error($canPay['msg']); } } // 保存用户IP地址信息到Redis,下单成功后用户画像打点使用 $ip_redis_key = CacheConstants::USER_IP_PREFIX . Cookie::get('user_id'); Redis::instance()->set( $ip_redis_key, json_encode([ 'ip' => Ip::ip(), 'country' => Ip::country(Ip::ip()), 'province' => Ip::province(Ip::ip()), 'city' => Ip::city(Ip::ip()), 'ua' => Ua::getUa() ]), 300 ); $result = []; switch ($payment_method) { case ApiConstants::PAYMENT_METHOD_PALM://四方支付 $result = $this->payPalm(); break; case ApiConstants::PAYMENT_METHOD_JOIN://汇聚支付 $result = $this->payJoin(); break; case ApiConstants::PAYMENT_METHOD_MIHUA://米花支付 $result = $this->payMihua(); break; case ApiConstants::PAYMENT_METHOD_UNS://银生宝支付 $result = $this->payUns(); break; case ApiConstants::PAYMENT_METHOD_IPAYNOW://现在支付 $result = $this->payIpaynow(); break; default://微信官方支付 $result = $this->payWechat(); break; } //更新订单号和用户id if ($this->request->has('url_id')) { SpecialPayService::instance()->updateUrl($url_id, ['user_id' => $user_id, 'out_trade_no' => $result['out_trade_no']]); } $this->success('订单创建成功', ['json' => $result['json']]); } public function payJoin() { list($goodsCategory, $goodsId, $adminId, $goodsInfo, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend) = $this->_initPayInfo(); $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15; $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port()); $userId = Cookie::get('user_id'); if ($pay_timeout) { $endTime = time() - intval($pay_timeout) * 60; $has_orders = model('orders') ->where([ 'money' => $goodsInfo['money'], 'goods_id' => $goodsId, 'user_id' => $userId, // 'admin_id' => $adminId, 'state' => '0', 'wxpay_id' => $payInfo['id'], 'payment_method' => ApiConstants::PAYMENT_METHOD_JOIN ]) ->where(function (Query $query) use ($adminId) { $query->where('admin_id', $adminId) ->whereOr('resource_id', $adminId); }) ->where('createtime', '>', $endTime) ->find(); } else { $has_orders = null; } if (!empty($has_orders)) { //如果用户已经在该代理商/渠道商下过该单 $json = $has_orders['pay_json']; $out_trade_no = $has_orders['out_trade_no']; } else { $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [ 'day' => $goodsInfo['day'], 'activity_id' => $goodsInfo['activity_id'], 'user_id' => Cookie::get('user_id'), 'book_id' => $this->request->request('book_id'), ])->data; $paymentApplication = Factory::payment(Config::get('wechat')); $paymentApplication['cache'] = new RedisCache(Redis::instanceCache()); $out_trade_no = date('YmdHis') . '_' . $userId . '_' . Random::build('alnum', 4); $productName = $goodsInfo['type'] == 2 ? '充值VIP' : '充值书币'; $data = [ 'p0_Version' => ApiConstants::JOIN_PAY_VERSION, 'p1_MerchantNo' => $payInfo['quartet_merchant_id'], 'p2_OrderNo' => $out_trade_no, 'p3_Amount' => $goodsInfo['money'], 'p4_Cur' => '1', 'p9_NotifyUrl' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/joinpay', 'q1_FrpCode' => ApiConstants::JOIN_PAY_TYPE, 'q5_OpenId' => Cookie::get('openid'), 'q7_AppId' => $payInfo['appid'], ]; $goods_des = Config::get('site.goodsdes'); if ($goods_des) { $data['p6_ProductDesc'] = $productName . ' ' . $goods_des; } else { $data['p6_ProductDesc'] = $productName; } if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) { if (empty($goods_des)) { $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName; } else { $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName . '_' . $goods_des; } } else { if (empty($goods_des)) { $zfxx = $userId . '_' . $productName; } else { $zfxx = $userId . '_' . $productName . '_' . $goods_des; } } $data['p5_ProductName'] = mb_substr($zfxx, 0, 120, 'utf-8'); $secret = $payInfo['quartet_app_key']; $signStr = $data['p0_Version'] . $data['p1_MerchantNo'] . $data['p2_OrderNo'] . $data['p3_Amount'] . $data['p4_Cur'] . $data['p5_ProductName'] . $data['p6_ProductDesc'] . $data['p9_NotifyUrl'] . $data['q1_FrpCode'] . $data['q5_OpenId'] . $data['q7_AppId'] . $secret; $data['hmac'] = md5($signStr); $orderInfo = [ 'goods_id' => $goodsId, 'out_trade_no' => $out_trade_no, 'admin_id' => $adminId, 'user_id' => $userId, ]; $joinService = JoinPayService::instance(); try { $result = $joinService->payJoinApi($data, $payInfo, $goodsInfo, $orderInfo); } catch (Exception $e) { $this->success($e->getMessage()); } $payInfoArr = json_decode($result['rc_Result'], true); $prepay_id = explode('=', $payInfoArr['package'])[1]; $this->_createOrderInfo(ApiConstants::PAYMENT_METHOD_JOIN, $adminId, $adminExtend, $goodsInfo, $goodsCategory, $result['r7_TrxNo'], $out_trade_no, $goodsId, $payInfo, $channelId, $prepay_id, $groupId, $result['rc_Result'], $kl_admin_info, $channelExtend ); $json = $result['rc_Result']; } //下单订单数据统计 return ['json' => $json, 'out_trade_no' => $out_trade_no]; } /** * 微信下单 */ public function payWechat() { list($goodsCategory, $goodsId, $adminId, $row, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend) = $this->_initPayInfo(); //本月 $paymentApplication = Factory::payment(Config::get('wechat')); $paymentApplication['cache'] = new RedisCache(Redis::instanceCache()); $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15; $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port()); $userId = Cookie::get('user_id'); if ($pay_timeout) { $endTime = time() - intval($pay_timeout) * 60; $has_orders = model('orders') ->where([ 'money' => $row['money'], 'goods_id' => $goodsId, 'user_id' => $userId, // 'admin_id' => $adminId, 'state' => '0', 'wxpay_id' => $payInfo['id'], 'payment_method' => ApiConstants::PAYMENT_METHOD_WECHAT ]) ->where(function (Query $query) use ($adminId) { $query->where('admin_id', $adminId) ->whereOr('resource_id', $adminId); }) ->where('createtime', '>', $endTime) ->find(); } else { $has_orders = null; } if (!empty($has_orders)) { //如果用户已经在该代理商/渠道商下过该单 $jssdk = $paymentApplication->jssdk; $json = $jssdk->bridgeConfig($has_orders['payid']); $out_trade_no = $has_orders['out_trade_no']; } else { $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [ 'day' => $row['day'], 'activity_id' => $row['activity_id'], 'user_id' => Cookie::get('user_id'), 'book_id' => $this->request->request('book_id'), ])->data; $out_trade_no = date('YmdHis') . '_' . $userId . '_' . Random::build('alnum', 4); $data = [ 'body' => $row['type'] == 2 ? '充值VIP' : '充值书币', 'out_trade_no' => $out_trade_no, 'total_fee' => $row['money'] * 100, 'spbill_create_ip' => Ip::ip(), 'notify_url' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/pay', // 支付结果通知网址,如果不设置则会使用配置里的默认地址 'trade_type' => 'JSAPI', 'openid' => Cookie::get('openid'), ]; $goods_des = Config::get('site.goodsdes'); if ($goods_des) { $data['body'] = $data['body'] . ' ' . $goods_des; } if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) { $zfxx = $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $data['body']; $data['body'] = mb_substr($zfxx, 0, 120, 'utf-8'); } $palmApiStartTime = microtime(true); $result = $paymentApplication->order->unify($data); $palmApiEndTime = microtime(true); $apiRunTime = round($palmApiEndTime - $palmApiStartTime, 3); if ($result['return_code'] == 'FAIL') { Log::error(sprintf('wechatpay_create_order_fail!wxpay_id:%s,wxpay_name:%s,mch_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s,errmessage:%s' , $payInfo['id'], $payInfo['name'], $payInfo['mcid'], $adminId, $userId, $row['money'], $goodsId, $out_trade_no, $apiRunTime, json_encode(var_export($result, true), JSON_UNESCAPED_UNICODE))); Log::error('微信订单创建失败!订单内容: ' . json_encode(var_export($data, true), JSON_UNESCAPED_UNICODE) . " 微信返回内容: " . json_encode(var_export($result, true), JSON_UNESCAPED_UNICODE)); $this->error('微信订单创建失败'); } $result['prepay_id'] = $result['prepay_id'] ?? 0; $this->_createOrderInfo(ApiConstants::PAYMENT_METHOD_WECHAT, $adminId, $adminExtend, $row, $goodsCategory, 0, $out_trade_no, $goodsId, $payInfo, $channelId, $result['prepay_id'], $groupId, '', $kl_admin_info, $channelExtend ); $jssdk = $paymentApplication->jssdk; $json = $jssdk->bridgeConfig($result['prepay_id']); Log::info(sprintf('wechatpay_create_order_success!wxpay_id:%s,wxpay_name:%s,mch_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s' , $payInfo['id'], $payInfo['name'], $payInfo['mcid'], $adminId, $userId, $row['money'], $goodsId, $out_trade_no, $apiRunTime)); } return ['json' => $json, 'out_trade_no' => $out_trade_no]; } public function payPalm() { list($goodsCategory, $goodsId, $adminId, $goodsInfo, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend) = $this->_initPayInfo(); $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15; $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port()); $userId = UserService::instance()->getUserInfo()->id; if ($pay_timeout) { $endTime = time() - intval($pay_timeout) * 60; $has_orders = model('orders') ->where([ 'money' => $goodsInfo['money'], 'goods_id' => $goodsId, 'user_id' => $userId, // 'admin_id' => $adminId, 'state' => '0', 'wxpay_id' => $payInfo['id'], 'payment_method' => ApiConstants::PAYMENT_METHOD_PALM ]) ->where(function (Query $query) use ($adminId) { $query->where('admin_id', $adminId) ->whereOr('resource_id', $adminId); }) ->where('createtime', '>', $endTime) ->find(); } else { $has_orders = null; } if (!empty($has_orders)) { //如果用户已经在该代理商/渠道商下过该单 $json = $has_orders['pay_json']; $out_trade_no = $has_orders['out_trade_no']; } else { $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [ 'day' => $goodsInfo['day'], 'activity_id' => $goodsInfo['activity_id'], 'user_id' => Cookie::get('user_id'), 'book_id' => $this->request->request('book_id'), ])->data; $paymentApplication = Factory::payment(Config::get('wechat')); $paymentApplication['cache'] = new RedisCache(Redis::instanceCache()); $out_trade_no = date('YmdHis') . '_' . $userId . '_' . Random::build('alnum', 4); $productName = $goodsInfo['type'] == 2 ? '充值VIP' : '充值书币'; $data = [ 'mchId' => $payInfo['quartet_merchant_id'], 'outTradeNo' => $out_trade_no, 'appid' => $payInfo['quartet_app_id'], 'version' => ApiConstants::PALM_PAY_VERSION, 'money' => $goodsInfo['money'] * 100, 'ip' => Ip::ip(), 'notifyUrl' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/palmpay', // 支付结果通知网址,如果不设置则会使用配置里的默认地址 'subAppid' => $payInfo['appid'], 'openid' => Cookie::get('openid'), ]; $palmPayCmdDefault = null; if ($payInfo['quartet_is_split'] == ApiConstants::QUARTET_IS_SPLIT) { if ($kl_admin_info && $kl_admin_info['admin_id'] != $channelId) { //仅扣量订单全部到自家子账号 $palmPayCmd = OrderService::instance()->getPalmPayCmd($goodsInfo['money'], 0)->data; $cmd = $palmPayCmd['cmd']; $palmPayCmdDefault = $palmPayCmd['default']; } else { $palmPayCmd = OrderService::instance()->getPalmPayCmd($goodsInfo['money'], $channelId)->data; $cmd = $palmPayCmd['cmd']; $palmPayCmdDefault = $palmPayCmd['default']; } if (!$cmd) { LogService::debug("微信分账设置错误"); $this->success('订单创建失败,请重新下单!'); } $data['cmd'] = $cmd; } $goods_des = Config::get('site.goodsdes'); if ($goods_des) { $data['productName'] = urlencode($productName . ' ' . $goods_des); } else { $data['productName'] = urlencode($productName); } if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) { if (empty($goods_des)) { $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName; } else { $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName . '_' . $goods_des; } $data['productDesc'] = mb_substr($zfxx, 0, 120, 'utf-8'); $data['productDesc'] = urlencode($data['productDesc']); } $signStr = $payInfo['quartet_app_id'] . 'WECHAT_SUB' . $data['money'] . $data['outTradeNo'] . $payInfo['quartet_app_key']; $data['sign'] = md5($signStr); $orderInfo = [ 'goods_id' => $goodsId, 'out_trade_no' => $out_trade_no, 'admin_id' => $adminId, 'user_id' => $userId, ]; try { $result = PalmPayService::instance()->payPalmApi($data, $payInfo, $goodsInfo, $orderInfo); } catch (Exception $e) { $this->success($e->getMessage()); } //分账记录日志 if (!empty($palmPayCmdDefault)) { $channel_palmpay_sub_account_id = $palmPayCmdDefault['channel_palmpay_sub_account_id']; $channel_amount = $palmPayCmdDefault['channel_amount']; $dz_palmpay_sub_account_id = $palmPayCmdDefault['dz_palmpay_sub_account_id']; $dz_amount = $palmPayCmdDefault['dz_amount']; PalmpaySplitAccountLog::create([ 'order_id' => $out_trade_no, 'dz_palmpay_sub_account_id' => $dz_palmpay_sub_account_id, 'dz_amount' => $dz_amount, 'channel_palmpay_sub_account_id' => $channel_palmpay_sub_account_id, 'channel_amount' => $channel_amount ])->insert(); } $result = $result['result']; $payInfoArr = json_decode($result['pay_info'], true); $prepay_id = explode('=', $payInfoArr['package'])[1]; $this->_createOrderInfo(ApiConstants::PAYMENT_METHOD_PALM, $adminId, $adminExtend, $goodsInfo, $goodsCategory, $result['pdorderid'], $out_trade_no, $goodsId, $payInfo, $channelId, $prepay_id, $groupId, $result['pay_info'], $kl_admin_info, $channelExtend ); $json = $result['pay_info']; } //下单订单数据统计 return ['json' => $json, 'out_trade_no' => $out_trade_no]; } public function payMihua() { list($goodsCategory, $goodsId, $adminId, $goodsInfo, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend) = $this->_initPayInfo(); $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15; $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port()); $userId = Cookie::get('user_id'); if ($pay_timeout) { $endTime = time() - intval($pay_timeout) * 60; $has_orders = model('orders') ->where([ 'money' => $goodsInfo['money'], 'goods_id' => $goodsId, 'user_id' => $userId, // 'admin_id' => $adminId, 'state' => '0', 'wxpay_id' => $payInfo['id'], 'payment_method' => ApiConstants::PAYMENT_METHOD_MIHUA ]) ->where(function (Query $query) use ($adminId) { $query->where('admin_id', $adminId) ->whereOr('resource_id', $adminId); }) ->where('createtime', '>', $endTime) ->find(); } else { $has_orders = null; } if (!empty($has_orders)) { //如果用户已经在该代理商/渠道商下过该单 $json = $has_orders['pay_json']; $out_trade_no = $has_orders['out_trade_no']; } else { $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [ 'day' => $goodsInfo['day'], 'activity_id' => $goodsInfo['activity_id'], 'user_id' => Cookie::get('user_id'), 'book_id' => $this->request->request('book_id'), ])->data; $paymentApplication = Factory::payment(Config::get('wechat')); $paymentApplication['cache'] = new RedisCache(Redis::instanceCache()); $out_trade_no = date('YmdHis') . '_' . $userId . '_' . Random::build('alnum', 4); $productName = $goodsInfo['type'] == 2 ? '充值VIP' : '充值书币'; $userId = Cookie::get('user_id'); // 用户ID $user = model('User')->getUserInfo($userId); $createtimeTs = empty($user) ? time() : $user['createtime']; $createtimeStr = date('YmdHis', $createtimeTs); $aRiskItem = [ 'userInfoMerchantNo' => $userId, 'userInfoDtRegister' => $createtimeStr, ]; $data = [ 'merAccount' => $payInfo['quartet_app_id'], 'merNo' => $payInfo['quartet_merchant_id'], 'orderId' => $out_trade_no, 'time' => time(), 'amount' => (int)($goodsInfo['money'] * 100), 'payWay' => 'WEIXIN', 'payType' => 'JSAPI_WEIXIN', 'userIp' => Ip::ip(), 'openId' => Cookie::get('openid'), 'returnUrl' => 'http://www.baidu.com',//前端页面回调地址 'notifyUrl' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/mihuapay', 'riskItem' => json_encode($aRiskItem), ]; $goods_des = Config::get('site.goodsdes'); if ($goods_des) { $data['productDesc'] = $productName . ' ' . $goods_des; } else { $data['productDesc'] = $productName; } if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) { if (empty($goods_des)) { $zfxx = $userId . '丨' . $adminConfig['json']['authorizer_info']['nick_name'] . '丨' . $productName; } else { $zfxx = $userId . '丨' . $adminConfig['json']['authorizer_info']['nick_name'] . '丨' . $productName . '丨' . $goods_des; } } else { if (empty($goods_des)) { $zfxx = $userId . '丨' . $productName; } else { $zfxx = $userId . '丨' . $productName . '丨' . $goods_des; } } $data['product'] = mb_substr($zfxx, 0, 120, 'utf-8'); $mihuaService = MihuaPayService::instance($payInfo['quartet_app_key'], $payInfo['quartet_app_public_key']); $data['sign'] = $mihuaService->getSign($data); Log::info('米花支付请求参数:' . json_encode($data)); $encode_data = $mihuaService->encrypt($data); $postData = array( 'merAccount' => $payInfo['quartet_app_id'],//商户标识 'data' => $encode_data ); $orderInfo = [ 'goods_id' => $goodsId, 'out_trade_no' => $out_trade_no, 'admin_id' => $adminId, 'user_id' => $userId, ]; try { $result = $mihuaService->payMihuaApi($postData, $data, $payInfo, $goodsInfo, $orderInfo); } catch (Exception $e) { $this->success($e->getMessage()); } $prepay_id = $result['data']['mbOrderId']; $this->_createOrderInfo(ApiConstants::PAYMENT_METHOD_MIHUA, $adminId, $adminExtend, $goodsInfo, $goodsCategory, 0, $out_trade_no, $goodsId, $payInfo, $channelId, $prepay_id, $groupId, $result['data']['payInfo'], $kl_admin_info, $channelExtend ); $json = $result['data']['payInfo']; } return ['json' => $json, 'out_trade_no' => $out_trade_no]; } public function payUns() { list($goodsCategory, $goodsId, $adminId, $goodsInfo, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend) = $this->_initPayInfo(); $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15; $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port()); $userId = Cookie::get('user_id'); if ($pay_timeout) { $endTime = time() - intval($pay_timeout) * 60; $has_orders = model('orders') ->where([ 'money' => $goodsInfo['money'], 'goods_id' => $goodsId, 'user_id' => $userId, // 'admin_id' => $adminId, 'state' => '0', 'wxpay_id' => $payInfo['id'], 'payment_method' => ApiConstants::PAYMENT_METHOD_UNS ]) ->where(function (Query $query) use ($adminId) { $query->where('admin_id', $adminId) ->whereOr('resource_id', $adminId); }) ->where('createtime', '>', $endTime) ->find(); } else { $has_orders = null; } if (!empty($has_orders)) { //如果用户已经在该代理商/渠道商下过该单 $json = $has_orders['pay_json']; $out_trade_no = $has_orders['out_trade_no']; } else { $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [ 'day' => $goodsInfo['day'], 'activity_id' => $goodsInfo['activity_id'], 'user_id' => Cookie::get('user_id'), 'book_id' => $this->request->request('book_id'), ])->data; $paymentApplication = Factory::payment(Config::get('wechat')); $paymentApplication['cache'] = new RedisCache(Redis::instanceCache()); $out_trade_no = date('YmdHis') . $userId . Random::build('alnum', 4); $productName = $goodsInfo['type'] == 2 ? '充值VIP' : '充值书币'; $data = [ 'accountId' => $payInfo['quartet_app_id'], 'orderId' => $out_trade_no, 'amount' => $goodsInfo['money'], 'responseUrl' => 'http://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/unspay', 'openId' => Cookie::get('openid'), 'version' => '1.0.1', ]; $goodsDes = Config::get('site.goodsdes'); if ($goodsDes) { $data['commodity'] = $productName . ' ' . $goodsDes; } else { $data['commodity'] = $productName; } if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) { if (empty($goods_des)) { $zfxx = $userId . '丨' . $adminConfig['json']['authorizer_info']['nick_name'] . '丨' . $productName; } else { $zfxx = $userId . '丨' . $adminConfig['json']['authorizer_info']['nick_name'] . '丨' . $productName . '丨' . $goods_des; } } else { if (empty($goods_des)) { $zfxx = $userId . '丨' . $productName; } else { $zfxx = $userId . '丨' . $productName . '丨' . $goods_des; } } $unsPayService = UnsPayService::instance($payInfo['quartet_app_key']); $data['subject'] = mb_substr($zfxx, 0, 120, 'utf-8'); $data['mac'] = $unsPayService->makeMacParams($data); $orderInfo = [ 'goods_id' => $goodsId, 'out_trade_no' => $out_trade_no, 'admin_id' => $adminId, 'user_id' => $userId, ]; try { $result = $unsPayService->payUnsApi($data, $payInfo, $goodsInfo, $orderInfo); } catch (Exception $e) { $this->success($e->getMessage()); } $strmPackage = $result['mPackage']; $amPackage = explode('=', $strmPackage); $prepayId = $amPackage[1]; $payJson = UnsPayService::makeJsJsonParam($result); $this->_createOrderInfo(ApiConstants::PAYMENT_METHOD_UNS, $adminId, $adminExtend, $goodsInfo, $goodsCategory, 0, $out_trade_no, $goodsId, $payInfo, $channelId, $prepayId, $groupId, $payJson, $kl_admin_info, $channelExtend ); $json = $payJson; } return ['json' => $json, 'out_trade_no' => $out_trade_no]; } public function payIpaynow() { list($goodsCategory, $goodsId, $adminId, $goodsInfo, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend) = $this->_initPayInfo(); $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15; $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port()); $userId = Cookie::get('user_id'); if ($pay_timeout) { $endTime = time() - intval($pay_timeout) * 60; $has_orders = model('orders') ->where([ 'money' => $goodsInfo['money'], 'goods_id' => $goodsId, 'user_id' => $userId, // 'admin_id' => $adminId, 'state' => '0', 'wxpay_id' => $payInfo['id'], 'payment_method' => ApiConstants::PAYMENT_METHOD_IPAYNOW ]) ->where(function (Query $query) use ($adminId) { $query->where('admin_id', $adminId) ->whereOr('resource_id', $adminId); }) ->where('createtime', '>', $endTime) ->find(); } else { $has_orders = null; } if (!empty($has_orders)) {//如果用户已经在该代理商/渠道商下过该单 $json = $has_orders['pay_json']; $out_trade_no = $has_orders['out_trade_no']; } else { $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [ 'day' => $goodsInfo['day'], 'activity_id' => $goodsInfo['activity_id'], 'user_id' => Cookie::get('user_id'), 'book_id' => $this->request->request('book_id'), ])->data; $paymentApplication = Factory::payment(Config::get('wechat')); $paymentApplication['cache'] = new RedisCache(Redis::instanceCache()); $out_trade_no = date('YmdHis') . '_' . $userId . '_' . Random::build('alnum', 4); $productName = $goodsInfo['type'] == 2 ? '充值VIP' : '充值书币'; $data = [ 'funcode' => 'WP001', 'version' => '1.0.0', 'appId' => $payInfo['quartet_app_id'], 'mhtOrderNo' => $out_trade_no, 'mhtOrderType' => '01', 'mhtCurrencyType' => '156', 'mhtOrderAmt' => $goodsInfo['money'] * 100, 'mhtOrderStartTime' => date('YmdHis'), 'notifyUrl' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/ipaynowpay', 'frontNotifyUrl' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/ipaynowpay', 'mhtCharset' => 'UTF-8', 'deviceType' => '0600', 'payChannelType' => '13', 'outputType' => '1', 'mhtSubAppId' => $payInfo['appid'], 'consumerId' => Cookie::get('openid'), 'mhtLimitPay' => '0', 'mhtSignType' => 'MD5', ]; $goodsDes = Config::get('site.goodsdes'); if ($goodsDes) { $data['mhtOrderDetail'] = $productName . ' ' . $goodsDes; } else { $data['mhtOrderDetail'] = $productName; } if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) { if (empty($goods_des)) { $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName; } else { $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName . '_' . $goods_des; } } else { if (empty($goods_des)) { $zfxx = $userId . '_' . $productName; } else { $zfxx = $userId . '_' . $productName . '_' . $goods_des; } } $data['mhtOrderName'] = mb_substr($zfxx, 0, 120, 'utf-8'); $privateKey = $payInfo['quartet_app_private_no']; $data['mhtSignature'] = IpaynowPayService::instance($privateKey)->makeSign($data); $orderInfo = [ 'goods_id' => $goodsId, 'out_trade_no' => $out_trade_no, 'admin_id' => $adminId, 'user_id' => $userId, ]; try { $result = IpaynowPayService::instance($payInfo['quartet_app_key'])->payIpaynowApi($data, $payInfo, $goodsInfo, $orderInfo); } catch (Exception $e) { $this->success($e->getMessage()); } $tnStr = urldecode($result['tn']); parse_str($tnStr, $aJson); $aJson['appId'] = $aJson['wxAppId']; $aJson['package'] = 'prepay_id=' . $aJson['prepay_id']; unset($aJson['wxAppId']); unset($aJson['prepay_id']); $json = json_encode($aJson); $this->_createOrderInfo(ApiConstants::PAYMENT_METHOD_IPAYNOW, $adminId, $adminExtend, $goodsInfo, $goodsCategory, 0, $out_trade_no, $goodsId, $payInfo, $channelId, '', $groupId, $json, $kl_admin_info, $channelExtend ); } return ['json' => $json, 'out_trade_no' => $out_trade_no]; } /** * 取消微信充值 */ public function wechatCancel() { try { $url = $this->request->request('url'); // 充值页的url $goodsId = $this->request->request('goods_id'); // 商品id $adminId = UserService::instance()->getAdminId()->data; $channelId = UserService::instance()->getUserInfo()->channel_id; //判断是否为代理商服务号 $groupids = Auth::instance()->getGroupIds($adminId); $groupid = current($groupids); if ($groupid == 4) { $row = model('Admin_extend')->where(['admin_id' => $adminId])->find(); if ($row['distribute'] == 1) { $channelId = $adminId; } if ($row['can_distribute'] == 1) { $config_row = model('AdminConfig')->where(['admin_id' => $adminId])->find(); } else { $config_row = model('AdminConfig')->where(['admin_id' => $row['create_by']])->find(); } } else { $config_row = model('AdminConfig')->where(['admin_id' => $adminId])->find(); } $userId = Cookie::get('user_id'); // 用户ID $user = model('User')->getUserInfo($userId); $goods = model('Goods')->getGoodsInfoById($goodsId); if ($goods && $user['is_subscribe'] == 1) { // 已关注 if ($goods['type'] == 1) { //书币充值 $msg = '亲,您的书币订单还未完成支付,现充值' . floatval($goods['money']) . '元可获' . ($goods['kandian'] + $goods['free_kandian']) . '书币,赶紧行动吧!'; } else { //vip充值 $msg = '亲,您的订单还未完成支付,现充值' . floatval($goods['money']) . '元,' . $goods['day'] . '天免费看,赶紧行动吧!'; } $url = del_url_params($url, 'code'); //文字 $ext_arr = [ 'mark' => BigData::BIG_DATA_CANCEL_RECHARGE, 'push_time' => time() ]; $url .= '&ext=' . urlencode(json_encode($ext_arr)); LogService::info('[ DOT] [URL] [ WNZI ]' . $url); $msg .= "\n\n" . '(立即充值)'; if (ActiveShareService::instance()->checkChannel($channelId)) { //转发分享赚书币 $msg .= "\n\n" . ActiveShareService::instance()->getPushReplyContent($channelId); } //防止消息队列重复入队 $redis = Redis::instance(); $payCancelKey = "O-C:{$userId}:{$goodsId}"; $status = $redis->exists($payCancelKey); if (!$status) { $activity = model("Activity")->get(100); //入消息队列 $data['user_id'] = $user['id']; $data['openid'] = $user['openid']; $data['goods_id'] = $goodsId; $data['channel_id'] = $channelId; //是否新充值用户且活动有效 if ($user['is_pay'] == 0 && $activity['status'] == 1) { //只发送一次图文消息 $ispay = $user['first_cancel_pay'] ?? UserConstants::USER_FIRST_CANCEL_NEVER; if ($ispay == 2) { //更新用户首冲标志位 // model('User')->setConnect($data['user_id']) // ->where('id', $data['user_id']) // ->update(['first_cancel_pay' => 1]); UserService::instance()->update(['first_cancel_pay' => UserConstants::USER_FIRST_CANCEL_START], ['id'=>$data['user_id']]); //图文消息 $activityinfo = model("ManageKey")->getOneByKey("firstpay"); $ext_arr = [ 'mark' => BigData::BIG_DATA_FIRST_RECHARGE, 'push_time' => time() ]; $msg2 = []; $msg2['title'] = $activityinfo['content']; $msg2['image'] = $activityinfo['image']; $msg2['url'] = getCurrentDomain($channelId, '/s/100?user_id=' . $user['id'] . '&ext=' . json_encode($ext_arr)); LogService::info('[ DOT] [URL] [ TW ]' . $msg2['url']); $msg2['description'] = '书币半价,仅限前100名'; $data['msg'] = $msg2; //添加定时客服消息任务(首冲9.9) if(!isset($config_row['block_ios_user_switch']) || (isset($config_row['block_ios_user_switch']) && $config_row['block_ios_user_switch'] == 0)){ if ($config_row['first_recharge_imgtext_post'] == 1) { $minites = $config_row['order_unrecharge_post_time']; MqUserPayCancelService::instance()->sendFirstCancel($data, $minites); } }else{ if(Ua::getOs() != 'iOS' && $config_row['first_recharge_imgtext_post'] == 1){ $minites = $config_row['order_unrecharge_post_time']; MqUserPayCancelService::instance()->sendFirstCancel($data, $minites); } } } } //redis标记设置 $expire = (intval(Config::get('site.user_cancel_pay_time')) * 60) + 60; //单位秒 $redis->setex($payCancelKey, $expire, 1); $data['msg'] = $msg; //添加定时客服消息任务(取消充值) if(!isset($config_row['block_ios_user_switch']) || (isset($config_row['block_ios_user_switch']) && $config_row['block_ios_user_switch'] == 0)){ MqUserPayCancelService::instance()->sendNormalCancel($data); }else{ if(Ua::getOs() != 'iOS'){ MqUserPayCancelService::instance()->sendNormalCancel($data); } } } } } catch (Exception $exception) { $this->error($exception->getMessage()); } } }