在生产环境的业务中经常用到支付接口,而支付体系下的微信支付和支付宝支付是比较常用的,但是有支付就会有退款,这里再讲一下支付宝退款和微信退款接口的实现方式。如果支付功能已经开发完毕那再开发退款接口的话就比较容易了,因为支付的算法和退款的一些签名算法都是一致的可以公用,下面分别针对微信和支付宝(新版+老版)的退款接口需要注意的地方做一下介绍。

  1.微信退款


 微信退款时需要向微信服务器发送退款请求,要发送的数据如下:

[
    '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']    //退款金额
];

其中最后四项是需要根据退款需求指定对应的值就可以了,组装好数据后加上签名转换为xml提交到微信接口就可以了。微信退款接口地址:

https://api.mch.weixin.qq.com/secapi/pay/refund

在请求的时候需要注意要携带证书请求,可参考《PHP使用CURL携带ssl证书和秘钥请求接口代码》。

  2.支付宝退款(旧版)


支付宝旧版本的退款接口实在太不人性化了,除了调用接口还需要管理员手动操作,所以如果使用的是旧版支付还是建议升级一下,这里说一下旧版退款接口的调用过程。第一步也是组装好需要发送给支付宝的数据,数据如下:

[
    'service' => 'refund_fastpay_by_platform_pwd' , //接口名称
    'partner' => self::PID ,//合作伙伴ID
    '_input_charset' => 'UTF-8' ,//字符集
    'sign_type' => 'MD5' ,//签名方式
    //'seller_email' => '' ,//卖家支付宝账号和合作伙伴ID二选一
    'seller_user_id' => self::PID , //合作伙伴ID
    'refund_date' => date('Y-m-d H:i:s') , //退款请求时间
    'batch_no' => date('Ymd') . '002' ,//退款批次号 格式为:退款日期(8位)+流水号(3~24位)
    'batch_num' => $batch_num , //总笔数
    'detail_data' => $detail_data, //单笔数据集 格式: 支付宝交易号^金额^退款理由
    'notify_url'    => ''//退款通知地址
];

同理要发送到支付网关https://mapi.alipay.com/gateway.do,但是问题来了发送到支付网关后并不是直接退款了,还会要求管理员输入密码,很无奈。看下图:

支付宝旧版退款接口

支付宝旧版退款界面

输入密码后提交支付宝会请求退款通知地址,如果商户需要做对应处理可以在支付通知里做处理,验证方式和支付通知类似,需要验证签名并处理后最后输出success。但是这种方式太原始了,除了有特别的要求否则很少有这么用的,实际上是半自动化的,还是建议升级为新接口,但是新接口退款必须使用新接口支付才可以的。

3.支付宝退款(新版)


下面看一下需要发送的参数,分为公共参数也业务参数两部分,其中公共参数基本都是固定值,业务参数是退款数据,组装后加入签名然后发送到接口地址。 

//公共参数 固定值
$pub_params = [
   'app_id'    => self::APPID,
   'method'    =>  'alipay.trade.refund', //接口名称 应填写固定值alipay.trade.refund
   'format'    =>  'JSON', //目前仅支持JSON
   'charset'    =>  'UTF-8',
   'sign_type'    =>  'RSA2',//签名方式
   'timestamp'    => date('Y-m-d H:i:s'), //发送时间 格式0000-00-00 00:00:00
   'version'    =>  '1.0', //固定为1.0
   'biz_content'    =>  '', //业务请求参数的集合
];

//业务参数
$api_params = [
   'out_trade_no'  => '20180124202357',//商户订单号 和支付宝交易号trade_no 二选一
   'refund_amount'  => '0.03', //退款金额
   'out_request_no'  => '001', //退款唯一标识  部分退款时必传
];
//公共参数中加入业务参数
$pub_params['biz_content'] = json_encode($api_params,JSON_UNESCAPED_UNICODE);

//加入签名请求接口.....

在请求接口后和微信类似,直接就退款了。