微信退款实战案例

简介: 微信退款实战案例
<?php
/* 
 * 咔咔
 * 微信号 fangkangfk
 * author:2018.6.20
 * 一个文件实现微信退款
 */
class Refund
{   
    const REFUND = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
    const KEY = 'h5l4P8S3u5n1H5Y4D7E5l9e6J4Y7S8h3';
    const CODEURL = 'https://open.weixin.qq.com/connect/oauth2/authorize?';
    const OPENIDURL = 'https://api.weixin.qq.com/sns/oauth2/access_token?';
    const APPID = '商户号id';
    const SECRET = '秘钥';
    const MCHID = '商户微信号';
    const UNURL = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
    private $params;
    public function __construct($data) {
        //组装数据
        $this->params = [
            'appid'   =>  self::APPID, //APPID
            'mch_id'  =>  self::MCHID, //商户号
            'nonce_str'=> md5(time()), //随机串
            'sign'  => 'md5',          //签名方式
            'transaction_id'=> $data['transaction_id'],//微信支付订单号 与商户订单号二选一
            //'out_trade_no'=> '', //商户订单号 和微信支付订单号二选一
            'out_refund_no' => $data['out_refund_no'],//退单号
            'total_fee'     => $data['total_fee'],    //订单金额
            'refund_fee'    => $data['refund_fee']    //退款金额
        ];
    }
    //发送退款请求
    public function orderRefund(){
        //生成签名
        $signParams = $this->setSign($this->params);
        //将数据转换为xml
        $xmlData = $this->ArrToXml($signParams);
        //发送请求
        return  $this->postStr(self::REFUND, $xmlData);
    }
    //post 字符串到接口
    public function postStr($url,$postfields){
        $ch = curl_init();
        $params[CURLOPT_URL] = $url;    //请求url地址
        $params[CURLOPT_HEADER] = false; //是否返回响应头信息
        $params[CURLOPT_RETURNTRANSFER] = true; //是否将结果返回
        $params[CURLOPT_FOLLOWLOCATION] = true; //是否重定向
        $params[CURLOPT_POST] = true;
        $params[CURLOPT_SSL_VERIFYPEER] = false;//禁用证书校验
    $params[CURLOPT_SSL_VERIFYHOST] = false;
      //以下是证书相关代码
    $params[CURLOPT_SSLCERTTYPE] = 'PEM';
    $params[CURLOPT_SSLCERT] = './cert/apiclient_cert.pem';
    $params[CURLOPT_SSLKEYTYPE] = 'PEM';
    $params[CURLOPT_SSLKEY] = './cert/apiclient_key.pem';
        $params[CURLOPT_POSTFIELDS] = $postfields;
        curl_setopt_array($ch, $params); //传入curl参数
        $content = curl_exec($ch); //执行
        curl_close($ch); //关闭连接
        return $content;
    }
    //生成签名
    public function getSign($arr){
        //去除空值
        $arr = array_filter($arr);
        if(isset($arr['sign'])){
            unset($arr['sign']);
        }
        //按照键名字典排序
        ksort($arr);
        //生成url格式的字符串
       $str = $this->arrToUrl($arr) . '&key=' . self::KEY;
       return strtoupper(md5($str));
    }
    //获取带签名的数组
    public function setSign($arr){
        $arr['sign'] = $this->getSign($arr);;
        return $arr;
    }
    public function arrToUrl($arr){
        return urldecode(http_build_query($arr));
    }
    //验证签名
    public function chekSign($arr){
        $sign = $this->getSign($arr);
        if($sign == $arr['sign']){
            return true;
        }else{
            return false;
        }
    }
     //数组转xml
    public function ArrToXml($arr)
    {
            if(!is_array($arr) || count($arr) == 0) return '';
            $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; 
    }
    public function XmlToArr($xml)
    {   
        if($xml == '') return '';
        libxml_disable_entity_loader(true);
        $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);     
        return $arr;
    }
}
// 获取订单号
$orderdata = D('foodorder')->where([
    'id'=>$_SESSION['orderid']
    ])->find();
// 传值
$data = [
    'transaction_id'    => $orderdata['wx_number'], //微信交易号
    'out_refund_no'    => $orderdata['wx_number'], //退款单号
    'total_fee'    => $orderdata['cash_fee'], //原订单金额
    'refund_fee'    => $orderdata['cash_fee'] //退款金额
];
// 实例化退款类
$obj = new Refund($data);
// 调用退款方法
$res = $obj->orderRefund();
// 退款微信返回数据
$refunddata = $obj->XmlToArr($res);
if($refunddata['return_code'] == 'SUCCESS'){
    $data['wx_refundorder'] = $orderdata['wx_number'];
    $data['user_id'] = $orderdata['userid'];
    $data['refund_fee'] = $orderdata['cash_fee'];
    $data['refund_time'] = time();
    $datas['wxrefund_number'] = $orderdata['wx_number'];
    $orderdata = D('foodorder')->where([
        'wx_number'=>$orderdata['wx_number']
        ])->save($datas);
    if(!$orderdata){
        $log_name= "./Public/Pay/refund_url.log";//log文件路径
        file_put_contents($log_name,"【退款成功 , 订单数据库添加失败通知", FILE_APPEND);
    }
    $refundorder = D('refundorder')->add($data);
    if(!$refundorder){
        $log_name= "./Public/Pay/refund_url.log";//log文件路径
        file_put_contents($log_name,"【退款成功 , 数据库添加失败通知", FILE_APPEND);
    }
}else{
    $log_name= "./Public/Pay/refund_url.log";//log文件路径
    file_put_contents($log_name,"【退款失败", FILE_APPEND);
}
相关文章
|
2月前
|
小程序 JavaScript 前端开发
【微信小程序】-- 案例 - 本地生活(二十)
【微信小程序】-- 案例 - 本地生活(二十)
|
2月前
|
JSON 小程序 前端开发
【微信小程序】-- 案例 - 自定义 tabBar(四十六)
【微信小程序】-- 案例 - 自定义 tabBar(四十六)
|
2月前
|
小程序
【微信小程序】-- 自定义组件 - 数据监听器 - 案例 (三十五)
【微信小程序】-- 自定义组件 - 数据监听器 - 案例 (三十五)
|
2月前
|
JSON 小程序 API
【微信小程序】-- 案例 - 本地生活(列表页面)(三十)
【微信小程序】-- 案例 - 本地生活(列表页面)(三十)
|
2月前
|
小程序
【微信小程序】-- 页面事件 - 上拉触底 - 案例(二十七)
【微信小程序】-- 页面事件 - 上拉触底 - 案例(二十七)
|
2月前
|
JSON 小程序 JavaScript
微信小程序快速入门02(含案例)
微信小程序快速入门02(含案例)
|
9月前
|
前端开发 容器
从零玩转系列之微信支付实战PC端装修下单页面2
从零玩转系列之微信支付实战PC端装修下单页面
56 0
|
4月前
|
小程序 前端开发 JavaScript
微信小程序快速入门01(含案例)
微信小程序快速入门01(含案例)
123 1
|
5月前
|
小程序 JavaScript
微信小程序学习笔记(5) -- todos案例
微信小程序学习笔记(5) -- todos案例
|
5月前
|
小程序 开发工具 开发者
微信小程序入门->小程序简介,小程序商城项目案例,小程序入门案例及目录结构
微信小程序入门->小程序简介,小程序商城项目案例,小程序入门案例及目录结构
64 0
微信小程序入门->小程序简介,小程序商城项目案例,小程序入门案例及目录结构

热门文章

最新文章