linwe
2024-08-09 8b7258c9427882bb1798f1502eaa35184c6e374e
src/main/java/org/springblade/modules/pay/service/impl/WxPayServiceImpl.java
@@ -1,25 +1,750 @@
package org.springblade.modules.pay.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.gson.Gson;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.common.config.WxPayConfig;
import org.springblade.common.enums.OrderStatus;
import org.springblade.common.enums.wxpay.WxApiType;
import org.springblade.common.enums.wxpay.WxNotifyType;
import org.springblade.common.enums.wxpay.WxRefundStatus;
import org.springblade.common.enums.wxpay.WxTradeState;
import org.springblade.common.exception.CustomException;
import org.springblade.common.utils.HttpUtils;
import org.springblade.common.utils.SpringUtils;
import org.springblade.common.utils.WechatPay2ValidatorForRequest;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.modules.pay.entity.OrderInfoEntity;
import org.springblade.modules.pay.entity.RefundInfoEntity;
import org.springblade.modules.pay.entity.WxPayInfo;
import org.springblade.modules.pay.mapper.WxPayMapper;
import org.springblade.modules.pay.service.IOrderInfoService;
import org.springblade.modules.pay.service.IPaymentInfoService;
import org.springblade.modules.pay.service.IRefundInfoService;
import org.springblade.modules.pay.service.IWxPayService;
import org.springframework.beans.factory.annotation.Value;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
@Service
public class WxPayServiceImpl extends ServiceImpl<WxPayMapper,WxPayInfo> implements IWxPayService {
public class WxPayServiceImpl extends ServiceImpl<WxPayMapper, WxPayInfo> implements IWxPayService {
   private static Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class);
   private final String  MINI_PROGRAM_APP_ID = "wx41aa8a5d2e565a05";
   @Resource
   private WxPayConfig wxPayConfig;
//   @Resource
//   private CloseableHttpClient wxPayClient;
   @Resource
   private IOrderInfoService orderInfoService;
   @Resource
   private IPaymentInfoService paymentInfoService;
   @Resource
   private IRefundInfoService refundsInfoService;
   private final ReentrantLock lock = new ReentrantLock();
   @Transactional(rollbackFor = Exception.class)
   @Override
   public void processOrder(Map<String, Object> bodyMap) throws GeneralSecurityException {
      logger.info("处理订单");
      //解密报文
      String plainText = decryptFromResource(bodyMap);
      //将明文转换成map
      Gson gson = new Gson();
      HashMap plainTextMap = gson.fromJson(plainText, HashMap.class);
      String orderNo = (String) plainTextMap.get("out_trade_no");
        /*在对业务数据进行状态检查和处理之前,
        要采用数据锁进行并发控制,
        以避免函数重入造成的数据混乱*/
      //尝试获取锁:
      // 成功获取则立即返回true,获取失败则立即返回false。不必一直等待锁的释放
      if (lock.tryLock()) {
         try {
            //处理重复的通知
            //接口调用的幂等性:无论接口被调用多少次,产生的结果是一致的。
            String orderStatus = orderInfoService.getOrderStatus(orderNo);
            if (!OrderStatus.NOTPAY.getType().equals(orderStatus)) {
               return;
            }
            //模拟通知并发
            try {
               TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
            //更新订单状态
            orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS);
            //记录支付日志
            paymentInfoService.createPaymentInfo(plainText);
         } finally {
            //要主动释放锁
            lock.unlock();
         }
      }
   }
   /**
    * 用户取消订单
    *
    * @param orderNo
    */
   @Override
   public void cancelOrder(String orderNo) throws Exception {
      //调用微信支付的关单接口
      this.closeOrder(orderNo);
      //更新商户端的订单状态
      orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.CANCEL);
   }
   @Override
   public Object getOpenId(String code) {
   public String queryOrder(String orderNo) throws Exception {
      logger.info("查单接口调用 ===> {}", orderNo);
      String url = String.format(WxApiType.ORDER_QUERY_BY_NO.getType(), orderNo);
      url = wxPayConfig.getDomain().concat(url).concat("?mchid=").concat(wxPayConfig.getMchId());
      HttpGet httpGet = new HttpGet(url);
      httpGet.setHeader("Accept", "application/json");
      //完成签名并执行请求
      CloseableHttpResponse response = null;//wxPayClient.execute(httpGet);
      try {
         String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
         int statusCode = response.getStatusLine().getStatusCode();//响应状态码
         if (statusCode == 200) { //处理成功
            logger.info("成功, 返回结果 = " + bodyAsString);
         } else if (statusCode == 204) { //处理成功,无返回Body
            logger.info("成功");
         } else {
            logger.info("查单接口调用,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
            throw new IOException("request failed");
         }
      return null;
         return bodyAsString;
      } finally {
         response.close();
      }
   }
   /**
    * 根据订单号查询微信支付查单接口,核实订单状态
    * 如果订单已支付,则更新商户端订单状态,并记录支付日志
    * 如果订单未支付,则调用关单接口关闭订单,并更新商户端订单状态
    *
    * @param orderNo
    */
   @Transactional(rollbackFor = Exception.class)
   @Override
   public void checkOrderStatus(String orderNo) throws Exception {
      logger.info("根据订单号核实订单状态 ===> {}", orderNo);
      //调用微信支付查单接口
      String result = this.queryOrder(orderNo);
      Gson gson = new Gson();
      Map<String, String> resultMap = gson.fromJson(result, HashMap.class);
      //获取微信支付端的订单状态
      String tradeState = resultMap.get("trade_state");
      //判断订单状态
      if (WxTradeState.SUCCESS.getType().equals(tradeState)) {
         logger.info("核实订单已支付 ===> {}", orderNo);
         //如果确认订单已支付则更新本地订单状态
         orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS);
         //记录支付日志
         paymentInfoService.createPaymentInfo(result);
      }
      if (WxTradeState.NOTPAY.getType().equals(tradeState)) {
         logger.info("核实订单未支付 ===> {}", orderNo);
         //如果订单未支付,则调用关单接口
         this.closeOrder(orderNo);
         //更新本地订单状态
         orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.CLOSED);
      }
   }
   /**
    * 退款
    *
    * @param orderNo
    * @param reason
    * @throws IOException
    */
   @Transactional(rollbackFor = Exception.class)
   @Override
   public void refund(String orderNo, String reason) throws Exception {
      logger.info("创建退款单记录");
      //根据订单编号创建退款单
      RefundInfoEntity refundsInfo = refundsInfoService.createRefundByOrderNo(orderNo, reason);
      logger.info("调用退款API");
      //调用统一下单API
      String url = wxPayConfig.getDomain().concat(WxApiType.DOMESTIC_REFUNDS.getType());
      HttpPost httpPost = new HttpPost(url);
      // 请求body参数
      Gson gson = new Gson();
      Map paramsMap = new HashMap();
      paramsMap.put("out_trade_no", orderNo);//订单编号
      paramsMap.put("out_refund_no", refundsInfo.getRefundNo());//退款单编号
      paramsMap.put("reason", reason);//退款原因
      paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.REFUND_NOTIFY.getType()));//退款通知地址
      Map amountMap = new HashMap();
      amountMap.put("refund", refundsInfo.getRefund());//退款金额
      amountMap.put("total", refundsInfo.getTotalFee());//原订单金额
      amountMap.put("currency", "CNY");//退款币种
      paramsMap.put("amount", amountMap);
      //将参数转换成json字符串
      String jsonParams = gson.toJson(paramsMap);
      logger.info("请求参数 ===> {}" + jsonParams);
      StringEntity entity = new StringEntity(jsonParams, "utf-8");
      entity.setContentType("application/json");//设置请求报文格式
      httpPost.setEntity(entity);//将请求报文放入请求对象
      httpPost.setHeader("Accept", "application/json");//设置响应报文格式
      //完成签名并执行请求,并完成验签
      CloseableHttpResponse response =null;// wxPayClient.execute(httpPost);
      try {
         //解析响应结果
         String bodyAsString = EntityUtils.toString(response.getEntity());
         int statusCode = response.getStatusLine().getStatusCode();
         if (statusCode == 200) {
            logger.info("成功, 退款返回结果 = " + bodyAsString);
         } else if (statusCode == 204) {
            logger.info("成功");
         } else {
            throw new RuntimeException("退款异常, 响应码 = " + statusCode + ", 退款返回结果 = " + bodyAsString);
         }
         //更新订单状态
         orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_PROCESSING);
         //更新退款单
         refundsInfoService.updateRefund(bodyAsString);
      } finally {
         response.close();
      }
   }
   /**
    * 查询退款接口调用
    *
    * @param refundNo
    * @return
    */
   @Override
   public String queryRefund(String refundNo) throws Exception {
      logger.info("查询退款接口调用 ===> {}", refundNo);
      String url = String.format(WxApiType.DOMESTIC_REFUNDS_QUERY.getType(), refundNo);
      url = wxPayConfig.getDomain().concat(url);
      //创建远程Get 请求对象
      HttpGet httpGet = new HttpGet(url);
      httpGet.setHeader("Accept", "application/json");
      //完成签名并执行请求
      CloseableHttpResponse response = null;//wxPayClient.execute(httpGet);
      try {
         String bodyAsString = EntityUtils.toString(response.getEntity());
         int statusCode = response.getStatusLine().getStatusCode();
         if (statusCode == 200) {
            logger.info("成功, 查询退款返回结果 = " + bodyAsString);
         } else if (statusCode == 204) {
            logger.info("成功");
         } else {
            throw new RuntimeException("查询退款异常, 响应码 = " + statusCode + ", 查询退款返回结果 = " + bodyAsString);
         }
         return bodyAsString;
      } finally {
         response.close();
      }
   }
   /**
    * 根据退款单号核实退款单状态
    *
    * @param refundNo
    * @return
    */
   @Transactional(rollbackFor = Exception.class)
   @Override
   public void checkRefundStatus(String refundNo) throws Exception {
      logger.info("根据退款单号核实退款单状态 ===> {}", refundNo);
      //调用查询退款单接口
      String result = this.queryRefund(refundNo);
      //组装json请求体字符串
      Gson gson = new Gson();
      Map<String, String> resultMap = gson.fromJson(result, HashMap.class);
      //获取微信支付端退款状态
      String status = resultMap.get("status");
      String orderNo = resultMap.get("out_trade_no");
      if (WxRefundStatus.SUCCESS.getType().equals(status)) {
         logger.info("核实订单已退款成功 ===> {}", refundNo);
         //如果确认退款成功,则更新订单状态
         orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_SUCCESS);
         //更新退款单
         refundsInfoService.updateRefund(result);
      }
      if (WxRefundStatus.ABNORMAL.getType().equals(status)) {
         logger.info("核实订单退款异常  ===> {}", refundNo);
         //如果确认退款成功,则更新订单状态
         orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_ABNORMAL);
         //更新退款单
         refundsInfoService.updateRefund(result);
      }
   }
   /**
    * 处理退款单
    */
   @Transactional(rollbackFor = Exception.class)
   @Override
   public void processRefund(Map<String, Object> bodyMap) throws Exception {
      logger.info("退款单");
      //解密报文
      String plainText = decryptFromResource(bodyMap);
      //将明文转换成map
      Gson gson = new Gson();
      HashMap plainTextMap = gson.fromJson(plainText, HashMap.class);
      String orderNo = (String) plainTextMap.get("out_trade_no");
      if (lock.tryLock()) {
         try {
            String orderStatus = orderInfoService.getOrderStatus(orderNo);
            if (!OrderStatus.REFUND_PROCESSING.getType().equals(orderStatus)) {
               return;
            }
            //更新订单状态
            orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_SUCCESS);
            //更新退款单
            refundsInfoService.updateRefund(plainText);
         } finally {
            //要主动释放锁
            lock.unlock();
         }
      }
   }
   @Override
   public Map<String, String> jsapiPay(Long properChargeRecordId) throws IOException {
      String prepayId = "";
      //生成订单
      OrderInfoEntity orderInfo = orderInfoService.getOne(Wrappers.<OrderInfoEntity>lambdaQuery().eq(OrderInfoEntity::getProperChargeRecordId, properChargeRecordId));
      if (orderInfo.getTotalFee() <= 0) {
         throw new CustomException("支付金额不能低于等于0元");
      }
      IUserService userService = SpringUtils.getBean(IUserService.class);
      User serviceOne = userService.getOne(Wrappers.<User>lambdaQuery().eq(User::getId, AuthUtil.getUserId()));
      logger.info("调用统一下单API");
      //调用统一下单API
      HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.JSAPI_PAY.getType()));
      // 请求body参数
      Gson gson = new Gson();
      Map paramsMap = new HashMap();
      paramsMap.put("appid", wxPayConfig.getAppid());
      paramsMap.put("mchid", wxPayConfig.getMchId());
      paramsMap.put("description", orderInfo.getTitle());
      paramsMap.put("out_trade_no", orderInfo.getOrderNo());
      paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));
      Map amountMap = new HashMap();
      amountMap.put("total", orderInfo.getTotalFee());
      amountMap.put("currency", "CNY");
      paramsMap.put("amount", amountMap);
      Map payerMap = new HashMap();
      payerMap.put("openid", serviceOne.getMiniOpenId());
      paramsMap.put("payer", payerMap);
      // 是否指定分账,枚举值 true:是 false:否
      paramsMap.put("profit_sharing", true);
      //将参数转换成json字符串
      String jsonParams = gson.toJson(paramsMap);
      logger.info("请求参数 ===> {}" + jsonParams);
      StringEntity entity = new StringEntity(jsonParams, "utf-8");
      entity.setContentType("application/json");
      httpPost.setEntity(entity);
      httpPost.setHeader("Accept", "application/json");
      //完成签名并执行请求
      CloseableHttpResponse response = null;//wxPayClient.execute(httpPost);
      try {
         String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
         int statusCode = response.getStatusLine().getStatusCode();//响应状态码
         if (statusCode == 200) { //处理成功
            logger.info("成功, 返回结果 = " + bodyAsString);
         } else if (statusCode == 204) { //处理成功,无返回Body
            logger.info("成功");
         } else {
            logger.info("jszpi下单失败,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
            throw new IOException("request failed");
         }
         //响应结果
         Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
         //预支付交易会话标识
         prepayId = resultMap.get("prepay_id");
         //返回预支付交易会话标识
         // 组装前端预下单参数
         /** 返回给前端所需要的数据 */
         SortedMap<String, String> payMap = new TreeMap<>();
         String nonceStr = WXPayUtil.generateNonceStr();
         String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
         payMap.put("appId", wxPayConfig.getAppid());
         payMap.put("timeStamp", timestamp);
         payMap.put("nonceStr", nonceStr);
         payMap.put("signType", "RSA");
         payMap.put("package", "prepay_id=" + prepayId);
         String paySign = getSign(wxPayConfig.getAppid(), prepayId, timestamp, nonceStr);
         payMap.put("paySign", paySign);
         logger.info("返回参数 ===> {}" + gson.toJson(payMap));
         return payMap;
      } catch (IOException e) {
         throw new RuntimeException(e);
      } catch (SignatureException e) {
         throw new RuntimeException(e);
      } catch (NoSuchAlgorithmException e) {
         throw new RuntimeException(e);
      } catch (InvalidKeyException e) {
         throw new RuntimeException(e);
      } finally {
         response.close();
      }
   }
   /**
    * 通过prepay_id获取签名
    *
    * @param appid
    * @param prepay_id
    * @param timestamp
    * @param nonceStr
    * @return
    * @throws IOException
    * @throws SignatureException
    * @throws NoSuchAlgorithmException
    * @throws InvalidKeyException
    */
   String getSign(String appid, String prepay_id, String timestamp, String nonceStr) throws IOException, SignatureException, NoSuchAlgorithmException, InvalidKeyException {
      //从下往上依次生成
      String message = getSignStr(appid, timestamp, nonceStr, "prepay_id=" + prepay_id);
      //签名
      String signature = sign(message.getBytes("utf-8"));
      return signature;
   }
   String sign(byte[] message) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException {
      //签名方式
      Signature sign = Signature.getInstance("SHA256withRSA");
      //私钥,通过MyPrivateKey来获取,这是个静态类可以接调用方法 ,需要的是_key.pem文件的绝对路径配上文件名
      sign.initSign(getPrivateKey(wxPayConfig.getPrivateKeyPath()));
      sign.update(message);
      return Base64.getEncoder().encodeToString(sign.sign());
   }
   /**
    * 按照前端签名文档规范进行排序
    *
    * @param appId
    * @param timeStamp
    * @param nonceStr
    * @param packageValue
    * @return
    */
   private String getSignStr(String appId, String timeStamp, String nonceStr, String packageValue) {
      return String.format("%s\n%s\n%s\n%s\n", appId, timeStamp, nonceStr, packageValue);
   }
   private PrivateKey getPrivateKey(String filename) {
      try {
         FileInputStream fileInputStream = new FileInputStream(filename);
         logger.info("文件内容:" + fileInputStream);
         return PemUtil.loadPrivateKey(fileInputStream);
      } catch (Exception e) {
         logger.info("私钥文件不存在", e);
         throw new RuntimeException("私钥文件不存在", e);
      }
   }
   /**
    * 关单接口的调用
    *
    * @param orderNo
    */
   private void closeOrder(String orderNo) throws Exception {
      logger.info("关单接口的调用,订单号 ===> {}", orderNo);
      //创建远程请求对象
      String url = String.format(WxApiType.CLOSE_ORDER_BY_NO.getType(), orderNo);
      url = wxPayConfig.getDomain().concat(url);
      HttpPost httpPost = new HttpPost(url);
      //组装json请求体
      Gson gson = new Gson();
      Map<String, String> paramsMap = new HashMap<>();
      paramsMap.put("mchid", wxPayConfig.getMchId());
      String jsonParams = gson.toJson(paramsMap);
      logger.info("请求参数 ===> {}", jsonParams);
      //将请求参数设置到请求对象中
      StringEntity entity = new StringEntity(jsonParams, "utf-8");
      entity.setContentType("application/json");
      httpPost.setEntity(entity);
      httpPost.setHeader("Accept", "application/json");
      //完成签名并执行请求
      CloseableHttpResponse response = null;//wxPayClient.execute(httpPost);
      try {
         int statusCode = response.getStatusLine().getStatusCode();//响应状态码
         if (statusCode == 200) { //处理成功
            logger.info("成功200");
         } else if (statusCode == 204) { //处理成功,无返回Body
            logger.info("成功204");
         } else {
            logger.info("Native下单失败,响应码 = " + statusCode);
            throw new IOException("request failed");
         }
      } finally {
         response.close();
      }
   }
   /**
    * 对称解密
    *
    * @param bodyMap
    * @return
    */
   private String decryptFromResource(Map<String, Object> bodyMap) throws GeneralSecurityException {
      logger.info("密文解密");
      //通知数据
      Map<String, String> resourceMap = (Map) bodyMap.get("resource");
      //数据密文
      String ciphertext = resourceMap.get("ciphertext");
      //随机串
      String nonce = resourceMap.get("nonce");
      //附加数据
      String associatedData = resourceMap.get("associated_data");
      logger.info("密文 ===> {}", ciphertext);
      AesUtil aesUtil = new AesUtil(wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
      String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
         nonce.getBytes(StandardCharsets.UTF_8),
         ciphertext);
      logger.info("明文 ===> {}", plainText);
      return plainText;
   }
   @Override
   public String nativeNotify(HttpServletRequest request, HttpServletResponse response) {
      Gson gson = new Gson();
      Map<String, String> map = new HashMap<>();//应答对象
      try {
         //处理通知参数
         String body = HttpUtils.readData(request);
         Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
         String requestId = (String) bodyMap.get("id");
         logger.info("支付通知的id ===> {}", requestId);
         logger.info("支付通知的完整数据 ===> {}", body);
         //int a = 9 / 0;
         //签名的验证
         WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
            = new WechatPay2ValidatorForRequest(wxPayConfig.getVerifier(), requestId, body);
         if (!wechatPay2ValidatorForRequest.validate(request)) {
            logger.error("通知验签失败");
            //失败应答
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "通知验签失败");
            return gson.toJson(map);
         }
         logger.info("通知验签成功");
         //处理订单
         processOrder(bodyMap);
         //成功应答
         response.setStatus(200);
         map.put("code", "SUCCESS");
         map.put("message", "成功");
         return gson.toJson(map);
      } catch (Exception e) {
         e.printStackTrace();
         //失败应答
         response.setStatus(500);
         map.put("code", "ERROR");
         map.put("message", "失败");
         return gson.toJson(map);
      }
   }
   @Override
   public String refundsNotify(HttpServletRequest request, HttpServletResponse response) {
      Gson gson = new Gson();
      Map<String, String> map = new HashMap<>();//应答对象
      try {
         //处理通知参数
         String body = HttpUtils.readData(request);
         Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
         String requestId = (String) bodyMap.get("id");
         logger.info("支付通知的id ===> {}", requestId);
         //签名的验证
         WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
            = new WechatPay2ValidatorForRequest(wxPayConfig.getVerifier(), requestId, body);
         if (!wechatPay2ValidatorForRequest.validate(request)) {
            logger.error("通知验签失败");
            //失败应答
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "通知验签失败");
            return gson.toJson(map);
         }
         logger.info("通知验签成功");
         //处理退款单
         processRefund(bodyMap);
         //成功应答
         response.setStatus(200);
         map.put("code", "SUCCESS");
         map.put("message", "成功");
         return gson.toJson(map);
      } catch (Exception e) {
         e.printStackTrace();
         //失败应答
         response.setStatus(500);
         map.put("code", "ERROR");
         map.put("message", "失败");
         return gson.toJson(map);
      }
   }
   //创建签名所需要的参数xml格式
//   public static String createXML(Map<String, Object> map) {
//      String xml = "<xml>";
//      Set<String> set = map.keySet();
//      Iterator<String> i = set.iterator();
//      while (i.hasNext()) {
//         String str = i.next();
//         xml += "<" + str + ">" + "<![CDATA[" + map.get(str) + "]]>" + "</" + str + ">";
//      }
//      xml += "</xml>";
//      return xml;
//   }
}