php微信小程序退款

/*
 * 微信统一退款接口
 * 参数说明:
 * $res-基层数据,$out_num-退款的订单号,$path-回调接收地址,
 * $title-退款说明,$money-订单总金额,$refund_money-要退款的金额,$out_refund_no-可选,退款单号
 * 返回值说明:
 * array,键值如下:
 * status:操作状态,包括:success-操作成功,no_money-余额不足,param_error-参数错误,cert_error-证书错误,has_refund-已经退款了,error-其他错误
 * refund_num-退款订单号
 * error_info-错误信息描述,当status不为success时返回
 * */
function weixin_refund($res, $out_num, $path, $title, $money, $refund_money, $out_refund_no = '')
{
    //微信小程序app_id,对应的appid需要跟商户所对应,别弄错了
    $appinfo['appi_d'] = '';
    //微信商户的商户号,自己可以微信商户后台进行查询
    $appinfo['mch_id'] = '';
    //微信的商户号的支付秘钥
    $appinfo['pay_secret'] = '';
    //下面的是 商户的私钥和公钥,放在public目录下面了
    $appinfo['app_wx_cert'] = public_path().'apiclient_cert.pem';
    $appinfo['app_wx_key'] = public_path().'apiclient_key.pem';
    //获取支付基础信息
    $appid = $appinfo['appi_d'];
    $mch_id = $appinfo['mch_id'];
    $miyao = $appinfo['pay_secret'];
    $cert_path['cert'] = $appinfo['app_wx_cert'];
    $cert_path['key'] = $appinfo['app_wx_key'];

    if (!$out_refund_no) {
        //生成退款订单号
        $out_refund_no = ikzOutNum('pb');
    }
    /*支付XML数组*/
    $pay_arr = array(
        //以下是必填项
        'appid' => $appid,//公众号appid
        'mch_id' => $mch_id,//商户号
        'nonce_str' => get_rand_str(), //随机字符串表
        'out_trade_no' => $out_num, //订单号
        'out_refund_no' => $out_refund_no,//退款订单号
        'total_fee' => $money * 100,//订单总金额
        'refund_fee' => $refund_money * 100,//退款总金额
        'refund_desc' => $title,//退款原因
        'notify_url' => $path //通知地址
    );
    $sing_str = get_sign($miyao, $pay_arr);
    //将拼接好的签名写入数组
    $pay_sign = array('sign' => $sing_str);
    $pay_xml_array = array_merge($pay_arr, $pay_sign);
    $pay_xml_array = arrayToXml($pay_xml_array);
    $url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
    $responseXml = curl_post_ssl($url, $pay_xml_array, true, $cert_path);
    $responseObj = (array)simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
    //先判断证书是否存在
    if ($responseObj !== false) {
        //证书正确,开始判断退款详情
        if ($responseObj['return_code'] == 'SUCCESS') {
            //请求成功
            if ($responseObj['result_code'] == 'SUCCESS') {
                //汇款成功
                $result['status'] = 'success';
            } else {
                //汇款失败,判断失败的信息
                if ($responseObj['err_code'] == 'SYSTEMERROR' || $responseObj['err_code'] == 'BIZERR_NEED_RETRY') {
                    //系统错误,再次发起
                    weixin_refund('', $out_num, $path, $title, $money, $refund_money, $out_refund_no);
                } elseif ($responseObj['err_code'] == 'NOTENOUGH') {
                    //余额不足
                    $result['status'] = 'no_money';
                } elseif ($responseObj['err_code'] == 'APPID_NOT_EXIST' || $responseObj['err_code'] == 'MCHID_NOT_EXIST') {
                    //参数错误
                    $result['status'] = 'param_error';
                } elseif ($responseObj['err_code'] == 'ERROR' && $responseObj['err_code_des'] == '订单已全额退款') {
                    //参数错误
                    $result['status'] = 'has_refund';
                } else {
                    //其他错误
                    $result['status'] = 'error';
                }
                $result['error_info'] = $responseObj['err_code_des'];
                //错误的状态,进行详细记录
                recordOrderError($out_num, json_encode($responseObj), '3');
            }
        } else {
            //系统错误
            $result['status'] = 'sys_fail';
            $result['error_info'] = '系统错误';
            //错误的状态,进行详细记录
            recordOrderError($out_num, json_encode($responseObj), '3');
        }
    } else {
        //系统错误
        $result['status'] = 'cert_error';
        $result['error_info'] = '证书错误';
        //错误的状态,进行详细记录
        recordOrderError($out_num, '证书错误', '3');
    }

    $result['refund_num'] = $out_refund_no;
    return $result;
}

//生成随机数
function get_rand_str()
{
    $str = '1234567890abcdefghijklmnopqrstuvwxyz';
    $t1 = '';
    for ($i = 0; $i < 30; $i++) {
        $j = rand(0, 35);
        $t1 .= $str[$j];
    }
    return $t1;
}

/**
 * 生成订单号
 * @param $length
 * @return string
 * @throws ClientException
 */
function ikzOutNum($info = '')
{
    return $info . date('YmdHis') . rand(1000000, 9999999);
}
/*
 *生成签名的方法
 *@param  $my 商户应用密钥
 */
function get_sign($my, $hongbao_arr)
{

    ksort($hongbao_arr); //按照ASCII 码 从 小 到 大 排 序

    $unSignParaString = formatQueryParaMap($hongbao_arr, false);

    return sign($unSignParaString, $my);
}

//设置请求参数的方法
function arrayToXml($arr)
{
    $xml = "<xml>";
    foreach ($arr as $key => $val) {
        if (is_numeric($val)) {
            $xml .= "<" . $key . ">" . $val . "</" . $key . ">";

        } else {
            $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
    }
    $xml .= "</xml>";
    return $xml;
}

//请求数据的方法
function curl_post_ssl($url, $vars, $cert = false, $cert_path = '', $second = 30, $aHeader = array())
{
    $ch = curl_init();
    //超时时间
    curl_setopt($ch, CURLOPT_TIMEOUT, $second);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    //这里设置代理,如果有的话
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    if ($cert) {
        //第一种方法,cert 与 key 分别属于两个.pem文件
        //默认格式为PEM,可以注释
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLCERT, $cert_path['cert']);
        //默认格式为PEM,可以注释
        curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLKEY, $cert_path['key']);
    }

    if (count($aHeader) >= 1) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
    }

    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
    $data = curl_exec($ch);
    if ($data) {
        curl_close($ch);
        return $data;
    } else {
        $error = curl_errno($ch);
        curl_close($ch);
        return false;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值