@@ -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 TENANT_ID = "tenantId"; | |||
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> |