<?php

namespace App\Http\Controllers\WeChatApplet\User;

use App\Services\ReceivablePay\ReceivablePayService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use DB;
use App\Services\LoginUserService;
use App\Http\Models\Services\Order;
use WeChatPay\Builder;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Util\PemUtil;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use WechatPay\GuzzleMiddleware\WechatPayMiddleware;
use GuzzleHttp\HandlerStack;
use App\Services\Business\WashPayservice;
use App\Http\Models\Api\Common;
use App\Services\Point\PointService;
use App\Services\Business\WashOrderBasicService;
use App\Http\Models\Api\CashierDesk;

class PayController extends Controller
{
    protected $appid = 'wx3d5338c9dbe01eaf';//小程序appid
    protected $appsecret = '23d512f5ebc9c1f3cf1b6f23a91ce77d';//小程序秘钥
    protected $mch_id = '1619735999'; //商户号
    // protected $mch_key = 'ebbe8a54fb239e80da5982dde4aec28c'; //商户号秘钥
	
	public function transactionsJsapi(Request $request)
    {
        $log_record['request'] = $request->all();
        $log_record['time'] = date('Y-m-d H:i:s');
        $log_record['function'] = 'transactionsJsapi';
        logFileRecord($log_record, 'wash/pay', 2);

        // 新增预约单
        request()->offsetSet('ip', getRealIp($request));
        $return_data = WashPayservice::transactionsjsapi($request->all());
        $return_data = json_decode($return_data);
        // 查询
        if (isset($return_data->prepay_id)) {
        	$res = WashPayservice::_PayJson(config('apisystem.XCX_APPID'), $return_data->prepay_id);
        	$paySign = json_decode($res);
        	$find_order = DB::table('order as o')
        		->leftjoin('order_client as orcl', 'orcl.orcl_ord_id', '=', 'o.ord_id')
        		->leftjoin('order_goods as orgo', 'orgo.orgo_ord_id', '=', 'o.ord_id')
        		->where('ord_id', $request['ord_id'])
        		->select('ord_shop_id', 'orcl_client_id', 'ord_type', 'ord_order_number', 'orgo_goo_name', 'ord_order_price')
        		->first();
            if ($find_order->ord_shop_id) {
                $shop_data = DB::table('shop')
                    ->where('shop_id', $find_order->ord_shop_id)
                    ->select('shop_id', 'shop_machid')
                    ->first();
                if ($shop_data->shop_machid) {
                    $XCX_MCHID = $shop_data->shop_machid;
                } else {
                    $XCX_MCHID = config('apisystem.XCX_MCHID');
                }
            }
            // 新增在线支付记录
            $were_add_data['were_shop_id'] = $find_order->ord_shop_id; //所属门店id
            $were_add_data['were_client_id'] = $find_order->orcl_client_id; //客户单位id，会员id
            $were_add_data['were_type'] = $find_order->ord_type; //类型：1个人会员
            $were_add_data['out_trade_no'] = $find_order->ord_order_number; //商户订单号
            $were_add_data['were_sp_appid'] = config('apisystem.COMBINE_APPID'); //服务商appid
            $were_add_data['were_sp_mchid'] = config('apisystem.MCHID'); //服务商    mch_id
            $were_add_data['were_sub_appid'] = config('apisystem.XCX_APPID'); //二级商户appid
            $were_add_data['were_sub_mchid'] = $XCX_MCHID; //二级商户    mch_id
            // $were_add_data['were_sub_mchid'] = config('apisystem.XCX_MCHID'); //二级商户    mch_id
            $were_add_data['were_description'] = '半径服务-'.$find_order->orgo_goo_name; //商品描述
            $were_add_data['were_openid'] = $request['weus_openid']; //用户标识,用户在直连商户appid下的唯一标识
            $were_add_data['were_pay_total_money'] = $find_order->ord_order_price; //支付总金额(单位分)
            $were_add_data['were_pay_way'] = 1; //在线支付方式1微信小程序支付
            $were_add_data['were_pay_type'] = 1; //在线支付类型1付款2退款
            $were_add_data['were_pre_id'] = $return_data->prepay_id; //在线支付类型1付款2退款
            $were_add_data['were_create_time'] = date('Y-m-d H:i:s');

            $were_add_data_res = DB::table('weixin_record')->insert($were_add_data);
            return response()->json(['code'=>200, 'msg'=>'支付成功', 'data'=>$paySign, 'ord_order_price'=>$find_order->ord_order_price]);
        } else {
            return response()->json(['code'=>500, 'msg'=>$return_data->message, 'data'=>'']);
        }
    }

    // 其他系统下单
    public function otherTransactionsJsapi(Request $request)
    {
        $get_ip = getRealIp($request); //获取ip
        // 接收数据流
        $request = file_get_contents("php://input");

        // 解析
        Common::write_log($request, 1, 'otherTransactionsJsapi');
        $request = json_decode($request, true);
        // 新增预约单
        $return_data = WashPayservice::otherTransactionsJsapi($request);
        $return_data = json_decode($return_data);
        // 查询
        if (isset($return_data->prepay_id)) {
            $res = WashPayservice::_PayJson($request['XCX_APPID'], $return_data->prepay_id);
            $find_otor_data = DB::table('other_order')
                ->where('otor_ord_number', $request['ord_order_number'])
                ->value('otor_id');
            if ($find_otor_data) {
                $update_otor_data['otor_pre_id'] = $return_data->prepay_id;
                $update_otor_data['otor_source'] = $request['otor_source'];
                $update_otor_data['otor_weus_openid'] = $request['weus_openid'];
                $update_otor_data['otor_xcx_appid'] = $request['XCX_APPID'];
                $update_otor_data['otor_xcx_name'] = $request['XCX_Name'];
                $update_otor_data['otor_goo_name'] = $request['orgo_goo_name'];
                $update_otor_data['otor_price'] = $request['ord_order_price'];
                $update_otor_data['otor_sub_mchid'] = $request['XCX_MCHID'];
                $update_otor_data['otor_pay_state'] = 1;
                $update_otor_res = DB::table('other_order')
                    ->where('otor_id', $find_otor_data)
                    ->update($update_otor_data);
            } else {
                $add_otor_data['otor_ord_number'] = $request['ord_order_number'];
                $add_otor_data['otor_pre_id'] = $return_data->prepay_id;
                $add_otor_data['otor_source'] = $request['otor_source'];
                $add_otor_data['otor_weus_openid'] = $request['weus_openid'];
                $add_otor_data['otor_xcx_appid'] = $request['XCX_APPID'];
                $add_otor_data['otor_xcx_name'] = $request['XCX_Name'];
                $add_otor_data['otor_goo_name'] = $request['orgo_goo_name'];
                $add_otor_data['otor_price'] = $request['ord_order_price'];
                $add_otor_data['otor_sub_mchid'] = $request['XCX_MCHID'];
                $add_otor_data['otor_pay_state'] = 1;
                $add_otor_data['otor_create_time'] = date('Y-m-d H:i:s');
                $add_res = DB::table('other_order')->insertGetId($add_otor_data);
            }
            $paySign = json_decode($res);
            return response()->json(['code'=>200, 'msg'=>'支付成功', 'data'=>$paySign, 'prepay_id'=>$return_data->prepay_id]);
        } else {
            return response()->json(['code'=>500, 'msg'=>'支付失败！', 'data'=>$return_data->message]);
        }
    }

    // 申请退款-其他小程序
    public function otherApplyRefund(Request $request)
    {
        $get_ip = getRealIp($request); //获取ip
        // 接收数据流
        $request = file_get_contents("php://input");

        // 解析
        Common::write_log($request, 1, 'otherApplyRefund');
        $request = json_decode($request, true);
        $request['notify_url'] = config('apisystem.server_name_https').'/index.php/api/u1/Pay/otherNotifyRefund';
        // 新增预约单
        $return_data = WashPayservice::applyRefund($request['sub_mchid'],$request['out_refund_no'],$request['transaction_id'],$request['out_trade_no'],$request['refund_fee'],$request['total_fee'],$request['notify_url'],$request['reason'],$request['sign']);
        $return_datas = json_decode($return_data,true);
        // 查询
        if (isset($return_datas["refund_id"])) {
            return response()->json(['code'=>200, 'msg'=>'退款成功', 'data'=>$return_data]);
        } else {
            return response()->json(['code'=>500, 'msg'=>'退款失败', 'data'=>$return_data]);
        }
    }

    /**
     * 支付成功回调
     * @param string jsonData 微信支付返回的数据 json字符串
     * @param array headers 头部信息
     */
    public function notifyPay(Request $request)
    {
        //然后对回报结果部分数据进行解密
        $resourceData = WashPayservice::decryptToString($request['resource']['associated_data'], $request['resource']['nonce'], $request['resource']['ciphertext']);
        // 解析
        // $resourceData = file_get_contents("php://input");
        Common::write_log($request, 1, 'notifyPay');
        $resourceData = json_decode($resourceData, true);
        Common::write_log($resourceData, 1, 'notifyPay');
        if ($resourceData['trade_state'] == 'SUCCESS') {
            DB::beginTransaction();
            $find_order = DB::table('order')
                ->leftjoin('order_client', 'ord_id', '=', 'orcl_ord_id')
                ->where('ord_order_number', $resourceData['out_trade_no'])
                ->first();

            // 修改支付信息
            $update_data1['were_pay_state'] = 2;//支付结果1未支付2已支付
            $update_data1['were_transaction_id'] = $resourceData['transaction_id'];//微信支付订单号
            $update_data1['were_update_time'] = date('Y-m-d H:i:s');//支付结果1未支付2已支付
            $update_res1 = DB::table('weixin_record')
            	->where('out_trade_no', $resourceData['out_trade_no'])
            	->update($update_data1);
            if ($find_order->ord_add_type == 1) {
                // 修改已售数量
                $pait_data = DB::table('order as o')
                    ->leftjoin('order_goods as orgo', 'orgo.orgo_ord_id', '=', 'o.ord_id')
                    ->leftjoin('package_items as pait', 'pait.pait_id', '=', 'orgo.orgo_goo_id')
                    ->where('ord_order_number', $resourceData['out_trade_no'])
                    ->where('orgo_goo_type', 3)
                    ->select('pait_id', 'pait_sell_number', 'pait_saleable_quantity', 'ord_type', 'pait_name')
                    ->first();
                if ($pait_data) {
                    $update_pait_data['pait_sell_number'] = $pait_data->pait_sell_number + 1;
                    $update_pait_data['pait_saleable_quantity'] = $pait_data->pait_saleable_quantity - 1;
                    if ($pait_data->pait_saleable_quantity - 1 == 0) {
                        $update_pait_data['pait_state'] = 2;//1上架2下架
                    }
                    $update_pait_data['pait_update_time'] = date('Y-m-d H:i:s');
                    $update_pait = DB::table('package_items')
                        ->where('pait_id', $pait_data->pait_id)
                        ->update($update_pait_data);
                } else {
                    $update_pait = true;
                }
                $adm_data = DB::table('admin_shop_role')
                    ->where('shop_id', $find_order->ord_shop_id)
                    ->where('adm_shop_leave', 1)
                    ->select('adm_id')
                    ->first();
                if ($adm_data) {
                    // 微信消息推送
                    $wechat_msg['pushtype'] = 7; //订单提醒
                    $wechat_msg['ord_id'] = $find_order->ord_id; //订单id
                    $wechat_msg['adm_id'] = $adm_data->adm_id; //推送人
                    $wechat_msg['ord_number'] = $find_order->ord_order_number; //订单号
                    $wechat_msg['sepr_name'] = $pait_data ? $pait_data->pait_name : ''; //服务项目
                    $wechat_msg['orcl_appoint_time'] = $find_order->orcl_appoint_time; //预约时间
                    $wechat_msg['orcl_phone'] = $find_order->orcl_phone; //客户电话
                    $wechat_msg['orcl_name'] = $find_order->orcl_name; //客户电话
                    $wechat_msg['ord_create_time'] = date('Y-m-d H:i:s'); //订单创建时间

                    $CashierDesk = new CashierDesk;
                    $wechat_msg_res = $CashierDesk->inforPush($wechat_msg);
                }
            } elseif ($find_order->ord_add_type == 3) {//积分兑换
                $find_order_goods = DB::table('order_goods')
                    ->leftjoin('point_gift_goods', 'pogg_id', '=', 'orgo_pogg_id')
                    ->where('orgo_ord_id', $find_order->ord_id)
                    ->first();
                
                if ($find_order_goods->pogg_id && $find_order_goods->pogg_goo_limitation == 1) {
                    if ($find_order_goods->pogg_goo_num - 1 == 0) {
                        $update_pogg['pogg_state'] = 2;//1上架2下架
                    }
                    $update_pogg['pogg_goo_num'] = $find_order_goods->pogg_goo_num - 1;
                    $update_pait = DB::table('point_gift_goods')
                        ->where('pogg_id', $find_order_goods->pogg_id)
                        ->update($update_pogg);
                } else {
                    $update_pait = true;
                }
                
                // 扣除积分+扣除积分记录+兑换记录
                $add_point['pode_shop_id'] = $find_order->ord_shop_id;
                $add_point['pode_mem_id'] = $find_order->ord_client_id;
                $add_point['pode_type'] = 3;
                $add_point['pode_name'] = '兑换'.$find_order_goods->orgo_goo_name;
                $add_point['pode_points'] = -$find_order_goods->pogg_goo_point;
                $add_point['pode_year_month'] = date('Y-m');
                $add_point['pode_create_time'] = date('Y-m-d H:i:s');
                $add_point['pode_create_id'] = 0;
                $add_point['pode_soure'] = 2;
                $add_point['pode_add_type'] = 15;//兑换商品
                $add_point['pode_ord_id'] = $find_order->ord_id;
                $add_point['pode_state'] = 1;
                $add_shord_point_res = PointService::addPointDetail($add_point);

                $add_goo_log['pglo_shop_id'] = $find_order->ord_shop_id;
                $add_goo_log['pglo_mem_id'] = $find_order->ord_client_id;
                $add_goo_log['pglo_ord_id'] = $find_order->ord_id;
                $add_goo_log['pglo_pogg_id'] = $find_order_goods->orgo_pogg_id;
                $add_goo_log['pglo_time'] = date('Y-m-d');
                $add_goo_log['pglo_create_time'] = date('Y-m-d H:i:s');
                $add_goo_log_res = DB::table('point_goods_log')->insertGetId($add_goo_log);
            }
            //修改订单信息
            if ($find_order->ord_service_type == 4) {
                $update_data['ord_customer_state'] = 1;
            }
            $update_data['ord_state'] = 2;
            $update_data['ord_pay_state'] = 1;
            $update_data['ord_actual_price'] = $find_order->ord_order_price;
            $update_data['ord_update_time'] = date('Y-m-d H:i:s');
            $update_data['ord_settlement_time'] = date('Y-m-d H:i:s');
            $update_res = DB::table('order')
                ->where('ord_order_number', $resourceData['out_trade_no'])
                ->update($update_data);
            if ($find_order) {
                if ($find_order->ord_service_type == 4) {//会员卡订单添加会员会员卡
                    $user_info = DB::table('weixin_user')
                        ->leftjoin('user_shop', 'weus_id', '=', 'ussh_weus_id')
                        ->where('ussh_shop_id', $find_order->ord_shop_id)
                        ->where('ussh_user_id', $find_order->ord_client_id)
                        ->first();
                    $user_info->adm_shop_id = $find_order->ord_shop_id;
                    $user_info->adm_id = 0;
                    $user_info->adm_cid = 0;
                    $add_point = WashOrderBasicService::addPoint($user_info,$find_order->ord_client_id,$find_order->ord_id);
                    $find_orgo_data = DB::table('order_goods')
                        ->where('orgo_ord_id', $find_order->ord_id)
                        ->first();
                    if ($find_orgo_data) {
                        $find_vica_data = DB::table('vip_card')
                            ->where('vica_name', $find_orgo_data->orgo_goo_name)
                            ->first();
                        if ($find_vica_data) {
                            $myvi_num = 'HYK'.time().rand(10000,99999);
                            $data['myvi_num'] = $myvi_num;//会员卡编号
                            $data['myvi_create_adm_id'] = $find_order->ord_create_id;
                            $data['myvi_shop_id'] = $find_order->ord_shop_id;
                            $data['myvi_adm_id'] = $find_order->orcl_client_id;
                            $data['myvi_surplus_times'] = $find_vica_data->vica_num; //剩余次数
                            $data['myvi_all_times'] = $find_vica_data->vica_num; //总次数
                            $data['myvi_long_term'] = $find_vica_data->vica_long_term; //是否长期1是2否
                            $data['myvi_carnum'] = $find_order->orcl_car_num; //绑定车牌
                            // $data['myvi_sepr_id'] = $find_vica_data->vica_sepr_id; //服务项目id
                            // $data['myvi_sepr_name'] = $find_vica_data->vica_sepr_name; //服务项目名称
                            $data['myvi_name'] = $find_vica_data->vica_name; //会员卡名称
                            $data['myvi_explain'] = $find_vica_data->vica_instructions; //会员卡使用说明
                            $data['myvi_vica_id'] = $find_vica_data->vica_id; //会员卡id
                            $data['myvi_create_time'] = date('Y-m-d H:i:s');
                            if ($find_vica_data->vica_long_term == 2) {//是否长期1是2否
                                $data['myvi_effective_date'] = $find_vica_data->vica_effective_date; //有效天数
                                $data['myvi_end_time'] = date('Y-m-d', strtotime(date('Y-m-d').'23:59:59') + ($find_vica_data->vica_effective_date)*60*60*24).' 23:59:59';
                            } else {
                                $data['myvi_end_time'] = date('Y-m-d', time() + 99999*60*60*24);
                            }
                            $myvi_id = DB::table('myvip')->insertGetId($data);
                            $find_detail = DB::table('vip_card_detail')
                                ->where('vicad_vcid', $find_vica_data->vica_id)
                                ->get()->toArray();
                            foreach ($find_detail as $key => $value) {
                                $add_detail['myvid_mvid'] = $myvi_id;
                                $add_detail['myvid_surplus_times'] = $value->vicad_num;
                                $add_detail['myvid_all_times'] = $value->vicad_num;
                                $add_detail['myvid_data_id'] = $value->vicad_data_id;
                                $add_detail['myvid_data_name'] = $value->vicad_data_name;
                                $add_detail['myvid_type'] = $value->vicad_type;
                                $add_detail['myvid_goo_price'] = $value->vicad_goo_price;
                                $add_detail_res = DB::table('myvip_detail')->insert($add_detail);
                            }
                        } else {
                            $myvi_id = true;
                        }
                    } else {
                        $myvi_id = true;
                    }
                } else {
                    $myvi_id = true;
                }
                if($find_order->ord_service_type == 7){//黑钻会员升级
                    $level_data = DB::table('member_level')
                        ->where('meml_shop_id', $find_order->ord_shop_id)
                        ->where('meml_level', 5)
                        ->first();
                    $mem_level =  DB::table('member')
                        ->where('mem_id', $find_order->ord_client_id)
                        ->first();
                    $mem_use_end_time = $mem_level->mem_level_end_time;
                    if($level_data->meml_forever == 1){//有效时间：1永久有效2月
                        $end_length = '永久有效';
                    }else if($level_data->meml_forever == 2){
                        $end_time = $level_data->meml_effect_length.' month';
                        $end_length = $level_data->meml_effect_length.'个月';
                    }
                    if($mem_level->mem_level_start_time == '0000-00-00 00:00:00'){
                        $level_update['mem_level_start_time'] =  date('Y-m-d H:i:s');
                    }
                    if($end_length){
                        $level_update['mem_level_length'] = $end_length;
                    }
                    if($mem_level->mem_level_end_time == '0000-00-00 00:00:00'){
                        if(isset($end_time)){
                            $level_update['mem_level_end_time'] = date('Y-m-d 23:59:59',strtotime('+'.$end_time, time()));;
                        }
                    }else{
                        if(isset($end_time)){
                            $mem_level_end_time = date('Y-m-d H:i:s',strtotime('+'.$end_time, strtotime($mem_level->mem_level_end_time)));
                            $level_update['mem_level_end_time'] = $mem_level_end_time;
                        }else{
                            $level_update['mem_level_end_time'] = '0000-00-00 23:59:59';
                        }
                    }
                    if(isset($level_update['mem_level_end_time'])){
                        $mem_use_end_time = $level_update['mem_level_end_time'];
                    }
                    if(isset($end_length) && $end_length =='永久有效' ){
                        $mem_use_end_time = '永久有效';
                    }
                    $level_update['mem_level'] = 5;
                    if($mem_level->mem_level == 5 && $mem_level->mem_level_length == '永久有效'){

                    }else{
                        $goods_ret = DB::table('member')
                            ->where('mem_id', $find_order->ord_client_id)
                            ->update($level_update);
                    }
                    //添加赠礼
                    $level_goods = DB::table('member_level_goods')
                        ->where('memlg_shop_id', $find_order->ord_shop_id)
                        ->where('memlg_meml_id', 5)
                        ->get()->toArray();
                    if(!empty($level_goods)){
                        foreach ($level_goods as $key => $value){
                            $add_data['memg_cid'] = $find_order->ord_cid;
                            $add_data['memg_shop_id'] = $find_order->ord_shop_id;
                            $add_data['memg_superior_shop_id'] = $find_order->ord_shop_id;
                            $add_data['memg_goo_type'] = $value->memlg_goo_type;//类型
                            $add_data['memg_goo_type_name'] = $value->memlg_goo_type_name;//类型名称
                            $add_data['memg_goo_id'] = $value->memlg_goo_id;//商品id
                            $add_data['memg_goo_name'] = $value->memlg_goo_name;//商品名称
                            $add_data['memg_meml_id'] = $value->memlg_meml_id;//礼品对应的等级
                            $add_data['memg_mem_id'] = $find_order->ord_client_id;//会员id
                            $add_data['memg_pic'] = $value->memlg_pic;//商品封面图
                            $add_data['memg_status'] = 2;//1已使用2未使用
                            if($mem_use_end_time != '0000-00-00 00:00:00'){
                                $add_data['memg_use_end_time'] = $mem_use_end_time;//有效截止时间
                            }
                            $add_data['memg_create_time'] = date('Y-m-d H:i:s');//添加时间
                            $level_id =  DB::table('member_goods')->insertGetId($add_data);
                        }
                    }else{
                        $level_id = true;
                    }
                    //添加积分
                    $find_order->adm_shop_id = $find_order->ord_shop_id;
                    $find_order->adm_id = $find_order->ord_client_id;
                    $find_order->adm_cid = $find_order->ord_cid;
                    //积分倍数
                    $meml_points_multiple = DB::table('member_level')
                        ->where('meml_shop_id', $find_order->ord_shop_id)
                        ->where('meml_level', $mem_level->mem_level)
                        ->value('meml_points_multiple');
                    if($meml_points_multiple <= 1){
                        $meml_points_multiple = 1;
                    }
                    $add_point = WashOrderBasicService::addPoint($find_order,$find_order->ord_client_id,$find_order->ord_id,$meml_points_multiple);
                    $update_data['ord_wor_state'] = 4;
                    $update_ress = DB::table('order')
                        ->where('ord_order_number', $resourceData['out_trade_no'])
                        ->update($update_data);
                    //修改应收应付
                    $edit_res = DB::table('receivable_pay')
                        ->where('recpay_original_number', $resourceData['out_trade_no'])
                        ->update(['recpay_arrears_price'=>0,'recpay_actual_price'=>$find_order->ord_order_price,'recpay_plus_minus'=>1,'recpay_profit'=>$find_order->ord_order_price]);
                }else{
                    $level_id = true;
                }
            } else {
                $myvi_id = true;
                $level_id = true;
            }
            if ($update_res && $update_res1 && $update_pait && $myvi_id && $level_id) {
                DB::commit();
    	        return response()->json(['code'=>200, 'message'=>'成功']);
            } else {
                DB::rollBack();
                return response()->json(['code'=>202, 'message'=>'成功']);
            }
        }
    }

    //获取商品图片
    public static function getGoodPic($type,$id){
        $img = '';
        if ($type == 2) {//商品
            $img = DB::table('goods')
                ->where('goo_id', $id)
                ->value('goo_pic');
                if(empty($img)){
                $img = config('apisystem.server_name_https').'/storage/image/default_goo_img.png';
            }
        }
        if ($type == 1) {//服务
            $img = DB::table('service_project')
                ->where('sepr_id', $id)
                ->value('sepr_img');
                if(empty($img)){
                $img = config('apisystem.server_name_https').'/storage/image/default_goo_img.png';
            }
        }
        if ($type == 3) {//会员卡
            $img = config('apisystem.server_name_https').'/image/customerImg/order_vip.png';
        }
        return $img;
    }

    /**
     * 支付成功回调
     * @param string jsonData 微信支付返回的数据 json字符串
     * @param array headers 头部信息
     */
    public function otherNotifyPay(Request $request)
    {
        Common::write_log($request, 2, 'otherNotifyPay');
        //然后对回报结果部分数据进行解密
        $resourceData = WashPayservice::decryptToString($request['resource']['associated_data'], $request['resource']['nonce'], $request['resource']['ciphertext']);

        $resourceData = json_decode($resourceData, true);
        // 解析
        $find_otor_data = DB::table('other_order')
            ->where('otor_ord_number', $resourceData['out_trade_no'])
            ->select('otor_ord_number', 'otor_id', 'otor_source')
            ->first();
        
        if ($find_otor_data) {
            if ($find_otor_data->otor_source == 1) {//来源1半径汽配
                $update_data['otor_pay_state'] = 2;//支付状态1未支付2已支付
                $update_data['otor_transaction_id'] = $resourceData['transaction_id'];//微信订单单号
                $update_data['otor_update_time'] = date('Y-m-d H:i:s');//更新时间
                $update_res = DB::table('other_order')
                    ->where('otor_id', $find_otor_data->otor_id)
                    ->update($update_data);

                // $url = config('apisystem.1mk_server_name') . '/index.php/api/a1/Pay/notifyPay';//正式版回调路径
                $url = config('apisystem.mktest_server_name') . '/index.php/api/a1/Pay/notifyPay';
                $param['out_trade_no'] = $resourceData['out_trade_no']; //订单单号
                $param['transaction_id'] = $resourceData['transaction_id']; //微信订单单号
                $param['ip'] = getRealIp($request);
                $param['time'] = date('Y-m-d H:i:s'); //
                $doPost_res = Common::doPost($param, $url, 2);
                $doPost_res = json_decode($doPost_res);
            } elseif ($find_otor_data->otor_source == 2) { //来源：2养老系统
                $update_data['otor_pay_state'] = 2;//支付状态1未支付2已支付
                $update_data['otor_transaction_id'] = $resourceData['transaction_id'];//微信订单单号
                $update_data['otor_update_time'] = date('Y-m-d H:i:s');//更新时间
                $update_res = DB::table('other_order')
                    ->where('otor_id', $find_otor_data->otor_id)
                    ->update($update_data);

                // $url = config('apisystem.1mk_server_name') . '/index.php/api/a1/Pay/notifyPay';//正式版回调路径
                $url = config('apisystem.yltest_server_name') . '/index.php/u1/Pay/notifyPay';
                $param['out_trade_no'] = $resourceData['out_trade_no']; //订单单号
                $param['transaction_id'] = $resourceData['transaction_id']; //微信订单单号
                $param['ip'] = getRealIp($request);
                $param['time'] = date('Y-m-d H:i:s'); //
                $doPost_res = Common::doPost($param, $url, 2);
                $get_data['doPost_res'] = $doPost_res;
                $doPost_res = json_decode($doPost_res);
                $get_data['param'] = $param;
                $get_data['url'] = $url;
                $get_data['doPost_res1'] = $doPost_res;
                Common::write_log($get_data, 2, 'otherNotifyPay');
            }
        }
        return response()->json(['code'=>200, 'msg'=>'成功']);
    }

    /**
     * 退款通知回调
     * @param string jsonData 退款通知返回的信息 json字符串
     * @param array headers 头部信息
     */
    public function notifyRefund(Request $request)
    {
        //然后对回报结果部分数据进行解密
        $resourceData = WashPayservice::decryptToString($request['resource']['associated_data'], $request['resource']['nonce'], $request['resource']['ciphertext']);
        return response()->json(['code'=>200, 'msg'=>'成功']);
    }

    /**
     * 退款通知回调
     * @param string jsonData 退款通知返回的信息 json字符串
     * @param array headers 头部信息
     */
    public function otherNotifyRefund(Request $request)
    {
        //然后对回报结果部分数据进行解密
        $resourceData = WashPayservice::decryptToString($request['resource']['associated_data'], $request['resource']['nonce'], $request['resource']['ciphertext']);
        $resourceDatas = json_decode($resourceData, true);
        // 解析
        $find_otor_data = DB::table('other_order')
            ->where('otor_ord_number', $resourceDatas['out_trade_no'])
            ->select('otor_ord_number', 'otor_id', 'otor_source')
            ->first();
        
        if ($find_otor_data) {
            if ($find_otor_data->otor_source == 1) {//来源1半径汽配
                $update_data['otor_pay_state'] = 3;//支付状态1未支付2已支付3已退款
                $update_data['otor_update_time'] = date('Y-m-d H:i:s');//更新时间
                $update_res = DB::table('other_order')
                    ->where('otor_id', $find_otor_data->otor_id)
                    ->update($update_data);

                // $url = config('apisystem.1mk_server_name') . '/index.php/api/a1/Pay/notifyRefund';//正式版回调路径
                $url = config('apisystem.mktest_server_name') . '/index.php/api/a1/Pay/notifyRefund';
                $param['sp_mchid'] = $resourceDatas['sp_mchid']; //服务商商户号
                $param['sub_mchid'] = $resourceDatas['sub_mchid']; //二级商户号
                $param['out_trade_no'] = $resourceDatas['out_trade_no']; //订单号
                $param['transaction_id'] = $resourceDatas['transaction_id']; //微信订单号
                $param['out_refund_no'] = $resourceDatas['out_refund_no']; //退款单号
                $param['refund_id'] = $resourceDatas['refund_id']; //退款id
                $param['refund_status'] = $resourceDatas['refund_status']; //退款状态
                $param['success_time'] = $resourceDatas['success_time']; //成功时间
                $param['refund_request_source'] = $resourceDatas['refund_request_source']; //请求来源
                $param['refund_account'] = $resourceDatas['refund_account']; //退款出资商户
                $param['user_received_account'] = $resourceDatas['user_received_account']; //用户退款账号
                $param['total'] = $resourceDatas['amount']['total']; //总金额
                $param['refund'] = $resourceDatas['amount']['refund']; //退款金额
                $param['payer_refund'] = $resourceDatas['amount']['payer_refund']; //退款给客户金额
                $param['payer_total'] = $resourceDatas['amount']['payer_total']; //客户
                $doPost_res = Common::doPost($param, $url, 2);
                $doPost_res = json_decode($doPost_res);
            }
        }
        return response()->json(['code'=>200, 'msg'=>'成功']);
    }

    /**
     * 发起分账请求 post 最大30%
     * 注意：对同一笔订单最多能发起20次分账请求，每次请求最多分给5个接收方
     * @param string out_order_no   商户分账单号 自己生成的唯一的单号 64位内
     * @param string transaction_id 微信订单号 订单支付流水号
     * @param string sub_mchid 分账出资的二级商户号，微信支付分配的
     * @param string receivers 分账接收方列表。最多5个，包括(类型，账号，金额，描述)
     * @param bool finish 是否结束分账，true是解冻二级商户金额，false可继续分账
     */
    // [{"type":"MERCHANT_ID","account":"1619735999","amount":"0.06","description":"给服务商分账"}]
    public function reqAccount(Request $request)
    {
    	$out_order_no = $request['out_order_no'];
    	$transaction_id = $request['transaction_id'];
    	$sub_mchid = $request['sub_mchid'];
    	// $receivers = $request['receivers'];
    	$receivers[0]['type'] = 'MERCHANT_ID';
        $receivers[0]['receiver_account'] = '1619735999';
        $receivers[0]['amount'] = 2;
        $receivers[0]['description'] = '给服务商分账';
    	$finish = true;
    	$res = WashPayservice::reqAccount($out_order_no, $transaction_id, $sub_mchid, $receivers, $finish);
    	return $res;
    }

    /**
     * 发起解冻请求 post
     * @param string out_order_no   商户分账单号 自己生成的唯一的单号 64位内
     * @param string transaction_id 微信订单号 订单支付流水号
     * @param string sub_mchid 分账出资的二级商户号，微信支付分配的
     * @param string description 描述
     */
    public function finishAccount(Request $request)
    {
        $get_ip = getRealIp($request); //获取ip
        // 接收数据流
        $request = file_get_contents("php://input");
        // 解析
        Common::write_log($request, 1, 'finishAccount');
        $request = json_decode($request, true);
        $out_order_no = $request['out_order_no'];
        $transaction_id = $request['transaction_id'];
        $sub_mchid = $request['sub_mchid'];
        $description = isset($request['description']) ?  $request['description']:'解冻金额';
        $res = WashPayservice::finishAccount($out_order_no, $transaction_id, $sub_mchid, $description);
        Common::write_log($res, 1, 'finishAccount1');
        return response()->json(['code'=>200, 'msg'=>'成功', 'data'=>$res]);
    }

    /**
     * 发起分账请求 post 最大30%
     * 注意：对同一笔订单最多能发起20次分账请求，每次请求最多分给5个接收方
     * @param string out_order_no   商户分账单号 自己生成的唯一的单号 64位内
     * @param string transaction_id 微信订单号 订单支付流水号
     * @param string sub_mchid 分账出资的二级商户号，微信支付分配的
     * @param string receivers 分账接收方列表。最多5个，包括(类型，账号，金额，描述)
     * @param bool finish 是否结束分账，true是解冻二级商户金额，false可继续分账
     */
    // [{"type":"MERCHANT_ID","account":"1619735999","amount":"0.06","description":"给服务商分账"}]
    public function otherReqAccount(Request $request)
    {
        $get_ip = getRealIp($request); //获取ip
        // 接收数据流
        $request = file_get_contents("php://input");
        // 解析
        Common::write_log($request, 1, 'otherReqAccount');
        $request = json_decode($request, true);
        $out_order_no = $request['out_order_no'];
        $transaction_id = $request['transaction_id'];
        $sub_mchid = $request['sub_mchid'];
        // $receivers = $request['description'];
        $receivers[0]['type'] = 'MERCHANT_ID';
        $receivers[0]['receiver_account'] = '1619735999';
        $receivers[0]['amount'] = (int)$request['amount'];//分账金额
        // $receivers[0]['description'] = '给服务商分账';
        $receivers[0]['description'] = isset($request['description']) ? $request['description'] : '给服务商分账';
        $finish = true;
        $res = WashPayservice::reqAccount($out_order_no, $transaction_id, $sub_mchid, $receivers, $finish);
        return response()->json(['code'=>200, 'msg'=>'成功', 'data'=>$res]);
        // return $res;
    }

     /**
     * 验签
     * 3 构造验签名串 （http头部的Wechatpay-Timestamp，HTTP头Wechatpay-Nonce，返回的body）
     * 4 3个都已 \n 结尾，
     * 获取应答签名 HTTP头Wechatpay-Signature 然后使用base64_decode 解码得到应答签名
     * @param string body 签名主体
     * @param array headers 头部信息
     */
    public function Verify($body, $headers)
    {
        $serial_no = WashPayservice::certificates();
        $mch_public_key = WashPayservice::getCertificate(getcwd() . config('apisystem.SSLCERT_PATH')); //获取平台的公钥
        $head_serial_no = $headers['HTTP_WECHATPAY_SERIAL'];
        if ($serial_no != $head_serial_no) {
            throw new Exception("回调请求证书序列化不一致");
        }
        $timestamp = $headers['HTTP_WECHATPAY_TIMESTAMP'];
        $nonce = $headers['HTTP_WECHATPAY_NONCE'];
        $signature = $headers['HTTP_WECHATPAY_SIGNATURE'];
        $str = $timestamp . "\n" . $nonce . "\n" . ($body ? $body . "\n" : ''); //验签名串
        $signature = base64_decode($signature); //应答签名
        $value = openssl_verify($str, $signature, $mch_public_key, 'sha256WithRSAEncryption');
        if ($value == 1) {
            return true;
        }
        return false;
    }

	public function getSignature()
	{
		// Authorization: <schema> <token>
		$url_parts = parse_url($url);
		$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
		$message = $http_method."\n".
		    $canonical_url."\n".
		    $timestamp."\n".
		    $nonce."\n".
		    $body."\n";

		openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
		$sign = base64_encode($raw_sign);

		$schema = 'WECHATPAY2-SHA256-RSA2048';
		$token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
	    $merchant_id, $nonce, $timestamp, $serial_no, $sign);
	    return $token;
	}

	// 微信支付回调地址
    public function wechatNotify(Request $request)
	{
		error_reporting(0);
		$wechat_config = config('pay.wechat');//微信小程序支付配置信息
        $pay = Pay::wechat($wechat_config);
       	try {
			// 微信小程序支付
        	$pay_data = $pay->verify(); // 是的，验签就这么简单
        } catch (\Exception $e) {
        	$pay_data = $e->getMessage();
			$log_record['code'] = 'error';
        }
		// 记录日志
		$log_record['request'] = $request->all();
		$log_record['data'] = $pay_data;
		$log_record['time'] = date('Y-m-d H:i:s');
		$log_record['function'] = 'wechatNotify';
		logFileRecord($log_record, 'xdc/pay/wechatNotify', 2);

		$add_wenr_data['wenr_appid'] = $pay_data->appid; //微信分配的小程序ID
		$add_wenr_data['wenr_bank_type'] = $pay_data->bank_type; //付款银行
		$add_wenr_data['wenr_cash_fee'] = $pay_data->cash_fee; //现金支付金额
		$add_wenr_data['wenr_fee_type'] = $pay_data->fee_type; //现金支付货币类型
		$add_wenr_data['wenr_is_subscribe'] = $pay_data->is_subscribe; //用户是否关注公众账号，Y-关注，N-未关注
		$add_wenr_data['wenr_mch_id'] = $pay_data->mch_id; //微信支付分配的商户号
		$add_wenr_data['wenr_nonce_str'] = $pay_data->nonce_str; //随机字符串，不长于32位
		$add_wenr_data['wenr_openid'] = $pay_data->openid; //用户在商户appid下的唯一标识
		$add_wenr_data['wenr_out_trade_no'] = $pay_data->out_trade_no; //商户订单号
		$add_wenr_data['wenr_result_code'] = $pay_data->result_code; //业务结果:SUCCESS/FAIL
		$add_wenr_data['wenr_return_code'] = $pay_data->return_code; //返回状态码:SUCCESS/FAIL,此字段是通信标识，非交易标识，交易是否成功需要查看result_code来判断
		$add_wenr_data['wenr_sign'] = $pay_data->sign; //签名
		$add_wenr_data['wenr_time_end'] = $pay_data->time_end; //支付完成时间
		$add_wenr_data['wenr_total_fee'] = $pay_data->total_fee; //订单总金额，单位为分
		$add_wenr_data['wenr_trade_type'] = $pay_data->trade_type; //交易类型:JSAPI、NATIVE、APP
		$add_wenr_data['wenr_transaction_id'] = $pay_data->transaction_id; //微信订单号
		$add_wenr_data['wenr_type'] = 2; //类型：1支付2退款
		$add_wenr_data['wenr_update_time'] = date('Y-m-d H:i:s'); //微信订单号
		$add_wenr_res = DB::table('wechat_notify_record')->insert($add_wenr_data);
		return response()->json(['code'=>200, 'msg'=>'测试成功', 'data'=>'']);
	}

	// 微信支付成功
    public function wechatPaySuccess(Request $request)
	{
		$edit_data['ord_pay_state'] = 1;//已支付
		$edit_data['ord_state'] = 2;//已结算
		$edit_data['ord_update_time'] = date('Y-m-d H:i:s');//更新时间
        $find_order = DB::table('order')
        	->where('ord_id', $request['ord_id'])
        	->update($edit_data);
    	if ($find_order) {
			return response()->json(['code'=>200, 'msg'=>'下单成功', 'data'=>'']);
        } else {
			return response()->json(['code'=>500, 'msg'=>'下单失败', 'data'=>'']);
        }
	}

	// 微信支付失败
    public function wechatPayError(Request $request)
	{
		if (empty($request['ord_id'])) {
			return response()->json(['code'=>500, 'msg'=>'请上传取消支付的订单', 'data'=>'']);
		}
        $edit_data['ord_wor_state'] = 11;//取消订单
        $edit_data['ord_settlement_time'] = '';//结算时间
		$edit_data['ord_payment_way'] = 0;//结算方式
		$edit_data['ord_update_time'] = date('Y-m-d H:i:s');//更新时间
        $find_order = DB::table('order')
        	->where('ord_id', $request['ord_id'])
        	->update($edit_data);
        if ($find_order) {
			return response()->json(['code'=>200, 'msg'=>'取消成功', 'data'=>'']);
        } else {
			return response()->json(['code'=>500, 'msg'=>'取消失败', 'data'=>'']);
        }
	}

	// 微信退款
    public function wechatRefund(Request $request)
	{
		$wechat_config = config('pay.wechat');//微信小程序支付配置信息
		$order = [
		    'out_trade_no' => 'YY202202247109200006',
		    'out_refund_no' => time(),
		    'total_fee' => '1',
		    'refund_fee' => '1',
		    'refund_desc' => '测试退款haha',
		    'type' => 'miniapp',
		];
		$wechat_config['notify_url'] = config('apisystem.server_name').'/index.php/api/a1/Pay/wechatRefundNotify';

		try {
			// 微信小程序退款
			$result = Pay::wechat($wechat_config)->refund($order);
			// 新增在线支付记录
			// $onpa_add_data['onpa_shop_id'] = $find_data->reli_shop_id; //所属门店id
			// $onpa_add_data['onpa_client_id'] = $find_data->reli_client_id; //客户单位id，会员id
			// $onpa_add_data['onpa_type'] = $find_data->reli_client_type; //类型：1个人会员2客户单位
			// $onpa_add_data['out_trade_no'] = $find_data->reli_number; //商户订单号
			// $onpa_add_data['onpa_appid'] = config('pay.miniapp_id'); //微信小程序应用ID   miniapp_id
			// $onpa_add_data['onpa_mchid'] = config('pay.mch_id'); //直连商户号    mch_id
			// $onpa_add_data['onpa_description'] = $order['body']; //商品描述
			// $onpa_add_data['onpa_openid'] = $request['weus_openid']; //用户标识,用户在直连商户appid下的唯一标识
			// $onpa_add_data['onpa_pay_total_money'] = $find_data->reli_actual_price; //支付总金额(单位分)
			// $onpa_add_data['onpa_pay_way'] = 1; //在线支付方式1微信小程序支付
			// $onpa_add_data['onpa_pay_type'] = 2; //在线支付类型1付款2退款
			// $onpa_add_data['onpa_update_time'] = date('Y-m-d H:i:s');
			// $onpa_add_res = DB::table('online_payment')->insert($onpa_add_data);
			return response()->json(['code'=>200, 'msg'=>'退款成功', 'data'=>$result]);
        } catch (\Exception $e) {
			return response()->json(['code'=>500, 'msg'=>'退款失败！ERROR_GATEWAY', 'data'=>$e->getMessage()]);
        }
	}

	// 微信退款回调地址
    public function wechatRefundNotify(Request $request)
	{
		error_reporting(0);
		$wechat_config = config('pay.wechat');//微信小程序支付配置信息
        $pay = Pay::wechat($wechat_config);
       	try {
			// 微信退款异步通知
        	$pay_data = $pay->verify(null, true); // 是的，验签就这么简单
        } catch (\Exception $e) {
        	$pay_data = $e->getMessage();
			$log_record['code'] = 'error';
        }
		// 记录日志
		$log_record['request'] = $request->all();
		$log_record['data'] = $pay_data;
		$log_record['time'] = date('Y-m-d H:i:s');
		$log_record['function'] = 'wechatRefundNotify';
		logFileRecord($log_record, 'xdc/pay/wechatRefundNotify', 2);

		$add_wenr_data['wenr_appid'] = $pay_data->appid; //微信分配的小程序ID
		$add_wenr_data['wenr_bank_type'] = $pay_data->bank_type; //付款银行
		$add_wenr_data['wenr_cash_fee'] = $pay_data->cash_fee; //现金支付金额
		$add_wenr_data['wenr_fee_type'] = $pay_data->fee_type; //现金支付货币类型
		$add_wenr_data['wenr_is_subscribe'] = $pay_data->is_subscribe; //用户是否关注公众账号，Y-关注，N-未关注
		$add_wenr_data['wenr_mch_id'] = $pay_data->mch_id; //微信支付分配的商户号
		$add_wenr_data['wenr_nonce_str'] = $pay_data->nonce_str; //随机字符串，不长于32位
		$add_wenr_data['wenr_openid'] = $pay_data->openid; //用户在商户appid下的唯一标识
		$add_wenr_data['wenr_out_trade_no'] = $pay_data->out_trade_no; //商户订单号
		$add_wenr_data['wenr_result_code'] = $pay_data->result_code; //业务结果:SUCCESS/FAIL
		$add_wenr_data['wenr_return_code'] = $pay_data->return_code; //返回状态码:SUCCESS/FAIL,此字段是通信标识，非交易标识，交易是否成功需要查看result_code来判断
		$add_wenr_data['wenr_sign'] = $pay_data->sign; //签名
		$add_wenr_data['wenr_time_end'] = $pay_data->time_end; //支付完成时间
		$add_wenr_data['wenr_total_fee'] = $pay_data->total_fee; //订单总金额，单位为分
		$add_wenr_data['wenr_trade_type'] = $pay_data->trade_type; //交易类型:JSAPI、NATIVE、APP
		$add_wenr_data['wenr_transaction_id'] = $pay_data->transaction_id; //微信订单号
		$add_wenr_data['wenr_type'] = 2; //类型：1支付2退款
		$add_wenr_data['wenr_update_time'] = date('Y-m-d H:i:s'); //微信订单号
		$add_wenr_res = DB::table('wechat_notify_record')->insert($add_wenr_data);

		return response()->json(['code'=>200, 'msg'=>'测试成功', 'data'=>'']);
	}

    // 微信支付
    public function unifiedOrder($params)
    {
        $nonce_str = $this->genRandomString();
        $spbill_create_ip = $_SERVER['REMOTE_ADDR'];
        $paramsw['appid'] = $this->appid; //appid
        $paramsw['mch_id'] = $this->mch_id; //mch_id
        $paramsw['nonce_str'] = $nonce_str; //nonce_str
        $paramsw['body'] = $params['body']; //body
        $paramsw['detail'] = $params['detail']; //detail
        $paramsw['openid'] = $params['opid']; //detail
        $paramsw['out_trade_no'] = $params['out_trade_no']; //out_trade_no
        $paramsw['total_fee'] = $params['total_fee']; //total_fee
        $paramsw['spbill_create_ip'] = $spbill_create_ip; //spbill_create_ip
        $paramsw['notify_url'] = config('apisystem.server_name_https').'/index.php/api/u1/Pay/wechatNotify'; //notify_url
        $paramsw['trade_type'] = $params['trade_type']; //trade_type
        $paramsw['sign_type'] = 'MD5';
        //获取签名数据
        $sign = $this->MakeSign($paramsw);
        $paramsw['sign'] = $sign;
        $xml = $this->dataToXml($paramsw);

        $response = $this->postXmlCurl($xml, 'https://api.mch.weixin.qq.com/pay/unifiedorder');
        if (!$response) {
            return false;
        }
        $result = $this->xml_to_data($response);
        if (!empty($result['result_code']) && !empty($result['err_code'])) {
            $result['err_msg'] = $this->error_code($result['err_code']);
        }
        return $result;
    }

    /**
     * 产生一个指定长度的随机字符串,并返回给用户
     * @param type $len 产生字符串的长度
     * @return string 随机字符串
     */
    public function genRandomString($len = 32)
    {
        $chars = array(
            "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
            "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
            "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
            "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
            "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2",
            "3", "4", "5", "6", "7", "8", "9"
        );
        $charsLen = count($chars) - 1;
        // 将数组打乱
        shuffle($chars);
        $output = "";
        for ($i = 0; $i < $len; $i++) {
            $output .= $chars[mt_rand(0, $charsLen)];
        }
        return $output;
    }
    /**
     * 生成签名
     *  @return 签名
     */
    public function MakeSign($params)
    {
        //签名步骤一：按字典序排序数组参数
        ksort($params);
        $string = $this->toUrlParams($params);
        //签名步骤二：在string后加入KEY
        $string = $string . "&key=ebbe8a54fb239e80da5982dde4aec28c";
        //签名步骤三：MD5加密
        $string = RSA($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    /**
     * 将参数拼接为url: key=value&key=value
     * @param   $params
     * @return  string
     */
    public function toUrlParams($params)
    {
        $string = '';
        if (!empty($params)) {
            $array = array();
            foreach ($params as $key => $value) {
                $array[] = $key . '=' . $value;
            }
            $string = implode("&", $array);
        }
        return $string;
    }

    /**
     * 输出xml字符
     * @param   $params     参数名称
     * return   string      返回组装的xml
     **/
    public function dataToXml($params)
    {
        if (!is_array($params) || count($params) <= 0) {
            return false;
        }

        $xml = "<xml>";
        foreach ($params as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

    /**
     * 以post方式提交xml到对应的接口url
     *
     * @param string $xml  需要post的xml数据
     * @param string $url  url
     * @param bool $useCert 是否需要证书，默认不需要
     * @param int $second   url执行超时时间，默认30s
     * @throws WxPayException
     */
    public function postXmlCurl($xml, $url, $useCert = false, $second = 30)
    {
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        if ($useCert == true) {
            //设置证书
            //使用证书：cert 与 key 分别属于两个.pem文件
            curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
            curl_setopt($ch, CURLOPT_SSLCERT, './Wxpay/apiclient_cert.pem');
            curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
            curl_setopt($ch, CURLOPT_SSLKEY, './Wxpay/apiclient_key.pem');
        }
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            return false;
        }
    }

    public function postXmlCurls($xml, $url)
    {
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        // if($useCert == true){
        //设置证书
        //使用证书：cert 与 key 分别属于两个.pem文件
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLCERT, './Lib/Action/Wxpay/apiclient_cert.pem');
        curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLKEY, './Lib/Action/Wxpay/apiclient_key.pem');

        // }
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            return false;
        }
    }

    /**
     * 错误代码
     * @param  $code       服务器输出的错误代码
     * return string
     */
    public function error_code($code)
    {
        $errList = array(
            'NOAUTH'                =>  '商户未开通此接口权限',
            'NOTENOUGH'             =>  '用户帐号余额不足',
            'ORDERNOTEXIST'         =>  '订单号不存在',
            'ORDERPAID'             =>  '商户订单已支付，无需重复操作',
            'ORDERCLOSED'           =>  '当前订单已关闭，无法支付',
            'SYSTEMERROR'           =>  '系统错误!系统超时',
            'APPID_NOT_EXIST'       =>  '参数中缺少APPID',
            'MCHID_NOT_EXIST'       =>  '参数中缺少MCHID',
            'APPID_MCHID_NOT_MATCH' =>  'appid和mch_id不匹配',
            'LACK_PARAMS'           =>  '缺少必要的请求参数',
            'OUT_TRADE_NO_USED'     =>  '同一笔交易不能多次提交',
            'SIGNERROR'             =>  '参数签名结果不正确',
            'XML_FORMAT_ERROR'      =>  'XML格式错误',
            'REQUIRE_POST_METHOD'   =>  '未使用post传递参数 ',
            'POST_DATA_EMPTY'       =>  'post数据不能为空',
            'NOT_UTF8'              =>  '未使用指定编码格式',
        );
        if (array_key_exists($code, $errList)) {
            return $errList[$code];
        }
    }

    /**
     * 将xml转为array
     * @param string $xml
     * return array
     */
    public function xml_to_data($xml)
    {
        if (!$xml) {
            return false;
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }

    public function https_request($url, $data = null)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }
}
