• <正则吃饺子> :关于微信支付的简单总结说明(二)


    关于微信退款

    一、官方文档

    申请退款:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_4&index=6

    二、退款流程图

    注意:微信退款时候,需要证书服务,这里可以参见官方文档中的说明,包括证书的具体下载,解析等。(后面我也补充个证书解析的文件,方便理解)

    一个百度文库的文档https://wenku.baidu.com/view/754c78e93186bceb19e8bbcc.html

    三、项目中使用的代码

    拿来作个参考吧,方便记忆和理解

    /**
         * 微信支付申请退款
         *
         * @param weChatPayRefund
         * @return
         */
        public boolean weChatPayRefundRequest(WeChatPayRefund weChatPayRefund, String source) {
            try {
                if (null == weChatPayRefund) {
                    throw new ArgumentException("参数异常");
                }
                if (Strings.isNullOrEmpty(weChatPayRefund.getRefund_fee())) {
                    throw new ArgumentException("退款金额为空");
                }
                if (Strings.isNullOrEmpty(weChatPayRefund.getOut_trade_no())) {
                    throw new ArgumentException("原交易编号为空");
                }
    
                //退款金额,微信金额单位为分,系统为元,做换算
                int refundFee = new BigDecimal(weChatPayRefund.getRefund_fee())
                        .multiply(new BigDecimal(100)).intValue();
                weChatPayRefund.setRefund_fee(String.valueOf(refundFee));
                //订单总金额单位为分
                int totalFee = new BigDecimal(weChatPayRefund.getTotal_fee())
                        .multiply(new BigDecimal(100)).intValue();
                weChatPayRefund.setTotal_fee(String.valueOf(totalFee));
                //生成随机流水号
                String timeStr = System.currentTimeMillis() + "";
                weChatPayRefund.setOut_refund_no("TK" + timeStr);
                //退款单号为UUID
                weChatPayRefund.setNonce_str(UUIDUtil.randrom());
                //生成退款参数XML
                String xml = this.createRefundXml(weChatPayRefund, source);
                String refundURL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
                ClientCustomSSL clientCustomSSL = new ClientCustomSSL();
                String result = "";
                if ("01".equals(source)) {
                    result = clientCustomSSL.doRefund(refundURL, xml, weChatPkcs12, "B2B");
                } else if ("02".equals(source)) {
                    result = clientCustomSSL.doRefund(refundURL, xml, b2cWeChatPkcs12, "B2C");
                } else if ("03".equals(source)) {
                    result = clientCustomSSL.doRefund(refundURL, xml, b2cWeChatPkcs12_new, "B2C_NEW");
                }
                //请求返回结果
                result = result.replaceAll("
    ", "").replaceAll("
    ", "").replaceAll("	", "");
                Document doc = DocumentHelper.parseText(result);
                
                Map<String, Object> resultMap = XmlMapHandle.Dom2Map(doc);
                String applyId = weChatPayRefund.getApplyId();
                StringHashMapper stringHashMapper = new StringHashMapper(WeChatPayRefund.class);
                WeChatPayRefund weChatPay = (WeChatPayRefund) stringHashMapper.fromHash(resultMap);
                ConvenienceRefund refund = createRefundInfo(weChatPayRefund);
            //根据返回结果,处理一些自己的业务
    if (weChatPay.getReturn_code().equalsIgnoreCase("SUCCESS") && weChatPay.getResult_code().equalsIgnoreCase("SUCCESS")) { weChatPay.setApplyId(applyId); refund.setRefundStatus("1"); this.rechargeOrderWriteDao.saveRefundInfo(refund);//保存退款信息 int updateFlag = rechargeOrderWriteDao.updateOrderPayStatus(RedisType.PAY_STATUS2.getIndex(), weChatPayRefund.getOut_trade_no()); if (updateFlag >= 1) { //退款成功 //订单日志保存 ConvenienceOrderLog orderLog = new ConvenienceOrderLog(); orderLog.setOrderId(String.valueOf(weChatPayRefund.getOut_trade_no())); orderLog.setStatusCode(50); orderLog.setStatusName("退款成功"); this.saveConvenienceOrderLog(orderLog); return true; } else { //退款失败 return false; } } else { refund.setRefundStatus("0"); this.rechargeOrderWriteDao.saveRefundInfo(refund); ConvenienceOrderLog orderLog = new ConvenienceOrderLog(); orderLog.setOrderId(String.valueOf(weChatPayRefund.getOut_trade_no())); orderLog.setStatusCode(99); orderLog.setStatusName("退款失败"); throw new BusinessException("退款失败:" + weChatPayRefund.getReturn_msg()); } } catch (Exception e) { throw new BusinessException("退款失败:请联系管理员"); } } /** * 根据订单来源生成退款参数XML * * @param weChatPayRefund * @param source * @return */ public String createRefundXml(WeChatPayRefund weChatPayRefund, String source) { String appId = ""; String mchId = ""; String key = ""; if ("01".equals(source)) { appId = weChatPayRefund.getB2b_appid_new(); mchId = weChatPayRefund.getB2b_mch_id_new(); key = weChatPayRefund.getB2b_appKey_new(); } else if ("02".equals(source)) { appId = weChatPayRefund.getB2c_appid(); mchId = weChatPayRefund.getB2c_mch_id(); key = weChatPayRefund.getB2c_appKey(); } else if ("03".equals(source)) { appId = weChatPayRefund.getB2c_appid_new(); mchId = weChatPayRefund.getB2c_mch_id_new(); key = weChatPayRefund.getB2c_appKey_new(); } //生成退款签名 SortedMap<String, String> packageParams = new TreeMap<String, String>(); packageParams.put("appid", appId); packageParams.put("mch_id", mchId); packageParams.put("nonce_str", weChatPayRefund.getNonce_str()); packageParams.put("out_trade_no", weChatPayRefund.getOut_trade_no()); packageParams.put("out_refund_no", weChatPayRefund.getOut_refund_no()); packageParams.put("total_fee", weChatPayRefund.getTotal_fee()); packageParams.put("refund_fee", weChatPayRefund.getRefund_fee()); packageParams.put("op_user_id", mchId); RequestHandler reqHandler = new RequestHandler(null, null); reqHandler.init(appId, "", key); String sign = reqHandler.createSign(packageParams); String xml = org.apache.commons.lang3.StringUtils.join("<xml>", "<appid>", appId, "</appid>", "<mch_id>", mchId, "</mch_id>", "<nonce_str>", weChatPayRefund.getNonce_str(), "</nonce_str>", "<sign><![CDATA[", sign, "]]></sign>", "<out_trade_no>", weChatPayRefund.getOut_trade_no(), "</out_trade_no>", "<out_refund_no>" + weChatPayRefund.getOut_refund_no(), "</out_refund_no>", "<total_fee>", weChatPayRefund.getTotal_fee(), "</total_fee>", "<refund_fee>" + weChatPayRefund.getRefund_fee(), "</refund_fee>", "<op_user_id>" + mchId, "</op_user_id>", "</xml>"); return xml; }

    四、引申与其他

    (待续..)

  • 相关阅读:
    前端模块化,AMD,CMD 总结
    前端基本网络协议知识整合
    websocket心跳机制
    js 数组方法的作用,各方法是否改变原有的数组
    React函数组件和类组件的区别
    js 单线程、宏任务与微任务的执行顺序
    js为什么是单线程
    allure清空上一次运行的记录(--clean-alluredir)
    allure的Tag标记(allure.story、allure.feature、severity)
    allure集成缺陷管理系统和测试管理系统(allure.link、allure.issue、allure.testcase)
  • 原文地址:https://www.cnblogs.com/zhengzeze/p/7397282.html
Copyright © 2020-2023  润新知