| @@ -0,0 +1,64 @@ | |||||
| package com.iformall.controller; | |||||
| import com.iformall.annotation.AuthIgnore; | |||||
| import com.iformall.domain.entity.WxPayment; | |||||
| import com.iformall.service.wx.WxPayService; | |||||
| import com.iformall.utils.XmlUtil; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.apache.commons.io.IOUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.annotation.PathVariable; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| import java.nio.charset.Charset; | |||||
| import java.util.Map; | |||||
| import java.util.SortedMap; | |||||
| import java.util.TreeMap; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| @Slf4j | |||||
| @RestController | |||||
| @RequestMapping("/paidCallback") | |||||
| public class WxPaidCallBackController extends BaseController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private WxPayService wxPayService; | |||||
| /** | |||||
| * @description 停车费支付成功通知 | |||||
| * {dataItems=[{"inTime":"2020-12-09 11:21:15","carNumber":"浙-AF81797","inCarPhoto":"p201127315/NISSP_IMG_PARK_IN/20201209/a9f1130651b9493f8eab64f14afbdd47","isReal":0,"itemId":"a9f1130651b9493f8eab64f14afbdd47","inOperator":"超级管理员","equipName":"东门入口","parkName":"杭州东站西子国际","vehicleInfo":"{\"plateNo\":\"浙-AF81797\",\"plateColor\":\"GREEN\",\"plateBackColor\":0,\"plateWordColor\":0,\"vehicleColor\":null,\"vehicleLogo\":null,\"vehicleModel\":null,\"mainModel\":0,\"subModel\":0,\"vehicleModelTrust\":0,\"mainModelTrust\":0,\"subModelTrust\":0,\"plateNoTrust\":1,\"vehicleLogoTrust\":0,\"vehicleColorTrust\":0}","equipCode":"208202496","parkCode":"p201127315"}], pno=dzxzgj, sn=6C958D99D2769AA16F3A3F06E962263F, tn=-2, ts=20201209112118886, ve=1.0} | |||||
| * | |||||
| * | |||||
| * | |||||
| * @Params [paramMap] | |||||
| * @return com.iformall.common.Result | |||||
| * @Author furunxin | |||||
| * @Date 2020/7/8 上午8:27 | |||||
| **/ | |||||
| @AuthIgnore | |||||
| @RequestMapping(value = "/paid/{tenantId}") | |||||
| public String parkInCallback(@PathVariable String tenantId,HttpServletRequest request) { | |||||
| Map<String, String> paramMap = null; | |||||
| String response = ""; | |||||
| String xml = ""; | |||||
| try { | |||||
| xml = IOUtils.toString(request.getInputStream(), Charset.forName("UTF-8")); | |||||
| paramMap = WxPayment.xmlToMap(xml); | |||||
| paramMap.put("tenantId", tenantId); | |||||
| wxPayService.handlePaidCallBack(tenantId, paramMap); | |||||
| logger.info("carPaid wxpay, notify success, req : " + xml + ", resp: " + response.toString()); | |||||
| return response; | |||||
| } catch (Exception e) { | |||||
| logger.error("Paid wxpay, notify error, req: " + xml + ", e: " + e.getMessage()); | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "FAIL"); | |||||
| resultMap.put("return_msg", e.getMessage()); | |||||
| return XmlUtil.getRequestXml(resultMap); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,143 @@ | |||||
| package com.iformall.controller; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.IdWorker; | |||||
| import com.iformall.common.Result; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.domain.entity.PayAdapterResult; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.domain.po.base.BaseEntity; | |||||
| import com.iformall.domain.po.base.BaseEntity.SortField; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import com.iformall.enums.*; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.service.*; | |||||
| import com.iformall.service.wx.WxPayService; | |||||
| import com.iformall.utils.Constant; | |||||
| import com.iformall.utils.SysConfigConstant; | |||||
| import io.swagger.annotations.Api; | |||||
| import io.swagger.annotations.ApiImplicitParam; | |||||
| import io.swagger.annotations.ApiImplicitParams; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.beans.factory.annotation.Qualifier; | |||||
| import org.springframework.data.redis.core.RedisTemplate; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| import java.util.Date; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| @RestController | |||||
| @RequestMapping("/api/pay") | |||||
| public class WxPayController extends BaseController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| WxPayService wxPayService; | |||||
| @Autowired | |||||
| WxAppinfoService wxAppinfoService; | |||||
| @Autowired | |||||
| WxPayAccountService wxPayAccountService; | |||||
| @Autowired | |||||
| SysConfigService sysConfigService; | |||||
| @Autowired | |||||
| @Qualifier("objectCommonRedisTemplate") | |||||
| RedisTemplate<String, Object> redisTemplate; | |||||
| /** | |||||
| * 停车费创建支付订单,只有supportPay=true时才调用此方法 | |||||
| * | |||||
| * @param paramMap | |||||
| * @return | |||||
| */ | |||||
| @ApiOperation(value = "创建支付订单", notes = "{}") | |||||
| @PostMapping("/createPayOrder") | |||||
| public ResultData createPayOrder(@RequestBody Map<String, String> paramMap) { | |||||
| WxCUser wxCUser = this.getCUser(); | |||||
| //String carNumber = paramMap.get("carNumber"); | |||||
| try { | |||||
| WxAppinfo cAppInfo = wxAppinfoService.getCAppInfoFromRedis(wxCUser.getTenantId()); | |||||
| if(cAppInfo == null){ | |||||
| throw new MallinkException(ErrorCode.APPINFO_NOFUND.getCode(),"未查询到C端小程序"); | |||||
| } | |||||
| WxPayAccount payAccount = wxPayAccountService.getByIdFromRedis(cAppInfo.getPayId()); | |||||
| if(payAccount == null){ | |||||
| throw new MallinkException(ErrorCode.APPINFO_NOFUND.getCode(),"未查询到payAccount."); | |||||
| } | |||||
| String receiverAccount = payAccount.getSubMchId(); | |||||
| String apiKey = payAccount.getMerchantApiKey(); | |||||
| int rlength = receiverAccount.length(); | |||||
| //最大128 cuserId,cuserPhone,carNumber,amountType,merchantAccount,parkOrderNo | |||||
| StringBuffer attachSb = new StringBuffer() | |||||
| .append(wxCUser.getId()).append(",") | |||||
| .append(wxCUser.getPhone()); | |||||
| //创建微信支付订单 | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| String uniquePayOrderNo = String.valueOf(idWorker.nextId()); | |||||
| String attach = attachSb.toString(); | |||||
| String productPre = uniquePayOrderNo;//中文签名错误 | |||||
| //String productPre = "ParkOrderId"; | |||||
| SysConfig sysConfig = sysConfigService.getByKey(SysConfigConstant.sale_price, payAccount); | |||||
| SysConfig payCallBack = sysConfigService.getByKey(SysConfigConstant.pay_call_back, payAccount); | |||||
| PayAdapterResult wxResult = wxPayService.createWxPayOrder(payAccount,cAppInfo,false,false,wxCUser.getOpenId(), receiverAccount, productPre, attach, uniquePayOrderNo, Integer.parseInt(sysConfig.getConfigItemValue()), | |||||
| "127.0.0.1", payCallBack.getConfigItemValue(), apiKey, new Date()); | |||||
| if (wxResult.isSuccess()) { | |||||
| return new ResultData(wxResult); | |||||
| }else { | |||||
| return new ResultData(Result.ERROR,wxResult.getMsg()); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| logger.error("createPayOrder error",e); | |||||
| return new ResultData(Result.ERROR,e.getMessage()); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 停车费支付订单列表 | |||||
| * | |||||
| * @param paramMap | |||||
| * @return | |||||
| */ | |||||
| @GetMapping("/payOrderList") | |||||
| @ApiImplicitParams({ | |||||
| @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), | |||||
| @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true), | |||||
| }) | |||||
| public ResultData payOrderList(Integer pageNum, Integer pageSize) { | |||||
| WxCUser wxCUser = this.getCUser(); | |||||
| WxPayOrder carPayOrder = new WxPayOrder(); | |||||
| carPayOrder.updateTenantInfo(getTenantInfo()); | |||||
| carPayOrder.setcUserId(wxCUser.getId()); | |||||
| carPayOrder.setSortColumns(BaseEntity.SortField.CreateTime_DESC); | |||||
| return new ResultData(wxPayService.listPayOrderAsPage(carPayOrder, pageNum, pageSize)); | |||||
| } | |||||
| /** | |||||
| * 停车费支付订单详情 | |||||
| * | |||||
| * @param paramMap | |||||
| * @return | |||||
| */ | |||||
| @GetMapping("/payOrderDetail") | |||||
| @ApiImplicitParams({ | |||||
| @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) | |||||
| }) | |||||
| public ResultData payOrderDetail(Long id) { | |||||
| return new ResultData(wxPayService.detailWxCarPayOrder(id, getTenantInfo().getTenantId())); | |||||
| } | |||||
| } | |||||
| @@ -1,13 +0,0 @@ | |||||
| package com.iformall.common; | |||||
| public class SysConfigConstant { | |||||
| public static final String vierfy_seconds_key="vierfySeconds"; | |||||
| public static final String card_vierfy_seconds_key="cardVierfySeconds"; | |||||
| public static final String default_merchant_b_user = "defaultMerchantBUserId"; | |||||
| public static final String coupon_detail_show_selled = "couponDetailShowSelled"; | |||||
| public static final String coupon_list_show_selled = "couponListShowSelled"; | |||||
| public static final String member_seconds_key="memberSeconds"; | |||||
| public static final String merchant_credit_locked="merchantCreditLocked"; | |||||
| } | |||||
| @@ -0,0 +1,50 @@ | |||||
| package com.iformall.domain.entity; | |||||
| import java.io.Serializable; | |||||
| public class PayAdapterResult implements Serializable{ | |||||
| private static final long serialVersionUID = -6647306162758854293L; | |||||
| private boolean isSuccess; | |||||
| private String msg; | |||||
| private Object data; | |||||
| private String transactionId; | |||||
| public PayAdapterResult() { | |||||
| } | |||||
| public PayAdapterResult(boolean isSuccess,String msg,Object data,String transactionId) { | |||||
| this.isSuccess = isSuccess; | |||||
| this.msg = msg; | |||||
| this.data = data; | |||||
| this.transactionId = transactionId; | |||||
| } | |||||
| public boolean isSuccess() { | |||||
| return isSuccess; | |||||
| } | |||||
| public void setSuccess(boolean isSuccess) { | |||||
| this.isSuccess = isSuccess; | |||||
| } | |||||
| public String getMsg() { | |||||
| return msg; | |||||
| } | |||||
| public void setMsg(String msg) { | |||||
| this.msg = msg; | |||||
| } | |||||
| public Object getData() { | |||||
| return data; | |||||
| } | |||||
| public void setData(Object data) { | |||||
| this.data = data; | |||||
| } | |||||
| public String getTransactionId() { | |||||
| return transactionId; | |||||
| } | |||||
| public void setTransactionId(String transactionId) { | |||||
| this.transactionId = transactionId; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,29 @@ | |||||
| package com.iformall.service.pay.entity; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| public class PayExtraParam { | |||||
| private Map map = new HashMap(); | |||||
| public PayExtraParam() { | |||||
| } | |||||
| public PayExtraParam(Object key,Object value) { | |||||
| map.put(key, value); | |||||
| } | |||||
| public Object getValue(String key) { | |||||
| if (map.containsKey(key)) { | |||||
| return map.get(key); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public PayExtraParam set(Object key,Object value) { | |||||
| this.map.put(key, value); | |||||
| return this; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,340 @@ | |||||
| package com.iformall.domain.entity; | |||||
| import java.security.cert.X509Certificate; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import javax.crypto.IllegalBlockSizeException; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils; | |||||
| import com.github.binarywang.wxpay.config.WxPayConfig; | |||||
| import com.github.binarywang.wxpay.exception.WxPayException; | |||||
| import com.github.binarywang.wxpay.service.WxPayService; | |||||
| import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; | |||||
| import com.iformall.domain.po.WxPayAccount; | |||||
| import com.iformall.utils.HttpUtil; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| public class WxPay { | |||||
| protected static Logger log = LoggerFactory.getLogger(WxPay.class); | |||||
| // 统一下单接口 | |||||
| private static final String UNIFIEDORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; | |||||
| // 订单查询 | |||||
| private static final String ORDERQUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery"; | |||||
| // 关闭订单 | |||||
| private static final String CLOSEORDER_URL = "https://api.mch.weixin.qq.com/pay/closeorder"; | |||||
| // 撤销订单 | |||||
| private static final String REVERSE_URL = "https://api.mch.weixin.qq.com/secapi/pay/reverse"; | |||||
| // 申请退款 | |||||
| private static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund"; | |||||
| // 查询退款 | |||||
| private static final String REFUNDQUERY_URL = "https://api.mch.weixin.qq.com/pay/refundquery"; | |||||
| // 下载对账单 | |||||
| private static final String DOWNLOADBILLY_URL = "https://api.mch.weixin.qq.com/pay/downloadbill"; | |||||
| // 交易保障 | |||||
| private static final String REPORT_URL = "https://api.mch.weixin.qq.com/payitil/report"; | |||||
| // 转换短链接 | |||||
| private static final String SHORT_URL = "https://api.mch.weixin.qq.com/tools/shorturl"; | |||||
| // 授权码查询openId接口 | |||||
| private static final String AUTHCODETOOPENID_URL = "https://api.mch.weixin.qq.com/tools/authcodetoopenid"; | |||||
| // 刷卡支付 | |||||
| private static final String MICROPAY_URL = "https://api.mch.weixin.qq.com/pay/micropay"; | |||||
| // 企业付款 | |||||
| private static final String TRANSFERS_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; | |||||
| // 查询企业付款 | |||||
| private static final String GETTRANSFERINFO_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo"; | |||||
| // 查询代金券批次 | |||||
| private static final String GETCOUPONSTOCK_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/query_coupon_stock"; | |||||
| // 查询代金券信息 | |||||
| private static final String GETCOUPONINFO_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/querycouponsinfo"; | |||||
| // 沙箱 | |||||
| private static final String SANDBOX_GETSIGNKEY_URL = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey"; | |||||
| private WxPay() { | |||||
| } | |||||
| /** | |||||
| * 交易类型枚举 | |||||
| * | |||||
| * @author Javen 2017年4月15日 | |||||
| * JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里 | |||||
| * MICROPAY--刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口 | |||||
| */ | |||||
| public static enum TradeType { | |||||
| JSAPI, NATIVE, APP, WAP, MICROPAY | |||||
| } | |||||
| /** | |||||
| * 统一下单 | |||||
| * 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/native_sl.php?chapter=9_1 | |||||
| * 商户模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1 | |||||
| * | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String pushOrder(Map<String, String> params) { | |||||
| return doPost(UNIFIEDORDER_URL, params); | |||||
| } | |||||
| /** | |||||
| * 订单查询 | |||||
| * 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_2 | |||||
| * 商户模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2 | |||||
| * | |||||
| * @param params | |||||
| * 请求参数 | |||||
| * @return | |||||
| */ | |||||
| public static String orderQuery(Map<String, String> params) { | |||||
| return doPost(ORDERQUERY_URL, params); | |||||
| } | |||||
| /** | |||||
| * 关闭订单 | |||||
| * 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_3 | |||||
| * 商户模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3 | |||||
| * | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String closeOrder(Map<String, String> params) { | |||||
| return doPost(CLOSEORDER_URL, params); | |||||
| } | |||||
| /** | |||||
| * 撤销订单 | |||||
| * 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_11&index=3 | |||||
| * 商户模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3 | |||||
| * | |||||
| * @param params | |||||
| * 请求参数 | |||||
| * @param certPath | |||||
| * 证书文件目录 | |||||
| * @param certPass | |||||
| * 证书密码 | |||||
| * @return | |||||
| */ | |||||
| public static String orderReverse(Map<String, String> params, String certPath, String certPass) { | |||||
| return doPostSSL(REVERSE_URL, params, certPath, certPass); | |||||
| } | |||||
| /** | |||||
| * 申请退款 | |||||
| * 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_4 | |||||
| * 商户模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_4 | |||||
| * | |||||
| * @param params | |||||
| * 请求参数 | |||||
| * @param certPath | |||||
| * 证书文件目录 | |||||
| * @param certPass | |||||
| * 证书密码 | |||||
| * @return | |||||
| */ | |||||
| public static String orderRefund(Map<String, String> params, String certPath, String certPass) { | |||||
| return doPostSSL(REFUND_URL, params, certPath, certPass); | |||||
| } | |||||
| /** | |||||
| * 查询退款 | |||||
| * 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_5 | |||||
| * 商户模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5 | |||||
| * | |||||
| * @param params | |||||
| * 请求参数 | |||||
| * @return | |||||
| */ | |||||
| public static String orderRefundQuery(Map<String, String> params) { | |||||
| return doPost(REFUNDQUERY_URL, params); | |||||
| } | |||||
| /** | |||||
| * 下载对账单 | |||||
| * 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_6 | |||||
| * 商户模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_6 | |||||
| * | |||||
| * @param params | |||||
| * 请求参数 | |||||
| * @return | |||||
| */ | |||||
| public static String downloadBill(Map<String, String> params) { | |||||
| return doPost(DOWNLOADBILLY_URL, params); | |||||
| } | |||||
| /** | |||||
| * 交易保障 | |||||
| * 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_14&index=7 | |||||
| * 商户模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_14&index=7 | |||||
| * | |||||
| * @param params | |||||
| * 请求参数 | |||||
| * @return | |||||
| */ | |||||
| public static String orderReport(Map<String, String> params) { | |||||
| return doPost(REPORT_URL, params); | |||||
| } | |||||
| /** | |||||
| * 转换短链接 | |||||
| * 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_9&index=8 | |||||
| * 商户模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_9&index=8 | |||||
| * | |||||
| * @param params | |||||
| * 请求参数 | |||||
| * @return | |||||
| */ | |||||
| public static String toShortUrl(Map<String, String> params) { | |||||
| return doPost(SHORT_URL, params); | |||||
| } | |||||
| /** | |||||
| * 授权码查询openId | |||||
| * 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_12&index=9 | |||||
| * 商户模式接入文档: | |||||
| * https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=9 | |||||
| * | |||||
| * @param params | |||||
| * 请求参数 | |||||
| * @return | |||||
| */ | |||||
| public static String authCodeToOpenid(Map<String, String> params) { | |||||
| return doPost(AUTHCODETOOPENID_URL, params); | |||||
| } | |||||
| /** | |||||
| * 刷卡支付 | |||||
| * 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_10&index=1 | |||||
| * 商户模式接入文档: | |||||
| * https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1 | |||||
| * | |||||
| * @param params | |||||
| * 请求参数 | |||||
| * @return | |||||
| */ | |||||
| public static String micropay(Map<String, String> params) { | |||||
| return WxPay.doPost(MICROPAY_URL, params); | |||||
| } | |||||
| /** | |||||
| *企业付款到零钱:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2, | |||||
| *微信后来改为 商家转账到零钱 产品 | |||||
| * @param params | |||||
| * 请求参数 | |||||
| * @param certPath | |||||
| * 证书文件目录 | |||||
| * @param certPassword | |||||
| * 证书密码 | |||||
| * @return {String} | |||||
| */ | |||||
| public static String transfers(Map<String, String> params, String certPath, String certPassword) { | |||||
| return WxPay.doPostSSL(TRANSFERS_URL, params, certPath, certPassword); | |||||
| } | |||||
| /** | |||||
| * 查询企业付款 | |||||
| * https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3 | |||||
| * @param params | |||||
| * 请求参数 | |||||
| * @param certPath | |||||
| * 证书文件目录 | |||||
| * @param certPassword | |||||
| * 证书密码 | |||||
| * @return {String} | |||||
| */ | |||||
| public static String getTransferInfo(Map<String, String> params, String certPath, String certPassword) { | |||||
| return WxPay.doPostSSL(GETTRANSFERINFO_URL, params, certPath, certPassword); | |||||
| } | |||||
| /** | |||||
| * 商户模式下 扫码模式一之生成二维码 | |||||
| * | |||||
| * @param appid | |||||
| * @param mch_id | |||||
| * @param product_id | |||||
| * @param partnerKey | |||||
| * @param isToShortUrl | |||||
| * 是否转化为短连接 | |||||
| * @return | |||||
| */ | |||||
| public static String getCodeUrl(String appid, String mch_id, String product_id, String partnerKey, | |||||
| boolean isToShortUrl) { | |||||
| String url = "weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXX&time_stamp=XXXXX&nonce_str=XXXXX"; | |||||
| String timeStamp = Long.toString(System.currentTimeMillis() / 1000); | |||||
| String nonceStr = Long.toString(System.currentTimeMillis()); | |||||
| Map<String, String> packageParams = new HashMap<String, String>(); | |||||
| packageParams.put("appid", appid); | |||||
| packageParams.put("mch_id", mch_id); | |||||
| packageParams.put("product_id", product_id); | |||||
| packageParams.put("time_stamp", timeStamp); | |||||
| packageParams.put("nonce_str", nonceStr); | |||||
| String packageSign = WxPayment.createSign(packageParams, partnerKey); | |||||
| String qrCodeUrl = WxPayment.replace(url, "XXXXX", packageSign, appid, mch_id, product_id, timeStamp, | |||||
| nonceStr); | |||||
| if (isToShortUrl) { | |||||
| String shortResult = WxPay | |||||
| .toShortUrl(WxPayment.buildShortUrlParasMap(appid, null, mch_id, null, qrCodeUrl, partnerKey)); | |||||
| if (log.isDebugEnabled()) { | |||||
| log.info(shortResult); | |||||
| } | |||||
| Map<String, String> shortMap = WxPayment.xmlToMap(shortResult); | |||||
| String return_code = shortMap.get("return_code"); | |||||
| if (WxPayment.codeIsOK(return_code)) { | |||||
| String result_code = shortMap.get("result_code"); | |||||
| if (WxPayment.codeIsOK(result_code)) { | |||||
| qrCodeUrl = shortMap.get("short_url"); | |||||
| } | |||||
| } | |||||
| } | |||||
| return qrCodeUrl; | |||||
| } | |||||
| /** | |||||
| * 查询代金券批次 | |||||
| * https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_4&index=5 | |||||
| * | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String getCouponStock(Map<String, String> params) { | |||||
| return doPost(GETCOUPONSTOCK_URL, params); | |||||
| } | |||||
| /** | |||||
| * 查询代金券信息 | |||||
| * https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_5&index=6 | |||||
| * | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String getCouponInfo(Map<String, String> params) { | |||||
| return doPost(GETCOUPONINFO_URL, params); | |||||
| } | |||||
| /** | |||||
| * 获取验签秘钥API | |||||
| * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_1 | |||||
| * | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String sanboxSignGet(Map<String, String> params) { | |||||
| return doPost(SANDBOX_GETSIGNKEY_URL, params); | |||||
| } | |||||
| public static String doPost(String url, Map<String, String> params) { | |||||
| return HttpUtil.payPost(url, WxPayment.toXml(params)); | |||||
| } | |||||
| public static String doPostSSL(String url, Map<String, String> params, String certPath, String certPass) { | |||||
| return HttpUtil.payPostSSL(url, WxPayment.toXml(params), certPath, certPass); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,50 @@ | |||||
| package com.iformall.domain.entity; | |||||
| import lombok.Data; | |||||
| /** | |||||
| * Created by Stormeye on 2018/8/10. | |||||
| * 普通商户模式 | |||||
| */ | |||||
| @Data | |||||
| public class WxPayOrderP { | |||||
| private String appid; // 小程序ID | |||||
| private String mch_id; // 商户号 | |||||
| private String nonce_str; // 随机字符串 | |||||
| private String sign; // 签名 | |||||
| private String body; // 商品简单描述 128 | |||||
| private String attach; // 附加数据 | |||||
| private String out_trade_no; // 商户订单号 | |||||
| private Integer total_fee; // 支付金额 | |||||
| private String spbill_create_ip; // 支付IP | |||||
| private String goods_tag; // 优惠标识 | |||||
| private String notify_url; // 通知地址 | |||||
| private String trade_type; // 支付类型 | |||||
| private String product_id; // 商品ID - 扫码必传 | |||||
| private String time_start; // 开始时间 | |||||
| private String time_expire; // 失效时间 | |||||
| private String openid; // openId | |||||
| @Override | |||||
| public String toString() { | |||||
| final StringBuilder sb = new StringBuilder("WxPayOrderP{"); | |||||
| sb.append("appid='").append(appid).append('\''); | |||||
| sb.append(", mch_id='").append(mch_id).append('\''); | |||||
| sb.append(", nonce_str='").append(nonce_str).append('\''); | |||||
| sb.append(", sign='").append(sign).append('\''); | |||||
| sb.append(", attach='").append(attach).append('\''); | |||||
| sb.append(", body='").append(body).append('\''); | |||||
| sb.append(", out_trade_no='").append(out_trade_no).append('\''); | |||||
| sb.append(", total_fee=").append(total_fee); | |||||
| sb.append(", spbill_create_ip='").append(spbill_create_ip).append('\''); | |||||
| sb.append(", goods_tag='").append(goods_tag).append('\''); | |||||
| sb.append(", notify_url='").append(notify_url).append('\''); | |||||
| sb.append(", trade_type='").append(trade_type).append('\''); | |||||
| sb.append(", product_id='").append(product_id).append('\''); | |||||
| sb.append(", time_start='").append(time_start).append('\''); | |||||
| sb.append(", time_expire='").append(time_expire).append('\''); | |||||
| sb.append(", openid='").append(openid).append('\''); | |||||
| sb.append('}'); | |||||
| return sb.toString(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,646 @@ | |||||
| package com.iformall.domain.entity; | |||||
| import com.iformall.utils.*; | |||||
| import org.apache.commons.codec.digest.HmacAlgorithms; | |||||
| import org.apache.commons.codec.digest.HmacUtils; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import java.io.UnsupportedEncodingException; | |||||
| import java.net.URLEncoder; | |||||
| import java.nio.charset.Charset; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| import java.util.Map.Entry; | |||||
| import java.util.TreeMap; | |||||
| public class WxPayment { | |||||
| /** | |||||
| * 构建参数 | |||||
| * | |||||
| * @param appid | |||||
| * @param sub_appid | |||||
| * @param mch_id | |||||
| * @param sub_mch_id | |||||
| * @param device_info | |||||
| * @param body | |||||
| * @param detail | |||||
| * @param attach | |||||
| * @param out_trade_no | |||||
| * @param total_fee | |||||
| * @param spbill_create_ip | |||||
| * @param auth_code | |||||
| * @param paternerKey | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> buildParasMap(String appid, String sub_appid, String mch_id, String sub_mch_id, | |||||
| String device_info, String body, String detail, String attach, String out_trade_no, String total_fee, | |||||
| String spbill_create_ip, String auth_code, String paternerKey) { | |||||
| Map<String, String> queryParas = new HashMap<String, String>(); | |||||
| queryParas.put("appid", appid); | |||||
| queryParas.put("sub_appid", sub_appid); | |||||
| queryParas.put("mch_id", mch_id); | |||||
| queryParas.put("sub_mch_id", sub_mch_id); | |||||
| queryParas.put("device_info", device_info); | |||||
| queryParas.put("nonce_str", String.valueOf(System.currentTimeMillis())); | |||||
| queryParas.put("body", body); | |||||
| queryParas.put("detail", detail); | |||||
| queryParas.put("attach", attach); | |||||
| queryParas.put("out_trade_no", out_trade_no); | |||||
| queryParas.put("total_fee", total_fee); | |||||
| queryParas.put("spbill_create_ip", spbill_create_ip); | |||||
| queryParas.put("auth_code", auth_code); | |||||
| String sign = WxPayment.createSign(queryParas, paternerKey); | |||||
| queryParas.put("sign", sign); | |||||
| return queryParas; | |||||
| } | |||||
| /** | |||||
| * 封装查询请求参数 参考代码 | |||||
| * | |||||
| * @param appid | |||||
| * @param sub_appid | |||||
| * @param mch_id | |||||
| * @param sub_mch_id | |||||
| * @param transaction_id | |||||
| * @param out_trade_no | |||||
| * @param paternerKey | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> buildQueryParasMap(String appid, String sub_appid, String mch_id, String sub_mch_id, | |||||
| String transaction_id, String out_trade_no, String paternerKey) { | |||||
| Map<String, String> params = new HashMap<String, String>(); | |||||
| params.put("appid", appid); | |||||
| params.put("sub_appid", sub_appid); | |||||
| params.put("mch_id", mch_id); | |||||
| params.put("sub_mch_id", sub_mch_id); | |||||
| params.put("transaction_id", transaction_id); | |||||
| params.put("out_trade_no", out_trade_no); | |||||
| return buildSignAfterParasMap(params, paternerKey); | |||||
| } | |||||
| /** | |||||
| * 构建统一下单参数 | |||||
| * | |||||
| * @param appid | |||||
| * @param sub_appid | |||||
| * 否 | |||||
| * @param mch_id | |||||
| * @param sub_mch_id | |||||
| * 服务商模式下必须 | |||||
| * @param device_info | |||||
| * 否 | |||||
| * @param body | |||||
| * @param detail | |||||
| * 否 | |||||
| * @param attach | |||||
| * 否 | |||||
| * @param out_trade_no | |||||
| * @param total_fee | |||||
| * @param spbill_create_ip | |||||
| * @param paternerKey | |||||
| * @param notify_url | |||||
| * @param openId // JSAPI 必传 | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> buildUnifiedOrderParasMap(String appid, String sub_appid, String mch_id, | |||||
| String sub_mch_id, String device_info, String body, String detail, String attach, String out_trade_no, | |||||
| String total_fee, String spbill_create_ip, String notify_url, String paternerKey, | |||||
| String openId) { | |||||
| Map<String, String> params = new HashMap<String, String>(); | |||||
| params.put("appid", appid); | |||||
| params.put("sub_appid", sub_appid); | |||||
| params.put("mch_id", mch_id); | |||||
| params.put("sub_mch_id", sub_mch_id); | |||||
| params.put("device_info", device_info); | |||||
| params.put("body", body); | |||||
| params.put("detail", detail); | |||||
| params.put("attach", attach); | |||||
| params.put("out_trade_no", out_trade_no); | |||||
| params.put("total_fee", total_fee); | |||||
| params.put("spbill_create_ip", spbill_create_ip); | |||||
| params.put("notify_url", notify_url); | |||||
| params.put("trade_type", "JSAPI"); | |||||
| // params.put("product_id", product_id); // trade_type=NATIVE时(即扫码支付)必传 | |||||
| params.put("openid", openId); | |||||
| return buildSignAfterParasMap(params, paternerKey); | |||||
| } | |||||
| /** | |||||
| * 构建短链接参数 | |||||
| * | |||||
| * @param appid | |||||
| * @param sub_appid | |||||
| * @param mch_id | |||||
| * @param sub_mch_id | |||||
| * @param long_url | |||||
| * @param paternerKey | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> buildShortUrlParasMap(String appid, String sub_appid, String mch_id, | |||||
| String sub_mch_id, String long_url, String paternerKey) { | |||||
| Map<String, String> params = new HashMap<String, String>(); | |||||
| params.put("appid", appid); | |||||
| params.put("sub_appid", sub_appid); | |||||
| params.put("mch_id", mch_id); | |||||
| params.put("sub_mch_id", sub_mch_id); | |||||
| params.put("long_url", long_url); | |||||
| return buildSignAfterParasMap(params, paternerKey); | |||||
| } | |||||
| /** | |||||
| * 小程序统一下单后二次签名 | |||||
| * | |||||
| * @param appId | |||||
| * @param timestamp | |||||
| * @param prepay_id | |||||
| * @param paternerKey | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> buildWeappSecondSignMap(String appId, String timestamp, String prepay_id, String paternerKey) { | |||||
| Map<String, String> params = new HashMap<String, String>(); | |||||
| Map<String, String> sighMap = MapUtil.getOrderMap(); | |||||
| sighMap.put("appId", appId); | |||||
| sighMap.put("timeStamp", timestamp); | |||||
| sighMap.put("package", "prepay_id="+prepay_id); | |||||
| //sighMap.put("signType", "MD5"); | |||||
| return buildSignAfterParasMap(params, paternerKey); | |||||
| } | |||||
| /** | |||||
| * 关闭订单 | |||||
| * | |||||
| * @param appid | |||||
| * @param sub_appid | |||||
| * @param mch_id | |||||
| * @param sub_mch_id | |||||
| * @param out_trade_no | |||||
| * @param paternerKey | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> buildCloseMap(String appid, String sub_appid, String mch_id, String sub_mch_id, | |||||
| String out_trade_no, String paternerKey) { | |||||
| Map<String, String> params = new HashMap<String, String>(); | |||||
| params.put("appid", appid); | |||||
| params.put("sub_appid", sub_appid); | |||||
| params.put("mch_id", mch_id); | |||||
| params.put("sub_mch_id", sub_mch_id); | |||||
| params.put("out_trade_no", out_trade_no); | |||||
| return buildSignAfterParasMap(params, paternerKey); | |||||
| } | |||||
| /** | |||||
| * 申请退款 | |||||
| * | |||||
| * @param appid | |||||
| * @param sub_appid | |||||
| * @param mch_id | |||||
| * @param sub_mch_id | |||||
| * @param out_trade_no | |||||
| * @param paternerKey | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> buildRefundMap(String appid, String sub_appid, String mch_id, String sub_mch_id, | |||||
| String transaction_id, String out_trade_no, String out_refund_no, | |||||
| String total_fee, String refund_fee, String refund_desc, String paternerKey) { | |||||
| Map<String, String> params = new HashMap<String, String>(); | |||||
| params.put("appid", appid); | |||||
| params.put("sub_appid", sub_appid); | |||||
| params.put("mch_id", mch_id); | |||||
| params.put("sub_mch_id", sub_mch_id); | |||||
| params.put("transaction_id", transaction_id); | |||||
| params.put("out_trade_no", out_trade_no); | |||||
| params.put("out_refund_no", out_refund_no); | |||||
| params.put("total_fee", total_fee); | |||||
| params.put("refund_fee", refund_fee); | |||||
| params.put("refund_desc", refund_desc); | |||||
| return buildSignAfterParasMap(params, paternerKey); | |||||
| } | |||||
| /** | |||||
| * 查询退款 | |||||
| * | |||||
| * @param appid | |||||
| * @param sub_appid | |||||
| * @param mch_id | |||||
| * @param sub_mch_id | |||||
| * @param out_trade_no | |||||
| * @param paternerKey | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> buildRefundQueryMap(String appid, String sub_appid, String mch_id, String sub_mch_id, | |||||
| String transaction_id, String out_trade_no, String out_refund_no, String refund_id, | |||||
| String paternerKey) { | |||||
| Map<String, String> params = new HashMap<String, String>(); | |||||
| params.put("appid", appid); | |||||
| params.put("sub_appid", sub_appid); | |||||
| params.put("mch_id", mch_id); | |||||
| params.put("sub_mch_id", sub_mch_id); | |||||
| if(!StringUtils.isBlank(refund_id)) { | |||||
| params.put("refund_id", refund_id); | |||||
| } else if (!StringUtils.isBlank(out_refund_no)) { | |||||
| params.put("out_refund_no", out_refund_no); | |||||
| } else if (!StringUtils.isBlank(transaction_id)) { | |||||
| params.put("transaction_id", transaction_id); | |||||
| } else if (!StringUtils.isBlank(out_trade_no)) { | |||||
| params.put("out_trade_no", out_trade_no); | |||||
| } | |||||
| return buildSignAfterParasMap(params, paternerKey); | |||||
| } | |||||
| /** | |||||
| * 查询退款 | |||||
| * | |||||
| * @param appid | |||||
| * @param mch_id | |||||
| * @param out_trade_no | |||||
| * @param paternerKey | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> buildWeappRefundQueryMap(String appid, String mch_id, | |||||
| String transaction_id, String out_trade_no, String out_refund_no, String refund_id, | |||||
| String paternerKey) { | |||||
| Map<String, String> params = new HashMap<String, String>(); | |||||
| params.put("appid", appid); | |||||
| params.put("mch_id", mch_id); | |||||
| if(!StringUtils.isBlank(refund_id)) { | |||||
| params.put("refund_id", refund_id); | |||||
| } else if (!StringUtils.isBlank(out_refund_no)) { | |||||
| params.put("out_refund_no", out_refund_no); | |||||
| } else if (!StringUtils.isBlank(transaction_id)) { | |||||
| params.put("transaction_id", transaction_id); | |||||
| } else if (!StringUtils.isBlank(out_trade_no)) { | |||||
| params.put("out_trade_no", out_trade_no); | |||||
| } | |||||
| return buildSignAfterParasMap(params, paternerKey); | |||||
| } | |||||
| /** | |||||
| * 服务商查询退款 | |||||
| * | |||||
| * @param appid | |||||
| * @param mch_id | |||||
| * @param out_trade_no | |||||
| * @param paternerKey | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> buildSWeappRefundQueryMap(String appid, String sub_appid, String mch_id, String sub_mch_id, | |||||
| String transaction_id, String out_trade_no, String out_refund_no, String refund_id, | |||||
| String paternerKey) { | |||||
| Map<String, String> params = new HashMap<String, String>(); | |||||
| params.put("appid", appid); | |||||
| params.put("sub_appid", sub_appid); | |||||
| params.put("mch_id", mch_id); | |||||
| params.put("sub_mch_id", sub_mch_id); | |||||
| if(!StringUtils.isBlank(refund_id)) { | |||||
| params.put("refund_id", refund_id); | |||||
| } else if (!StringUtils.isBlank(out_refund_no)) { | |||||
| params.put("out_refund_no", out_refund_no); | |||||
| } else if (!StringUtils.isBlank(transaction_id)) { | |||||
| params.put("transaction_id", transaction_id); | |||||
| } else if (!StringUtils.isBlank(out_trade_no)) { | |||||
| params.put("out_trade_no", out_trade_no); | |||||
| } | |||||
| return buildSignAfterParasMap(params, paternerKey); | |||||
| } | |||||
| /** | |||||
| * 组装签名的字段 | |||||
| * | |||||
| * @param params | |||||
| * 参数 | |||||
| * @param urlEncoder | |||||
| * 是否urlEncoder | |||||
| * @return String | |||||
| */ | |||||
| public static String packageSign(Map<String, String> params, boolean urlEncoder) { | |||||
| // 先将参数以其参数名的字典序升序进行排序 | |||||
| TreeMap<String, String> sortedParams = new TreeMap<String, String>(params); | |||||
| // 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起 | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| boolean first = true; | |||||
| for (Entry<String, String> param : sortedParams.entrySet()) { | |||||
| String value = param.getValue(); | |||||
| if (StringUtils.isBlank(value)) { | |||||
| continue; | |||||
| } | |||||
| if (first) { | |||||
| first = false; | |||||
| } else { | |||||
| sb.append("&"); | |||||
| } | |||||
| sb.append(param.getKey()).append("="); | |||||
| if (urlEncoder) { | |||||
| try { | |||||
| value = urlEncode(value); | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| } | |||||
| } | |||||
| sb.append(value); | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| /** | |||||
| * urlEncode | |||||
| * | |||||
| * @param src | |||||
| * 微信参数 | |||||
| * @return String | |||||
| * @throws UnsupportedEncodingException | |||||
| * 编码错误 | |||||
| */ | |||||
| public static String urlEncode(String src) throws UnsupportedEncodingException { | |||||
| return URLEncoder.encode(src, Charset.forName("UTF-8").name()).replace("+", "%20"); | |||||
| } | |||||
| /** | |||||
| * 构建签名之后的参数 | |||||
| * | |||||
| * @param params | |||||
| * @param paternerKey | |||||
| * @return Map | |||||
| */ | |||||
| public static Map<String, String> buildSignAfterParasMap(Map<String, String> params, String paternerKey) { | |||||
| params.put("nonce_str", Utility.generateUUID().replace("-", "")); | |||||
| String sign = WxPayment.createSign(params, paternerKey); | |||||
| params.put("sign", sign); | |||||
| return params; | |||||
| } | |||||
| /** | |||||
| * 构建签名之后的参数 | |||||
| * | |||||
| * @param params | |||||
| * @param paternerKey | |||||
| * @return Map | |||||
| */ | |||||
| public static Map<String, String> buildSignAfterParasMapForHMAC(Map<String, String> params, String paternerKey) { | |||||
| params.put("nonce_str", Utility.generateUUID().replace("-", "")); | |||||
| String sign = WxPayment.createSignHMAC(params, paternerKey); | |||||
| params.put("sign", sign); | |||||
| return params; | |||||
| } | |||||
| /** | |||||
| * 生成签名 | |||||
| * | |||||
| * @param params | |||||
| * 参数 | |||||
| * @param partnerKey | |||||
| * 支付密钥 | |||||
| * @return sign | |||||
| */ | |||||
| public static String createSign(Map<String, String> params, String partnerKey) { | |||||
| // 生成签名前先去除sign | |||||
| params.remove("sign"); | |||||
| String stringA = packageSign(params, false); | |||||
| String stringSignTemp = stringA + "&key=" + partnerKey; | |||||
| return HashUtil.md5(stringSignTemp).toUpperCase(); | |||||
| } | |||||
| /** | |||||
| * 生成签名 | |||||
| * | |||||
| * @param params | |||||
| * 参数 | |||||
| * @param partnerKey | |||||
| * 支付密钥 | |||||
| * @return sign | |||||
| */ | |||||
| public static String createSignHMAC(Map<String, String> params, String partnerKey) { | |||||
| // 生成签名前先去除sign | |||||
| params.remove("sign"); | |||||
| String stringA = packageSign(params, false); | |||||
| String stringSignTemp = stringA + "&key=" + partnerKey; | |||||
| return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, partnerKey).hmacHex(stringSignTemp).toUpperCase(); | |||||
| } | |||||
| /** | |||||
| * 支付异步通知时校验sign | |||||
| * | |||||
| * @param params | |||||
| * 参数 | |||||
| * @param paternerKey | |||||
| * 支付密钥 | |||||
| * @return {boolean} | |||||
| */ | |||||
| public static boolean verifyNotify(Map<String, String> params, String paternerKey) { | |||||
| String sign = params.get("sign"); | |||||
| if (sign == null) | |||||
| return true; | |||||
| String localSign = WxPayment.createSign(params, paternerKey); | |||||
| return sign.equals(localSign); | |||||
| } | |||||
| /** | |||||
| * 支付异步通知时校验sign | |||||
| * | |||||
| * @param params | |||||
| * 参数 | |||||
| * @param paternerKey | |||||
| * 支付密钥 | |||||
| * @return {boolean} | |||||
| */ | |||||
| public static boolean verifyNotifyHMAC(Map<String, String> params, String paternerKey) { | |||||
| String sign = params.get("sign"); | |||||
| if (sign == null) | |||||
| return true; | |||||
| String localSign = WxPayment.createSignHMAC(params, paternerKey); | |||||
| return sign.equals(localSign); | |||||
| } | |||||
| /** | |||||
| * 判断接口返回的code是否是SUCCESS | |||||
| * | |||||
| * @param return_code、result_code | |||||
| * @return | |||||
| */ | |||||
| public static boolean codeIsOK(String return_code) { | |||||
| return StringUtils.isNotBlank(return_code) && "SUCCESS".equals(return_code); | |||||
| } | |||||
| /** | |||||
| * 微信下单map to xml | |||||
| * | |||||
| * @param params | |||||
| * 参数 | |||||
| * @return String | |||||
| */ | |||||
| private static String toXmlContent(Map<String, String> params,boolean containChinese) { | |||||
| StringBuilder xml = new StringBuilder(); | |||||
| xml.append("<xml>"); | |||||
| for (Entry<String, String> entry : params.entrySet()) { | |||||
| String key = entry.getKey(); | |||||
| String value = entry.getValue(); | |||||
| // 略过空值 | |||||
| if (StringUtils.isBlank(value)) | |||||
| continue; | |||||
| xml.append("<").append(key).append(">"); | |||||
| xml.append(entry.getValue()); | |||||
| xml.append("</").append(key).append(">"); | |||||
| } | |||||
| xml.append("</xml>"); | |||||
| return xml.toString(); | |||||
| } | |||||
| public static String toXml(Map<String, String> params) { | |||||
| return toXmlContent(params,false); | |||||
| } | |||||
| public static String toXmlWhitChinese(Map<String, String> params) { | |||||
| return toXmlContent(params,true); | |||||
| } | |||||
| /** | |||||
| * 针对支付的xml,没有嵌套节点的简单处理 | |||||
| * | |||||
| * @param xmlStr | |||||
| * xml字符串 | |||||
| * @return map集合 | |||||
| */ | |||||
| @SuppressWarnings("unchecked") | |||||
| public static Map<String, String> xmlToMap(String xmlStr) { | |||||
| return XmlUtil.parseXml2Map(xmlStr); | |||||
| } | |||||
| /** | |||||
| * 替换url中的参数 | |||||
| * | |||||
| * @param str | |||||
| * @param regex | |||||
| * @param args | |||||
| * @return | |||||
| */ | |||||
| public static String replace(String str, String regex, String... args) { | |||||
| int length = args.length; | |||||
| for (int i = 0; i < length; i++) { | |||||
| str = str.replaceFirst(regex, args[i]); | |||||
| } | |||||
| return str; | |||||
| } | |||||
| private static void getSanboxKeyTest() { | |||||
| Map map = MapUtil.getOrderMap(); | |||||
| map.put("mch_id", "1511925291"); | |||||
| // map.put("sub_mch_id", "1513691501"); | |||||
| map.put("nonce_str", RandomUtils.getStr(32)); | |||||
| String sign = WxPayment.createSign(map, "XHZfpVA0NzoXgLEjsujctUTcyj8Zur2C"); | |||||
| map.put("sign", sign); | |||||
| String response = WxPay.sanboxSignGet(map); | |||||
| System.out.println(response); | |||||
| /* | |||||
| <xml> | |||||
| <return_code><![CDATA[SUCCESS]]></return_code> | |||||
| <return_msg><![CDATA[ok]]></return_msg> | |||||
| <sandbox_signkey><![CDATA[7e9d244da17632cdf608e04564a628da]]></sandbox_signkey> | |||||
| </xml> | |||||
| */ | |||||
| } | |||||
| private static void getDownloadBillTest(String signKey) { | |||||
| Map map = MapUtil.getOrderMap(); | |||||
| map.put("appid", "wxed2f44705544b892"); | |||||
| map.put("mch_id", "1511925291"); | |||||
| map.put("nonce_str", RandomUtils.getStr(32)); | |||||
| map.put("bill_date", "20190524"); | |||||
| map.put("bill_type", "ALL"); | |||||
| String sign = WxPayment.createSign(map, signKey); | |||||
| map.put("sign", sign); | |||||
| String response = WxPay.downloadBill(map); | |||||
| System.out.println(response); | |||||
| } | |||||
| private static void microPaySanbox(String signKey, String outTradeNo) { | |||||
| Map map = MapUtil.getOrderMap(); | |||||
| map.put("appid", "wxed2f44705544b892"); | |||||
| map.put("mch_id", "1511925291"); | |||||
| map.put("nonce_str", RandomUtils.getStr(32)); | |||||
| map.put("body", "image形象店-深圳腾大- QQ公仔"); | |||||
| map.put("out_trade_no", outTradeNo); | |||||
| map.put("total_fee", "502"); | |||||
| map.put("spbill_create_ip", "172.16.115.182"); | |||||
| map.put("auth_code", "134659695358765866"); | |||||
| String sign = WxPayment.createSign(map, signKey); | |||||
| map.put("sign", sign); | |||||
| String response = WxPay.micropay(map); | |||||
| System.out.println("micropay"); | |||||
| System.out.println(response); | |||||
| } | |||||
| private static void queryPaySanbox(String signKey, String outTradeNo) { | |||||
| Map map = MapUtil.getOrderMap(); | |||||
| map.put("appid", "wxed2f44705544b892"); | |||||
| map.put("mch_id", "1511925291"); | |||||
| map.put("out_trade_no", outTradeNo); | |||||
| map.put("nonce_str", RandomUtils.getStr(32)); | |||||
| String sign = WxPayment.createSign(map, signKey); | |||||
| map.put("sign", sign); | |||||
| String response = WxPay.orderQuery(map); | |||||
| System.out.println("micropayQuery"); | |||||
| System.out.println(response); | |||||
| } | |||||
| private static void refundSanbox(String signKey, String outTradeNo, String outRefundNo) { | |||||
| Map map = MapUtil.getOrderMap(); | |||||
| map.put("appid", "wxed2f44705544b892"); | |||||
| map.put("mch_id", "1511925291"); | |||||
| map.put("nonce_str", RandomUtils.getStr(32)); | |||||
| map.put("out_trade_no", outTradeNo); | |||||
| map.put("out_refund_no", outRefundNo); | |||||
| map.put("total_fee", "502"); | |||||
| map.put("refund_fee", "501"); | |||||
| String sign = WxPayment.createSign(map, signKey); | |||||
| map.put("sign", sign); | |||||
| String response = WxPay.orderRefund(map, "/opt/iformall/service/apiclient_cert.p12", "1511925291"); | |||||
| System.out.println("refund"); | |||||
| System.out.println(response); | |||||
| } | |||||
| private static void refundQuerySanbox(String signKey, String outTradeNo, String outRefundNo) { | |||||
| Map map = MapUtil.getOrderMap(); | |||||
| map.put("appid", "wxed2f44705544b892"); | |||||
| map.put("mch_id", "1511925291"); | |||||
| map.put("nonce_str", RandomUtils.getStr(32)); | |||||
| map.put("out_trade_no", outTradeNo); | |||||
| map.put("out_refund_no", outRefundNo); | |||||
| String sign = WxPayment.createSign(map, signKey); | |||||
| map.put("sign", sign); | |||||
| String response = WxPay.orderRefundQuery(map); | |||||
| System.out.println("refundQuery"); | |||||
| System.out.println(response); | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| String signKey = "7e9d244da17632cdf608e04564a628da"; | |||||
| String outTradeNo = "1459833232543346"; | |||||
| String outRefundNo = "143446547"; | |||||
| microPaySanbox(signKey, outTradeNo); | |||||
| queryPaySanbox(signKey, outTradeNo); | |||||
| refundSanbox(signKey, outTradeNo, outRefundNo); | |||||
| refundQuerySanbox(signKey, outTradeNo, outRefundNo); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| package com.iformall.domain.po; | |||||
| import java.util.Date; | |||||
| import com.baomidou.mybatisplus.annotation.TableField; | |||||
| import com.baomidou.mybatisplus.annotation.TableName; | |||||
| import com.iformall.domain.po.base.BaseEntity; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| @TableName(value = "sys_config") | |||||
| @Data | |||||
| @EqualsAndHashCode(callSuper = true) | |||||
| public class SysConfig extends BaseEntity { | |||||
| private static final long serialVersionUID = 1L; | |||||
| protected Long id; | |||||
| @io.swagger.annotations.ApiModelProperty(value="配置项key",name="configItemKey") | |||||
| private String configItemKey; | |||||
| @io.swagger.annotations.ApiModelProperty(value="配置项说明",name="configItemRemark") | |||||
| private String configItemRemark; | |||||
| @io.swagger.annotations.ApiModelProperty(value="",name="createDate") | |||||
| private Date createDate; | |||||
| @io.swagger.annotations.ApiModelProperty(value="",name="updateDate") | |||||
| private Date updateDate; | |||||
| @io.swagger.annotations.ApiModelProperty(value="是否隐藏",name="isHide") | |||||
| private Integer isHide; | |||||
| @io.swagger.annotations.ApiModelProperty(value="0-有效 1-无效",name="status") | |||||
| private Integer status; | |||||
| @io.swagger.annotations.ApiModelProperty(value="配置项value,查询显示用",name="configItemValue") | |||||
| @TableField(exist = false) | |||||
| private String configItemValue; | |||||
| } | |||||
| @@ -0,0 +1,38 @@ | |||||
| package com.iformall.domain.po; | |||||
| import com.baomidou.mybatisplus.annotation.IdType; | |||||
| import com.baomidou.mybatisplus.annotation.TableId; | |||||
| import com.baomidou.mybatisplus.annotation.TableName; | |||||
| import com.iformall.domain.po.base.BaseEntity; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import java.util.Date; | |||||
| /** | |||||
| * 系统用户Token | |||||
| * | |||||
| * @author Stormeye | |||||
| */ | |||||
| @Data | |||||
| @TableName("sys_config_value") | |||||
| @EqualsAndHashCode(callSuper = true) | |||||
| public class SysConfigValue extends TenantEntity { | |||||
| private static final long serialVersionUID = -5887774776970688169L; | |||||
| private Long id; | |||||
| @io.swagger.annotations.ApiModelProperty(value="配置项id",name="configItemId") | |||||
| private Long configItemId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="配置项value",name="configItemValue") | |||||
| private String configItemValue; | |||||
| @io.swagger.annotations.ApiModelProperty(value="过期时间",name="expireTime") | |||||
| private Date createDate; | |||||
| @io.swagger.annotations.ApiModelProperty(value="更新时间",name="updateTime") | |||||
| private Date updateDate; | |||||
| } | |||||
| @@ -0,0 +1,55 @@ | |||||
| package com.iformall.domain.po; | |||||
| import com.baomidou.mybatisplus.annotation.TableField; | |||||
| import com.baomidou.mybatisplus.annotation.TableName; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import lombok.ToString; | |||||
| import java.util.*; | |||||
| @TableName(value = "wx_pay_order") | |||||
| @Data | |||||
| @EqualsAndHashCode(callSuper = true) | |||||
| @ToString | |||||
| public class WxPayOrder extends TenantEntity { | |||||
| private static final long serialVersionUID = -5094915301794376964L; | |||||
| protected Long id; | |||||
| @io.swagger.annotations.ApiModelProperty(value="创建时间",name="createTime") | |||||
| private Date createTime; | |||||
| @io.swagger.annotations.ApiModelProperty(value="更新时间",name="updateTime") | |||||
| private Date updateTime; | |||||
| @io.swagger.annotations.ApiModelProperty(value="用户ID",name="cUserId") | |||||
| private Long cUserId; | |||||
| @TableField(exist = false) | |||||
| private List<Long> userIds; | |||||
| @io.swagger.annotations.ApiModelProperty(value="用户手机号",name="cUserPhone") | |||||
| private String cUserPhone; | |||||
| public Long getcUserId() { | |||||
| return cUserId; | |||||
| } | |||||
| public void setcUserId(Long cUserId) { | |||||
| this.cUserId = cUserId; | |||||
| } | |||||
| public String getcUserPhone() { | |||||
| return cUserPhone; | |||||
| } | |||||
| public void setcUserPhone(String cUserPhone) { | |||||
| this.cUserPhone = cUserPhone; | |||||
| } | |||||
| @io.swagger.annotations.ApiModelProperty(value="支付金额(分)",name="payAmount") | |||||
| private Integer payAmount; | |||||
| @io.swagger.annotations.ApiModelProperty(value="支付时间",name="payTime") | |||||
| private Date payTime; | |||||
| @io.swagger.annotations.ApiModelProperty(value="微信生成的订单号",name="transactionId") | |||||
| private String transactionId; | |||||
| @TableField(exist = false) | |||||
| private Date begin; | |||||
| @TableField(exist = false) | |||||
| private Date end; | |||||
| } | |||||
| @@ -0,0 +1,34 @@ | |||||
| package com.iformall.enums; | |||||
| public enum EnumPayType { | |||||
| CAR_ISV_MERCHANT(1, "特约停车商户"), | |||||
| CAR_OWN_MERCHANT(2, "自有停车商户"), | |||||
| PAY_ACCOUNT(3,"小程序收款账户") | |||||
| ; | |||||
| public static EnumPayType getEnum(Integer code) { | |||||
| for (EnumPayType value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String message; | |||||
| EnumPayType(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,33 @@ | |||||
| package com.iformall.enums; | |||||
| public enum EnumYesOrNo { | |||||
| YES(1, "是"), | |||||
| NO(0, "否"), | |||||
| ; | |||||
| public static EnumYesOrNo getEnum(Integer code) { | |||||
| for (EnumYesOrNo value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String message; | |||||
| EnumYesOrNo(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,14 @@ | |||||
| package com.iformall.mapper; | |||||
| import java.util.*; | |||||
| import com.iformall.common.CommonMapper; | |||||
| import com.iformall.domain.po.SysConfig; | |||||
| public interface SysConfigMapper extends CommonMapper<SysConfig, Long> { | |||||
| List<SysConfig> findList(SysConfig sysMonitor); | |||||
| SysConfig findByKey(SysConfig sysMonitor); | |||||
| } | |||||
| @@ -0,0 +1,10 @@ | |||||
| package com.iformall.mapper; | |||||
| import com.iformall.common.CommonMapper; | |||||
| import com.iformall.domain.po.SysConfigValue; | |||||
| public interface SysConfigValueMapper extends CommonMapper<SysConfigValue, Long> { | |||||
| SysConfigValue findByItemId(SysConfigValue record); | |||||
| } | |||||
| @@ -0,0 +1,20 @@ | |||||
| package com.iformall.mapper; | |||||
| import java.util.*; | |||||
| import org.apache.ibatis.annotations.Param; | |||||
| import com.iformall.common.CommonMapper; | |||||
| import com.iformall.domain.po.WxPayOrder; | |||||
| public interface WxPayOrderMapper extends CommonMapper<WxPayOrder, Long> { | |||||
| WxPayOrder selectById(@Param("id")Long id,@Param("tenantId")String tenantId); | |||||
| List<WxPayOrder> findList(WxPayOrder wxCarPayOrder); | |||||
| WxPayOrder findOneByParkOderNo(@Param("parkOrderNo")String parkOrderNo,@Param("tenantId")String tenantId); | |||||
| Integer sum(WxPayOrder wxCarPayOrder); | |||||
| } | |||||
| @@ -0,0 +1,40 @@ | |||||
| package com.iformall.service; | |||||
| import com.github.pagehelper.PageInfo; | |||||
| import com.iformall.domain.po.SysConfig; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import java.util.List; | |||||
| public interface SysConfigService { | |||||
| PageInfo<SysConfig> listAsPage(SysConfig record, Integer pageIndex, Integer pageSize,TenantEntity tenantEntity); | |||||
| /** | |||||
| * 根据实体查询列表 | |||||
| * | |||||
| * @param record | |||||
| * @return | |||||
| */ | |||||
| List<SysConfig> getList(SysConfig record,TenantEntity tenantEntity); | |||||
| /** | |||||
| * 根据Id获得实体 | |||||
| * | |||||
| * @param id | |||||
| * @return | |||||
| */ | |||||
| SysConfig getById(Long id,TenantEntity tenantEntity); | |||||
| SysConfig getByKey(String key,TenantEntity tenantEntity); | |||||
| /** | |||||
| * 保存或更新实体 | |||||
| * | |||||
| * @param | |||||
| */ | |||||
| void saveConfigValue(Long id,TenantEntity tenantEntity,String value); | |||||
| void saveOrUpdate(SysConfig record); | |||||
| } | |||||
| @@ -0,0 +1,147 @@ | |||||
| package com.iformall.service.impl; | |||||
| import java.util.*; | |||||
| import com.iformall.domain.po.SysConfig; | |||||
| import com.iformall.domain.po.SysConfigValue; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import com.iformall.mapper.SysConfigMapper; | |||||
| import com.iformall.mapper.SysConfigValueMapper; | |||||
| import com.iformall.service.SysConfigService; | |||||
| import com.iformall.utils.RedisCacheUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.beans.factory.annotation.Qualifier; | |||||
| import org.springframework.data.redis.core.RedisTemplate; | |||||
| import org.springframework.stereotype.Service; | |||||
| import com.github.pagehelper.PageHelper; | |||||
| import com.github.pagehelper.PageInfo; | |||||
| import com.iformall.common.IdWorker; | |||||
| @Service | |||||
| public class SysConfigServiceImpl implements SysConfigService { | |||||
| private static final String cache_prex = "sysconfig:%s:%s"; | |||||
| @Autowired | |||||
| SysConfigMapper sysConfigMapper; | |||||
| @Autowired | |||||
| SysConfigValueMapper sysConfigValueMapper; | |||||
| @Autowired | |||||
| @Qualifier("objectCommonRedisTemplate") | |||||
| RedisTemplate<String, Object> baseRedisTemplate; | |||||
| @Override | |||||
| public PageInfo<SysConfig> listAsPage(SysConfig record, Integer pageIndex, Integer pageSize,TenantEntity tenantEntity) { | |||||
| PageInfo<SysConfig> page = PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> sysConfigMapper.findList(record)); | |||||
| if (null != page && null != page.getList()) { | |||||
| for (SysConfig config : page.getList()) { | |||||
| SysConfigValue cvq = new SysConfigValue(); | |||||
| cvq.setConfigItemId(config.getId()); | |||||
| cvq.updateTenantInfo(tenantEntity); | |||||
| SysConfigValue configValue = sysConfigValueMapper.findByItemId(cvq); | |||||
| if (null != configValue) { | |||||
| config.setConfigItemValue(configValue.getConfigItemValue()); | |||||
| } | |||||
| } | |||||
| } | |||||
| return page; | |||||
| } | |||||
| @Override | |||||
| public List<SysConfig> getList(SysConfig record,TenantEntity tenantEntity) { | |||||
| List<SysConfig> list = sysConfigMapper.findList(record); | |||||
| if (null != list) { | |||||
| for (SysConfig config : list) { | |||||
| SysConfigValue cvq = new SysConfigValue(); | |||||
| cvq.setConfigItemId(config.getId()); | |||||
| cvq.updateTenantInfo(tenantEntity); | |||||
| SysConfigValue configValue = sysConfigValueMapper.findByItemId(cvq); | |||||
| if (null != configValue) { | |||||
| config.setConfigItemValue(configValue.getConfigItemValue()); | |||||
| } | |||||
| } | |||||
| } | |||||
| return list; | |||||
| } | |||||
| @Override | |||||
| public SysConfig getById(Long id,TenantEntity tenantEntity) { | |||||
| SysConfig config = sysConfigMapper.selectById(id); | |||||
| if (null != config ) { | |||||
| SysConfigValue cvq = new SysConfigValue(); | |||||
| cvq.setConfigItemId(config.getId()); | |||||
| cvq.updateTenantInfo(tenantEntity); | |||||
| SysConfigValue configValue = sysConfigValueMapper.findByItemId(cvq); | |||||
| if (null != configValue) { | |||||
| config.setConfigItemValue(configValue.getConfigItemValue()); | |||||
| } | |||||
| } | |||||
| return config; | |||||
| } | |||||
| @Override | |||||
| public SysConfig getByKey(String key,TenantEntity tenantEntity) { | |||||
| SysConfig config = RedisCacheUtils.getCacheObject(baseRedisTemplate, String.format(cache_prex, tenantEntity.getTenantId(),key), SysConfig.class); | |||||
| if (null == config) { | |||||
| SysConfig cq = new SysConfig(); | |||||
| cq.setConfigItemKey(key); | |||||
| config = sysConfigMapper.findByKey(cq); | |||||
| if (null != config ) { | |||||
| SysConfigValue cvq = new SysConfigValue(); | |||||
| cvq.setConfigItemId(config.getId()); | |||||
| cvq.updateTenantInfo(tenantEntity); | |||||
| SysConfigValue configValue = sysConfigValueMapper.findByItemId(cvq); | |||||
| if (null != configValue) { | |||||
| config.setConfigItemValue(configValue.getConfigItemValue()); | |||||
| RedisCacheUtils.cache(baseRedisTemplate, String.format(cache_prex, tenantEntity.getTenantId(),key), config, 3600*24*3); | |||||
| } | |||||
| } | |||||
| } | |||||
| return config; | |||||
| } | |||||
| @Override | |||||
| public void saveConfigValue(Long id,TenantEntity tenantEntity,String value) { | |||||
| SysConfig config = sysConfigMapper.selectById(id); | |||||
| SysConfigValue cvq = new SysConfigValue(); | |||||
| cvq.setConfigItemId(config.getId()); | |||||
| cvq.updateTenantInfo(tenantEntity); | |||||
| SysConfigValue configValue = sysConfigValueMapper.findByItemId(cvq); | |||||
| if (null != configValue) { | |||||
| configValue.setConfigItemValue(value); | |||||
| configValue.setUpdateDate(new Date()); | |||||
| sysConfigValueMapper.updateById(configValue); | |||||
| }else { | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| configValue = new SysConfigValue(); | |||||
| configValue.setConfigItemId(config.getId()); | |||||
| configValue.setId(idWorker.nextId()); | |||||
| configValue.updateTenantInfo(tenantEntity); | |||||
| configValue.setConfigItemValue(value); | |||||
| configValue.setCreateDate(new Date()); | |||||
| sysConfigValueMapper.insert(configValue); | |||||
| } | |||||
| RedisCacheUtils.removeCache(baseRedisTemplate, String.format(cache_prex, tenantEntity.getTenantId(),config.getConfigItemKey())); | |||||
| } | |||||
| @Override | |||||
| public void saveOrUpdate(SysConfig record) { | |||||
| Date curr = new Date(); | |||||
| if (record.getId() == null) { | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| record.setId(idWorker.nextId()); | |||||
| record.setCreateDate(curr); | |||||
| record.setUpdateDate(curr); | |||||
| sysConfigMapper.insert(record); | |||||
| } else { | |||||
| record.setUpdateDate(curr); | |||||
| sysConfigMapper.updateById(record); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,198 @@ | |||||
| package com.iformall.service.wx; | |||||
| import java.io.File; | |||||
| import java.util.Date; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||||
| import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.Result; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.domain.po.PosCouponOrderVerify; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.domain.po.WxBatchOrder; | |||||
| import com.iformall.domain.po.WxCouponOrder; | |||||
| import com.iformall.domain.po.WxOrder; | |||||
| import com.iformall.domain.po.WxPayAccount; | |||||
| import com.iformall.domain.po.WxPayOrder; | |||||
| import com.iformall.enums.EnumCouponOrderStatus; | |||||
| import com.iformall.enums.EnumOrderFrom; | |||||
| import com.iformall.enums.EnumOrderStatus; | |||||
| import com.iformall.enums.EnumOrderType; | |||||
| import com.iformall.enums.EnumPayMode; | |||||
| import com.iformall.enums.EnumPayStatus; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.pay.WxPay; | |||||
| import com.iformall.pay.WxPayOrderQ; | |||||
| import com.iformall.pay.WxPayOrderSQ; | |||||
| import com.iformall.pay.WxPayment; | |||||
| import com.iformall.service.QrCodeService; | |||||
| import com.iformall.service.helper.WxPayOrderServiceHelper; | |||||
| import com.iformall.service.order.entity.WxComposeChildOrderShare; | |||||
| import com.iformall.service.pay.service.pay.PayAdapterService; | |||||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.utils.BeanUtils; | |||||
| import com.iformall.utils.MaUtil; | |||||
| import com.iformall.utils.MapUtil; | |||||
| import com.iformall.utils.QRCodeUtils; | |||||
| import com.iformall.utils.Utility; | |||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | |||||
| import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.open.api.WxOpenService; | |||||
| @Slf4j | |||||
| public class BaseWxPayAdapterService { | |||||
| @Autowired | |||||
| WxOpenService openService; | |||||
| @Autowired | |||||
| MaUtil maUtil; | |||||
| /** | |||||
| * 做为支付的扩展数据 | |||||
| * @param payOrder | |||||
| * @return | |||||
| */ | |||||
| protected String getAttach(WxPayOrder payOrder) { | |||||
| Map<String,String> map = new HashMap<>(); | |||||
| map.put("tenantId",payOrder.getTenantId()); | |||||
| return JSON.toJSONString(map); | |||||
| } | |||||
| protected String getMerchantUid(WxPayOrder payOrder,WxOrder order) { | |||||
| WxComposeChildOrderShare share = payOrder.getChildOrderShare(order.getId()); | |||||
| return share.getMerchantUid(); | |||||
| } | |||||
| protected File getQrCode(WxAppinfo appinfo,String pageUrl,int type,String sceneParam) throws WxErrorException { | |||||
| boolean isFmOpen = false; | |||||
| WxMaService wxMaService; | |||||
| if(isFmOpen) { | |||||
| wxMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appinfo.getAppId()); | |||||
| } else { | |||||
| wxMaService = maUtil.getWeappService(appinfo); | |||||
| } | |||||
| boolean autoColor = false; | |||||
| boolean isHyaline = true; | |||||
| WxMaCodeLineColor color = new WxMaCodeLineColor("0", "0", "0"); | |||||
| String pathStr = ""; | |||||
| if (StringUtils.isNotBlank(sceneParam)) { | |||||
| pathStr = pageUrl + "?scene="+sceneParam; | |||||
| } else { | |||||
| pathStr = pageUrl; | |||||
| } | |||||
| if(type == 0) { | |||||
| final File codeFile = wxMaService.getQrcodeService().createQrcode(pathStr, QRCodeUtils.QR_WIDTH); | |||||
| return codeFile; | |||||
| }else { | |||||
| final File codeFile = wxMaService.getQrcodeService().createWxaCodeUnlimit(sceneParam, pageUrl, QRCodeUtils.QR_WIDTH, autoColor, color, isHyaline); | |||||
| return codeFile; | |||||
| } | |||||
| } | |||||
| JSONObject errorMapClose = JSON.parseObject("{" + | |||||
| "\"ORDERPAID\":{\"detail\":\"订单已支付\",\"reason\":\"订单已支付,不能发起关单\",\"resolution\":\"订单已支付,不能发起关单,请当作已支付的正常交易\"}," + | |||||
| "\"SYSTEMERROR\":{\"detail\":\"系统错误\",\"reason\":\"系统错误\",\"resolution\":\"系统异常,请重新调用该API\"}," + | |||||
| "\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"订单已关闭,无法重复关闭\",\"resolution\":\"订单已关闭,无需继续调用\"}," + | |||||
| "\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," + | |||||
| "\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," + | |||||
| "\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"reason\":\"请检查XML参数格式是否正确\"}}"); | |||||
| /** | |||||
| * 收款码支付回撤,都是2.0版本 | |||||
| * @param appInfo | |||||
| * @param record | |||||
| * @param payAccount | |||||
| * @return | |||||
| * @throws Exception | |||||
| */ | |||||
| protected PayAdapterResult payOrderReverse(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount,String subMchId) throws Exception { | |||||
| String response = payOrderReverseWx(appInfo, record,payAccount,subMchId); | |||||
| log.info("pay order reverse, " + record.toString() + ", response: " + response); | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| String return_code = returnMap.get("return_code"); | |||||
| String result_code = returnMap.get("result_code"); | |||||
| if ("SUCCESS".equalsIgnoreCase(return_code)) { | |||||
| if ("SUCCESS".equals(result_code)) { | |||||
| return new PayAdapterResult(true, "订单撤销成功", returnMap, null); | |||||
| } else { | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorMapClose.getJSONObject(result_code); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| } else { | |||||
| errMsg = returnMap.get("return_msg"); | |||||
| } | |||||
| return new PayAdapterResult(false, errMsg, returnMap, null); | |||||
| } | |||||
| } else { | |||||
| String errMsg = returnMap.get("return_msg"); | |||||
| return new PayAdapterResult(false, errMsg, returnMap, null); | |||||
| } | |||||
| } | |||||
| private String payOrderReverseWx(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount,String subMchId) { | |||||
| // get payAccount | |||||
| if (payAccount.getType() == EnumPayMode.MCH.getCode()) { | |||||
| // 普通商户号模式 | |||||
| WxPayOrderQ payOrderC = new WxPayOrderQ(); | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| payOrderC.setAppid(appInfo.getAppId()); | |||||
| payOrderC.setMch_id(payAccount.getMchId()); | |||||
| payOrderC.setNonce_str(noncestr); | |||||
| payOrderC.setOut_trade_no(record.getPayOrderNo()); | |||||
| try { | |||||
| Map map = BeanUtils.toStringMap(payOrderC); | |||||
| payOrderC.setSign(WxPayment.createSign(map, payAccount.getApiKey())); | |||||
| map = BeanUtils.toStringMap(payOrderC); | |||||
| String response = WxPay.orderReverse(map, payAccount.getCertPath(), payAccount.getMchId()); | |||||
| log.info("request:" + map.toString() + "\nresponse:" + response); | |||||
| return response; | |||||
| } catch (RuntimeException e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| } else { | |||||
| // 服务商模式 | |||||
| WxPayOrderSQ payOrderSC = new WxPayOrderSQ(); | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| payOrderSC.setAppid(appInfo.getParentAppId()); | |||||
| payOrderSC.setSub_appid(appInfo.getAppId()); | |||||
| payOrderSC.setMch_id(payAccount.getMchId()); | |||||
| payOrderSC.setSub_mch_id(subMchId); | |||||
| payOrderSC.setNonce_str(noncestr); | |||||
| payOrderSC.setOut_trade_no(record.getPayOrderNo()); | |||||
| payOrderSC.setSign_type("HMAC-SHA256"); | |||||
| try { | |||||
| Map map = BeanUtils.toStringMap(payOrderSC); | |||||
| payOrderSC.setSign(WxPayment.createSignHMAC(map, payAccount.getApiKey())); | |||||
| map = BeanUtils.toStringMap(payOrderSC); | |||||
| String response = WxPay.orderReverse(map, payAccount.getCertPath(), payAccount.getMchId()); | |||||
| log.info("request:" + map.toString() + "\nresponse:" + response); | |||||
| return response; | |||||
| } catch (RuntimeException e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,159 @@ | |||||
| package com.iformall.service.wx; | |||||
| import java.io.File; | |||||
| import java.util.Date; | |||||
| import java.util.Map; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||||
| import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.Result; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.domain.po.PosCouponOrderVerify; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.domain.po.WxBatchOrder; | |||||
| import com.iformall.domain.po.WxCouponOrder; | |||||
| import com.iformall.domain.po.WxOrder; | |||||
| import com.iformall.domain.po.WxPayAccount; | |||||
| import com.iformall.domain.po.WxPayOrder; | |||||
| import com.iformall.enums.EnumCouponOrderStatus; | |||||
| import com.iformall.enums.EnumOrderFrom; | |||||
| import com.iformall.enums.EnumOrderStatus; | |||||
| import com.iformall.enums.EnumOrderType; | |||||
| import com.iformall.enums.EnumPayMode; | |||||
| import com.iformall.enums.EnumPayStatus; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.pay.WxPay; | |||||
| import com.iformall.pay.WxPayOrderQ; | |||||
| import com.iformall.pay.WxPayOrderSQ; | |||||
| import com.iformall.pay.WxPayment; | |||||
| import com.iformall.service.QrCodeService; | |||||
| import com.iformall.service.helper.WxPayOrderServiceHelper; | |||||
| import com.iformall.service.pay.service.pay.PayAdapterService; | |||||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.wx.BaseWxPayAdapterService; | |||||
| import com.iformall.utils.BeanUtils; | |||||
| import com.iformall.utils.MaUtil; | |||||
| import com.iformall.utils.QRCodeUtils; | |||||
| import com.iformall.utils.Utility; | |||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | |||||
| import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | |||||
| import me.chanjar.weixin.open.api.WxOpenService; | |||||
| @Slf4j | |||||
| public class BaseWxPayV2AdapterService extends BaseWxPayAdapterService{ | |||||
| protected PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxAppinfo appInfo, WxPayAccount payAccount) | |||||
| throws Exception { | |||||
| Map<String, String> retMap = WxPayOrderServiceHelper.wxOrderPayStatusMap(oldRecord, appInfo, payAccount); | |||||
| int code = WxPayOrderServiceHelper.getPayStatusFromMap(retMap,oldRecord.getPayOrderNo()); | |||||
| String msg = WxPayOrderServiceHelper.getPayStatusMsg(retMap, oldRecord.getPayOrderNo()); | |||||
| PayQueryAdapterResult result = new PayQueryAdapterResult(code, msg,null, retMap,retMap.get("transaction_id"),retMap.get("time_end")); | |||||
| return result; | |||||
| } | |||||
| protected int queryPayStatus(PayQueryAdapterResult statusObject, String orderOutNo) throws Exception { | |||||
| return WxPayOrderServiceHelper.getPayStatusFromMap((Map<String, String>) statusObject.getData(),orderOutNo); | |||||
| } | |||||
| protected int queryPayStatusCode(WxPayOrder oldRecord, WxAppinfo appInfo, WxPayAccount payAccount) | |||||
| throws Exception { | |||||
| return WxPayOrderServiceHelper.wxOrderPayStatus(oldRecord, appInfo, payAccount); | |||||
| } | |||||
| JSONObject errorMapClose = JSON.parseObject("{" + | |||||
| "\"ORDERPAID\":{\"detail\":\"订单已支付\",\"reason\":\"订单已支付,不能发起关单\",\"resolution\":\"订单已支付,不能发起关单,请当作已支付的正常交易\"}," + | |||||
| "\"SYSTEMERROR\":{\"detail\":\"系统错误\",\"reason\":\"系统错误\",\"resolution\":\"系统异常,请重新调用该API\"}," + | |||||
| "\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"订单已关闭,无法重复关闭\",\"resolution\":\"订单已关闭,无需继续调用\"}," + | |||||
| "\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," + | |||||
| "\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," + | |||||
| "\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"reason\":\"请检查XML参数格式是否正确\"}}"); | |||||
| protected PayAdapterResult closeOrder(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) { | |||||
| String response = closeOrderWx(appInfo, record,payAccount); | |||||
| log.info("pay order close, " + record.toString() + ", response: " + response); | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| String return_code = returnMap.get("return_code"); | |||||
| String result_code = returnMap.get("result_code"); | |||||
| if ("SUCCESS".equalsIgnoreCase(return_code)) { | |||||
| if ("SUCCESS".equals(result_code)) { | |||||
| return new PayAdapterResult(true, "success", returnMap, null); | |||||
| } else { | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorMapClose.getJSONObject(result_code); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| } else { | |||||
| errMsg = returnMap.get("return_msg"); | |||||
| } | |||||
| return new PayAdapterResult(false, errMsg, returnMap, null); | |||||
| } | |||||
| } else { | |||||
| String errMsg = returnMap.get("return_msg"); | |||||
| return new PayAdapterResult(false, errMsg, returnMap, null); | |||||
| } | |||||
| } | |||||
| private String closeOrderWx(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) { | |||||
| // get payAccount | |||||
| if (payAccount.getType() == EnumPayMode.MCH.getCode()) { | |||||
| // 普通商户号模式 | |||||
| WxPayOrderQ payOrderC = new WxPayOrderQ(); | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| payOrderC.setAppid(appInfo.getAppId()); | |||||
| payOrderC.setMch_id(payAccount.getMchId()); | |||||
| payOrderC.setNonce_str(noncestr); | |||||
| payOrderC.setOut_trade_no(record.getPayOrderNo()); | |||||
| try { | |||||
| Map map = BeanUtils.toStringMap(payOrderC); | |||||
| payOrderC.setSign(WxPayment.createSign(map, payAccount.getApiKey())); | |||||
| map = BeanUtils.toStringMap(payOrderC); | |||||
| String response = WxPay.closeOrder(map); | |||||
| log.info("request:" + map.toString() + "\nresponse:" + response); | |||||
| return response; | |||||
| } catch (RuntimeException e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| } else { | |||||
| // 服务商模式 | |||||
| WxPayOrderSQ payOrderSC = new WxPayOrderSQ(); | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| payOrderSC.setAppid(appInfo.getParentAppId()); | |||||
| payOrderSC.setSub_appid(appInfo.getAppId()); | |||||
| payOrderSC.setMch_id(payAccount.getMchId()); | |||||
| payOrderSC.setSub_mch_id(payAccount.getSubMchId()); | |||||
| payOrderSC.setNonce_str(noncestr); | |||||
| payOrderSC.setOut_trade_no(record.getPayOrderNo()); | |||||
| payOrderSC.setSign_type("HMAC-SHA256"); | |||||
| try { | |||||
| Map map = BeanUtils.toStringMap(payOrderSC); | |||||
| payOrderSC.setSign(WxPayment.createSignHMAC(map, payAccount.getApiKey())); | |||||
| map = BeanUtils.toStringMap(payOrderSC); | |||||
| String response = WxPay.closeOrder(map); | |||||
| log.info("request:" + map.toString() + "\nresponse:" + response); | |||||
| return response; | |||||
| } catch (RuntimeException e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,114 @@ | |||||
| package com.iformall.service.wx; | |||||
| import java.util.Date; | |||||
| import java.util.Map; | |||||
| import com.iformall.domain.entity.PayAdapterResult; | |||||
| import com.iformall.domain.entity.WxPay; | |||||
| import com.iformall.domain.entity.WxPayOrderP; | |||||
| import com.iformall.domain.entity.WxPayment; | |||||
| import org.springframework.stereotype.Service; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.utils.BeanUtils; | |||||
| import com.iformall.utils.MapUtil; | |||||
| import com.iformall.utils.Utility; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| @Slf4j | |||||
| @Service | |||||
| public class WxMiniAppPayAdapterService extends BaseWxPayV2AdapterService{ | |||||
| JSONObject errorMap = JSON.parseObject("{" + | |||||
| "\"NOAUTH\":{\"detail\":\"商户无此接口权限\",\"reason\":\"商户未开通此接口权限\",\"resolution\":\"请商户前往申请此接口权限\"}," + | |||||
| "\"NOTENOUGH\":{\"detail\":\"余额不足\",\"reason\":\"用户帐号余额不足\",\"resolution\":\"用户帐号余额不足,请用户充值或更换支付卡后再支付\"}," + | |||||
| "\"ORDERPAID\":{\"detail\":\"商户订单已支付\",\"reason\":\"商户订单已支付,无需重复操作\",\"resolution\":\"商户订单已支付,无需更多操作\"}," + | |||||
| "\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"当前订单已关闭,无法支付\",\"resolution\":\"当前订单已关闭,请重新下单\"}," + | |||||
| "\"SYSTEMERROR\":{\"detail\":\"系统错误\t\",\"reason\":\"系统超时\",\"resolution\":\"系统异常,请用相同参数重新调用\"}," + | |||||
| "\"APPID_NOT_EXIST\":{\"detail\":\"APPID不存在\",\"reason\":\"参数中缺少APPID\",\"resolution\":\"请检查APPID是否正确\"}," + | |||||
| "\"MCHID_NOT_EXIST\":{\"detail\":\"MCHID不存在\",\"reason\":\"参数中缺少MCHID\",\"resolution\":\"请检查MCHID是否正确\"}," + | |||||
| "\"APPID_MCHID_NOT_MATCH\":{\"detail\":\"appid和mch_id不匹配\",\"reason\":\"appid和mch_id不匹配\",\"resolution\":\"请确认appid和mch_id是否匹配\"}," + | |||||
| "\"LACK_PARAMS\":{\"detail\":\"缺少参数\t\",\"reason\":\"缺少必要的请求参数\",\"resolution\":\"请检查参数是否齐全\"}," + | |||||
| "\"OUT_TRADE_NO_USED\":{\"detail\":\"商户订单号重复\",\"reason\":\"同一笔交易不能多次提交\",\"resolution\":\"请核实商户订单号是否重复提交\"}," + | |||||
| "\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," + | |||||
| "\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"resolution\":\"请检查XML参数格式是否正确\"}," + | |||||
| "\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," + | |||||
| "\"POST_DATA_EMPTY\":{\"detail\":\"post数据为空\",\"reason\":\"post数据不能为空\",\"resolution\":\"请检查post数据是否为空\"}," + | |||||
| "\"NOT_UTF8\":{\"detail\":\"编码格式错误\",\"reason\":\"未使用指定编码格式\",\"resolution\":\"请使用UTF-8编码格式\"}}"); | |||||
| private WxPayOrderP generateWxPayOrderP(String openId,String appId,String mchId,String productName,String attach,String payOrderNo,Integer fee,String ip,String notifyUrl,String apiKey,Date currentDate,String productId)throws Exception { | |||||
| // 统一下单 普通商户模式 | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| WxPayOrderP wxPayOrderP = new WxPayOrderP(); | |||||
| wxPayOrderP.setOpenid(openId); | |||||
| wxPayOrderP.setAppid(appId); | |||||
| wxPayOrderP.setMch_id(mchId); | |||||
| wxPayOrderP.setNonce_str(noncestr); | |||||
| wxPayOrderP.setBody(productName); | |||||
| wxPayOrderP.setAttach(attach); | |||||
| wxPayOrderP.setOut_trade_no(payOrderNo); | |||||
| wxPayOrderP.setTotal_fee(fee); | |||||
| wxPayOrderP.setSpbill_create_ip(ip); // 终端IP | |||||
| wxPayOrderP.setGoods_tag(productName); | |||||
| wxPayOrderP.setNotify_url(notifyUrl); | |||||
| wxPayOrderP.setTrade_type(WxPay.TradeType.JSAPI.name()); // 终端类型 | |||||
| if (null != productId) { | |||||
| wxPayOrderP.setProduct_id(productId); | |||||
| } | |||||
| wxPayOrderP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate)); | |||||
| Date futureDate = new Date(); | |||||
| futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000); | |||||
| wxPayOrderP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); // 15分钟后结束 | |||||
| Map<String, String> payOrderMap = BeanUtils.toStringMap(wxPayOrderP); | |||||
| wxPayOrderP.setSign(WxPayment.createSign(payOrderMap, apiKey)); | |||||
| return wxPayOrderP; | |||||
| } | |||||
| private PayAdapterResult getOrderPResult(Map<String, String> returnMap,String noncestr,String apiKey) { | |||||
| PayAdapterResult par = new PayAdapterResult(); | |||||
| String result_code = returnMap.get("result_code"); | |||||
| if ("SUCCESS".equals(result_code)) { | |||||
| par.setSuccess(true); | |||||
| par.setMsg("success."); | |||||
| par.setData(returnMap); | |||||
| String prepay_id = returnMap.get("prepay_id"); | |||||
| String timestamp = String.valueOf(Utility.getCurrentTimeStamp()); | |||||
| Map<String, String> sighMap = MapUtil.getOrderMap(); | |||||
| sighMap.put("appId", returnMap.get("appid")); | |||||
| sighMap.put("timeStamp", timestamp); | |||||
| sighMap.put("nonceStr", noncestr); | |||||
| sighMap.put("package", "prepay_id=" + prepay_id); | |||||
| sighMap.put("signType", "MD5"); | |||||
| String signAgent = WxPayment.createSign(sighMap, apiKey); | |||||
| returnMap.put("timeStamp", timestamp); | |||||
| returnMap.put("nonceStr", noncestr); | |||||
| returnMap.put("package", "prepay_id=" + prepay_id); | |||||
| returnMap.put("paySign", signAgent); | |||||
| log.info("back to UI: " + returnMap.toString()); | |||||
| } else { | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorMap.getJSONObject(result_code); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| } else { | |||||
| errMsg = returnMap.get("return_msg"); | |||||
| } | |||||
| par.setSuccess(false); | |||||
| par.setMsg(errMsg); | |||||
| par.setData(returnMap); | |||||
| } | |||||
| return par; | |||||
| } | |||||
| public PayAdapterResult pay(String openId,String appId,String mchId,String productName,String attach,String payOrderNo,Integer fee,String ip,String notifyUrl,String apiKey,Date currentDate) throws Exception { | |||||
| WxPayOrderP wxPayOrderP = generateWxPayOrderP(openId, appId, mchId, productName, attach, payOrderNo, fee, ip, notifyUrl, apiKey, currentDate,null); | |||||
| String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayOrderP)); | |||||
| log.info("pay order, wechat pushOrder, " + wxPayOrderP.toString() + ", response: " + response.toString()); | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| return getOrderPResult(returnMap,wxPayOrderP.getNonce_str(),apiKey); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,28 @@ | |||||
| package com.iformall.service.wx; | |||||
| import java.util.Date; | |||||
| import java.util.Map; | |||||
| import com.github.pagehelper.PageInfo; | |||||
| import com.iformall.domain.entity.PayAdapterResult; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.domain.po.WxPayOrder; | |||||
| import com.iformall.domain.po.WxPayAccount; | |||||
| public interface WxPayService { | |||||
| public PageInfo<WxPayOrder> listPayOrderAsPage(WxPayOrder record, Integer pageIndex, Integer pageSize); | |||||
| //share:是否分账,服务商模式下生效 | |||||
| public PayAdapterResult createWxPayOrder(WxPayAccount payAccount,WxAppinfo cAppInfo,boolean isIsvModel,boolean share,String appId,String mchId,String productName,String attach,String payOrderNo, | |||||
| Integer fee,String ip,String notifyUrl,String apiKey,Date currentDate) throws Exception; | |||||
| public String handlePaidCallBack(String tenantId,Map<String, String> paramMap); | |||||
| public void handlePaidSuccess(String tenantId,Long orderId,Long cUserId,Integer fee,Date paidTime,String transcationId, | |||||
| String userPhone) throws Exception; | |||||
| public WxPayOrder detailPayOrder(Long id,String tenantId); | |||||
| public Integer sumPayOrder(WxPayOrder record); | |||||
| } | |||||
| @@ -0,0 +1,182 @@ | |||||
| package com.iformall.service.wx; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.github.pagehelper.PageHelper; | |||||
| import com.github.pagehelper.PageInfo; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.IdWorker; | |||||
| import com.iformall.domain.entity.PayAdapterResult; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.domain.po.WxPayOrder; | |||||
| import com.iformall.domain.po.WxPayAccount; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.mapper.WxAppinfoMapper; | |||||
| import com.iformall.mapper.WxPayOrderMapper; | |||||
| import com.iformall.mapper.WxPayAccountMapper; | |||||
| import com.iformall.service.WxAppinfoService; | |||||
| import com.iformall.service.WxPayAccountService; | |||||
| import com.iformall.utils.DateUtils; | |||||
| import com.iformall.utils.RedisLock; | |||||
| import com.iformall.utils.XmlUtil; | |||||
| import java.util.Date; | |||||
| import java.util.Map; | |||||
| import java.util.SortedMap; | |||||
| import java.util.TreeMap; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.context.annotation.Lazy; | |||||
| import org.springframework.stereotype.Service; | |||||
| @Service | |||||
| public class WxPayServiceImpl implements WxPayService { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| WxPayOrderMapper wxPayOrderMapper; | |||||
| @Autowired | |||||
| WxMiniAppPayAdapterService wxMiniAppPayAdapterService; | |||||
| @Autowired | |||||
| WxAppinfoMapper wxAppinfoMapper; | |||||
| @Autowired | |||||
| WxPayAccountMapper wxPayAccountMapper; | |||||
| @Autowired | |||||
| RedisLock redisLock; | |||||
| @Lazy | |||||
| @Autowired | |||||
| WxAppinfoService wxAppinfoService; | |||||
| @Lazy | |||||
| @Autowired | |||||
| WxPayAccountService wxPayAccountService; | |||||
| @Override | |||||
| public PageInfo<WxPayOrder> listPayOrderAsPage(WxPayOrder record, Integer pageIndex, Integer pageSize) { | |||||
| return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxPayOrderMapper.findList(record)); | |||||
| } | |||||
| @Override | |||||
| public PayAdapterResult createWxPayOrder(WxPayAccount payAccount,WxAppinfo cAppInfo,boolean isIsvModel,boolean share,String openId,String mchId,String productName,String attach,String payOrderNo, | |||||
| Integer fee,String ip,String notifyUrl,String apiKey,Date currentDate) throws Exception { | |||||
| return wxMiniAppPayAdapterService.pay(openId, cAppInfo.getAppId(),mchId, productName, attach, payOrderNo, fee, ip, notifyUrl, apiKey, currentDate); | |||||
| } | |||||
| private String notifyErrorResult(String msg) { | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "FAIL"); | |||||
| resultMap.put("return_msg", msg); | |||||
| return XmlUtil.getRequestXml(resultMap); | |||||
| } | |||||
| private String notifySuccessResult() { | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "SUCCESS"); | |||||
| resultMap.put("return_msg", "OK"); | |||||
| return XmlUtil.getRequestXml(resultMap); | |||||
| } | |||||
| @Override | |||||
| public String handlePaidCallBack(String tenantId,Map<String, String> paramMap) { | |||||
| logger.info("handleCarPaidCallBack."+JSON.toJSONString(paramMap)); | |||||
| //支付返回消息 | |||||
| String returnCode = paramMap.get("return_code"); | |||||
| if ("SUCCESS".equals(returnCode)) { | |||||
| String resultCode = paramMap.get("result_code"); | |||||
| if ("SUCCESS".equals(resultCode)) { | |||||
| //判断支付金额是否大于0 | |||||
| String cashFeeStr = paramMap.get("cash_fee"); | |||||
| Integer cashFee = Integer.parseInt(cashFeeStr); | |||||
| if (cashFee > 0 ) { | |||||
| try { | |||||
| //String payOrderNo = paramMap.get("out_trade_no"); | |||||
| String time_end = paramMap.get("time_end"); | |||||
| String transcationId = paramMap.get("transaction_id"); | |||||
| TenantEntity teq = new TenantEntity(); | |||||
| teq.setTenantId(tenantId); | |||||
| String attach = paramMap.get("attach"); | |||||
| Long cUserId = null; | |||||
| String userPhone = null; | |||||
| if (!StringUtils.isBlank(attach)) { | |||||
| String[] attrs = attach.split(","); | |||||
| if (attrs.length == 2) { | |||||
| cUserId = Long.parseLong(attrs[0]); | |||||
| userPhone = attrs[1]; | |||||
| } | |||||
| } | |||||
| String payOrderNo = paramMap.get("out_trade_no"); | |||||
| handlePaidSuccess(tenantId,Long.parseLong(payOrderNo),cUserId,Integer.parseInt(cashFeeStr), | |||||
| DateUtils.string2Date(time_end, DateUtils.DATE_PATTERN_ALL_NOSPACE).getTime(),transcationId, | |||||
| userPhone); | |||||
| } catch (Exception e) { | |||||
| logger.error("handlePaidCallBackError.",e); | |||||
| return notifyErrorResult(e.getMessage()); | |||||
| } | |||||
| } | |||||
| return notifySuccessResult(); | |||||
| }else { | |||||
| String errorMsg = paramMap.get("err_code_des"); | |||||
| return notifyErrorResult(errorMsg); | |||||
| } | |||||
| }else { | |||||
| String errorMsg = paramMap.get("return_msg"); | |||||
| return notifyErrorResult(errorMsg); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public void handlePaidSuccess(String tenantId,Long orderId,Long cUserId,Integer fee,Date paidTime,String transcationId, | |||||
| String userPhone) throws Exception{ | |||||
| //查询该笔订单是否已经存在 | |||||
| WxPayOrder payOrder = wxPayOrderMapper.selectById(orderId, tenantId); | |||||
| //String parkOrderNo = ParkCreatePayOrder.getRealParkOrderNumber(payOrderNo,EnumCarVendor.getEnum(carVendor)); | |||||
| if (null == payOrder) { | |||||
| //此处需要加锁,防止并发设置 | |||||
| long time = System.currentTimeMillis() + RedisLock.TIMEOUT; | |||||
| String timeStr = String.valueOf(time); | |||||
| boolean stocksetlock = redisLock.lock("carPayOrderLock_"+orderId, timeStr); | |||||
| if (stocksetlock) { | |||||
| try { | |||||
| //创建停车支付订单记录 | |||||
| final IdWorker idworker = IdWorker.get(); | |||||
| payOrder = new WxPayOrder(); | |||||
| Long id = idworker.nextId(); | |||||
| payOrder.setId(id); | |||||
| payOrder.setTenantId(tenantId); | |||||
| payOrder.setCreateTime(new Date()); | |||||
| payOrder.setUpdateTime(new Date()); | |||||
| payOrder.setcUserId(cUserId); | |||||
| payOrder.setPayAmount(fee); | |||||
| payOrder.setPayTime(paidTime); | |||||
| payOrder.setTransactionId(transcationId); | |||||
| payOrder.setcUserPhone(userPhone); | |||||
| wxPayOrderMapper.insert(payOrder); | |||||
| }catch(Exception e) { | |||||
| logger.error("handlePaidSuccess fail.",e); | |||||
| throw new MallinkException(ErrorCode.SERVER_ERROR.getCode(),"支付失败"+orderId); | |||||
| }finally { | |||||
| redisLock.unlock("carPayOrderLock_"+orderId, timeStr); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public WxPayOrder detailPayOrder(Long id,String tenantId) { | |||||
| return wxPayOrderMapper.selectById(id, tenantId); | |||||
| } | |||||
| @Override | |||||
| public Integer sumPayOrder(WxPayOrder record) { | |||||
| return wxPayOrderMapper.sum(record); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,165 @@ | |||||
| package com.iformall.utils; | |||||
| import com.google.gson.internal.LinkedTreeMap; | |||||
| import java.beans.BeanInfo; | |||||
| import java.beans.IntrospectionException; | |||||
| import java.beans.Introspector; | |||||
| import java.beans.PropertyDescriptor; | |||||
| import java.lang.reflect.InvocationTargetException; | |||||
| import java.lang.reflect.Method; | |||||
| import java.util.Map; | |||||
| import java.util.Objects; | |||||
| /** | |||||
| * Created by Stormeye on 2018/8/10. | |||||
| */ | |||||
| public class BeanUtils { | |||||
| /** | |||||
| * 如果是null,将返回字符串0 | |||||
| * | |||||
| * @param param | |||||
| * @return | |||||
| */ | |||||
| public static String ifNullTo0(String param) { | |||||
| if (param == null || param.equals("null")) { | |||||
| return "0"; | |||||
| } | |||||
| return param; | |||||
| } | |||||
| public static Object getValue(Object obj, String pro) throws NoSuchMethodException { | |||||
| return getValue(obj, pro, null); | |||||
| } | |||||
| /** | |||||
| * 根据属性名称获取JavaBean中对应的属性值 | |||||
| * | |||||
| * @param obj 对象 | |||||
| * @param pro 对应属性名称 | |||||
| * @param num 整型参数 | |||||
| * @return 对象对应属性值 | |||||
| */ | |||||
| public static Object getValue(Object obj, String pro, Integer num) throws NoSuchMethodException { | |||||
| Class<?> clazz = obj.getClass(); | |||||
| do { | |||||
| try { | |||||
| String methodName = "getSimpleRegionModel" + pro.substring(0, 1).toUpperCase() + pro.substring(1); | |||||
| Method method; | |||||
| if (!Objects.isNull(num)) { | |||||
| method = clazz.getDeclaredMethod(methodName, Integer.class); | |||||
| return method.invoke(obj, num); | |||||
| } else { | |||||
| method = clazz.getDeclaredMethod(methodName); | |||||
| return method.invoke(obj); | |||||
| } | |||||
| } catch (NoSuchMethodException e) { | |||||
| clazz = clazz.getSuperclass(); | |||||
| } catch (InvocationTargetException | IllegalAccessException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } while (clazz != Object.class); | |||||
| throw new NoSuchMethodException("no such method name : " + "getSimpleRegionModel" + pro.substring(0, 1).toUpperCase() + pro.substring(1)); | |||||
| } | |||||
| public static void transMap2Bean2(Map<String, Object> map, Object obj) { | |||||
| if (map == null || obj == null) { | |||||
| return; | |||||
| } | |||||
| try { | |||||
| org.apache.commons.beanutils.BeanUtils.populate(obj, map); | |||||
| } catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 根据key数组和value数组拼接json | |||||
| * | |||||
| * @param keys key数组 | |||||
| * @param values value数据 | |||||
| * @return json | |||||
| * @throws Exception | |||||
| */ | |||||
| public static String wrapToJsonByKeyValue(String[] keys, String[] values) throws Exception { | |||||
| StringBuilder stringBuilder = new StringBuilder(); | |||||
| if (keys.length != values.length) { | |||||
| throw new Exception("长度不匹配,不能进行JSON格式的转换"); | |||||
| } | |||||
| for (int i = 0; i < keys.length; i++) { | |||||
| stringBuilder.append("\"").append(keys[i]).append("\":\"").append(values[i]).append("\","); | |||||
| } | |||||
| return "{" + stringBuilder.substring(0, stringBuilder.length() - 1) + "}"; | |||||
| } | |||||
| /** | |||||
| * Converts a JavaBean to a map | |||||
| * | |||||
| * @param bean JavaBean to convert | |||||
| * @return map converted | |||||
| * @throws IntrospectionException failed to get class fields | |||||
| * @throws IllegalAccessException failed to instant JavaBean | |||||
| * @throws InvocationTargetException failed to call setters | |||||
| */ | |||||
| public static final Map<String, Object> toMap(Object bean) | |||||
| throws Exception { | |||||
| Map<String, Object> returnMap = new LinkedTreeMap(); | |||||
| if (bean instanceof Map) { | |||||
| returnMap.putAll((Map<String, Object>)bean); | |||||
| return returnMap; | |||||
| } | |||||
| BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); | |||||
| PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); | |||||
| for (int i = 0; i< propertyDescriptors.length; i++) { | |||||
| PropertyDescriptor descriptor = propertyDescriptors[i]; | |||||
| String propertyName = descriptor.getName(); | |||||
| if (!propertyName.equals("class")) { | |||||
| Method readMethod = descriptor.getReadMethod(); | |||||
| Object result = readMethod.invoke(bean, new Object[0]); | |||||
| if (result != null) { | |||||
| returnMap.put(propertyName, result); | |||||
| } else { | |||||
| returnMap.put(propertyName, ""); | |||||
| } | |||||
| } | |||||
| } | |||||
| return returnMap; | |||||
| } | |||||
| /** | |||||
| * Converts a JavaBean to a map | |||||
| * | |||||
| * @param bean JavaBean to convert | |||||
| * @return map converted | |||||
| * @throws IntrospectionException failed to get class fields | |||||
| * @throws IllegalAccessException failed to instant JavaBean | |||||
| * @throws InvocationTargetException failed to call setters | |||||
| */ | |||||
| public static final Map<String, String> toStringMap(Object bean) | |||||
| throws Exception { | |||||
| Map<String, String> returnMap = new LinkedTreeMap(); | |||||
| if (bean instanceof Map) { | |||||
| returnMap.putAll((Map<String, String>)bean); | |||||
| return returnMap; | |||||
| } | |||||
| BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); | |||||
| PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); | |||||
| for (int i = 0; i< propertyDescriptors.length; i++) { | |||||
| PropertyDescriptor descriptor = propertyDescriptors[i]; | |||||
| String propertyName = descriptor.getName(); | |||||
| if (!propertyName.equals("class")) { | |||||
| Method readMethod = descriptor.getReadMethod(); | |||||
| Object result = readMethod.invoke(bean, new Object[0]); | |||||
| if (result != null) { | |||||
| returnMap.put(propertyName, String.valueOf(result)); | |||||
| } else { | |||||
| returnMap.put(propertyName, ""); | |||||
| } | |||||
| } | |||||
| } | |||||
| return returnMap; | |||||
| } | |||||
| } | |||||
| @@ -9,5 +9,6 @@ public class Constant { | |||||
| public static final String currentUser = "currentUser"; | public static final String currentUser = "currentUser"; | ||||
| public static final String TENANT_ID = "tenantId"; | public static final String TENANT_ID = "tenantId"; | ||||
| public static final String PARENT_TENANT_ID = "parentTenantId"; | public static final String PARENT_TENANT_ID = "parentTenantId"; | ||||
| public static final String paymentReceiverParamIsv = "isvModel"; | |||||
| public static final String paymentReceicerParamApiKey = "apiKey"; | |||||
| } | } | ||||
| @@ -0,0 +1,323 @@ | |||||
| package com.iformall.utils; | |||||
| import org.apache.commons.lang3.ArrayUtils; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import java.io.File; | |||||
| import java.io.IOException; | |||||
| import java.net.MalformedURLException; | |||||
| import java.net.URL; | |||||
| import java.security.CodeSource; | |||||
| import java.security.ProtectionDomain; | |||||
| import java.util.Collection; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * 常见的辅助类 | |||||
| * | |||||
| * @author Stormeye | |||||
| * @since 2011-11-08 | |||||
| */ | |||||
| public final class DataUtil { | |||||
| private DataUtil() { | |||||
| } | |||||
| /** | |||||
| * 十进制字节数组转十六进制字符串 | |||||
| * | |||||
| * @param b | |||||
| * @return | |||||
| */ | |||||
| public static final String byte2hex(byte[] b) { // 一个字节数,转成16进制字符串 | |||||
| StringBuilder hs = new StringBuilder(b.length * 2); | |||||
| String stmp = ""; | |||||
| for (int n = 0; n < b.length; n++) { | |||||
| // 整数转成十六进制表示 | |||||
| stmp = Integer.toHexString(b[n] & 0XFF); | |||||
| if (stmp.length() == 1) | |||||
| hs.append("0").append(stmp); | |||||
| else | |||||
| hs.append(stmp); | |||||
| } | |||||
| return hs.toString(); // 转成大写 | |||||
| } | |||||
| /** | |||||
| * 十六进制字符串转十进制字节数组 | |||||
| * | |||||
| * @param hs | |||||
| * @return | |||||
| */ | |||||
| public static final byte[] hex2byte(String hs) { | |||||
| byte[] b = hs.getBytes(); | |||||
| if ((b.length % 2) != 0) | |||||
| throw new IllegalArgumentException("长度不是偶数"); | |||||
| byte[] b2 = new byte[b.length / 2]; | |||||
| for (int n = 0; n < b.length; n += 2) { | |||||
| String item = new String(b, n, 2); | |||||
| // 两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个十进制字节 | |||||
| b2[n / 2] = (byte) Integer.parseInt(item, 16); | |||||
| } | |||||
| return b2; | |||||
| } | |||||
| /** | |||||
| * 这个方法可以通过与某个类的class文件的相对路径来获取文件或目录的绝对路径。 通常在程序中很难定位某个相对路径,特别是在B/S应用中。 | |||||
| * 通过这个方法,我们可以根据我们程序自身的类文件的位置来定位某个相对路径。 | |||||
| * 比如:某个txt文件相对于程序的Test类文件的路径是../../resource/test.txt, | |||||
| * 那么使用本方法Path.getFullPathRelateClass("../../resource/test.txt",Test.class) | |||||
| * 得到的结果是txt文件的在系统中的绝对路径。 | |||||
| * | |||||
| * @param relatedPath 相对路径 | |||||
| * @param cls 用来定位的类 | |||||
| * @return 相对路径所对应的绝对路径 | |||||
| * @throws IOException 因为本方法将查询文件系统,所以可能抛出IO异常 | |||||
| */ | |||||
| public static final String getFullPathRelateClass(String relatedPath, Class<?> cls) { | |||||
| String path = null; | |||||
| if (relatedPath == null) { | |||||
| throw new NullPointerException(); | |||||
| } | |||||
| String clsPath = getPathFromClass(cls); | |||||
| File clsFile = new File(clsPath); | |||||
| String tempPath = clsFile.getParent() + File.separator + relatedPath; | |||||
| File file = new File(tempPath); | |||||
| try { | |||||
| path = file.getCanonicalPath(); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return path; | |||||
| } | |||||
| /** | |||||
| * 获取class文件所在绝对路径 | |||||
| * | |||||
| * @param cls | |||||
| * @return | |||||
| * @throws IOException | |||||
| */ | |||||
| public static final String getPathFromClass(Class<?> cls) { | |||||
| String path = null; | |||||
| if (cls == null) { | |||||
| throw new NullPointerException(); | |||||
| } | |||||
| URL url = getClassLocationURL(cls); | |||||
| if (url != null) { | |||||
| path = url.getPath(); | |||||
| if ("jar".equalsIgnoreCase(url.getProtocol())) { | |||||
| try { | |||||
| path = new URL(path).getPath(); | |||||
| } catch (MalformedURLException e) { | |||||
| } | |||||
| int location = path.indexOf("!/"); | |||||
| if (location != -1) { | |||||
| path = path.substring(0, location); | |||||
| } | |||||
| } | |||||
| File file = new File(path); | |||||
| try { | |||||
| path = file.getCanonicalPath(); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| return path; | |||||
| } | |||||
| /** | |||||
| * 判断对象是否Empty(null或元素为0)<br> | |||||
| * 实用于对如下对象做判断:String Collection及其子类 Map及其子类 | |||||
| * | |||||
| * @param pObj 待检查对象 | |||||
| * @return boolean 返回的布尔值 | |||||
| */ | |||||
| public static final boolean isEmpty(Object pObj) { | |||||
| if (pObj == null) | |||||
| return true; | |||||
| if (pObj == "") | |||||
| return true; | |||||
| if (pObj instanceof String) { | |||||
| if (((String) pObj).trim().length() == 0) { | |||||
| return true; | |||||
| } | |||||
| } else if (pObj instanceof Collection<?>) { | |||||
| if (((Collection<?>) pObj).size() == 0) { | |||||
| return true; | |||||
| } | |||||
| } else if (pObj instanceof Map<?, ?>) { | |||||
| if (((Map<?, ?>) pObj).size() == 0) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /** | |||||
| * 判断对象是否为NotEmpty(!null或元素>0)<br> | |||||
| * 实用于对如下对象做判断:String Collection及其子类 Map及其子类 | |||||
| * | |||||
| * @param pObj 待检查对象 | |||||
| * @return boolean 返回的布尔值 | |||||
| */ | |||||
| public static final boolean isNotEmpty(Object pObj) { | |||||
| if (pObj == null) | |||||
| return false; | |||||
| if (pObj == "") | |||||
| return false; | |||||
| if (pObj instanceof String) { | |||||
| if (((String) pObj).trim().length() == 0) { | |||||
| return false; | |||||
| } | |||||
| } else if (pObj instanceof Collection<?>) { | |||||
| if (((Collection<?>) pObj).size() == 0) { | |||||
| return false; | |||||
| } | |||||
| } else if (pObj instanceof Map<?, ?>) { | |||||
| if (((Map<?, ?>) pObj).size() == 0) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * JS输出含有\n的特殊处理 | |||||
| * | |||||
| * @param pStr | |||||
| * @return | |||||
| */ | |||||
| public static final String replace4JsOutput(String pStr) { | |||||
| pStr = pStr.replace("\r\n", "<br/> "); | |||||
| pStr = pStr.replace("\t", " "); | |||||
| pStr = pStr.replace(" ", " "); | |||||
| return pStr; | |||||
| } | |||||
| /** | |||||
| * 分别去空格 | |||||
| * | |||||
| * @param paramArray | |||||
| * @return | |||||
| */ | |||||
| public static final String[] trim(String[] paramArray) { | |||||
| if (ArrayUtils.isEmpty(paramArray)) { | |||||
| return paramArray; | |||||
| } | |||||
| String[] resultArray = new String[paramArray.length]; | |||||
| for (int i = 0; i < paramArray.length; i++) { | |||||
| String param = paramArray[i]; | |||||
| resultArray[i] = StringUtils.trim(param); | |||||
| } | |||||
| return resultArray; | |||||
| } | |||||
| /** | |||||
| * 获取类的class文件位置的URL | |||||
| * | |||||
| * @param cls | |||||
| * @return | |||||
| */ | |||||
| private static URL getClassLocationURL(final Class<?> cls) { | |||||
| if (cls == null) | |||||
| throw new IllegalArgumentException("null input: cls"); | |||||
| URL result = null; | |||||
| final String clsAsResource = cls.getName().replace('.', '/').concat(".class"); | |||||
| final ProtectionDomain pd = cls.getProtectionDomain(); | |||||
| if (pd != null) { | |||||
| final CodeSource cs = pd.getCodeSource(); | |||||
| if (cs != null) | |||||
| result = cs.getLocation(); | |||||
| if (result != null) { | |||||
| if ("file".equals(result.getProtocol())) { | |||||
| try { | |||||
| if (result.toExternalForm().endsWith(".jar") || result.toExternalForm().endsWith(".zip")) | |||||
| result = new URL("jar:".concat(result.toExternalForm()).concat("!/").concat(clsAsResource)); | |||||
| else if (new File(result.getFile()).isDirectory()) | |||||
| result = new URL(result, clsAsResource); | |||||
| } catch (MalformedURLException ignore) { | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| if (result == null) { | |||||
| final ClassLoader clsLoader = cls.getClassLoader(); | |||||
| result = clsLoader != null ? clsLoader.getResource(clsAsResource) | |||||
| : ClassLoader.getSystemResource(clsAsResource); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** 初始化设置默认值 */ | |||||
| public static final <K> K ifNull(K k, K defaultValue) { | |||||
| if (k == null) { | |||||
| return defaultValue; | |||||
| } | |||||
| return k; | |||||
| } | |||||
| public static String unicodeToUtf8(String theString) { | |||||
| char aChar; | |||||
| int len = theString.length(); | |||||
| StringBuffer outBuffer = new StringBuffer(len); | |||||
| for (int x = 0; x < len;) { | |||||
| aChar = theString.charAt(x++); | |||||
| if (aChar == '\\') { | |||||
| aChar = theString.charAt(x++); | |||||
| if (aChar == 'u') { | |||||
| // Read the xxxx | |||||
| int value = 0; | |||||
| for (int i = 0; i < 4; i++) { | |||||
| aChar = theString.charAt(x++); | |||||
| switch (aChar) { | |||||
| case '0': | |||||
| case '1': | |||||
| case '2': | |||||
| case '3': | |||||
| case '4': | |||||
| case '5': | |||||
| case '6': | |||||
| case '7': | |||||
| case '8': | |||||
| case '9': | |||||
| value = (value << 4) + aChar - '0'; | |||||
| break; | |||||
| case 'a': | |||||
| case 'b': | |||||
| case 'c': | |||||
| case 'd': | |||||
| case 'e': | |||||
| case 'f': | |||||
| value = (value << 4) + 10 + aChar - 'a'; | |||||
| break; | |||||
| case 'A': | |||||
| case 'B': | |||||
| case 'C': | |||||
| case 'D': | |||||
| case 'E': | |||||
| case 'F': | |||||
| value = (value << 4) + 10 + aChar - 'A'; | |||||
| break; | |||||
| default: | |||||
| throw new IllegalArgumentException( | |||||
| "Malformed \\uxxxx encoding."); | |||||
| } | |||||
| } | |||||
| outBuffer.append((char) value); | |||||
| } else { | |||||
| if (aChar == 't') | |||||
| aChar = '\t'; | |||||
| else if (aChar == 'r') | |||||
| aChar = '\r'; | |||||
| else if (aChar == 'n') | |||||
| aChar = '\n'; | |||||
| else if (aChar == 'f') | |||||
| aChar = '\f'; | |||||
| outBuffer.append(aChar); | |||||
| } | |||||
| } else | |||||
| outBuffer.append(aChar); | |||||
| } | |||||
| return outBuffer.toString(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,644 @@ | |||||
| package com.iformall.utils; | |||||
| import okhttp3.MediaType; | |||||
| import okhttp3.OkHttpClient; | |||||
| import okhttp3.Request; | |||||
| import okhttp3.RequestBody; | |||||
| import org.apache.commons.io.IOUtils; | |||||
| import org.apache.http.*; | |||||
| import org.apache.http.client.CookieStore; | |||||
| import org.apache.http.client.entity.UrlEncodedFormEntity; | |||||
| 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.conn.ssl.SSLConnectionSocketFactory; | |||||
| import org.apache.http.entity.StringEntity; | |||||
| import org.apache.http.impl.client.BasicCookieStore; | |||||
| import org.apache.http.impl.client.CloseableHttpClient; | |||||
| import org.apache.http.impl.client.HttpClients; | |||||
| import org.apache.http.message.BasicNameValuePair; | |||||
| import org.apache.http.protocol.HTTP; | |||||
| import org.apache.http.ssl.SSLContexts; | |||||
| import org.apache.http.util.EntityUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import com.github.binarywang.wxpay.service.WxPayService; | |||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | |||||
| import javax.net.ssl.HttpsURLConnection; | |||||
| import javax.net.ssl.KeyManager; | |||||
| import javax.net.ssl.KeyManagerFactory; | |||||
| import javax.net.ssl.SSLContext; | |||||
| import java.io.*; | |||||
| import java.net.URI; | |||||
| import java.net.URL; | |||||
| import java.nio.charset.Charset; | |||||
| import java.security.KeyManagementException; | |||||
| import java.security.KeyStore; | |||||
| import java.security.KeyStoreException; | |||||
| import java.security.NoSuchAlgorithmException; | |||||
| import java.security.SecureRandom; | |||||
| import java.security.UnrecoverableKeyException; | |||||
| import java.security.cert.CertificateException; | |||||
| import java.util.*; | |||||
| import java.util.concurrent.ConcurrentHashMap; | |||||
| /** | |||||
| * @author | |||||
| * @date | |||||
| * HttpClient工具类 | |||||
| */ | |||||
| public class HttpUtil { | |||||
| private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class); | |||||
| private static final MediaType CONTENT_TYPE_FORM = MediaType.parse("application/x-www-form-urlencoded"); | |||||
| private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36"; | |||||
| // /** | |||||
| // * get请求 | |||||
| // * @return | |||||
| // */ | |||||
| // public static String doGet(String url) { | |||||
| // try { | |||||
| // CloseableHttpClient client = HttpClients.createDefault(); | |||||
| // //发送get请求 | |||||
| // HttpGet request = new HttpGet(url); | |||||
| // HttpResponse response = client.execute(request); | |||||
| // | |||||
| // /**请求发送成功,并得到响应**/ | |||||
| // if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { | |||||
| // /**读取服务器返回过来的json字符串数据**/ | |||||
| // String strResult = EntityUtils.toString(response.getEntity()); | |||||
| // | |||||
| // return strResult; | |||||
| // } | |||||
| // } | |||||
| // catch (IOException e) { | |||||
| // logger.error(e.getMessage()); | |||||
| // throw new RuntimeException(e); | |||||
| // } | |||||
| // | |||||
| // return null; | |||||
| // } | |||||
| /** | |||||
| * get请求 | |||||
| * @return | |||||
| */ | |||||
| public static byte[] doWiwidePicGet(String url, String signature) { | |||||
| try { | |||||
| CloseableHttpClient client = HttpClients.createDefault(); | |||||
| //发送get请求 | |||||
| HttpGet request = new HttpGet(url); | |||||
| request.setHeader("Cookie", "Signature="+signature); | |||||
| HttpResponse response = client.execute(request); | |||||
| /**请求发送成功,并得到响应**/ | |||||
| if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { | |||||
| /**读取服务器返回过来的json字符串数据**/ | |||||
| byte[] bytes = EntityUtils.toByteArray(response.getEntity()); | |||||
| return bytes; | |||||
| } | |||||
| } | |||||
| catch (IOException e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| /** | |||||
| * post请求(用于key-value格式的参数) | |||||
| * @param url | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String doPost(String url, Map params){ | |||||
| // 定义HttpClient | |||||
| CloseableHttpClient client = HttpClients.createDefault(); | |||||
| BufferedReader in = null; | |||||
| try { | |||||
| // 实例化HTTP方法 | |||||
| HttpPost request = new HttpPost(); | |||||
| request.setURI(new URI(url)); | |||||
| //设置参数 | |||||
| List<NameValuePair> nvps = new ArrayList<NameValuePair>(); | |||||
| for (Iterator iter = params.keySet().iterator(); iter.hasNext();) { | |||||
| String name = (String) iter.next(); | |||||
| String value = String.valueOf(params.get(name)); | |||||
| nvps.add(new BasicNameValuePair(name, value)); | |||||
| //System.out.println(name +"-"+value); | |||||
| } | |||||
| request.setEntity(new UrlEncodedFormEntity(nvps,HTTP.UTF_8)); | |||||
| HttpResponse response = client.execute(request); | |||||
| int code = response.getStatusLine().getStatusCode(); | |||||
| if(code == 200){ //请求成功 | |||||
| in = new BufferedReader(new InputStreamReader(response.getEntity() | |||||
| .getContent(),"utf-8")); | |||||
| StringBuilder sb = new StringBuilder(""); | |||||
| String line = ""; | |||||
| String NL = System.getProperty("line.separator"); | |||||
| while ((line = in.readLine()) != null) { | |||||
| sb.append(line + NL); | |||||
| } | |||||
| in.close(); | |||||
| client.close(); | |||||
| return sb.toString(); | |||||
| } | |||||
| else{ // | |||||
| logger.info("状态码:" + code); | |||||
| client.close(); | |||||
| } | |||||
| } | |||||
| catch(Exception e){ | |||||
| logger.error(e.getMessage()); | |||||
| return null; | |||||
| } | |||||
| return null; | |||||
| } | |||||
| // /** | |||||
| // * post请求(用于key-value格式的参数) | |||||
| // * @param url | |||||
| // * @param params | |||||
| // * @return | |||||
| // */ | |||||
| // public static String doPost(String url,Map<String,String> headMap, Map params){ | |||||
| // | |||||
| // // 定义HttpClient | |||||
| // CloseableHttpClient client = HttpClients.createDefault(); | |||||
| // | |||||
| // BufferedReader in = null; | |||||
| // try { | |||||
| // | |||||
| // // 实例化HTTP方法 | |||||
| // HttpPost request = new HttpPost(); | |||||
| // request.setURI(new URI(url)); | |||||
| // if(headMap != null){ | |||||
| // Set<String> set = headMap.keySet(); | |||||
| // for(String key: set){ | |||||
| // request.addHeader(key,headMap.get(key)); | |||||
| // } | |||||
| // } | |||||
| // | |||||
| // //设置参数 | |||||
| // List<NameValuePair> nvps = new ArrayList<NameValuePair>(); | |||||
| // for (Iterator iter = params.keySet().iterator(); iter.hasNext();) { | |||||
| // String name = (String) iter.next(); | |||||
| // String value = String.valueOf(params.get(name)); | |||||
| // nvps.add(new BasicNameValuePair(name, value)); | |||||
| // | |||||
| // //System.out.println(name +"-"+value); | |||||
| // } | |||||
| // request.setEntity(new UrlEncodedFormEntity(nvps,HTTP.UTF_8)); | |||||
| // | |||||
| // HttpResponse response = client.execute(request); | |||||
| // int code = response.getStatusLine().getStatusCode(); | |||||
| // if(code == 200){ //请求成功 | |||||
| // in = new BufferedReader(new InputStreamReader(response.getEntity() | |||||
| // .getContent(),"utf-8")); | |||||
| // StringBuilder sb = new StringBuilder(""); | |||||
| // String line = ""; | |||||
| // String NL = System.getProperty("line.separator"); | |||||
| // while ((line = in.readLine()) != null) { | |||||
| // sb.append(line + NL); | |||||
| // } | |||||
| // | |||||
| // in.close(); | |||||
| // | |||||
| // client.close(); | |||||
| // | |||||
| // return sb.toString(); | |||||
| // } | |||||
| // else{ // | |||||
| // logger.info("状态码:" + code); | |||||
| // client.close(); | |||||
| // } | |||||
| // } | |||||
| // catch(Exception e){ | |||||
| // logger.error(e.getMessage()); | |||||
| // return null; | |||||
| // } | |||||
| // | |||||
| // return null; | |||||
| // } | |||||
| /** | |||||
| * post请求(用于key-value格式的参数,wiwide) | |||||
| * @param url | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String doPostWiwide(String url, String token, Map params){ | |||||
| //CookieStore store= new BasicCookieStore(); | |||||
| //HttpClients.custom().setDefaultCookieStore(store).build(); | |||||
| // 定义HttpClient | |||||
| CloseableHttpClient client = HttpClients.createDefault(); | |||||
| BufferedReader in = null; | |||||
| try { | |||||
| // 实例化HTTP方法 | |||||
| HttpPost request = new HttpPost(); | |||||
| request.setURI(new URI(url)); | |||||
| request.setHeader("Content-Type", "application/x-www-form-urlencoded"); | |||||
| request.setHeader("Accept-Charset", "utf-8"); | |||||
| request.setHeader("wiwidefumaotoken", token); | |||||
| //设置参数 | |||||
| List<NameValuePair> nvps = new ArrayList<NameValuePair>(); | |||||
| for (Iterator iter = params.keySet().iterator(); iter.hasNext();) { | |||||
| String name = (String) iter.next(); | |||||
| String value = String.valueOf(params.get(name)); | |||||
| nvps.add(new BasicNameValuePair(name, value)); | |||||
| //System.out.println(name +"-"+value); | |||||
| } | |||||
| request.setEntity(new UrlEncodedFormEntity(nvps,HTTP.UTF_8)); | |||||
| HttpResponse response = client.execute(request); | |||||
| int code = response.getStatusLine().getStatusCode(); | |||||
| if(code == 200){ //请求成功 | |||||
| in = new BufferedReader(new InputStreamReader(response.getEntity() | |||||
| .getContent(),"utf-8")); | |||||
| StringBuilder sb = new StringBuilder(""); | |||||
| String line = ""; | |||||
| String NL = System.getProperty("line.separator"); | |||||
| while ((line = in.readLine()) != null) { | |||||
| sb.append(line + NL); | |||||
| } | |||||
| in.close(); | |||||
| client.close(); | |||||
| return sb.toString(); | |||||
| } | |||||
| else{ // | |||||
| logger.info("状态码:" + code); | |||||
| client.close(); | |||||
| } | |||||
| } | |||||
| catch(Exception e){ | |||||
| logger.error(e.getMessage()); | |||||
| return null; | |||||
| } | |||||
| return null; | |||||
| } | |||||
| /** | |||||
| * post请求(用于key-value格式的参数,wiwide) | |||||
| * @param url | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String doPostWiwideNew(String url, String signature, Map params){ | |||||
| //CookieStore store= new BasicCookieStore(); | |||||
| //HttpClients.custom().setDefaultCookieStore(store).build(); | |||||
| // 定义HttpClient | |||||
| CloseableHttpClient client = HttpClients.createDefault(); | |||||
| BufferedReader in = null; | |||||
| try { | |||||
| // 实例化HTTP方法 | |||||
| HttpPost request = new HttpPost(); | |||||
| request.setURI(new URI(url)); | |||||
| request.setHeader("Content-Type", "application/x-www-form-urlencoded"); | |||||
| request.setHeader("Accept-Charset", "utf-8"); | |||||
| request.setHeader("Cookie", "Signature="+signature); | |||||
| //设置参数 | |||||
| List<NameValuePair> nvps = new ArrayList<NameValuePair>(); | |||||
| for (Iterator iter = params.keySet().iterator(); iter.hasNext();) { | |||||
| String name = (String) iter.next(); | |||||
| String value = String.valueOf(params.get(name)); | |||||
| nvps.add(new BasicNameValuePair(name, value)); | |||||
| //System.out.println(name +"-"+value); | |||||
| } | |||||
| request.setEntity(new UrlEncodedFormEntity(nvps,HTTP.UTF_8)); | |||||
| HttpResponse response = client.execute(request); | |||||
| int code = response.getStatusLine().getStatusCode(); | |||||
| if(code == 200){ //请求成功 | |||||
| in = new BufferedReader(new InputStreamReader(response.getEntity() | |||||
| .getContent(),"utf-8")); | |||||
| StringBuilder sb = new StringBuilder(""); | |||||
| String line = ""; | |||||
| String NL = System.getProperty("line.separator"); | |||||
| while ((line = in.readLine()) != null) { | |||||
| sb.append(line + NL); | |||||
| } | |||||
| in.close(); | |||||
| client.close(); | |||||
| return sb.toString(); | |||||
| } | |||||
| else{ // | |||||
| logger.info("状态码:" + code); | |||||
| client.close(); | |||||
| } | |||||
| } | |||||
| catch(Exception e){ | |||||
| logger.error(e.getMessage()); | |||||
| return null; | |||||
| } | |||||
| return null; | |||||
| } | |||||
| // /** | |||||
| // * post请求(用于请求json格式的参数) | |||||
| // * @param url | |||||
| // * @param params | |||||
| // * @return | |||||
| // */ | |||||
| // public static String doPost(String url, String params) throws Exception { | |||||
| // | |||||
| // CloseableHttpClient httpclient = HttpClients.createDefault(); | |||||
| // HttpPost httpPost = new HttpPost(url);// 创建httpPost | |||||
| // httpPost.setHeader("Accept", "application/json"); | |||||
| // httpPost.setHeader("Content-Type", "application/json"); | |||||
| // String charSet = "UTF-8"; | |||||
| // StringEntity entity = new StringEntity(params, charSet); | |||||
| // httpPost.setEntity(entity); | |||||
| // CloseableHttpResponse response = null; | |||||
| // | |||||
| // try { | |||||
| // response = httpclient.execute(httpPost); | |||||
| // StatusLine status = response.getStatusLine(); | |||||
| // int state = status.getStatusCode(); | |||||
| // if (state == HttpStatus.SC_OK) { | |||||
| // HttpEntity responseEntity = response.getEntity(); | |||||
| // String jsonString = EntityUtils.toString(responseEntity); | |||||
| // return jsonString; | |||||
| // } | |||||
| // else{ | |||||
| // logger.info("请求返回:"+state+"("+url+")"); | |||||
| // } | |||||
| // } | |||||
| // finally { | |||||
| // if (response != null) { | |||||
| // try { | |||||
| // response.close(); | |||||
| // } catch (IOException e) { | |||||
| // logger.error(e.getMessage()); | |||||
| // } | |||||
| // } | |||||
| // try { | |||||
| // httpclient.close(); | |||||
| // } catch (IOException e) { | |||||
| // logger.error(e.getMessage()); | |||||
| // } | |||||
| // } | |||||
| // return null; | |||||
| // } | |||||
| /** | |||||
| * post请求(用于请求json格式的参数) | |||||
| * @param url | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String doPost(String url, Map<String,String> headMap, String params){ | |||||
| CloseableHttpClient httpclient = HttpClients.createDefault(); | |||||
| HttpPost httpPost = new HttpPost(url);// 创建httpPost | |||||
| httpPost.setHeader("Accept", "application/json"); | |||||
| httpPost.setHeader("Content-Type", "application/json"); | |||||
| if(headMap != null){ | |||||
| Set<String> set = headMap.keySet(); | |||||
| for(String key: set){ | |||||
| httpPost.addHeader(key,headMap.get(key)); | |||||
| } | |||||
| } | |||||
| String charSet = "UTF-8"; | |||||
| StringEntity entity = new StringEntity(params, charSet); | |||||
| httpPost.setEntity(entity); | |||||
| CloseableHttpResponse response = null; | |||||
| try { | |||||
| response = httpclient.execute(httpPost); | |||||
| StatusLine status = response.getStatusLine(); | |||||
| int state = status.getStatusCode(); | |||||
| if (state == HttpStatus.SC_OK) { | |||||
| HttpEntity responseEntity = response.getEntity(); | |||||
| String jsonString = EntityUtils.toString(responseEntity); | |||||
| return jsonString; | |||||
| } | |||||
| else{ | |||||
| logger.info("请求返回:"+state+"("+url+")"); | |||||
| } | |||||
| } | |||||
| catch(Exception e){ | |||||
| logger.error(e.getMessage()); | |||||
| return null; | |||||
| } | |||||
| finally { | |||||
| if (response != null) { | |||||
| try { | |||||
| response.close(); | |||||
| } catch (IOException e) { | |||||
| logger.error(e.getMessage()); | |||||
| } | |||||
| } | |||||
| try { | |||||
| httpclient.close(); | |||||
| } catch (IOException e) { | |||||
| logger.error(e.getMessage()); | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public static String payPost(String url, String params) { | |||||
| RequestBody body = RequestBody.create(CONTENT_TYPE_FORM, params); | |||||
| Request request = null; | |||||
| try { | |||||
| request = new Request.Builder().addHeader("Accept-Charset", "utf-8") | |||||
| .addHeader("Content-Type", "application/x-www-form-urlencoded") | |||||
| .addHeader("Content-Length", String.valueOf(body.contentLength())) | |||||
| .url(url).post(body).build(); | |||||
| return exec(request); | |||||
| } catch (IOException e) { | |||||
| logger.error(e.getMessage()); | |||||
| return null; | |||||
| } | |||||
| } | |||||
| private static OkHttpClient OkHttpClient = new OkHttpClient(); | |||||
| private static String exec(okhttp3.Request request) { | |||||
| try { | |||||
| okhttp3.Response response = OkHttpClient.newCall(request).execute(); | |||||
| // String header = response.header("X-Tt-Logid"); | |||||
| // logger.info("X-Tt-Logid="+header); | |||||
| if (!response.isSuccessful()) | |||||
| throw new RuntimeException("Unexpected code " + response); | |||||
| return response.body().string(); | |||||
| } catch (IOException e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| } | |||||
| private static Map<String,SSLContext> sslContextMap = new ConcurrentHashMap<String,SSLContext>(); | |||||
| private static SSLContext getSSLContext(String certPath, String certPass) throws KeyStoreException, NoSuchAlgorithmException, | |||||
| CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException { | |||||
| String key = certPath+certPass; | |||||
| SSLContext sslContext = sslContextMap.get(key); | |||||
| if ( null == sslContext ) { | |||||
| synchronized("sslContextLock"+key) { | |||||
| sslContext = sslContextMap.get(key); | |||||
| if (null == sslContext) { | |||||
| KeyStore clientStore = KeyStore.getInstance("PKCS12"); | |||||
| clientStore.load(new FileInputStream(certPath), certPass.toCharArray()); | |||||
| KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); | |||||
| kmf.init(clientStore, certPass.toCharArray()); | |||||
| KeyManager[] kms = kmf.getKeyManagers(); | |||||
| sslContext = SSLContext.getInstance("TLS"); | |||||
| sslContext.init(kms, null, new SecureRandom()); | |||||
| sslContextMap.put(key, sslContext); | |||||
| } | |||||
| } | |||||
| } | |||||
| return sslContext; | |||||
| } | |||||
| public static String payPostSSL(String url, String data, String certPath, String certPass) { | |||||
| HttpsURLConnection conn = null; | |||||
| OutputStream out = null; | |||||
| InputStream inputStream = null; | |||||
| BufferedReader reader = null; | |||||
| try { | |||||
| SSLContext sslContext = getSSLContext(certPath, certPass); | |||||
| HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); | |||||
| URL _url = new URL(url); | |||||
| conn = (HttpsURLConnection) _url.openConnection(); | |||||
| conn.setConnectTimeout(25000); | |||||
| conn.setReadTimeout(25000); | |||||
| conn.setRequestMethod("POST"); | |||||
| conn.setDoOutput(true); | |||||
| conn.setDoInput(true); | |||||
| conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); | |||||
| conn.setRequestProperty("User-Agent", DEFAULT_USER_AGENT); | |||||
| conn.connect(); | |||||
| out = conn.getOutputStream(); | |||||
| out.write(data.getBytes(Charset.forName("UTF-8"))); | |||||
| out.flush(); | |||||
| inputStream = conn.getInputStream(); | |||||
| reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| String line = null; | |||||
| while ((line = reader.readLine()) != null) { | |||||
| sb.append(line).append("\n"); | |||||
| } | |||||
| return sb.toString(); | |||||
| } catch (Exception e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new RuntimeException(e); | |||||
| } finally { | |||||
| IOUtils.closeQuietly(out); | |||||
| IOUtils.closeQuietly(reader); | |||||
| IOUtils.closeQuietly(inputStream); | |||||
| if (conn != null) { | |||||
| conn.disconnect(); | |||||
| } | |||||
| } | |||||
| } | |||||
| // private static String ClientCustomSSL(String url, String p12file, String mch_id, String xmlStr) throws Exception{ | |||||
| // KeyStore keyStore = KeyStore.getInstance("PKCS12"); | |||||
| // FileInputStream instream = new FileInputStream(new File(p12file)); | |||||
| // try { | |||||
| // keyStore.load(instream, mch_id.toCharArray()); | |||||
| // } finally { | |||||
| // instream.close(); | |||||
| // } | |||||
| // | |||||
| // // Trust own CA and all self-signed certs | |||||
| // SSLContext sslcontext = SSLContexts.custom() | |||||
| // .loadKeyMaterial(keyStore, mch_id.toCharArray()) | |||||
| // .build(); | |||||
| // // Allow TLSv1 protocol only | |||||
| // SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( | |||||
| // sslcontext, | |||||
| // new String[] { "TLSv1" }, | |||||
| // null, | |||||
| // SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); | |||||
| // CloseableHttpClient httpclient = HttpClients.custom() | |||||
| // .setSSLSocketFactory(sslsf) | |||||
| // .build(); | |||||
| // try { | |||||
| // HttpPost httpPost = new HttpPost(url); | |||||
| // StringEntity entityStr = new StringEntity(xmlStr); | |||||
| // entityStr.setContentType("text/xml"); | |||||
| // //logger.info("entityStr--------------"+entityStr); | |||||
| // httpPost.setEntity(entityStr); | |||||
| // | |||||
| // CloseableHttpResponse response = httpclient.execute(httpPost); | |||||
| // try { | |||||
| // HttpEntity entity = response.getEntity(); | |||||
| // | |||||
| // //System.out.println("----------------------------------------"); | |||||
| // //System.out.println(response.getStatusLine()); | |||||
| // if (entity != null) { | |||||
| // //System.out.println("Response content length: " + entity.getContentLength()); | |||||
| // BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent())); | |||||
| // StringBuilder sb = new StringBuilder(); | |||||
| // String line = null; | |||||
| // while ((line = bufferedReader.readLine()) != null) { | |||||
| // sb.append(line).append("\n"); | |||||
| // } | |||||
| // return sb.toString(); | |||||
| // } | |||||
| // EntityUtils.consume(entity); | |||||
| // } finally { | |||||
| // response.close(); | |||||
| // } | |||||
| // } finally { | |||||
| // httpclient.close(); | |||||
| // return null; | |||||
| // } | |||||
| // | |||||
| // } | |||||
| } | |||||
| @@ -0,0 +1,22 @@ | |||||
| package com.iformall.utils; | |||||
| import java.util.Comparator; | |||||
| import java.util.Map; | |||||
| import java.util.TreeMap; | |||||
| public class MapUtil { | |||||
| /** | |||||
| * 获取带排序的Map | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, String> getOrderMap() { | |||||
| Map<String, String> paramMap = new TreeMap<String, String>( | |||||
| new Comparator<String>() { | |||||
| public int compare(String obj1, String obj2) { | |||||
| // 降序排序 | |||||
| return obj1.compareTo(obj2); | |||||
| } | |||||
| }); | |||||
| return paramMap; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,8 @@ | |||||
| package com.iformall.utils; | |||||
| public class SysConfigConstant { | |||||
| public static final String sale_price="salePrice"; | |||||
| public static final String pay_call_back = "payCallBack"; | |||||
| } | |||||
| @@ -0,0 +1,612 @@ | |||||
| package com.iformall.utils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import java.io.File; | |||||
| import java.io.UnsupportedEncodingException; | |||||
| import java.math.BigDecimal; | |||||
| import java.net.URLDecoder; | |||||
| import java.net.URLEncoder; | |||||
| import java.text.NumberFormat; | |||||
| import java.text.ParseException; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.*; | |||||
| import java.util.regex.Matcher; | |||||
| import java.util.regex.Pattern; | |||||
| /** | |||||
| * @author Stormeye | |||||
| * @since 2018.08.09 | |||||
| */ | |||||
| public final class Utility { | |||||
| private final static Logger logger = LoggerFactory.getLogger(Utility.class); | |||||
| // @Autowired | |||||
| // private ReloadableResourceBundleMessageSource messageSource; | |||||
| public static String generateUUID() { | |||||
| return UUID.randomUUID().toString(); | |||||
| } | |||||
| public static String generate32UUID() { | |||||
| return UUID.randomUUID().toString().replaceAll("-", ""); | |||||
| } | |||||
| public static boolean isEmpty(CharSequence str) { | |||||
| if (str == null || str.length() == 0) | |||||
| return true; | |||||
| else | |||||
| return false; | |||||
| } | |||||
| public static boolean isBlank(CharSequence str) { | |||||
| int strLen; | |||||
| if (str == null || (strLen = str.length()) == 0) { | |||||
| return true; | |||||
| } | |||||
| for (int i = 0; i < strLen; i++) { | |||||
| if ((Character.isWhitespace(str.charAt(i)) == false)) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * format time to "yyyy-MM-dd" | |||||
| * @param time | |||||
| * @return | |||||
| */ | |||||
| public static String formatTime(int time){ | |||||
| long t = time * 1000l; | |||||
| SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); | |||||
| String ret = formatter.format(new Date(t)); | |||||
| return ret; | |||||
| } | |||||
| /** | |||||
| * format timestamp to "yyyy-MM-dd HH:mm:ss" | |||||
| * @param time | |||||
| * @return | |||||
| */ | |||||
| public static String formatTimestamp(int time){ | |||||
| long t = time * 1000l; | |||||
| SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |||||
| String ret = formatter.format(new Date(t)); | |||||
| return ret; | |||||
| } | |||||
| /** | |||||
| * getSimpleRegionModel the day end time by given the time point | |||||
| * e.g. given timePoint is "2015.5.13 13:45:32", the returned day end time is "2015.5.13 23:59:59" | |||||
| * @param timePoint | |||||
| * @return | |||||
| */ | |||||
| public static int getDayEndTime(int timePoint){ | |||||
| Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+8")); | |||||
| long theTime = ((long)timePoint)*1000; | |||||
| calendar.setTimeInMillis(theTime); | |||||
| int year = calendar.get(Calendar.YEAR); | |||||
| int month = calendar.get(Calendar.MONTH); | |||||
| int day = calendar.get(Calendar.DAY_OF_MONTH); | |||||
| int hour = calendar.get(Calendar.HOUR_OF_DAY); | |||||
| int minute = calendar.get(Calendar.MINUTE); | |||||
| int second = calendar.get(Calendar.SECOND); | |||||
| calendar.clear(); | |||||
| calendar.set(year, month, day, 23, 59, 59); | |||||
| int ret = (int)(calendar.getTimeInMillis()/1000); | |||||
| return ret; | |||||
| } | |||||
| public static int getDayStartTime(int timePoint) { | |||||
| Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+8")); | |||||
| long theTime = ((long)timePoint)*1000; | |||||
| calendar.setTimeInMillis(theTime); | |||||
| int year = calendar.get(Calendar.YEAR); | |||||
| int month = calendar.get(Calendar.MONTH); | |||||
| int day = calendar.get(Calendar.DAY_OF_MONTH); | |||||
| int hour = calendar.get(Calendar.HOUR_OF_DAY); | |||||
| int minute = calendar.get(Calendar.MINUTE); | |||||
| int second = calendar.get(Calendar.SECOND); | |||||
| calendar.clear(); | |||||
| calendar.set(year, month, day, 0, 0, 0); | |||||
| int ret = (int)(calendar.getTimeInMillis()/1000); | |||||
| return ret; | |||||
| } | |||||
| public static int getLastHourEndTime(int timePoint) { | |||||
| SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd-HH"); | |||||
| String curHour = sf.format(System.currentTimeMillis()); | |||||
| int ret = timePoint; | |||||
| try { | |||||
| ret = (int)((sf.parse(curHour).getTime())/1000); | |||||
| } catch(ParseException ex) { | |||||
| ex.printStackTrace(); | |||||
| } | |||||
| return ret - 1; | |||||
| } | |||||
| /** | |||||
| * Encrypt plain text | |||||
| * @param plainText | |||||
| * @return encrypted string for cvn2 | |||||
| */ | |||||
| public static String encryptText(String plainText) { | |||||
| return plainText; | |||||
| } | |||||
| /** | |||||
| * Decrypt to plain text | |||||
| * @param decryptedText | |||||
| * @return encrypted string for cvn2 | |||||
| */ | |||||
| public static String decryptedText(String decryptedText) { | |||||
| return decryptedText; | |||||
| } | |||||
| /** | |||||
| * Mask the bankcard Number, e.g. 18911113927 to 189******3927 | |||||
| * @param idCardNo | |||||
| * @return masked phone number | |||||
| */ | |||||
| public static String maskIdCard(String idCardNo) { | |||||
| if(isEmpty(idCardNo) || idCardNo.length() < 18) { | |||||
| return idCardNo; | |||||
| } | |||||
| return idCardNo.substring(0,4) + "**" + idCardNo.substring(6, 12) + "***" + idCardNo.substring(15, 18); | |||||
| } | |||||
| /** | |||||
| * Mask the bankcard Number, e.g. 18911113927 to 189******3927 | |||||
| * @param bankCardNo | |||||
| * @return masked phone number | |||||
| */ | |||||
| public static String maskBankCard(String bankCardNo) { | |||||
| if(bankCardNo.length() <= 8) { | |||||
| return bankCardNo; | |||||
| } | |||||
| return bankCardNo.substring(0,4) + "******" + bankCardNo.substring(bankCardNo.length() - 4, bankCardNo.length()); | |||||
| } | |||||
| /** | |||||
| * Mask the user name, e.g. | |||||
| * @param userName | |||||
| * @return masked phone number | |||||
| */ | |||||
| public static String maskUserName(String userName) { | |||||
| switch (userName.length()) { | |||||
| case 0: | |||||
| case 1: | |||||
| return "*"; | |||||
| default: | |||||
| return userName.replaceAll(".", "*").replaceFirst(".$",userName.substring(userName.length() - 1)); | |||||
| } | |||||
| } | |||||
| public static String maskPhoneNum(String phoneNum) { | |||||
| if(phoneNum==null || phoneNum.length() < 4) { | |||||
| return phoneNum; | |||||
| } | |||||
| return phoneNum.substring(0,3) + "****" + phoneNum.substring(phoneNum.length() - 4, phoneNum.length()); | |||||
| } | |||||
| /** | |||||
| * Convert current time into int type. used for create_time/update time | |||||
| * @param | |||||
| * @return timestamp | |||||
| */ | |||||
| public static int getCurrentTimeStamp() { | |||||
| if(debugCurrentTimeStamp == 0) { | |||||
| return (int) (System.currentTimeMillis() / 1000); | |||||
| }else { | |||||
| return debugCurrentTimeStamp; | |||||
| } | |||||
| } | |||||
| public static int convertDate2TimeStamp(Date date) { | |||||
| return (int) (date.getTime() / 1000); | |||||
| } | |||||
| private static int debugCurrentTimeStamp = 0; | |||||
| /** | |||||
| * For test purpose, getCurrentTimeStamp will return the timestamp if non-zero. | |||||
| * @param | |||||
| * @return timestamp | |||||
| */ | |||||
| public static void setDebugCurrentTimeStamp(int timeStamp) { | |||||
| debugCurrentTimeStamp = timeStamp; | |||||
| } | |||||
| public static String generateInvitationCode(Set<String> existingCode){ | |||||
| int invitationCode = (int)((Math.random()*9+1)*100000); | |||||
| if(existingCode != null){ | |||||
| while(existingCode.contains(String.valueOf(invitationCode))){ | |||||
| invitationCode++; | |||||
| if(invitationCode>=999999){ | |||||
| invitationCode = (int)((Math.random()*9+1)*100000); | |||||
| } | |||||
| } | |||||
| } | |||||
| return String.valueOf(invitationCode); | |||||
| } | |||||
| public static String generateOrderId(String gid) { | |||||
| if (null == gid) { | |||||
| return ""; | |||||
| } | |||||
| return "SDLC" + gid.replaceAll("-", ""); | |||||
| } | |||||
| public static String getDataFormatString(int currentSec) { | |||||
| SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |||||
| return sf.format(((long) currentSec) * 1000); | |||||
| } | |||||
| public static String getDataFormatString2(int currentSec) { | |||||
| SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日"); | |||||
| return sf.format(((long) currentSec) * 1000); | |||||
| } | |||||
| public static String getDataFormatString3(Date date) { | |||||
| SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日"); | |||||
| return sf.format(date); | |||||
| } | |||||
| public static String convertDecimal2PercentRate(BigDecimal rate) { | |||||
| NumberFormat percent = NumberFormat.getPercentInstance(); | |||||
| percent.setMaximumFractionDigits(1); | |||||
| return percent.format(rate.setScale(3, BigDecimal.ROUND_DOWN)); | |||||
| } | |||||
| public static String convertLineFeedCharacter(String msg){ | |||||
| if(msg == null || msg.isEmpty()){ | |||||
| return ""; | |||||
| } | |||||
| msg = msg.replace("\\\\n", "\\n"); | |||||
| return msg; | |||||
| } | |||||
| public static int getSimpleDayEndTime(int timePoint){ | |||||
| Calendar ca = new GregorianCalendar(); | |||||
| ca.setTime(new Date(((long) timePoint) * 1000)); | |||||
| ca.set(Calendar.HOUR_OF_DAY, 23); | |||||
| ca.set(Calendar.MINUTE, 59); | |||||
| ca.set(Calendar.SECOND, 59); | |||||
| long ret = ca.getTime().getTime()/1000; | |||||
| return (int) ret; | |||||
| } | |||||
| public static String urlEncodeUTF8(String s) { | |||||
| try { | |||||
| return URLEncoder.encode(s, "UTF-8"); | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| throw new UnsupportedOperationException(e); | |||||
| } | |||||
| } | |||||
| public static String urlDecodeUTF8(String s) { | |||||
| try { | |||||
| return URLDecoder.decode(s, "UTF-8"); | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| throw new UnsupportedOperationException(e); | |||||
| } | |||||
| } | |||||
| public static int dateStringToTimeStamp(String dateStr){ | |||||
| int timeStamp = 0; | |||||
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |||||
| try { | |||||
| Date date = sdf.parse(dateStr); | |||||
| timeStamp= (int) (date.getTime()/1000); | |||||
| } catch (ParseException e) { | |||||
| logger.error("dateStringToTimeStamp exception = {}", e); | |||||
| } | |||||
| return timeStamp; | |||||
| } | |||||
| public static int dateStringToTimeStamp(String dateStr,String format){ | |||||
| int timeStamp = 0; | |||||
| SimpleDateFormat sdf = new SimpleDateFormat(format); | |||||
| try { | |||||
| Date date = sdf.parse(dateStr); | |||||
| timeStamp= (int) (date.getTime()/1000); | |||||
| } catch (ParseException e) { | |||||
| logger.error("dateStringToTimeStamp exception = {}", e); | |||||
| } | |||||
| return timeStamp; | |||||
| } | |||||
| public static Object convert(Object object, Class<?> type) { | |||||
| if (object instanceof Number) { | |||||
| Number number = (Number) object; | |||||
| if (type.equals(byte.class) || type.equals(Byte.class)) { | |||||
| return number.byteValue(); | |||||
| } | |||||
| if (type.equals(short.class) || type.equals(Short.class)) { | |||||
| return number.shortValue(); | |||||
| } | |||||
| if (type.equals(int.class) || type.equals(Integer.class)) { | |||||
| return number.intValue(); | |||||
| } | |||||
| if (type.equals(long.class) || type.equals(Long.class)) { | |||||
| return number.longValue(); | |||||
| } | |||||
| if (type.equals(float.class) || type.equals(Float.class)) { | |||||
| return number.floatValue(); | |||||
| } | |||||
| if (type.equals(double.class) || type.equals(Double.class)) { | |||||
| return number.doubleValue(); | |||||
| } | |||||
| } | |||||
| return object; | |||||
| } | |||||
| public static int getFirstDayByDate(final Date date) { | |||||
| Calendar instance = Calendar.getInstance(); | |||||
| instance.setTime(date); | |||||
| instance.set(instance.get(Calendar.YEAR), instance.get(Calendar.MONTH), 1, 0, 0, 0); | |||||
| int ret = (int) (instance.getTimeInMillis()/1000); | |||||
| return ret; | |||||
| } | |||||
| public static boolean decimalEqualsScale2(BigDecimal one , BigDecimal two) { | |||||
| if (one == null || two == null) { | |||||
| return false; | |||||
| } | |||||
| final BigDecimal o1 = one.setScale(2 , BigDecimal.ROUND_DOWN); | |||||
| final BigDecimal o2 = two.setScale(2 , BigDecimal.ROUND_DOWN); | |||||
| return o1.compareTo(o2) == 0; | |||||
| } | |||||
| public static int decimalCompareScale2(BigDecimal one , BigDecimal two) { | |||||
| if (one == null || two == null) { | |||||
| return -1; | |||||
| } | |||||
| final BigDecimal o1 = one.setScale(2 , BigDecimal.ROUND_DOWN); | |||||
| final BigDecimal o2 = two.setScale(2 , BigDecimal.ROUND_DOWN); | |||||
| return o1.compareTo(o2); | |||||
| } | |||||
| public static BigDecimal setScale2RoundDown(BigDecimal one) { | |||||
| if (one == null) { | |||||
| return null; | |||||
| } | |||||
| return one.setScale(2, BigDecimal.ROUND_DOWN); | |||||
| } | |||||
| public static boolean isNumeric(String str){ | |||||
| Pattern pattern = Pattern.compile("[0-9]*"); | |||||
| Matcher isNum = pattern.matcher(str); | |||||
| if( !isNum.matches() ){ | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| public static String dateFormat(Date date, String pattern) { | |||||
| SimpleDateFormat sdf = new SimpleDateFormat(pattern); | |||||
| return sdf.format(date); | |||||
| } | |||||
| public static int getCurrentWeekStartTime(int dayTime) { | |||||
| Calendar currentDate = Calendar.getInstance(); | |||||
| currentDate.setTime(new Date(dayTime * 1000L)); | |||||
| currentDate.setFirstDayOfWeek(Calendar.MONDAY); | |||||
| currentDate.set(Calendar.HOUR_OF_DAY, 0); | |||||
| currentDate.set(Calendar.MINUTE, 0); | |||||
| currentDate.set(Calendar.SECOND, 0); | |||||
| currentDate.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); | |||||
| return (int)(currentDate.getTimeInMillis() / 1000L); | |||||
| } | |||||
| public static int getCurrentWeekEndTime(int dayTime) { | |||||
| Calendar currentDate = Calendar.getInstance(); | |||||
| currentDate.setTime(new Date(dayTime * 1000L)); | |||||
| currentDate.setFirstDayOfWeek(Calendar.MONDAY); | |||||
| currentDate.set(Calendar.HOUR_OF_DAY, 23); | |||||
| currentDate.set(Calendar.MINUTE, 59); | |||||
| currentDate.set(Calendar.SECOND, 59); | |||||
| currentDate.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); | |||||
| return (int)(currentDate.getTimeInMillis() / 1000L); | |||||
| } | |||||
| public static int getCurrentMonthStartTime(int dayTime) { | |||||
| Calendar currentDate = Calendar.getInstance(); | |||||
| currentDate.setTime(new Date(dayTime * 1000L)); | |||||
| currentDate.set(Calendar.HOUR_OF_DAY, 0); | |||||
| currentDate.set(Calendar.MINUTE, 0); | |||||
| currentDate.set(Calendar.SECOND, 0); | |||||
| currentDate.set(Calendar.DAY_OF_MONTH, currentDate | |||||
| .getActualMinimum(Calendar.DAY_OF_MONTH)); | |||||
| return (int)(currentDate.getTimeInMillis() / 1000L); | |||||
| } | |||||
| public static int getCurrentMonthEndTime(int dayTime) { | |||||
| Calendar currentDate = Calendar.getInstance(); | |||||
| currentDate.setTime(new Date(dayTime * 1000L)); | |||||
| currentDate.set(Calendar.HOUR_OF_DAY, 23); | |||||
| currentDate.set(Calendar.MINUTE, 59); | |||||
| currentDate.set(Calendar.SECOND, 59); | |||||
| currentDate.set(Calendar.DAY_OF_MONTH, currentDate | |||||
| .getActualMaximum(Calendar.DAY_OF_MONTH)); | |||||
| return (int)(currentDate.getTimeInMillis() / 1000L); | |||||
| } | |||||
| /** | |||||
| * format time to "yyyy-MM-dd" | |||||
| * @param time | |||||
| * @return | |||||
| */ | |||||
| public static String formatTimeYYMMDDHH(int time){ | |||||
| long t = time * 1000l; | |||||
| SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHH"); | |||||
| String ret = formatter.format(new Date(t)); | |||||
| return ret; | |||||
| } | |||||
| public static String formatTimeMMDD(int time){ | |||||
| long t = time * 1000l; | |||||
| SimpleDateFormat formatter = new SimpleDateFormat("MMdd"); | |||||
| String ret = formatter.format(new Date(t)); | |||||
| return ret; | |||||
| } | |||||
| public static String formatTimeMMDotDD(int time) { | |||||
| long t = time * 1000l; | |||||
| SimpleDateFormat formatter = new SimpleDateFormat("MM.dd"); | |||||
| String ret = formatter.format(new Date(t)); | |||||
| return ret; | |||||
| } | |||||
| public static String formatTimeYmdHm(int time) { | |||||
| long t = time * 1000l; | |||||
| SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmm"); | |||||
| String ret = formatter.format(new Date(t)); | |||||
| return ret; | |||||
| } | |||||
| public static int getDayByType(int time, int type) { | |||||
| long t = time * 1000L; | |||||
| Calendar calendar = Calendar.getInstance(); | |||||
| calendar.setTime(new Date(t)); | |||||
| return calendar.get(type); | |||||
| } | |||||
| public static int addTime(int time , int type , int nums) { | |||||
| long t = time * 1000L; | |||||
| Calendar calendar = Calendar.getInstance(); | |||||
| calendar.setTime(new Date(t)); | |||||
| calendar.add(type, nums); | |||||
| return (int)(calendar.getTimeInMillis() / 1000L); | |||||
| } | |||||
| public static BigDecimal convertCoord2Decimal(Integer coordLat) { | |||||
| return new BigDecimal(coordLat).divide(new BigDecimal(100000), 5, BigDecimal.ROUND_HALF_DOWN); | |||||
| } | |||||
| public static BigDecimal convertScale(Double amount) { | |||||
| return amount != null ? new BigDecimal(amount).setScale(1,BigDecimal.ROUND_HALF_DOWN) : BigDecimal.ZERO; | |||||
| } | |||||
| public static String convertLevel(String level) { | |||||
| if (level != null && level.matches("\\d+(.\\d+)?")) { | |||||
| return new BigDecimal(level) | |||||
| .multiply(new BigDecimal(2.0)) | |||||
| .setScale(1, BigDecimal.ROUND_HALF_UP).toString(); | |||||
| } | |||||
| return level; | |||||
| } | |||||
| public static String getUTFString(String content) { | |||||
| try { | |||||
| return new String(content.getBytes("ISO-8859-1"), "utf-8"); | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return ""; | |||||
| } | |||||
| /** | |||||
| * 金额 分转换元(精确到2位小数) | |||||
| * @param money (单位分) | |||||
| * @return | |||||
| */ | |||||
| public static BigDecimal getAmount(Integer money) { | |||||
| return new BigDecimal(money).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN); | |||||
| } | |||||
| public static String getDataFormatStringYYYYMMDDHHmmss(int currentSec) { | |||||
| SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss"); | |||||
| return sf.format(((long) currentSec) * 1000); | |||||
| } | |||||
| public static String getDataFormatStringYYYYMMDDHHmmss(Date currentDate) { | |||||
| SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss"); | |||||
| return sf.format(currentDate); | |||||
| } | |||||
| public static Date getDateFromString(String timeEnd) throws ParseException { | |||||
| timeEnd = timeEnd.replaceAll("[[\\s-:punct:]]",""); | |||||
| SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); | |||||
| return sdf.parse(timeEnd); | |||||
| } | |||||
| public static Date getDateTtFromString(String timeEnd) throws ParseException { | |||||
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |||||
| return sdf.parse(timeEnd); | |||||
| } | |||||
| public static String getOrderNo() { | |||||
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |||||
| String dateStr = sdf.format(new Date()); | |||||
| return dateStr.substring(0,4)+dateStr.substring(5,7)+dateStr.substring(8,10)+dateStr.substring(11,13)+dateStr.substring(14,16)+dateStr.substring(17,19)+RandomUtils.getNum(5); | |||||
| } | |||||
| /** | |||||
| * 金额 分转换元(精确到1位小数) | |||||
| * @param money (单位角) | |||||
| * @return | |||||
| */ | |||||
| public static String getAmountStr(Integer money) { | |||||
| return new BigDecimal(money).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN).toString(); | |||||
| } | |||||
| /** | |||||
| * format time to "yyyyMMdd" | |||||
| * @param time | |||||
| * @return | |||||
| */ | |||||
| public static String formatTimeYmd(int time){ | |||||
| long t = time * 1000l; | |||||
| SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd"); | |||||
| String ret = formatter.format(new Date(t)); | |||||
| return ret; | |||||
| } | |||||
| public static boolean isFileExist(String filePath) { | |||||
| File path=new File(filePath); | |||||
| if(path.exists()){ | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /** | |||||
| * @param text | |||||
| * 目标字符串 | |||||
| * @param length | |||||
| * 截取长度 | |||||
| * @param encode | |||||
| * 采用的编码方式 | |||||
| * @return | |||||
| * @throws UnsupportedEncodingException | |||||
| */ | |||||
| public static String substring(String text, int length, String encode) | |||||
| throws UnsupportedEncodingException { | |||||
| if (text == null) { | |||||
| return null; | |||||
| } | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| int currentLength = 0; | |||||
| for (char c : text.toCharArray()) { | |||||
| currentLength += String.valueOf(c).getBytes(encode).length; | |||||
| if (currentLength <= length) { | |||||
| sb.append(c); | |||||
| } else { | |||||
| break; | |||||
| } | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,459 @@ | |||||
| package com.iformall.utils; | |||||
| import org.apache.commons.logging.Log; | |||||
| import org.apache.commons.logging.LogFactory; | |||||
| import org.dom4j.*; | |||||
| import org.dom4j.tree.DefaultElement; | |||||
| import javax.xml.parsers.DocumentBuilder; | |||||
| import javax.xml.parsers.DocumentBuilderFactory; | |||||
| import javax.xml.transform.OutputKeys; | |||||
| import javax.xml.transform.Transformer; | |||||
| import javax.xml.transform.TransformerFactory; | |||||
| import javax.xml.transform.dom.DOMSource; | |||||
| import javax.xml.transform.stream.StreamResult; | |||||
| import java.io.StringWriter; | |||||
| import java.util.*; | |||||
| /** | |||||
| * XML处理器<br> | |||||
| * | |||||
| * @author XiongChun | |||||
| * @since 2009-07-07 | |||||
| */ | |||||
| @SuppressWarnings({ "rawtypes", "unchecked" }) | |||||
| public final class XmlUtil { | |||||
| private static Log log = LogFactory.getLog(XmlUtil.class); | |||||
| private XmlUtil() { | |||||
| } | |||||
| /** | |||||
| * 解析XML并将其节点元素压入Dto返回(基于节点值形式的XML格式) | |||||
| * | |||||
| * @param pStrXml 待解析的XML字符串 | |||||
| * @return outDto 返回Dto | |||||
| */ | |||||
| public static final Map parseXml2Map(String pStrXml) { | |||||
| Map map = new HashMap(); | |||||
| String strTitle = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; | |||||
| Document document = null; | |||||
| try { | |||||
| if (pStrXml.indexOf("<?xml") < 0) | |||||
| pStrXml = strTitle + pStrXml; | |||||
| document = DocumentHelper.parseText(pStrXml); | |||||
| } catch (DocumentException e) { | |||||
| log.error("==开发人员请注意:==\n将XML格式的字符串转换为XML DOM对象时发生错误啦!" + "\n详细错误信息如下:", e); | |||||
| } | |||||
| // 获取根节点 | |||||
| Element elNode = document.getRootElement(); | |||||
| // 遍历节点属性值将其压入Dto | |||||
| for (Iterator it = elNode.elementIterator(); it.hasNext();) { | |||||
| Element leaf = (Element) it.next(); | |||||
| map.put(leaf.getName().toLowerCase(), leaf.getData()); | |||||
| } | |||||
| return map; | |||||
| } | |||||
| /** | |||||
| * 解析XML并将其节点元素压入Dto返回(基于节点值形式的XML格式) 应用于复杂对象 | |||||
| * | |||||
| * @param doc 待解析的XML字符串 | |||||
| * @return outDto 返回Dto | |||||
| */ | |||||
| public static Map Dom2Map(Document doc) { | |||||
| Map map = new HashMap(); | |||||
| if (doc == null) | |||||
| return map; | |||||
| Element root = doc.getRootElement(); | |||||
| for (Iterator iterator = root.elementIterator(); iterator.hasNext();) { | |||||
| Element e = (Element) iterator.next(); | |||||
| // System.out.println(e.getName()); | |||||
| List list = e.elements(); | |||||
| if (list.size() > 0) { | |||||
| map.put(e.getName(), Dom2Map(e)); | |||||
| } else | |||||
| map.put(e.getName(), e.getText()); | |||||
| } | |||||
| return map; | |||||
| } | |||||
| public static Map Dom2Map(Element e) { | |||||
| Map map = new HashMap(); | |||||
| List list = e.elements(); | |||||
| if (list.size() > 0) { | |||||
| for (int i = 0; i < list.size(); i++) { | |||||
| Element iter = (Element) list.get(i); | |||||
| List mapList = new ArrayList(); | |||||
| if (iter.elements().size() > 0) { | |||||
| Map m = Dom2Map(iter); | |||||
| if (map.get(iter.getName()) != null) { | |||||
| Object obj = map.get(iter.getName()); | |||||
| if (!obj.getClass().getName().equals("java.util.ArrayList")) { | |||||
| mapList = new ArrayList(); | |||||
| mapList.add(obj); | |||||
| mapList.add(m); | |||||
| } | |||||
| if (obj.getClass().getName().equals("java.util.ArrayList")) { | |||||
| mapList = (List) obj; | |||||
| mapList.add(m); | |||||
| } | |||||
| map.put(iter.getName(), mapList); | |||||
| } else | |||||
| map.put(iter.getName(), m); | |||||
| } else { | |||||
| if (map.get(iter.getName()) != null) { | |||||
| Object obj = map.get(iter.getName()); | |||||
| if (!obj.getClass().getName().equals("java.util.ArrayList")) { | |||||
| mapList = new ArrayList(); | |||||
| mapList.add(obj); | |||||
| mapList.add(iter.getText()); | |||||
| } | |||||
| if (obj.getClass().getName().equals("java.util.ArrayList")) { | |||||
| mapList = (List) obj; | |||||
| mapList.add(iter.getText()); | |||||
| } | |||||
| map.put(iter.getName(), mapList); | |||||
| } else | |||||
| map.put(iter.getName(), iter.getText()); | |||||
| } | |||||
| } | |||||
| } else | |||||
| map.put(e.getName(), e.getText()); | |||||
| return map; | |||||
| } | |||||
| /** | |||||
| * 解析XML并将其节点元素压入Dto返回(基于节点值形式的XML格式) | |||||
| * | |||||
| * @param pStrXml 待解析的XML字符串 | |||||
| * @param pXPath 节点路径(例如:"//paralist/row" 则表示根节点paralist下的row节点的xPath路径) | |||||
| * @return outDto 返回Dto | |||||
| */ | |||||
| public static final Map parseXml2Map(String pStrXml, String pXPath) { | |||||
| Map map = new HashMap(); | |||||
| String strTitle = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; | |||||
| Document document = null; | |||||
| try { | |||||
| if (pStrXml.indexOf("<?xml") < 0) | |||||
| pStrXml = strTitle + pStrXml; | |||||
| document = DocumentHelper.parseText(pStrXml); | |||||
| } catch (DocumentException e) { | |||||
| log.error("==开发人员请注意:==\n将XML格式的字符串转换为XML DOM对象时发生错误啦!" + "\n详细错误信息如下:", e); | |||||
| } | |||||
| // 获取根节点 | |||||
| Element elNode = document.getRootElement(); | |||||
| // 遍历节点属性值将其压入Dto | |||||
| for (Iterator it = elNode.elementIterator(); it.hasNext();) { | |||||
| Element leaf = (Element) it.next(); | |||||
| map.put(leaf.getName().toLowerCase(), leaf.getData()); | |||||
| } | |||||
| return map; | |||||
| } | |||||
| /** | |||||
| * 将Dto转换为符合XML标准规范格式的字符串(基于节点值形式) | |||||
| * | |||||
| * @param map 传入的Dto对象 | |||||
| * @param pRootNodeName 根结点名 | |||||
| * @return string 返回XML格式字符串 | |||||
| */ | |||||
| public static final String parseDto2Xml(Map map, String pRootNodeName) { | |||||
| Document document = DocumentHelper.createDocument(); | |||||
| // 增加一个根元素节点 | |||||
| document.addElement(pRootNodeName); | |||||
| Element root = document.getRootElement(); | |||||
| Iterator keyIterator = map.keySet().iterator(); | |||||
| while (keyIterator.hasNext()) { | |||||
| String key = (String) keyIterator.next(); | |||||
| String value = (String) map.get(key); | |||||
| Element leaf = root.addElement(key); | |||||
| leaf.setText(value); | |||||
| } | |||||
| // 将XML的头声明信息截去 | |||||
| String outXml = document.asXML().substring(39); | |||||
| return outXml; | |||||
| } | |||||
| /** | |||||
| * 将Dto转换为符合XML标准规范格式的字符串(基于节点值形式) | |||||
| * | |||||
| * @param map 传入的Dto对象 | |||||
| * @param pRootNodeName 根结点名 | |||||
| * @return string 返回XML格式字符串 | |||||
| */ | |||||
| public static final String parseDto2XmlHasHead(Map map, String pRootNodeName) { | |||||
| Document document = DocumentHelper.createDocument(); | |||||
| // 增加一个根元素节点 | |||||
| document.addElement(pRootNodeName); | |||||
| Element root = document.getRootElement(); | |||||
| Iterator keyIterator = map.keySet().iterator(); | |||||
| while (keyIterator.hasNext()) { | |||||
| String key = (String) keyIterator.next(); | |||||
| String value = (String) map.get(key); | |||||
| Element leaf = root.addElement(key); | |||||
| leaf.setText(value); | |||||
| } | |||||
| // 将XML的头声明信息截去 | |||||
| // String outXml = document.asXML().substring(39); | |||||
| String outXml = document.asXML(); | |||||
| return outXml; | |||||
| } | |||||
| /** | |||||
| * 将Dto转换为符合XML标准规范格式的字符串(基于属性值形式) | |||||
| * | |||||
| * @param map 传入的Dto对象 | |||||
| * @param pRootNodeName 根节点名 | |||||
| * @param pFirstNodeName 一级节点名 | |||||
| * @return string 返回XML格式字符串 | |||||
| */ | |||||
| public static final String parseMap2Xml(Map map, String pRootNodeName, String pFirstNodeName) { | |||||
| Document document = DocumentHelper.createDocument(); | |||||
| // 增加一个根元素节点 | |||||
| document.addElement(pRootNodeName); | |||||
| Element root = document.getRootElement(); | |||||
| root.addElement(pFirstNodeName); | |||||
| Element firstEl = (Element) document.selectSingleNode("/" + pRootNodeName + "/" + pFirstNodeName); | |||||
| Iterator keyIterator = map.keySet().iterator(); | |||||
| while (keyIterator.hasNext()) { | |||||
| String key = (String) keyIterator.next(); | |||||
| String value = (String) map.get(key); | |||||
| firstEl.addAttribute(key, value); | |||||
| } | |||||
| // 将XML的头声明信息丢去 | |||||
| String outXml = document.asXML().substring(39); | |||||
| return outXml; | |||||
| } | |||||
| /** | |||||
| * 将List数据类型转换为符合XML格式规范的字符串(基于节点属性值的方式) | |||||
| * | |||||
| * @param pList 传入的List数据(List对象可以是Dto、VO、Domain的属性集) | |||||
| * @param pRootNodeName 根节点名称 | |||||
| * @param pFirstNodeName 行节点名称 | |||||
| * @return string 返回XML格式字符串 | |||||
| */ | |||||
| public static final String parseList2Xml(List pList, String pRootNodeName, String pFirstNodeName) { | |||||
| Document document = DocumentHelper.createDocument(); | |||||
| Element elRoot = document.addElement(pRootNodeName); | |||||
| for (int i = 0; i < pList.size(); i++) { | |||||
| Map map = (Map) pList.get(i); | |||||
| Element elRow = elRoot.addElement(pFirstNodeName); | |||||
| Iterator it = map.entrySet().iterator(); | |||||
| while (it.hasNext()) { | |||||
| Map.Entry entry = (Map.Entry) it.next(); | |||||
| elRow.addAttribute((String) entry.getKey(), String.valueOf(entry.getValue())); | |||||
| } | |||||
| } | |||||
| String outXml = document.asXML().substring(39); | |||||
| return outXml; | |||||
| } | |||||
| /** | |||||
| * 将List数据类型转换为符合XML格式规范的字符串(基于节点值的方式) | |||||
| * | |||||
| * @param pList 传入的List数据(List对象可以是Dto、VO、Domain的属性集) | |||||
| * @param pRootNodeName 根节点名称 | |||||
| * @param pFirstNodeName 行节点名称 | |||||
| * @return string 返回XML格式字符串 | |||||
| */ | |||||
| public static final String parseList2XmlBasedNode(List pList, String pRootNodeName, String pFirstNodeName) { | |||||
| Document document = DocumentHelper.createDocument(); | |||||
| Element output = document.addElement(pRootNodeName); | |||||
| for (int i = 0; i < pList.size(); i++) { | |||||
| Map map = (Map) pList.get(i); | |||||
| Element elRow = output.addElement(pFirstNodeName); | |||||
| Iterator it = map.entrySet().iterator(); | |||||
| while (it.hasNext()) { | |||||
| Map.Entry entry = (Map.Entry) it.next(); | |||||
| Element leaf = elRow.addElement((String) entry.getKey()); | |||||
| leaf.setText(String.valueOf(entry.getValue())); | |||||
| } | |||||
| } | |||||
| String outXml = document.asXML().substring(39); | |||||
| return outXml; | |||||
| } | |||||
| /** | |||||
| * 将XML规范的字符串转为List对象(XML基于节点属性值的方式) | |||||
| * | |||||
| * @param pStrXml 传入的符合XML格式规范的字符串 | |||||
| * @return list 返回List对象 | |||||
| */ | |||||
| public static final List parseXml2List(String pStrXml) { | |||||
| List lst = new ArrayList(); | |||||
| String strTitle = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; | |||||
| Document document = null; | |||||
| try { | |||||
| if (pStrXml.indexOf("<?xml") < 0) | |||||
| pStrXml = strTitle + pStrXml; | |||||
| document = DocumentHelper.parseText(pStrXml); | |||||
| } catch (DocumentException e) { | |||||
| log.error("==开发人员请注意:==\n将XML格式的字符串转换为XML DOM对象时发生错误啦!" + "\n详细错误信息如下:", e); | |||||
| } | |||||
| // 获取到根节点 | |||||
| Element elRoot = document.getRootElement(); | |||||
| // 获取根节点的所有子节点元素 | |||||
| Iterator elIt = elRoot.elementIterator(); | |||||
| while (elIt.hasNext()) { | |||||
| Element el = (Element) elIt.next(); | |||||
| Iterator attrIt = el.attributeIterator(); | |||||
| Map map = new HashMap(); | |||||
| while (attrIt.hasNext()) { | |||||
| Attribute attribute = (Attribute) attrIt.next(); | |||||
| map.put(attribute.getName().toLowerCase(), attribute.getData()); | |||||
| } | |||||
| lst.add(map); | |||||
| } | |||||
| return lst; | |||||
| } | |||||
| /** | |||||
| * Document to map | |||||
| * | |||||
| * @param doc | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, Object> dom2Map(Document doc) { | |||||
| Map<String, Object> maproot = new HashMap<String, Object>(); | |||||
| if (doc == null) | |||||
| return maproot; | |||||
| Element root = doc.getRootElement(); | |||||
| List list1 = root.elements(); | |||||
| for (Object obj : list1) { | |||||
| Element element = (Element) obj; | |||||
| Map<String, Object> map = new HashMap<String, Object>(); | |||||
| element2Map(element, map); | |||||
| maproot.put(element.getName(), map); | |||||
| } | |||||
| return maproot; | |||||
| } | |||||
| /** | |||||
| * Element to map | |||||
| * | |||||
| * @param e | |||||
| * @return | |||||
| */ | |||||
| public static void element2Map(Element e, Map<String, Object> map) { | |||||
| List<Element> list = e.elements(); | |||||
| if (e.attributeCount() > 0) { | |||||
| for (Object attri : e.attributes()) { | |||||
| Attribute at = (Attribute) attri; | |||||
| map.put(at.getName(), at.getValue()); | |||||
| } | |||||
| } | |||||
| if (list.size() < 1 && DataUtil.isEmpty(e.getText())) { | |||||
| return; | |||||
| } else if (list.size() < 1 && !DataUtil.isEmpty(e.getText())) { | |||||
| map.put("text", e.getText()); | |||||
| } | |||||
| for (Object aList : list) { | |||||
| Element iter = (Element) aList; | |||||
| Map<String, Object> cMap = new HashMap<String, Object>(); | |||||
| element2Map(iter, cMap); | |||||
| map.put(iter.getName(), cMap); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 将mq查询结果包装成list--dto的形式,dto内容为item中的内容 | |||||
| * | |||||
| * @param recv | |||||
| * @return | |||||
| */ | |||||
| public static Map MqResToDto(String recv) { | |||||
| // System.out.println("####recv"+recv); | |||||
| List res = new ArrayList(); | |||||
| Map map = new HashMap(); | |||||
| try { | |||||
| Document doc = DocumentHelper.parseText(recv); | |||||
| List list = doc.selectNodes("//item"); | |||||
| Iterator<DefaultElement> it = list.iterator(); | |||||
| while (it.hasNext()) { | |||||
| Map elementdto = XmlUtil.Dom2Map(it.next()); | |||||
| res.add(elementdto); | |||||
| } | |||||
| map.put("resultList", res);// 放入结果集 | |||||
| /* | |||||
| * 如果存在REC_MNT,说明是分页查询类,需要将总记录数返回 | |||||
| */ | |||||
| Node de = doc.selectSingleNode("//REC_MNT"); | |||||
| if (DataUtil.isNotEmpty(de)) { | |||||
| map.put("countInteger", de.getText()); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| log.error(XmlUtil.class, e); | |||||
| } | |||||
| return map; | |||||
| } | |||||
| /** | |||||
| * 将Map转换为XML格式的字符串 | |||||
| * | |||||
| * @param data Map类型数据 | |||||
| * @return XML格式的字符串 | |||||
| * @throws Exception | |||||
| */ | |||||
| public static String mapToXml(Map<String, String> data) throws Exception { | |||||
| DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); | |||||
| DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder(); | |||||
| org.w3c.dom.Document document = documentBuilder.newDocument(); | |||||
| org.w3c.dom.Element root = document.createElement("xml"); | |||||
| document.appendChild(root); | |||||
| for (String key: data.keySet()) { | |||||
| String value = data.get(key); | |||||
| if (value == null) { | |||||
| value = ""; | |||||
| } | |||||
| value = value.trim(); | |||||
| org.w3c.dom.Element filed = document.createElement(key); | |||||
| filed.appendChild(document.createTextNode(value)); | |||||
| root.appendChild(filed); | |||||
| } | |||||
| TransformerFactory tf = TransformerFactory.newInstance(); | |||||
| Transformer transformer = tf.newTransformer(); | |||||
| DOMSource source = new DOMSource(document); | |||||
| transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); | |||||
| transformer.setOutputProperty(OutputKeys.INDENT, "yes"); | |||||
| StringWriter writer = new StringWriter(); | |||||
| StreamResult result = new StreamResult(writer); | |||||
| transformer.transform(source, result); | |||||
| String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", ""); | |||||
| try { | |||||
| writer.close(); | |||||
| } | |||||
| catch (Exception ex) { | |||||
| } | |||||
| return output; | |||||
| } | |||||
| /* | |||||
| * 将SortedMap<Object,Object> 集合转化成 xml格式 | |||||
| */ | |||||
| public static String getRequestXml(SortedMap<Object,Object> parameters){ | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| sb.append("<xml>"); | |||||
| Set es = parameters.entrySet(); | |||||
| Iterator it = es.iterator(); | |||||
| while(it.hasNext()) { | |||||
| Map.Entry entry = (Map.Entry)it.next(); | |||||
| String k = (String)entry.getKey(); | |||||
| String v = (String)entry.getValue(); | |||||
| if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)|| | |||||
| "return_code".equalsIgnoreCase(k)||"return_msg".equalsIgnoreCase(k)) { | |||||
| sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">"); | |||||
| }else { | |||||
| sb.append("<"+k+">"+v+"</"+k+">"); | |||||
| } | |||||
| } | |||||
| sb.append("</xml>"); | |||||
| return sb.toString(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,50 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||||
| <mapper namespace="com.iformall.mapper.SysConfigMapper"> | |||||
| <resultMap id="BaseResultMap" type="com.iformall.domain.po.SysConfig"> | |||||
| <id column="id" jdbcType="BIGINT" property="id" /> | |||||
| <result column="config_item_key" jdbcType="VARCHAR" property="configItemKey" /> | |||||
| <result column="config_item_remark" jdbcType="VARCHAR" property="configItemRemark" /> | |||||
| <result column="create_date" jdbcType="TIMESTAMP" property="createDate" /> | |||||
| <result column="update_date" jdbcType="TIMESTAMP" property="updateDate" /> | |||||
| <result column="is_hide" jdbcType="INTEGER" property="isHide" /> | |||||
| <result column="status" jdbcType="INTEGER" property="status" /> | |||||
| </resultMap> | |||||
| <sql id="allColumns"> | |||||
| `id`,`config_item_key`,`config_item_remark`,`create_date`,`update_date`,`is_hide`,`status` | |||||
| </sql> | |||||
| <sql id="dynamicWhereConditions"> | |||||
| where 1 = 1 | |||||
| <if test=" null != id "> | |||||
| and `id` = #{id} | |||||
| </if> | |||||
| <if test=" null != configItemKey "> | |||||
| and `config_item_key` = #{configItemKey} | |||||
| </if> | |||||
| <if test=" null != isHide "> | |||||
| and `is_hide` = #{isHide} | |||||
| </if> | |||||
| <if test=" null != status "> | |||||
| and `status` = #{status} | |||||
| </if> | |||||
| <if test=" null != ids "> | |||||
| and id in | |||||
| <foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")"> | |||||
| #{idItem} | |||||
| </foreach> | |||||
| </if> | |||||
| <if test=" null != sortColumns"> order by ${sortColumns} </if> | |||||
| </sql> | |||||
| <select id="findList" parameterType="com.iformall.domain.po.SysConfig" resultMap="BaseResultMap"> | |||||
| select <include refid="allColumns" /> from sys_config | |||||
| <include refid="dynamicWhereConditions" /> | |||||
| </select> | |||||
| <select id="findByKey" parameterType="com.iformall.domain.po.SysConfig" resultMap="BaseResultMap"> | |||||
| select <include refid="allColumns" /> from sys_config where `config_item_key` = #{configItemKey} | |||||
| </select> | |||||
| </mapper> | |||||
| @@ -0,0 +1,54 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||||
| <mapper namespace="com.iformall.mapper.SysConfigValueMapper"> | |||||
| <resultMap id="BaseResultMap" type="com.iformall.domain.po.SysConfigValue"> | |||||
| <id column="id" jdbcType="BIGINT" property="id"/> | |||||
| <result column="tenant_id" jdbcType="VARCHAR" property="tenantId"/> | |||||
| <result column="parent_tenant_id" jdbcType="VARCHAR" property="parentTenantId"/> | |||||
| <result column="config_item_id" jdbcType="BIGINT" property="configItemId"/> | |||||
| <result column="config_item_value" jdbcType="VARCHAR" property="configItemValue"/> | |||||
| <result column="update_date" jdbcType="TIMESTAMP" property="updateDate"/> | |||||
| <result column="create_date" jdbcType="TIMESTAMP" property="createDate"/> | |||||
| </resultMap> | |||||
| <sql id="allColumns"> | |||||
| `id`,`tenant_id`,`parent_tenant_id`,`config_item_id`,`config_item_value`,`update_date`,`create_date` | |||||
| </sql> | |||||
| <sql id="dynamicWhereConditions"> | |||||
| where 1=1 | |||||
| <if test=" null != id "> | |||||
| and `id` = #{id} | |||||
| </if> | |||||
| <if test=" null != tenantId and '' != tenantId"> | |||||
| and `tenant_id` = #{tenantId} | |||||
| </if> | |||||
| <if test=" null != parentTenantId and '' != parentTenantId"> | |||||
| and `parent_tenant_id` = #{parentTenantId} | |||||
| </if> | |||||
| <if test=" null != configItemId "> | |||||
| and `config_item_id` = #{configItemId} | |||||
| </if> | |||||
| <if test=" null != configItemValue "> | |||||
| and `config_item_value` = #{configItemValue} | |||||
| </if> | |||||
| <if test=" null != ids "> | |||||
| and id in | |||||
| <foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")"> | |||||
| #{idItem} | |||||
| </foreach> | |||||
| </if> | |||||
| <if test=" null != sortColumns">order by ${sortColumns}</if> | |||||
| </sql> | |||||
| <select id="findByItemId" parameterType="com.iformall.domain.po.SysConfigValue" resultMap="BaseResultMap"> | |||||
| select <include refid="allColumns"/> from sys_config_value | |||||
| where `config_item_id` = #{configItemId} and `tenant_id` = #{tenantId} | |||||
| </select> | |||||
| </mapper> | |||||
| @@ -0,0 +1,102 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||||
| <mapper namespace="com.iformall.mapper.WxPayOrderMapper"> | |||||
| <resultMap id="BaseResultMap" type="com.iformall.domain.po.WxPayOrder"> | |||||
| <id column="id" jdbcType="BIGINT" property="id"/> | |||||
| <result column="tenant_id" jdbcType="VARCHAR" property="tenantId"/> | |||||
| <result column="parent_tenant_id" jdbcType="VARCHAR" property="parentTenantId" /> | |||||
| <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> | |||||
| <result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/> | |||||
| <result column="c_user_id" jdbcType="BIGINT" property="cUserId"/> | |||||
| <result column="c_user_phone" jdbcType="VARCHAR" property="cUserPhone"/> | |||||
| <result column="pay_amount" jdbcType="INTEGER" property="payAmount"/> | |||||
| <result column="pay_time" jdbcType="TIMESTAMP" property="payTime"/> | |||||
| <result column="transaction_id" jdbcType="VARCHAR" property="transactionId"/> | |||||
| </resultMap> | |||||
| <sql id="allColumns"> | |||||
| `id`,`tenant_id`,`parent_tenant_id`,`create_time`,`update_time`,`c_user_id`,`c_user_phone`,`pay_amount`, | |||||
| `pay_time`,`transaction_id` | |||||
| </sql> | |||||
| <sql id="dynamicWhereConditions"> | |||||
| where `tenant_id` = #{tenantId} | |||||
| <if test=" null != id "> | |||||
| and `id` = #{id} | |||||
| </if> | |||||
| <if test=" null != parentTenantId and '' != parentTenantId"> | |||||
| and `parent_tenant_id` = #{parentTenantId} | |||||
| </if> | |||||
| <if test=" null != createTime "> | |||||
| and `create_time` = #{createTime} | |||||
| </if> | |||||
| <if test=" null != updateTime "> | |||||
| and `update_time` = #{updateTime} | |||||
| </if> | |||||
| <if test=" null != cUserId "> | |||||
| and `c_user_id` = #{cUserId} | |||||
| </if> | |||||
| <if test=" null != payAmount "> | |||||
| and `pay_amount` = #{payAmount} | |||||
| </if> | |||||
| <if test=" null != payTime "> | |||||
| and `pay_time` = #{payTime} | |||||
| </if> | |||||
| <if test=" null != transactionId "> | |||||
| and `transaction_id` like concat('%', #{transactionId},'%') | |||||
| </if> | |||||
| <if test=" null != cUserPhone "> | |||||
| and `c_user_phone` like concat('%', #{cUserPhone},'%') | |||||
| </if> | |||||
| <if test=" null != begin "> | |||||
| and `create_time` >= #{begin} | |||||
| </if> | |||||
| <if test=" null != end "> | |||||
| and `create_time` <= #{end} | |||||
| </if> | |||||
| <if test=" null != userIds "> | |||||
| and c_user_id in | |||||
| <foreach collection="userIds" index="index" item="uidItem" open="(" separator="," close=")"> | |||||
| #{uidItem} | |||||
| </foreach> | |||||
| </if> | |||||
| <if test=" null != ids "> | |||||
| and id in | |||||
| <foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")"> | |||||
| #{idItem} | |||||
| </foreach> | |||||
| </if> | |||||
| <if test=" null != sortColumns">order by ${sortColumns}</if> | |||||
| </sql> | |||||
| <select id="selectById" parameterType="java.util.HashMap" resultMap="BaseResultMap"> | |||||
| select <include refid="allColumns"/> from wx_pay_order where id = #{id} and tenant_id = #{tenantId} | |||||
| </select> | |||||
| <select id="findList" parameterType="com.iformall.domain.po.WxPayOrder" resultMap="BaseResultMap"> | |||||
| select | |||||
| <include refid="allColumns"/> | |||||
| from wx_pay_order | |||||
| <include refid="dynamicWhereConditions"/> | |||||
| </select> | |||||
| <select id="sum" parameterType="com.iformall.domain.po.WxPayOrder" resultType="Integer"> | |||||
| select sum(pay_amount) | |||||
| from wx_pay_order | |||||
| <include refid="dynamicWhereConditions"/> | |||||
| </select> | |||||
| </mapper> | |||||