微信小程序支付和退款(微信公众号和微信小程序支付和退款属于一个爹妈)

一、微信小程序支付

1.前端小程序支付页面

<template>
  <div class="bg">
    <section>
      <div class="safe_lc">
        <h1>基本安全检测服务具体包含以下20项服务</h1>
        <p style="color:#f60;font-size:28rpx;line-height:40rpx;">注:基本安全检测服务,不包含问题部件的更换、维修及车辆保养。</p>
        <p>1.发动机怠速运转;</p>
        <p>2.空调及暖风系统;</p>
        <p>3.倒车雷达、影像;</p>
        <p>4.全车灯光、喇叭、反光镜、雨刷;</p>
        <p>5.发动机运转是否有杂音或有异响;</p>
        <p>6.机油油位及清洁程度;</p>
        <p>7.防冻液液位及冰点;</p>
        <p>8.蓄电池启动电压;</p>
        <p>9.备胎、三角牌、灭火器;</p>
        <p>10.四轮轮胎状态、气压;</p>
        <p>11.检查四轮刹车盘;</p>
        <p>12.检查四轮刹车片;</p>
        <p>13.检查车身外观/轮毂;</p>
        <p>14.检查故障灯;</p>
        <p>15.鼓风机运转;</p>
        <p>16.轮胎花纹深度;</p>
        <p>17.轮胎胎侧;</p>
        <p>18.油液渗漏检查;</p>
        <p>19.转向拉杆球头、上下支臂球头;</p>
        <p>20.内外球笼及防尘套,共20项。</p>
      </div>
      <div class="p_bottom">
         <form report-submit @submit="uploadFormId">
        <ul class="safety">
          <li>
            <span class="tit">品牌</span>
            <div class="clearfix">
              <picker
                @change="bindPickerChange"
                :value="index"
                :range="array"
                :index="array[index]"
                v-model="index"
              >
                <view class="picker">
                  <!-- <img class="ret_right" src="/static/images/right.png" /> -->
                  <span v-if="index===''">{{time}}</span>
                  <span v-else>{{array[index]}}</span>
                  <img
                    class="ret_right"
                    src="https://nc.mcwyou.com/upload/api/images/arrow.png"
                    alt
                  />
                </view>
              </picker>
            </div>
          </li>
          <li>
            <span class="tit">车牌号</span>
            <div class="clearfix">
              <!-- 豫AF58G5 -->
              <input type="text" :platenumber="platenumber" v-model="platenumber" />
            </div>
          </li>
          <li>
            <span class="tit">手机号</span>
            <div class="clearfix">
              <input type="text" :phonenumber="phonenumber" v-model="phonenumber" />
            </div>
          </li>
          <li>
            <span class="tit">所在地</span>

            <div class="f_right clearfix">
              <picker @change="bindProvinceChange" :value="index1" :range="Province" class="inline">
                <view class="picker">{{Province[index1]}}-</view>
              </picker>

              <picker @change="bindCityChange" :value="index2" :range="City" class="inline">
                <view class="picker">{{City[index2]}}</view>
              </picker>
              <img
                class="ret_right inline"
                src="https://nc.mcwyou.com/upload/api/images/arrow.png"
                alt
              />
              <!-- <picker @change="bindAreaChange" :value="index3" :range="Area" class="inline">
              <view class="picker">{{Area[index3]}}</view>
              </picker>-->
            </div>
          </li>
          <li>
            <span class="tit">预约时间</span>
            <view class="clearfix">
              <picker
                mode="multiSelector"
                @change="bindMultiPickerChange"
                :value="multiIndex"
                :range="newMultiArray"
                :appointment="appointment"
                v-model="appointment"
              >
                <span>{{appointment}}</span>
                <img class="ret_right" src="https://nc.mcwyou.com/upload/api/images/arrow.png" alt />
              </picker>
            </view>
          </li>
        </ul>
        <!-- <a
        :href="'/pages/index/Apply/main?startPlace=' + position + ' &endPlace=' + endPlace+'&tab=' + tab+'&flag='+flag"
        >-->
        <button form-type="submit" class="safety_btn" @click="saveOrder">立即办理</button>
         </form>
        <!-- </a> -->
      </div>
    </section>
  </div>
</template>

<script>
import QQMapWX from "../../../../static/qqmap-wx-jssdk.js";
export default {
  data() {
    return {
      pageUrl: "",
      index: 0,
      array: [],
      time: "请选择",
      multiArray: [],
      multiIndex: [0, 0, 0, 0, 0],
      phonenumber: "",
      platenumber: "",
      appointment: "",
      carType: "",
      index1: 0,
      Province: ["河南省"],
      index2: 0,
      City: [
        "郑州市",
        "三门峡",
        "焦作",
        "新乡",
        "鹤壁",
        "安阳",
        "濮阳",
        "开封",
        "洛阳",
        "许昌",
        "平顶山",
        "漯河",
        "周口",
        "商丘",
        "南阳",
        "驻马店",
        "信阳"
      ],
      formId: "",
      date:"",
      canAjax:true
    };
  },
  //下拉刷新
  onPullDownRefresh: function() {
    wx.stopPullDownRefresh();
  },
  computed: {
    newMultiArray: () => {
      let array = [];
      const date = new Date();
      const years = [];
      const months = [];
      const days = [];
      const hours = [];
      const minutes = [];

      for (let i = 2019; i <= date.getFullYear() + 10; i++) {
        years.push("" + i);
      }
      array.push(years);

      for (let i = 1; i <= 12; i++) {
        if (i < 10) {
          i = "0" + i;
        }
        months.push("" + i);
      }
      array.push(months);

      for (let i = 1; i <= 31; i++) {
        if (i < 10) {
          i = "0" + i;
        }
        days.push("" + i);
      }
      array.push(days);

      for (let i = 0; i < 24; i++) {
        if (i < 10) {
          i = "0" + i;
        }
        hours.push("" + i);
      }
      array.push(hours);

      for (let i = 0; i < 60; i++) {
        if (i < 10) {
          i = "0" + i;
        }
        minutes.push("" + i);
      }
      array.push(minutes);
      return array;
    }
  },
  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function() {
    return {
      title: "车主有福了,一站式车生活服务尽在车后链!", //分享内容
      path: "/pages/index/main", //分享地址
      imageUrl: "https://nc.mcwyou.com/upload/api/images/2019.9.05.jpg" //分享图片
    };
  },
  onLoad(options) {
    let that = this;
    that.options = options;
    //  that.getAllBrandSeries();
    wx.setNavigationBarTitle({
        title:"安全检测"
      })
  },
  onShow() {
    this.toLogin();
     this.getAllBrandSeries();
      this.getUserDefaultInfo();
     this.getDate()
  },
  methods: {
    toLogin(){
      console.log(wx.getStorageSync("openid"));
      var openid = wx.getStorageSync("openid");
      if ("" == openid) {
        wx.redirectTo({
          url: "/pages/index/lawSafety/main"
        });
      }
    },
    empty() {
      let that = this;
      this.platenumber = "";
      this.phonenumber = "";
      this.appointment = "";
    },

     //获取所有品牌
     getAllBrandSeries() {
      let that = this;
      wx.request({
        url: this.globalData.baseUrl + "xxx/xxx.html",
        data: {},
        header: this.globalData.header,
        success: function(res) {
         var list = res.data.obj.list;
         var array=[];
           for (var i in list){
                var item = list[i];
              //  array = item.name;
               array.push(item.name)
           }
           that.array=array;
        }
      });
    },

  //当前日期格式化 年/月/日/时/分/
     getDate(){
  let that = this;
       that.date=that.$utils.formatDate(new Date)
      // console.log("+++++++++++++++"+ that.date)
    },
   


   uploadFormId(e) {
     let that = this;
// console.log('form发生了submit事件,携带数据为:', e.target.formId)
      this.formId = e.target.formId;
    console.log( e.target.formId);
},
  
//根据userId获取默认信息
    getUserDefaultInfo() {
      let that = this;
      wx.request({
        url: this.globalData.baseUrl + "/xxx/xxx.html",
        data: {
          userId: wx.getStorageSync("userId")
        },
        header: this.globalData.header,
        success(res) {
          if(res.data.obj.insureDefaultInfo){
            that.phonenumber = res.data.obj.insureDefaultInfo.tel;
            that.platenumber = res.data.obj.insureDefaultInfo.licensePlate;
          }      
          console.log( that.platenumber)
          console.log( that.phonenumber)
           
        }
      });
    },

//前端微信小程序支付函数
    saveOrder() {
      let that = this;
      if (!that.$utils.check_licensePlate(that.platenumber)) {
        return false;
      }
      if (!that.$utils.regPhone(that.phonenumber)) {
        return false;
      }
      if(that.appointment == ""){
        wx.showToast({
          title: "请选择预约时间",
          icon:'none',
          success:function(){
          }
        })
        return false;
      }
      if(that.canAjax){
        that.canAjax=false
        wx.request({
          url: this.globalData.baseUrl + "xxx/xxx.html",
          data: {
            userId: wx.getStorageSync("userId"),
            phonenumber: that.phonenumber,
            platenumber: that.platenumber,
            startPlace: that.Province[that.index1] + that.City[that.index2],
            carType: that.array[that.index],
            appointment: that.appointment,
            formId:that.formId,
            city:that.City[that.index2]
          },
          header: this.globalData.header,
          success: function(res) {
            that.canAjax=true;
            console.log(res)
            if (res.data.result) {
              that.empty();
              if(res.data.obj.timestamp){
                that.pay(res.data.obj);
              }else{
                wx.showToast({
                  title: "您是保险公司用户,本次服务免费!!",
                  icon:'none',
                  success:function(){
                    wx.makePhoneCall({
                      phoneNumber: "xxx" //仅为示例,并非真实的电话号码
                    });
                  }
                })
              }
            }
          }
        });
      }
      
    },
    //支付
    pay: function(obj) {
      var that = this;
      wx.requestPayment({
        timeStamp: obj.timestamp,
        nonceStr: obj.nonceStr,
        package: obj.package,
        signType: "MD5",
        paySign: obj.paySign,
        success: function(data) {
          wx.makePhoneCall({
            phoneNumber: "xxx" //仅为示例,并非真实的电话号码
          });
        },
        fail: function(res) {
          wx.showToast({
            title: "支付失败",
            icon: "none",
            success: function() {
              setTimeout(function() {
                wx.navigateBack(); //返回会上个页面
              }, 2000);
            }
          });
        }
      });
    },

    bindPickerChange: function(e) {
      //console.log(e)
      this.index = e.mp.detail.value;
    },
    //所在地
    bindProvinceChange: function(e) {
      this.index1 = e.mp.detail.value;
      // this.getCity();
    },
    bindCityChange: function(e) {
      this.index2 = e.mp.detail.value;
      // this.getArea();
    },
    // bindAreaChange: function(e) {
    //   this.index3 = e.mp.detail.value;
    // },
    //获取时间日期
    bindMultiPickerChange(e) {
      this.multiIndex = e.target.value;
      console.log("当前选择的时间", this.multiIndex);
      console.log("时间", e);
      const index = this.multiIndex;
      const year = this.newMultiArray[0][index[0]];
      const month = this.newMultiArray[1][index[1]];
      const day = this.newMultiArray[2][index[2]];
      const hour = this.newMultiArray[3][index[3]];
      const minute = this.newMultiArray[4][index[4]];
      console.log(year + "-" + month + "-" + day + " " + hour + ":" + minute);
        var that = this;
       if((year + "-" + month + "-" + day + " " + hour + ":" + minute) >=that.date) {
         this.appointment =
        year + "-" + month + "-" + day + " " + hour + ":" + minute;
       }
    }
  }
};
</script>

2、微信小程序支付控制层

 /**
     * 安全检测
     *
     * @param platenumber
     * @param phonenumber
     * @param appointment
     * @param carType
     * @param request
     * @param response
     */
    @RequestMapping("safetyMonitoring")
    public void safetyMonitoring(@RequestParam(required = false) String userId, @RequestParam(required = false) String platenumber, @RequestParam(required = false) String phonenumber,
                                 @RequestParam(required = false) String appointment, @RequestParam(required = false) String carType, @RequestParam(required = false) String startPlace,
                                 @RequestParam(required = false) String formId,  @RequestParam(required = false) String city,HttpServletRequest request, HttpServletResponse response) {
        ReturnInfo info = new ReturnInfo();
        try {
            InsureRealOrder order = new InsureRealOrder();
            User user = userService.get(userId);
            order.setName(user.getUserName());
            order.setUserId(userId);
            order.setFromId(formId);
            order.setStartTime(new Date());
            order.setIsApi("1");
            order.setState("0");
            if (StringUtils.isNotBlank(platenumber)) {
                platenumber = new String(platenumber.getBytes("iso8859-1"), "utf-8");
                order.setLicensePlate(platenumber);
            }
            if (StringUtils.isNotBlank(startPlace)) {
                startPlace = new String(startPlace.getBytes("iso8859-1"), "utf-8");
                order.setStartPlace(startPlace);
            }
            if (StringUtils.isNotBlank(phonenumber)) {

                order.setTel(phonenumber);
            }
            if (StringUtils.isNotBlank(appointment)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                Date parse = sdf.parse(appointment);
                order.setAppointment(parse);
            }
            if (StringUtils.isNotBlank(carType)) {
                carType = new String(carType.getBytes("iso8859-1"), "utf-8");
                order.setCarType(carType);
            }
            if (StringUtils.isNotBlank(city)) {
                city = new String(city.getBytes("iso8859-1"), "utf-8");
                order.setCity(city);
            }
            String serviceType = "安全检测";
            InsureService insureService = insureServiceService.getInsurePayMoney(serviceType);
            order.setServiceType(serviceType);
            String json = ChinaCoalUtil.queryTimes(platenumber, "12");
            JSONObject object = JSONObject.parseObject(json);
            log.info(object);
            Integer customerAttr = object.getInteger("customerAttr");
            Integer lastTimes = object.getInteger("lastTimes");
            //是中煤保险客户剩余次数大于零,继续提供免费服务
            if (customerAttr.equals(0)&& lastTimes>0){
                log.info("-----------------中煤保险公司用户---------------");
                order.setType("1");
                order.setPayTime(new Date());
                order.setPayMoney(0.00);
                order.setSubsidyMoney(insureService.getPrice());
                order.setPayState("1");
                order = insureRealOrderService.save(order);
                //再调更新次数接口
               ChinaCoalUtil.updateTimes(platenumber,"12","success");
                NcscMerchant ncscMerchant = ncscMerchantService.getByProperty("city",city);
                if (ncscMerchant!=null){
                    //该市代理授权过的服务
                    String agentServices=ncscMerchant.getAgentService();
                    String[] str=agentServices.split(",");
                    List<String> asList = Arrays.asList(str);
                    String st = serviceType.substring(0,4);
                    //判断该订单的服务是否在商家市代理授权服务中
                    if (asList.contains(st)){
                        String city2=order.getCity();
                        if (StringUtils.isNotBlank(city2)){
                                String tel2=ncscMerchant.getTel();
                                String licensePlate2=order.getLicensePlate();
                                String serviceType2=order.getServiceType();
                                JuheMsgUtil.smsSend(tel2, "195559", "#code#=" + "用户位置-"+city2 + "-服务类型-"+serviceType2 + "-车牌号-"+licensePlate2 + "-联系方式-"+tel2);
                                info.setResult(true);
                                info.setMsg("下单成功");
                                this.writeJson(response, info);
                                return;
                        }
                    }

                }
            }else if (customerAttr.equals(0)&& lastTimes==0){
                //是中煤保险客户但剩余次数为0,需支付金额,不在提供免费服务
                order.setType("1");
                order.setPayMoney(insureService.getPrice());
                order.setPayState("0");
                order.setSubsidyMoney(0.00);

            }else {

                InsureUser insureUser = insureUserService.getByProperty("licensePlate", platenumber);
                if (insureUser != null) {
                    order.setType(insureUser.getType());
                    order.setPayMoney(0.00);
                    order.setSubsidyMoney(insureService.getPrice());
                    order.setPayState("1");
                    order.setType(insureUser.getType());
                    String state = order.getState();
                    if (StringUtils.isNotBlank(state)) {
                        state = "待处理";

                    }
                    String payState = order.getPayState();
                    if (StringUtils.isNotBlank(payState)) {
                        payState = "已支付";

                    }

                    if (StringUtils.isNotBlank(user.getMiniappOpenId())) {
                        String template_id = Constants.API_MOVECARInsure_TEMPLATE_ID;
                        String data = Constants.API_MOVECAR_TEMPLATE_DATA2;
                        Date date = new Date();
                        data = String.format(data, order.getId(), order.getServiceType(), state, payState, "保险公司vip用户无需支付", date, date);
                        String sysUserMsgId = ConfigUtil.getValue("chl_program_sys_user_msg_id");
                        TemplateMessageUtil.sendApiMsg(formId, user.getMiniappOpenId(), template_id, data, sysUserMsgId, "pages/index/main");
                    }

                } else {
                    order.setPayMoney(insureService.getPrice());
                    order.setSubsidyMoney(0.00);
                    order.setType("0");
                    order.setPayState("0");
                }
            }

            insureRealOrderService.saveOrUpdate(order);
            if (order.getPayMoney() != 0) {
                //这里先获取用户要支付的公众号配置
                String appid = ConfigUtil.getValue("chl_program_app_id");
                String mch_id = ConfigUtil.getValue("chl_program_mch_id");
                String key = ConfigUtil.getValue("chl_program_pay_key");


                //微信支付部分
                String ip = IPUtil.getIpAddr(request);
                Map<String, Object> paramsMap = new HashMap<String, Object>();
                //拼接参数开始
                paramsMap.put("appid", appid);           //公众账号ID
                paramsMap.put("mch_id", mch_id);          //商户号
                paramsMap.put("nonce_str", ConfigUtil.getValue("randomStr"));        //随机字符串,不长于32位
                paramsMap.put("body", "微信支付!");                             //商品描述
                paramsMap.put("out_trade_no", order.getId());                          //商户订单号
                DecimalFormat decimalFormat = new DecimalFormat("#");
                paramsMap.put("spbill_create_ip", ip);                   //终端IP
                String path = request.getContextPath();
                String basePath = request.getScheme() + "://"
                        + request.getServerName() + ":" + request.getServerPort()
                        + path + "/";
               //接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
                paramsMap.put("notify_url", basePath + "/xxx/xxx.html");

                paramsMap.put("trade_type", "JSAPI");
                paramsMap.put("total_fee", decimalFormat.format(order.getPayMoney() * 100));  //总金额
                paramsMap.put("openid", user.getMiniappOpenId());    //用户标识
                paramsMap.put("sign", AdvancedWeiXinPaySignUtils.buildRequestMysign(paramsMap, key));//签名          
                //把参数转换成xml字符串
                String xmlParam = WeiXinPayUtil.getRequestXml(paramsMap);
                log.info("----------------------给微信发送---------------------------");
                log.info(xmlParam);
                //返回微信服务器响应的信息
                String returnResult = WeiXinPayUtil.httpsRequest(xmlParam);
                log.info("----------------------微信返回---------------------------");
                log.info(returnResult);
                if (!StringUtils.isBlank(returnResult)) {
                    Map<String, String> resMap = new HashMap<String, String>();
                    resMap = WeiXinPayUtil.doXMLParse(returnResult);
                    String return_code = resMap.get("return_code");
                    String result_code = resMap.get("result_code");
                    String return_msg = resMap.get("return_msg");
                    if ("SUCCESS".equalsIgnoreCase(return_code) && "SUCCESS".equalsIgnoreCase(result_code)) {
                        String prepay_id = resMap.get("prepay_id");         //预支付交易会话标识
                        Map<String, Object> wxPayParams = new HashMap<>();
                        long timeStamp = new Date().getTime();
                        wxPayParams.put("timestamp", String.valueOf(timeStamp));
                        wxPayParams.put("nonceStr", ConfigUtil.getValue("randomStr"));
                        wxPayParams.put("package", "prepay_id=" + prepay_id);
                        wxPayParams.put("paySign", WeChatUtils.sha2Str(String.valueOf(timeStamp), "prepay_id=" + prepay_id, appid, key));
                        wxPayParams.put("appId", appid);
                        wxPayParams.put("insureRealOrderId", order.getId());
                        info.setObj(wxPayParams);
                        info.setResult(true);
                        info.setMsg(return_msg);
                    } else {
                        info.setResult(false);
                        info.setMsg(return_msg);
                    }
                }
            } else {
                info.setResult(true);
                info.setMsg("保险公司用户无需支付");
            }

        } catch (Exception e) {
            e.printStackTrace();
            info.setResult(false);
            info.setObj(e);
        } finally {
            this.writeJson(response, info);
        }

    }

3.微信支付回调
    /**
     * 安全监测支付异步回调
     *
     * @param response
     * @param request
     */
    @RequestMapping("safetyMonitoringNotify")
    public void safetyMonitoringNotify(HttpServletResponse response, HttpServletRequest request) {
        String result = "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
        Map<String, Object> returnMap;
        try {
            returnMap = WeiXinPayUtil.parseXml(request);
            if (returnMap.size() > 0) {
                Object out_trade_no = returnMap.get("out_trade_no");
                if (out_trade_no != null) {
                    InsureRealOrder insureRealOrder = insureRealOrderService.get((String) out_trade_no);
                    if (insureRealOrder != null) {
                        //这里先获取用户要支付的公众号配置
                        insureRealOrder.setPayTime(new Date());
                        insureRealOrder.setPayState("1");
                        insureRealOrderService.update(insureRealOrder);
                        String state = insureRealOrder.getState();
                        if (StringUtils.isNotBlank(state)) {
                            state = "待处理";

                        }
                        String payState = insureRealOrder.getPayState();
                        if (StringUtils.isNotBlank(payState)) {
                            payState = "已支付";

                        }
                        User user = userService.get(insureRealOrder.getUserId());
                        if (StringUtils.isNotBlank(user.getMiniappOpenId())) {
                            String template_id = Constants.API_MOVECARInsure_TEMPLATE_ID;
                            String data = Constants.API_MOVECAR_TEMPLATE_DATA2;
                            Date date = new Date();
                            data = String.format(data, insureRealOrder.getId(), insureRealOrder.getServiceType(), state, payState, insureRealOrder.getPayMoney(), date, date);
                            String sysUserMsgId = ConfigUtil.getValue("chl_program_sys_user_msg_id");
                            TemplateMessageUtil.sendApiMsg(insureRealOrder.getFromId(), user.getMiniappOpenId(), template_id, data, sysUserMsgId, "pages/index/main");
                        }
                      //这个是微信支付回调必须要的,不然会多次回调
                        result = "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";

                    }
                }
            }
            response.getWriter().write(result);
            response.getWriter().flush();
            response.getWriter().close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

二、微信退款  
1. 
   /**
     * 改变订单状态(微信小程序或者微信公众号申请退款需要的证书可以是同一个,每次下载都会不同,使用最新下载证书)
     *
     * @param
     * @return
     */
    @RequestMapping("safeChangeStateById")
    public void safeChangeStateById(@RequestParam(required = false) String id, @RequestParam(required = false) String state,
                                HttpServletResponse response, HttpServletRequest request) {
        ReturnInfo info = new ReturnInfo();
        try {
            InsureRealOrder insureRealOrder = insureRealOrderService.get(id);
            User user = userService.get(insureRealOrder.getUserId());
            if (user == null) {
                throw new Exception("用户为空");
            }
            String tel = insureRealOrder.getTel();

            String openId = user.getMiniappOpenId();

            String sys_user_msg_id = ConfigUtil.getValue("sys_user_msg_id");

            //这里先获取退款用户的公众号配置
            String appid = ConfigUtil.getValue("appID");
            String mch_id = ConfigUtil.getValue("shop_mchid");
            String key = ConfigUtil.getValue("weixin.key");
            if (StringUtils.isNotBlank(sysUserMsgId)) {
                SysUserMsg sysUserMsg = sysUserMsgService.get(sysUserMsgId);
                if (sysUserMsg != null) {
                    appid = sysUserMsg.getAppId();
                    mch_id = sysUserMsg.getShopMchId();
                    key = sysUserMsg.getPayKey();
                }
            }
            if ("1".equals(insureRealOrder.getIsApi())) {
                appid = ConfigUtil.getValue("chl_program_app_id");
                mch_id = ConfigUtil.getValue("chl_program_mch_id");
                key = ConfigUtil.getValue("chl_program_pay_key");
            }
            Date date = new Date();
            if ("1".equals(state)) {
                state = "2";

            }
            else if ("1".equals(state)) {
                state = "2";
                info.setResult(true);
            }
            else if ("-1".equals(state)) {
                //只有在支付后才能退金额AND抵扣余额(订单存在且存在支付金额,支付时间)
                if (insureRealOrder != null) {
                    String state1 = insureRealOrder.getState();
                    //有已支付订单,-->有无付款
                    if (insureRealOrder.getPayTime() != null) {
                        //付款
                        if (insureRealOrder.getPayMoney() > 0) {
                            //处理中,支付成功的违章才能处理失败
                            if (state1.equals("2") || state1.equals("1")||state1.equals("0")) {
                                HashMap<String, Object> paramsMap = new HashMap<>();
                                DecimalFormat decimalFormat = new DecimalFormat("#");
                                paramsMap.put("appid", appid);  //公众号id
                                paramsMap.put("mch_id", mch_id);    //商户号
                                paramsMap.put("nonce_str", ConfigUtil.getValue("randomStr"));   //随机字符串
                                paramsMap.put("out_trade_no", insureRealOrder.getId());  //订单号
                                paramsMap.put("out_refund_no", insureRealOrder.getId());  //退款订单号
                                paramsMap.put("fee_type", "CNY");
                                paramsMap.put("total_fee", decimalFormat.format(insureRealOrder.getPayMoney() * 100));  //订单金额
                                paramsMap.put("refund_fee", decimalFormat.format(insureRealOrder.getPayMoney() * 100));  //退款金额
                                paramsMap.put("sign", AdvancedWeiXinPaySignUtils.buildRequestMysign(paramsMap, key));         //签名
                                //把参数转换成xml字符串
                                //这个在下面工具类里 
                                String reuqestXml = WeiXinPayUtil.getRequestXml(paramsMap);
                                log.info("----------------------给微信发送-----退款----------------------");
                                log.info(reuqestXml);
                                log.info("----------------------微信返回-----退款----------------------");
                                //这个也在下面工具类里 
                                String returnResult = WeiXinPayUtil.httpsRequestForReturn(reuqestXml, mch_id.toCharArray(), insureRealOrder.getIsApi());
                                log.info(returnResult);
                                if (!StringUtils.isBlank(returnResult)) {
                                    Map<String, String> resMap = new HashMap<String, String>();
                                    resMap = WeiXinPayUtil.doXMLParse(returnResult);
                                    log.info(resMap);
                                    String return_code = resMap.get("return_code");
                                    String result_code = resMap.get("result_code");
                                    String return_msg = resMap.get("return_msg");
                                    if ("SUCCESS".equalsIgnoreCase(return_code) && "SUCCESS".equalsIgnoreCase(result_code)) {
                                        info.setResult(true);
                                        log.info("return_msg----------" + return_msg);
                                    } else {
                                        info.setResult(false);
                                    }
                                }
                                //-------------------支付金额退还结束---------------------
                          

                            }
                        }

  
                    }
               }
                    } else if (state.equals("0")) {
                        state = "1";
                    }
            if (info.isResult()) {
                insureRealOrder.setState(state);
                insureRealOrder.setUpdateTime(date);
                    insureRealOrderService.saveOrUpdate(insureRealOrder);
                    info.setObj(insureRealOrder);
                    info.setResult(true);
            } else {
               info.setObj(insureRealOrder);
               this.writeJson(response, info);
           }
                } catch (Exception e) {
                    e.printStackTrace();
                    info.setMsg("系统异常");
                    info.setResult(false);
                }
                this.writeJson(response, info);

            }

2.工具类util(微信支付工具)

package com.zc.project.utils.pay;
import java.io.*;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.xml.XMLConstants;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.dom4j.io.SAXReader;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import com.zc.project.utils.ConfigUtil;

/**
 * 微信支付工具
 *
 * @author zhangxiao
 * @author 2016年11月25日下午4:15:51
 * @Description
 */
public class WeiXinPayUtil {


    public static final String WEIXIN_APP_CS_APPID = ConfigUtil.getValue("weixinappcs.appid");
    public static final String WEIXIN_APP_SHOP_APPID = ConfigUtil.getValue("appID");


    public static final String WEIXIN_APP_CS_MCHID = ConfigUtil.getValue("weixinappcs.mch_id");
    public static final String WEIXIN_APP_SHOP_MCHID = ConfigUtil.getValue("shop_mchid");
    public static final String NOTIFY_URL = ConfigUtil.getValue("weixin.notify_url");

    /**
     * 把参数转换成xml字符串
     *
     * @param parameters
     * @return
     */
    public static String getRequestXml(Map<String, Object> parameters) {
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set<Entry<String, Object>> es = parameters.entrySet();
        Iterator<Entry<String, Object>> it = es.iterator();
        while (it.hasNext()) {
            Entry<String, Object> entry = it.next();
            String k = entry.getKey();
            Object v = entry.getValue();
            if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
                sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
            } else {
                sb.append("<" + k + ">" + v + "</" + k + ">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }

    /**
     * 微信提供给商户的服务接入网关URL
     */
    private static final String WEIXINPAY_GATEWAY = "https://api.mch.weixin.qq.com/pay/unifiedorder";

    /**
     * 发送https请求
     *
     * @param xmlParam 提交的数据
     * @return 返回微信服务器响应的信息
     */
    public static String httpsRequest(String xmlParam) {
        String result = "";
        //创建httpclient工具对象
        DefaultHttpClient client = new DefaultHttpClient();
        //创建post请求方法
        HttpPost method = new HttpPost(WEIXINPAY_GATEWAY);
        StringEntity entity = new StringEntity(xmlParam, "UTF-8");
        entity.setContentType("text/xml");
        method.setEntity(entity);
        try {
            HttpResponse response = client.execute(method);
            result = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 微信退款发送https请求
     *
     * @param xmlParam 提交的数据
     * @return 返回微信服务器响应的信息
     */
    public static String httpsRequestForReturn(String xmlParam, char[] chars, String isApi) throws IOException {
        CloseableHttpClient httpclient = null;
        StringBuilder sb = new StringBuilder();
        try {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            File file = null;
            //证书路径(证书路径)线上
//            if("1".equals(isApi)){
//                file = new File("/usr/apiclient_cert_api.p12");
//            }else{
//                file = new File("/usr/apiclient_cert.p12");
//            }
            //测试路径
            if("1".equals(isApi)){
//                file = new File("D:/微信商户平台支付证书/apiclient_cert_api.p12");
                file = new File("D:/微信商户平台支付证书/apiclient_cert.p12");
            }else{
                file = new File("D:/微信商户平台支付证书/apiclient_cert.p12");
            }


            FileInputStream instream = new FileInputStream(file);//放退款证书的路径
            try {
                keyStore.load(instream, chars);
            } finally {
                instream.close();
            }
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, chars).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");//退款接口
            System.out.println("executing request" + httpPost.getRequestLine());
            StringEntity reqEntity = new StringEntity(xmlParam);
            // 设置类型
            reqEntity.setContentType("application/x-www-form-urlencoded");
            httpPost.setEntity(reqEntity);
            CloseableHttpResponse cresponse = httpclient.execute(httpPost);
            HttpEntity entity = cresponse.getEntity();
            System.out.println("----------------------------------------");
            System.out.println(cresponse.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
                String text;
                while ((text = bufferedReader.readLine()) != null) {
                    sb.append(text);
                }
            }
            EntityUtils.consume(entity);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpclient.close();
        }
        return sb.toString();
    }

    /**
     * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
     *
     * @param strxml
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public static Map<String, String> doXMLParse(String strxml) throws JDOMException, IOException {
        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");

        if (null == strxml || "".equals(strxml)) {
            return null;
        }

        Map<String, String> m = new HashMap<String, String>();

        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        SAXBuilder builder = new SAXBuilder();
        // 这是优先选择. 如果不允许DTDs (doctypes) ,几乎可以阻止所有的XML实体攻击
        builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

        builder.setFeature("http://xml.org/sax/features/external-general-entities", false);

        builder.setFeature("http://xml.org/sax/features/external-parameter-entities", false);

        builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        builder.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Element e = (Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if (children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v = getChildrenText(children);
            }

            m.put(k, v);
        }
        //关闭流
        in.close();

        return m;
    }

    /**
     * 获取子结点的xml
     *
     * @param children
     * @return String
     */
    public static String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if (!children.isEmpty()) {
            Iterator it = children.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<" + name + ">");
                if (!list.isEmpty()) {
                    sb.append(getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }

        return sb.toString();
    }

    /**
     * * 解析微信发来的请求(XML)
     * * @param request
     * * @return
     * * @throws Exception
     **/
    public static Map<String, Object> parseXml(HttpServletRequest request) throws Exception {
        // 将解析结果存储在HashMap中
        Map<String, Object> map = new HashMap<String, Object>();

        // 从request中取得输入流
        InputStream inputStream = request.getInputStream();
        // 读取输入流
        SAXReader reader = new SAXReader();
        // 这是优先选择. 如果不允许DTDs (doctypes) ,几乎可以阻止所有的XML实体攻击
        reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

        reader.setFeature("http://xml.org/sax/features/external-general-entities", false);

        reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);

        reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        reader.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        org.dom4j.Document document = reader.read(inputStream);
        // 得到xml根元素
        org.dom4j.Element root = document.getRootElement();
        // 得到根元素的所有子节点
        List<org.dom4j.Element> elementList = root.elements();

        // 遍历所有子节点
        for (org.dom4j.Element e : elementList)
            map.put(e.getName(), e.getText());
        // 释放资源
        inputStream.close();
        inputStream = null;
        return map;
    }

}
这只是自己的简单笔记!
发布了24 篇原创文章 · 获赞 0 · 访问量 735

猜你喜欢

转载自blog.csdn.net/weixin_43355449/article/details/103166570