美文网首页iOS开发iOS程序员
带你实现支付宝/微信金额原路返回(格式修改版)

带你实现支付宝/微信金额原路返回(格式修改版)

作者: itcjj | 来源:发表于2016-08-20 10:53 被阅读1384次

    公司首个外包项目的退换货流程的退款操作是走原路返回的,而我有幸负责这个功能模块开发,在实践中总结了一些经验,特此分享出来。
    一、支付宝退款。
    支付宝提供了有密以及普通退款接口,两者的区别就是前者不需要申请即时到账支付而后者需要,本文使用了有密退款接口;支付宝四要素:PID(合作者id),private_key(私钥,我使用的是RSA加密方式生成的)、alipay_public_key(公钥,支付宝提供的)以及支付账号。
    1.1先看配置文件:

    // 合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串
    public static String partner = "";
    // 收款支付宝账号,以2088开头由16位纯数字组成的字符串,一般情况下收款账号就是签约账号public static String seller_user_id = partner;
    // 商户的私钥,需要PKCS8格式,RSA公私钥生成
    public static String private_key = "";
    // 支付宝公钥
    public static String alipay_public_key  = "";
    // 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    public static String notify_url = "http://xxx.xxxx.com/api/refund/refundBack_001";
    

    1.2关键代码:


    两种退款方式.png
    /** * 退款操作(请求) * @param response * @return * @throws Exception  * trade_no 支付宝返回的交易号 * money  退款金额 */
    public String aliRefund(HttpServletRequest request, HttpServletResponse response, String trade_no, String money,String refundId,String batch_no) throws Exception {PrintWriter out = ControllerUtils.getPrintWriter(response, logger, "------------AlipayRefundActionMultiController.aliRefund start------------");
    //服务器异步通知页面路径
     String notify_url;
     String sHtmlText = "";
     try {MapsParaTemp = new HashMap();
     //退款详细数据,必填,格式(支付宝交易号^退款金额^备注),多笔请用#隔开
     String detail_data = trade_no + "^" + money + "^退款";
     sParaTemp.put("detail_data", detail_data);//退款详情
     sParaTemp.put("service", AlipayConfig.service);//
     sParaTemp.put("partner", AlipayConfig.partner);//合作者id
     sParaTemp.put("_input_charset", AlipayConfig.input_charset);//字符集格式
    sParaTemp.put("notify_url", AlipayConfig.notify_url);//回调地址
    sParaTemp.put("seller_email", "商家账号");//账号
    sParaTemp.put("refund_date", UtilDate.getDateFormatter());//退款时间
    sParaTemp.put("batch_no", batch_no);//批次号,必填,格式:当天日期[8位]+序列号[3至24位],如:201603081000001
    sParaTemp.put("batch_num", "1"); //退款笔数,必填,参数detail_data的值中,“#”字符出现的数量加1,最大支持1000笔(即“#”字符出现的数量999个)
    sHtmlText = AlipaySubmit.buildRequest(sParaTemp, "get", "确认");
    } catch (Exception e) {
    e.printStackTrace();
    }
    return sHtmlText;
    }```
    
    ***注意:***此处的交易号必须是你支付时保存的交易号,以及退款金额不能大于实付金额且不能<=0,否则无法调起支付。我是将退款信息用一个form表单封装起来然后以流的方式输出,前端页面只需要拿到该信息然后填充到一个div中。
    **1.3表单封装:**
    

    /** * 建立请求,以表单HTML形式构造(默认) * @param sParaTemp 请求参数数组 * @param strMethod 提交方式。两个值可选:post、get * @param strButtonName 确认按钮显示文字 * @return 提交表单HTML文本 */
    public static String buildRequest(Map < String, String > sParaTemp, String strMethod, String strButtonName){ //待请求参数数组
    Map < String, String > sPara = buildRequestPara(sParaTemp);
    List < String > keys = new ArrayList < String > (sPara.keySet());
    StringBuffer sbHtml = new StringBuffer();
    sbHtml.append("");
    for (int i = 0; i < keys.size(); i++) {
    String name = (String)keys.get(i);
    String value = (String)sPara.get(name);
    sbHtml.append("");
    }
    //submit按钮控件请不要含有name属性
    sbHtml.append("");
    sbHtml.append("document.forms['alipaysubmit'].submit();");
    return sbHtml.toString();}

    
    **1.4前端页面拿到信息后进行填充:**
    
    
    ![div.png](http:https://img.haomeiwen.com/i2536237/738fbd47bcc6454a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![](http:https://img.haomeiwen.com/i2536237/26d747c282f25dfc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    **1.5效果展示:**
    ****
    [图片上传中。。。(4)]
    
    ![](http:https://img.haomeiwen.com/i2536237/1cb4826902fb8fb6.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ***二、微信退款。***
    ***2.1配置文件***
    ******
    ![](http:https://img.haomeiwen.com/i2536237/efcd58ddf33ad42b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    **2.2退款前提条件:**
    商户必须开通微信支付功能,开发人员要拿到账号以及**证书**(重点),退款金额不能大于实付价、小于等于0,并且传入的实际支付价必须跟微信那边保持一致,否则无法完成退款操作。
    2.2关键代码:
    

    private String doRefundByWX(String money, String bankSerialNumber, long numberCount, String no,String sumAmout) throws UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, IOException{
    String result="";
    String appid=WeiXinUtil.appid;//应用ID
    String mch_id=WeiXinUtil.mch_id;//商户号
    String nonce_str=WeiXinUtil.CreateNoncestr();//随机字符串
    String transaction_id=bankSerialNumber;//微信订单号
    String out_refund_no=no;//商户退款单号
    Double total_fee=0d;
    try {
    total_fee = StringUtil.getDouble(sumAmout);
    } catch (NumberFormatException e)
    {e.printStackTrace();}
    catch (Exception e) {
    e.printStackTrace();
    }
    long totalAmount = new BigDecimal(total_fee * 100d).longValue();//总金额以分为单位Double refund_fee=Double.parseDouble(money);
    long Amount = new BigDecimal(refund_fee * 100d).longValue();//退款金额以分为单位
    String op_user_id=WeiXinUtil.mch_id;//操作员帐号, 默认为商户号 /签名算法SortedMapSortedMap = new TreeMap();
    SortedMap.put("appid", appid);
    SortedMap.put("mch_id",mch_id);
    SortedMap.put("nonce_str",nonce_str);
    SortedMap.put("transaction_id", transaction_id);
    SortedMap.put("out_refund_no", out_refund_no);
    SortedMap.put("total_fee",String.valueOf(totalAmount));
    SortedMap.put("refund_fee", String.valueOf(Amount));
    SortedMap.put("op_user_id", op_user_id);
    String sign=WeiXinUtil.createSign("UTF-8",SortedMap);
    //获取最终待发送的数据
    String requestXml=WeiXinUtil.getRequestXml(SortedMap);
    //(2)建立连接并发送数据
    result=WeixinSendPost(requestXml);
    return result;
    }```

    2.3退款操作:
    先申明一点:微信退款没有提供跳转页面,也就是一点击退款,只要信息正确就会自动打钱到退款账户。

    我们平台的操作.png 退款成功结果.png 微信退款成功了.png

    三、关于保存微信支付、支付宝交易号作为退款字段的代码图(订单支付的回调方法):

    支付宝支付回调方式.png 微信支付回调方法.png

    备注:由于时间问题就不上全部代码,如若要具体代码请关注我,如果响应激烈我将会将代码放到GitHub。

    相关文章

      网友评论

        本文标题:带你实现支付宝/微信金额原路返回(格式修改版)

        本文链接:https://www.haomeiwen.com/subject/zahisttx.html