| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462 |
- <?php
- /**
- * H5支付控制器 [为避免ios审查的敏感词,使用拼音命名控制器]
- *
- */
- namespace app\api\controller\v1;
- use app\api\controller\Api;
- use app\common\model\Game;
- use app\common\model\PayType;
- use app\common\model\Payrule;
- use app\common\model\Members;
- use app\common\model\ChannelFrozen;
- use app\common\model\Cpurl;
- use app\common\model\Pay as PayModel;
- use app\common\model\MemberCoin;
- use app\common\model\PayCpinfo;
- use app\common\model\MemberChannelGame;
- use app\common\logic\PayCallback;
- use app\common\logic\Pay as PayLogic;
- use app\common\library\WeixinPay;
- use app\common\model\App;
- use think\Db;
- use think\Config;
- use think\Cache;
- use think\Env;
- class HwuXiaofei extends Api {
-
- protected $nowTime;
- protected $payRequestLimit = 15; //重复下单的限制时间
- protected $redis; //redis的句柄对象
- protected $game_id;
- protected $username;
- protected $userid;
- protected $sub_username; //子账号名
-
- public function _initialize()
- {
-
- }
-
-
- private function _ini_config()
- {
- $token = $_REQUEST['token'];
-
- if (empty($token) || !Cache::store('default')->get($token)) {
- $this->error('请先登录!');
- }
- list($userid, $username, $gameid,$sub_username,$token_random) = explode('|', auth_code($token, "DECODE", Env::get('auth_key')));
-
- $redisTokenRandom = Cache::store('default')->get('token|sdk|'.$userid.'|'.$gameid);
-
- //redis中玩家登录安全控制的随机码不存在时
- if ( !$redisTokenRandom ) {
-
- Cache::store('default')->rm($token);
-
- $this->error('token随机码不存在,请重新登录');
- }
- //两个token随机码不同时
- elseif($redisTokenRandom!=$token_random){
-
- Cache::store('default')->rm($token);
-
- $this->error('token随机码错误,请重新登录');
- }
-
- $this->userid = $userid;
- $this->username = $username;
- $this->game_id = $gameid;
- $this->sub_username = $sub_username;
- $this->nowTime = NOW_TIMESTAMP;
- $this->redis = \think\Cache::store('default')->handler();
-
- }
- /**
- * 选择支付方式
- */
- public function index() {
-
- $this->_ini_config();
-
- $gameModel = new Game;
- $payRuleModel = new Payrule;
- $payTypeModel = new PayType;
- $sdkModel = model('common/AndroidSdk');
-
- $version = input('version'); //sdk版本号 [v3.0.2 参数]
-
- $data = input();
- $data['productname']= input('productname','','urldecode');
- $data['rolename'] = input('rolename','','urldecode');
- $data['serverid'] = input('serverid','','urldecode');
- $data['gameid'] = $this->game_id;
- $data['userid'] = $this->userid;
-
- $validResult = $this->validate($data, 'Pay.index');
-
- if (true !== $validResult) {
- $this->error($validResult);
- }
- elseif(!($gameInfo = $gameModel->field('id,android_sdk_id,name')->where(['id' => $this->game_id,'isdelete'=>0])->find())){
- $this->error('传入游戏参数错误');
- }
-
- //游戏禁止的支付方式
- $denyPayType = $payRuleModel->where("game_id=".$this->game_id)->column('deny_paytype');
-
- if(!empty($version)){
-
- $android_sdk_id = $sdkModel->where(['version'=>$version])->value('id');
-
- if(empty($android_sdk_id)){
-
- $this->error('sdk版本信息不存在');
- }
-
- $arrPayType = $payTypeModel->field('paytype,payname')->where('paytype',['not in',$denyPayType],['like','%h5%'])->where(['status'=>1,'used_sdk_id'=>['like','%,'.$android_sdk_id.',%']])->select();
- }
- else{
-
- $arrPayType = $payTypeModel->field('paytype,payname')->where('paytype',['not in',$denyPayType],['like','%h5%'])->where(['status'=>1,'used_sdk_id'=>['like','%,'.$gameInfo['android_sdk_id'].',%']])->select();
- }
-
-
- if(empty($arrPayType)){
-
- $this->error('该游戏的h5支付方式还未配置,请到后台配置');
- }
-
- $this->assign('arrPayType',$arrPayType);
-
- return $this->fetch();
- }
-
- /**
- * 支付处理
- */
- public function pay()
- {
- die();
- $this->_ini_config();
-
- $gameid = $this->game_id; //游戏ID
- $member_id = $this->userid; //用户ID
- $appid = input('appid'); //APPID
- $serverid = input('serverid'); //服务器ID
- $servername = input('servername'); //区服名称
- $amount = input('amount'); //充值金额
- $roleid = input('roleid'); //角色ID
- $attach = input('attach'); //上一级的扩展参数,多数是订单编号[麻花网络自己聚合自己时,会加个aoyou###前缀]
- $mc_id = input('mc_id',0); //平台币劵ID
- $pay_channel_id = input('channel_id',0); //当前SDK的渠道
- $imeil = input('imeil'); //手机imeil码
- $productname= input('productname'); //消费的商品名称
- $paytype = input('paytype'); //支付类型
- $rolename = input('rolename',''); //角色名
- $rolelevel = input('rolelevel',''); //角色角色等级
-
- $orderid = makeOrderid();
- $pay_status = 0; //cy_pay表的支付状态
- $cp_payflag = 0; //cy_paycpinfo表的支付状态
-
- $memberModel = new Members;
- $frozenModel = new ChannelFrozen;
- $cpurlModel = new Cpurl;
- $gameModel = new Game;
- $payModel = new PayModel;
- $coinModel = new MemberCoin;
- $payCpinfoModel = new PayCpinfo;
- $memberChannelGameModel = new MemberChannelGame;
- $appModel = new App;
- $payLogic = new PayLogic();
-
-
- $checkResult = $this->validate(['gameid' =>$gameid,
- 'userid' =>$member_id,
- 'appid' =>$appid,
- 'serverid' =>$serverid,
- 'servername' =>$servername,
- 'amount' =>$amount,
- 'roleid' =>$roleid,
- 'attach' =>$attach,
- 'mc_id' =>$mc_id,
- 'channel_id' =>$pay_channel_id,
- 'productname' =>$productname,
- 'paytype' =>$paytype,
- 'imeil' =>$imeil
- ], 'Pay.add');
-
- if (true !== $checkResult) {
- $this->error($checkResult);
- }
-
- if (empty($mc_id) && (substr($paytype,0,4)=='mix-' || $paytype=='ptb')) {
- $this->error('请选择平台币使用劵');
- }
-
- //玩家在这款游戏的归属渠道
- $channel_id = $memberChannelGameModel->where(['member_id'=>$member_id,'game_id'=>$gameid])->value('channel_id');
-
- if (empty($channel_id)) {
- $this->error('无关联的归属渠道信息');
- }
-
- //当前游戏的渠道是否禁止消费(非归属渠道)
- if (isFrozenOption($pay_channel_id,$gameid,'consume')) {
-
- $this->error('您所在渠道已经被禁止在此游戏消费');
- }
-
- //充值回调地址
- $cpurl = $cpurlModel->where(['appid'=>$appid])->value('url');
-
- if(empty($cpurl)){
- $this->error('没有回调地址,请通知我方配置');
- }
-
- $appInfo = $appModel->field('id,appkey,client_appkey,gameid')->where(['id'=>$appid])->find();
-
- if(empty($appInfo)){
- $this->error('密钥信息不存在');
- }
-
- //游戏信息
- $gameInfo = $gameModel->field('order_recheck')->where(['id' => $gameid])->find();
-
- if(empty($gameInfo)){
- $this->error('游戏id参数错误');
- }
-
- //有使用平台币劵时
- if(!empty($mc_id)){
- $coinInfo = $coinModel->field('mc_id,coin_sn,mc_coin_residue,history_id,mc_coin_amount,mc_coin_number')
- ->where(['mc_id'=>$mc_id,'mc_userid'=>$member_id,'mc_gameid'=>$gameid,'mc_coin_residue'=>['>',0]])
- ->where('(mc_expire_time=0 or mc_expire_time>'.$this->nowTime.')')
- ->find();
-
- if(empty($coinInfo)){
- $this->error('有效的平台币劵不存在');
- }
-
- $arrPayAmount = $payLogic->calPayAmount($amount,$coinInfo['mc_coin_residue'],($coinInfo['mc_coin_amount']/$coinInfo['mc_coin_number']));
- }
- else{
- $arrPayAmount = $payLogic->calPayAmount($amount);
- }
-
- //实际支付金额为0时
- if (!($arrPayAmount['real_amount']>0)) {
-
- $paytype = 'ptb'; //全部用平台币支付
- $pay_status = 1; //支付成功
- $cp_payflag = 1;
-
- //付款时间
- $payData['pay_time'] = $this->nowTime;
- }
- //有实际支付金额并且支付方式是平台币时
- elseif($arrPayAmount['real_amount']>0 && $paytype=='ptb'){
-
- $this->error('平台币劵金额不足,请使用混合支付');
- }
-
- //指定时间内,禁止重复下单
- if(!requestDuplicateCheck('pay_duplicate_'.$member_id.'_'.$gameid,$this->payRequestLimit)){
-
- $this->error('充值请求过多,请于'.$this->payRequestLimit.'s以后,再次进行充值操作');
- }
-
-
- if($payModel->where(['attach'=>$attach,'gameid'=>$gameid])->find()){
-
- $this->redis->del('pay_duplicate_'.$member_id.'_'.$gameid);
-
- $this->error('游戏合作方的订单参数不能重复');
- }
-
- $payData['orderid'] = $orderid;
- $payData['use_coin_sn'] = !empty($mc_id) ? $coinInfo['coin_sn'] : ''; //平台币劵订单号
- $payData['amount'] = $amount;
- $payData['real_amount'] = $arrPayAmount['real_amount'];
- $payData['real_ptb'] = $arrPayAmount['real_ptb'];
- $payData['real_ptb_amount'] = $arrPayAmount['real_ptb_amount'];
- $payData['userid'] = $member_id;
- $payData['username'] = $this->username;
- $payData['roleid'] = $roleid;
- $payData['rolename'] = $rolename;
- $payData['rolelevel'] = $rolelevel;
- $payData['paytype'] = $paytype;
- $payData['productname'] = $productname;
- $payData['serverid'] = $serverid;
- $payData['gameid'] = $gameid;
- $payData['status'] = $pay_status;
- $payData['ip'] = request()->ip();
- $payData['imeil'] = $imeil;
- $payData['create_time'] = $this->nowTime;
- $payData['channel_id'] = $channel_id;
- $payData['recheck_status'] = $gameInfo['order_recheck'];
- $payData['attach'] = $attach;
-
- // 启动事务
- Db::startTrans();
-
- try{
- $result = ''; //返回值
-
- $payModel->insert($payData);
-
- //如果是自己聚合自己时,支付回调地址固定
- if(mb_substr($attach,0,8,'UTF-8')=='xkhyn###'){
-
- $cpurl = Config::get('self_complex_callback_url');
-
- $attach = str_replace("xkhyn###","",$attach); //聚合的订单编号,去掉[aoyou###]前缀
- }
-
- //给Cp的用户名用子账号名
- $paycp_username = (!empty($this->sub_username) ? $this->sub_username : $this->username);
-
- $str = "orderid=".urlencode($orderid)."&username=".urlencode($paycp_username)."&gameid=".$gameid."&roleid=".urlencode($roleid)."&serverid=".urlencode($serverid)."&paytype=".urlencode($paytype)."&amount=".$amount."&paytime=".$this->nowTime."&attach=".urlencode($attach);
- $param = $str."&appkey=".urlencode($appInfo['appkey']);
- $md5params = md5($param);
- $params = $str . "&sign=".urlencode($md5params);
-
-
- $paycpData['orderid'] = $orderid;
- $paycpData['fcallbackurl'] = $cpurl;
- $paycpData['params'] = $params;
- $paycpData['create_time'] = $this->nowTime;
- $paycpData['payflag'] = $cp_payflag;
-
- //写入cy_paycpinfo表数据
- $payCpinfoModel->insert($paycpData);
-
- //如果使用了平台币
- if($arrPayAmount['real_ptb']>0){
- $payLogic->saveCoinData($coinInfo,$payData);
- }
-
- //第三方支付用的商品简单描述 (去除&+等特殊字符)
- $payBody = preg_replace("/[\&\+]+/", '', $productname);
-
- //全部平台币支付,并且支付成功时
- if($pay_status){
-
- //更新member表的total_pay_amount
- $memberModel->where(['id'=>$member_id])->update(['total_pay_amount'=>Db::raw('total_pay_amount+'.$amount)]);
- }
-
- $this->redis->del('pay_duplicate_'.$member_id.'_'.$gameid);
-
- // 提交事务
- Db::commit();
-
- } catch (\Exception $e) {
- // 回滚事务
- Db::rollback();
-
- $this->error('订单生成失败'.$e->getMessage());
- }
-
- //全部平台币支付,并且支付成功时
- if($pay_status){
-
- // 通知CP,支付成功
- (new PayCallback())->callBackToCp($orderid);
- $payLogic->payWarning($member_id, $channel_id, $gameid, $amount);
- }
-
-
- //支付方式是支付宝或者支付宝混合支付时
- if($paytype=='zfb' || $paytype=='mix-zfb'){
- //支付宝支付参数
- $alipayParam = $this->getAlipayParam($orderid,$arrPayAmount['real_amount'],$payBody);
-
- $result = ['alipay_param'=>$alipayParam];
- }
- //支付方式是微信官方h5支付或者微信官方h5混合支付时
- elseif($paytype=='wxpay-h5' || $paytype=='mix-wxpay-h5')
- {
- $wxpayh5_param = $this->getWxpayH5Param($orderid,$arrPayAmount['real_amount'],$payBody);
-
- if(is_array($wxpayh5_param)){
-
- $this->redirect($wxpayh5_param['mweb_url'].'&redirect_url='.url('weixinFinish'));
- }
- else{
- $this->error($wxpayh5_param);
- }
- }
- //更新游戏区服信息
- $this->saveGameServer($member_id,$gameid,$imeil,'pay');
- }
-
- /**
- * 微信官方h5支付
- *
- * @param string $orderid 订单号
- * @param float $real_amount 支付金额
- * @param string $body 商品名称
- *
- * @return array 支付参数数组
- */
- private function getWxpayH5Param($orderid,$real_amount,$body)
- {
- $pay_return = false;
-
- $wxPay = new WeixinPay;
-
- $params['appid'] = Config::get('wxpay-h5')['appid'];
- $params['mch_id'] = Config::get('wxpay-h5')['mch_id'];
- $params['nonce_str'] = random(10);
- $params['body'] = $body;
- $params['out_trade_no'] = $orderid;
- $params['total_fee'] = $real_amount*100; // 支付金额,以分为单位
- $params['spbill_create_ip'] = $this->request->ip();
- $params['notify_url'] = Config::get('wxpay-h5')['notify_url'];
- $params['trade_type'] = 'MWEB';
- $params['scene_info'] = '{"h5_info":{"type":"Wap","wap_url":"http://m.weilongwl.com","wap_name":"麻花网络游戏"}}';
- //获取签名数据
- $params['sign'] = $wxPay->MakeSign($params,Config::get('wxpay-h5')['key']);
-
-
- $xml = dataToXml($params);
- $response = $wxPay->postXmlCurl($xml);
- if (!$response) {
- return '微信支付请求失败';
- }
-
- $result = $wxPay->xmlToArray($response);
-
- if( array_key_exists("return_code", $result) && $result["return_code"] == "SUCCESS" && array_key_exists("result_code", $result) && $result["result_code"] == "SUCCESS")
- {
- $pay_return['prepay_id'] = $result['prepay_id'];
- $pay_return['trade_type'] = $result['trade_type'];
- $pay_return['mweb_url'] = $result['mweb_url'];
- $pay_return['referer'] = Config::get('wxpay-h5')['referer'];
- }
- else{
- return ' 错误代码:'.$result["err_code"].' 错误代码描述:'.$result["err_code_des"];
- }
-
- return $pay_return;
- }
-
- /**
- * 微信支付完成后的跳转页
- *
- */
- public function weixinFinish()
- {
-
- return $this->fetch('weixin_finish');
- }
- }
|