• 关于微信支付,退款操作,原路返回


    有这样的场景,用户购买商品。但是退款的时候要去除运费。
    或者,用户购买多个商家的商品,统一支付。但是用户只退其中一个商家的商品。
    又或者,用户一个订单购买多个商品。只退其中一个商品。

    微信退款接口可以满足这些需求,前提是总的退款金额不能超过总的支付金额。
    支付的时候,不需要证书。
    但是退款的时候,需要提供证书。

    下面看看实际的情况。

    从上图可以看出,我支付2分钱,可以一次性退。

    也可以,一次退1分,分两次退还。

    而且,用银行卡就退到银行卡,用信用卡就退到信用卡。

    这些支付,退款相关的信息,可以在管理后台中统一管理。或者写到配置文件中。


    退款需要证书,需要到微信商户平台进行下载。(开放平台【app】,公众平台【微信,pc,小程序】)分别有一个商户号。

    退款的时候,需要提供支付的订单号或者微信提供的transaction_id。每一个退款都有自己的退款号(确保不要相同)。

    一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号。

    private function refundWx($data)
        {
            Clog::setLog($data);
            vendor('Wxpay.WxPay');
    
            $input = new WxPayRefund();
            $input->SetOut_trade_no($data['out_trade_no']);
            $input->SetAppid($data['app_id']);
            $input->SetMch_id($data['mch_id']);
            $input->SetOut_refund_no($data['out_trade_no'] . 'R');
            $input->SetTotal_fee($data['price']);
            $input->SetRefund_fee($data['price']);
            $input->SetOp_user_id($data['mch_id']);
            $input->key = $data['key'];
            $path = C('WX_KEY_PATH');
            switch ($data['type']) {
                case 1:
                    $path = $path . 'open/';
                    break;
                case 2:
                    $path = $path . 'public/';
                    break;
            }
            $response = WxPayApi::refund($input, $path);
    
            if ($response['return_code'] == 'SUCCESS' && $response['result_code'] == 'SUCCESS') {
                return true;
            } else {
                return false;
            }
    }
    
    /**
    	 * 
    	 * 申请退款,WxPayRefund中out_trade_no、transaction_id至少填一个且
    	 * out_refund_no、total_fee、refund_fee、op_user_id为必填参数
    	 * appid、mchid、spbill_create_ip、nonce_str不需要填入
    	 * @param WxPayRefund $inputObj
    	 * @param int $timeOut
    	 * @throws WxPayException
    	 * @return 成功时返回,其他抛异常
    	 */
    	public static function refund($inputObj, $path, $timeOut = 6)
    	{
    		$url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
    		//检测必填参数
    		if(!$inputObj->IsOut_trade_noSet() && !$inputObj->IsTransaction_idSet()) {
    			throw new WxPayException("退款申请接口中,out_trade_no、transaction_id至少填一个!");
    		}else if(!$inputObj->IsOut_refund_noSet()){
    			throw new WxPayException("退款申请接口中,缺少必填参数out_refund_no!");
    		}else if(!$inputObj->IsTotal_feeSet()){
    			throw new WxPayException("退款申请接口中,缺少必填参数total_fee!");
    		}else if(!$inputObj->IsRefund_feeSet()){
    			throw new WxPayException("退款申请接口中,缺少必填参数refund_fee!");
    		}else if(!$inputObj->IsOp_user_idSet()){
    			throw new WxPayException("退款申请接口中,缺少必填参数op_user_id!");
    		}
    
      
    		$inputObj->SetNonce_str(self::getNonceStr());//随机字符串
    		
    		$inputObj->SetSign();//签名
    		$xml = $inputObj->ToXml();
    		$startTimeStamp = self::getMillisecond();//请求开始时间
    		$response = self::postXmlCurl($xml, $url, true, $timeOut, $path);
    		$result = WxPayResults::Init($response);
    		self::reportCostTime($url, $startTimeStamp, $result);//上报请求花费时间
    		
    		return $result;
    }
    	
    
    /**
    	 * 以post方式提交xml到对应的接口url
    	 * 
    	 * @param string $xml  需要post的xml数据
    	 * @param string $url  url
    	 * @param bool $useCert 是否需要证书,默认不需要
    	 * @param int $second   url执行超时时间,默认30s
    	 * @throws WxPayException
    	 */
    	private static function postXmlCurl($xml, $url, $useCert = false, $second = 30, $certPath = '')
    	{		
    		$ch = curl_init();
    		//设置超时
    		curl_setopt($ch, CURLOPT_TIMEOUT, $second);
    		
    		//如果有配置代理这里就设置代理
    		if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0" 
    			&& WxPayConfig::CURL_PROXY_PORT != 0){
    			curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
    			curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
    		}
    		curl_setopt($ch,CURLOPT_URL, $url);
    		curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
    		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, $certPath . 'apiclient_cert.pem');
    			curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
    			curl_setopt($ch,CURLOPT_SSLKEY, $certPath . '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);
    			throw new WxPayException("curl出错,错误码:$error");
    		}
    }
    

    具体的参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4

  • 相关阅读:
    oracle 动态SQL
    Oracle 学习PL/SQL
    SQL优化原理
    JAVA环境配置
    Java接口
    Java数据类型、操作符、表达式
    C#-VS配置开发环境-摘
    Java版本
    网站构建
    Java 时间、字符串
  • 原文地址:https://www.cnblogs.com/jiqing9006/p/9897532.html
Copyright © 2020-2023  润新知