前期准备:首先要搞定微信支付,不然怎么退款,这次用官方demo。当然网上可能有很多高手自己改写封装了demo。可能更方便简洁,但我还是不提倡。原因如下:(1)可能功能不全。可能他刚刚开通了微信支付,但是还有退款申请。支付、查询退款、订单查询、订单取消等业务功能可能是你以后需要的。如果依赖大神SDK的便利,如果有新的业务需求,就会一头雾水;(2)安全方面的考虑,在支付的时候涉及到钱,一定要非常安全。虽然我也吐槽官方的SDK,但至少会相对安全一些。它将再次被重写。虽然暂时没看出问题,但要是有漏洞就不好了。本文使用官方SDK中最重要的类文件WxPay.Api.PHP中提供的refund()方法实现。此方法位于WxPay.Api.php文件的第141行。代码如下:/****申请退款,WxPayRefund中out_trade_no和transaction_id至少填写一项*out_refund_no,total_fee,refund_fee,op_user_id为必填参数*appid,mchid,spbill_create_ip,nonce_str不要需要填写*@paramWxPayRefund$inputObj*@paramint$timeOut*@throwsWxPayException*@return成功返回,否则抛出异常*/publicstaticfunctionrefund($inputObj,$timeOut=6){$url="https://api.mch.weixin.qq.com/secapi/pay/refund";//检测所需参数if(!$inputObj->IsOut_trade_noSet()&&!$inputObj->IsTransaction_idSet()){thrownewWxPayException("退款申请界面中out_trade_no和transaction_id至少要填写一??个!");}elseif(!$inputObj->IsOut_refund_noSet()){thrownewWxPayException("退款申请接口中,缺少参数out_refund_no!");}elseif(!$inputObj->IsTotal_feeSet()){thrownewWxPayException("退款申请界面中,需要的参数tota丢失l_fee!");}elseif(!$inputObj->IsRefund_feeSet()){thrownewWxPayException("退款申请界面中,缺少所需参数refund_fee!");}elseif(!$inputObj->IsOp_user_idSet()){thrownewWxPayException("退款申请界面缺少必填参数op_user_id!");}$inputObj->SetAppid(WxPayConfig::APPID);//公众号ID$inputObj->SetMch_id(WxPayConfig::MCHID);//商户号$inputObj->SetNonce_str(self::getNonceStr());//随机字符串$inputObj->SetSign();//签名$xml=$inputObj->ToXml();$startTimeStamp=self::getMillisecond();//请求开始时间$response=self::postXmlCurl($xml,$url,true,$timeOut);$result=WxPayResults::Init($response);self::reportCostTime($url,$startTimeStamp,$result);//上报请求耗时return$result;}官方方法里写的很清楚,需要哪些参数,SDK已经帮我们填好了一些必要的参数,我会重新封装这个方法是方便的在项目中调用:/***微信退款*@paramstring$order_id订单ID*@return成功返回(数组类型),否则抛出异常*/functionwxRefund($order_id){//我的SDK放在项目根目录下的Api目录下require_onceAPP_ROOT."/Api/wxpay/lib/WxPay.Api.php";//查询订单,根据顺序$order=M('order')->where(array('id'=>$order_id,'is_refund'=>2,'order_status'=>1))->寻找();$merchid=WxPayConfig::MCHID;如果(!$order)返回假;$input=newWxPayRefund();$input->SetOut_trade_no($order['order_sn']);//自己的订单号$input->SetTransaction_id($order['transaction_id']);//微信官方生成的订单流水号,会返回$input->SetOut_refund_no(getrand_num(true));//退款订单号$input->SetTotal_fee($order['total_price']);//下单价格金额,单位为分$input->SetRefund_fee($order['total_price']);//退款总金额,订单总金额,单位是分,只能是整数$input->SetOp_user_id($merchid);$result=WxPayApi::refund($input);//退款操作//这一句file_put_contents用于查看服务器返回的退款结果。删除//file_put_contents(APP_ROOT.'/Api/wxpay/logs/log3.txt',arrayToXml($result),FILE_APPEND);返回$结果;这里需要吐槽一下返回值的类型。它返回XML数据的时候,这里返回了一个数组,让我措手不及,不过还是返回一个数组比较好,直接判断处理方法调用更容易://WeChatRefund$result=wxRefund($order_id);//这句file_put_contents是用来查看服务器返回的退款结果,测试后可以删除//file_put_contents(APP_ROOT.'/Api/wxpay/logs/log4.txt',arrayToXml($result),FILE_APPEND);if($result['return_code']=='SUCCESS')&&($result['result_code']=='SUCCESS')){//退款成功}elseif(($result['return_code']=='FAIL')||($result['result_code']=='FAIL')){//退款失败//原因$reason=(empty($result['err_code_des'])?$result['return_msg']:$result['err_code_des']);}else{//failed}退款成功返回如下:
