app_id = config('wxmp_config.app_id'); $this->secret = config('wxmp_config.secret'); } // 获取微信小程序支付订单参数 public function getWxmpPay($pay_type, $data){ if(empty($pay_type)){ return ['code' => 100, 'data' => [], 'msg' => '缺少必要参数:pay_type']; } if(empty($data['title'])){ return ['code' => 100, 'data' => [], 'msg' => '缺少必要参数:title']; } if(empty($data['order_id'])){ return ['code' => 100, 'data' => [], 'msg' => '缺少必要参数:order_id']; } if(empty($data['amount'])){ return ['code' => 100, 'data' => [], 'msg' => '缺少必要参数:amount']; } if(empty($data['open_id'])){ return ['code' => 100, 'data' => [], 'msg' => '缺少必要参数:open_id']; } $orderInfo = Cache::store('redis')->get($this->order_prefix.$data['order_id']); if(!$orderInfo){ return ['code' => 100, 'data' => [], 'msg' => '订单号有误,请重新支付!']; } // $data = [ // 'title' => 'xxx', // 'amount' => 'xxx', // 'game_id' => 'xxx', // 'is_coin' => 'xxx', // ]; $config = Config::get('ldys_pay'); $orderInfo = json_decode($orderInfo, true); $notify_url = $config['notify'][$pay_type]['notify_url']; if (!empty($orderInfo['is_coin']) && $orderInfo['is_coin'] == 1) { $notify_url = $config['notify'][$pay_type]['notify_coin_url']; } $params = [ "mer_id" => $config['mer_id'], "notify_url" => $notify_url, "amt_type" => "RMB", "goods_inf" => $data['title'], "order_id" => $data['order_id'], "mer_date" => date("Ymd"), "amount" => formatYuanToFen($data['amount']), // 分 "user_ip" => getUserIp(), "open_id" => $data['open_id'], "app_id" => $config['app_id'], "scancode_type" => "WECHAT", "mer_flag" => "KMER", ]; log_message('# '. $data['order_id'].' : ' . json_encode($params), 'log', LOG_PATH . 'three/ldys_pay/'); $service = new UmfService($config['mer_id']); $res = $service->miniProgramPayMap($params); /** * *
array(13) {
         * ["app_id"]=>
         * string(18) "wx117849d0c0632d22"
         * ["bank_seq"]=>
         * string(0) ""
         * ["mer_date"]=>
         * string(8) "20240425"
         * ["mer_id"]=>
         * string(5) "55282"
         * ["nonce_str"]=>
         * string(32) "7a9effbfe6324e089de9feb49c5f019f"
         * ["order_id"]=>
         * string(9) "633876442"
         * ["package"]=>
         * string(46) "prepay_id=wx25163615048261aa76cccf65807c9b0000"
         * ["pay_sign"]=>
         * string(344) "eHqSBYowy6LjbDYcHCcuh1GpY8K+mndcSU/WgWzmJlHWeUgefcix8yniZq4vVvgdODc2dZTwenPZa4hJhbp0Vw9x8uW6jb+GnlziJRZzj1mfer84UgoFh5iZy00mkBobe9VMdyZIFSbIhp41ICFpJulIFPqqrZ6T+kB4rw/kRkYNf7Px48w8XUWB2uGvLllUhjGQMdmnkULBO6x246GaXs2x6BFQbDxShOTX7KI48Whp6d4ZbJhLTSXUhN4N+6cKf7OH2jZNk/crBoQobQT4hhhUYnR44dIXimFsjLXCh+TQ5ZiNSw9xnj5Q7ER40ncl/5GSqectmtG4hCmrCv3xDg=="
         * ["ret_code"]=>
         * string(4) "0000"
         * ["ret_msg"]=>
         * string(12) "交易成功"
         * ["time_stamp"]=>
         * string(10) "1714034175"
         * ["trade_no"]=>
         * string(16) "3404251636078494"
         * ["weixin_sign_type"]=>
         * string(3) "RSA"
         * }
         */
        if ($res['ret_code'] == '00060780') {
            return ['code' => 110, 'data' => [], 'msg' => '订单已支付成功,无须再次支付'];
        }
        if ($res['ret_code'] != '0000') {
            // TODO: 钉钉通知
            return ['code' => 120, 'data' => [], 'msg' => $res['ret_msg']];
        }
        $res = [
            'timeStamp' => $res['time_stamp'],
            'nonceStr' => $res['nonce_str'],
            'package' => $res['package'],
            'signType' => $res['weixin_sign_type'],
            'paySign' => $res['pay_sign'],
        ];
        return ['code' => 200, 'data' => $res, 'msg' => 'success'];
    }

    // 生成微信下单URL
    public function generateWxmpPayUrl($order_id, $game_id){
        // return ['error' => false, 'data' => 'https://wxaurl.cn/qmyZ8gwAjKv', 'msg' => 'success'];

        try {
            $access_token = $this->getWxToekn();
            $env_version = 'release';
            // if(config('app_status') == 'dev'){
            //     $env_version = 'develop';
            // }
            $data = [
                'path' => '/pages/index/pay',
                'is_expire' => true,
                'query' => "order_id={$order_id}&game_id={$game_id}",
                'expire_type' => 0,
                'expire_time' => time() + 300,
                // 'expire_type' => 1,
                // 'expire_interval' => 1,
                'env_version' => $env_version, // 默认值"release"。要打开的小程序版本。正式版为 "release",体验版为"trial",开发版为"develop",仅在微信外打开时生效。
            ];
            $res = getHttpPost("https://api.weixin.qq.com/wxa/generate_urllink?access_token=" . $access_token, json_encode($data));
            $res = json_decode($res, true);
            if ($res['errcode'] !== 0 || empty($res['url_link'])) {
                return ['error' => true, 'data' => [], 'msg' => '001-1_LdysPay_生成微信URL失败'];
            }
        }catch (Exception $e) {
            // dump($e->getMessage(), $e->getFile(), $e->getLine());
            return ['error' => true, 'data' => [], 'msg' => '001-2_LdysPay_生成微信URL失败.Exception:' . $e->getMessage()];
        }

        return ['error' => false, 'data' => $res['url_link'], 'msg' => 'success'];
    }
    // 获取微信Token
    public function getWxToekn(){
        $cache_key = 'wx_token:'.$this->app_id;
        $token = Cache::get($cache_key);
        if(!$token){
            $res = getHttpGet("https://api.weixin.qq.com/cgi-bin/token", [
                'grant_type' => 'client_credential',
                'appid' => $this->app_id,
                'secret' => $this->secret
            ]);
            $res = json_decode($res, true);
            Cache::set($cache_key, $res['access_token'], $res['expires_in']-30);
            $token = $res['access_token'];
        }

        return $token;
    }


    // 记录订单
    public function recordOrder($order_id, $data){
        $payUrl = '';
        try {
            $urlResult = $this->generateWxmpPayUrl($order_id, $data['game_id']);
            if($urlResult['error'] == true){
                return ['error' => true, 'data' => [], 'msg' => "001_".$urlResult['msg']];
            }
            $payUrl = $urlResult['data'];
            Cache::store('redis')->set($this->order_prefix.$order_id, json_encode($data), 300);
        }catch (Exception $e) {
            return ['error' => true, 'data' => [], 'msg' => '002_LdysPay_下单失败:'.$e->getMessage()];
        }
        return ['error' => false, 'data' => ['pay_url' => $payUrl], 'msg' => 'success'];
    }
    // 查询订单
    public function queryOrder($order_id){
        try {
            $result = Cache::store('redis')->get($this->order_prefix.$order_id);
            if(!$result){
                return ['error' => true, 'data' => [], 'msg' => '当前订单已过期或不存在!'];
            }
        }catch (Exception $e) {
            return ['error' => true, 'data' => [], 'msg' => '查询失败!'];
        }
        return ['error' => false, 'data' => json_decode($result, true), 'msg' => 'success'];;
    }

    // 回调处理
    public function notify(){
        $data = request()->only([
            "amount", "amt_type", "bank_mer_id", "bank_trace", "charset", "error_code", "media_type", "mer_date", "mer_id", "open_id", "order_id", "pay_date", "pay_seq", "pay_success_time", "pay_type", "service", "settle_date", "trade_no", "trade_state", "version", "sign", "sign_type"
        ]);

        $notifyParamsStr = http_build_query($data);
        $config = Config::get('ldys_pay');

        $service = new UmfService($config['mer_id']);
        $array = $service->notifyDataParserMap($notifyParamsStr);
        $mer2UmfPlatStr = $service->responseUMFMap($array, $config['private_file']);
        $resultStr = '';

        if ($array === false) {
            return ['error' => true, 'data' => ['result' => '', 'data' => $resultStr], 'msg' => '回调效验失败!'];
        }
        return ['error' => false, 'data' => $resultStr, 'msg' => 'success'];
    }

    public function getWxH5Pay($pay_type, $data)
    {
        try {
            $config = Config::get('ldys_pay');
            $notify_url = $config['notify'][$pay_type]['notify_url'];
            if (!empty($data['is_coin']) && $data['is_coin'] == 1) {
                $notify_url = $config['notify'][$pay_type]['notify_coin_url'];
            }

            // 预下载
            $params = array(
                "mer_id" => $config['mer_id'],
                "notify_url" => $notify_url,
                "order_id" => $data['orderid'],
                "mer_date" => date("Ymd"),
                "amount" => formatYuanToFen($data['real_amount']), // 分
                "user_ip" => getUserIp(),
                "goods_inf" => $data['productname'],
                "pay_type" => 2, // 支付类型: 1=支付宝, 2=微信支付, 3=微信云闪付
                "page_order_type" => "H5",

                "mer_flag" => "KMER",
                "consumer_id" => $data['userid'], // 消费者ID
                "app_id" => $config['app_id'],
            );
            $service = new UmfService($config['mer_id']);
            $result = $service->appOrderMap($params);
            if ($result['ret_code'] == '0000') {
                return ['code' => 200, 'data' => ['pay_url' => $result['page_link']], 'msg' => 'success'];
            }
            // TODO: 钉钉通知
            return ['code' => 110, 'data' => [], 'msg' => $result['ret_msg']];
        } catch (Exception $e) {
            return ['code' => 120, 'data' => [], 'msg' => '下单失败: ' . $e->getMessage()];
        }
    }
}