app.id=wx2ff
app.secret=2fd0d010
token=debe817e7
#公众号网页授权
oauth.url=http://api.china-start.cn-api/oauth
oauth.redirect.url=http://api.china-start.cn/shop-api
#JSAPI支付配置
mch.id=148392
order.notify.url=http://pi/order/notify
luckyorder.notify.url=http://api.china-start.cn/shop-api/lucky/notify
deposit.notify.url=http://api./deposit/notify
pay.secret=7dc985d317d5ea2b
life.order.notify.url=http://life/order/notify
hotel.order.notify.url=http://rchant/hotel/order/notify
@Data
@ApiModel("订单支付信息-调起支付")
public class OrderPayDto implements Serializable {
@ApiModelProperty("微信公众号appId")
private String appId;
@ApiModelProperty("时间戳")
private String timeStamp;
@ApiModelProperty("随机字符串")
private String nonceStr;
@ApiModelProperty("支付信息")
@JsonProperty("package")
private String packageStr;
@ApiModelProperty("签名类型")
private String signType;
@ApiModelProperty("支付签名")
private String paySign;
}
@ApiOperation(value = "订单支付回调通知", notes = "订单支付回调通知", hidden = true)
@PostMapping(value = "/notify")
@Authority(AuthorityEnum.NOCHECK)
public String payNotify() {
boolean checkFlag = false;
try {
String notifyInfo = RequestUtil.parseWechatNotifyParams(request);
checkFlag = WechatPayUtil.checkCallBackWechatPaySign(notifyInfo);
if (checkFlag) {
checkFlag = orderService.updatePayStatus(notifyInfo);
//模板消息通知(通知用户-购物成功、通知商户-新订单)
if (checkFlag) {
orderService.wechatTemplateNotify(notifyInfo);
}
}
} catch (IOException | DocumentException e) {
e.printStackTrace();
}
return WechatPayUtil.generateWxCallBackResponse(checkFlag);
}
/**
* 解析微信回调通知参数(简单封装,仅限微信回调用)
*
* @param request request
* @return 微信回调通知参数
* @throws IOException e
*/
public static String parseWechatNotifyParams(HttpServletRequest request) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
in.close();
return sb.toString();
}
/**
* 订单支付-用户下单
*
* @param userId 用户ID
* @param orderPayNo 订单支付单号
* @param clientIp 客户端IP
* @return 公众号支付参数
*/
@Transactional(rollbackFor = Exception.class)
public OrderPayDto orderPay(Integer userId, String orderPayNo, String clientIp) {
User user = userService.getUserInfo(userId);
GoodsPayOrder goodsPayOrder = orderDao.getGoodsPayOrder(userId, orderPayNo);
Map<String, String> payInfo = WechatPayUtil.fetchOrder("中广融媒数字科技", "中广融媒数字科技",
goodsPayOrder.getTradeNo(), goodsPayOrder.getPayAmount(), clientIp, user.getOpenId(), WechatPayUtil.ORDER_NOTIFY_URL);
//根据订单编号获取订单id
GoodsOrder goodsOrder = goodsOrderMapper.selectByPrimaryKey(orderPayNo);
//支付成功后修改基础销量信息
// goodsMapper.updateSalesVolume(goodsOrder.getId());
return JsonUtil.getInstance().toJsonObj(payInfo, OrderPayDto.class);
}
/**
* 订单支付-订单列表
*
* @param userId 用户ID
* @param orderId 订单支ID
* @param clientIp 客户端IP
* @return 公众号支付参数
*/
@Transactional(rollbackFor = Exception.class)
public OrderPayDto orderPay(Integer userId, Integer orderId, String clientIp) {
User user = userService.getUserInfo(userId);
GoodsOrder goodsOrder = orderDao.getGoodsOrderByStatus(userId, orderId, OrderStatusEnum.waitPay);
AssertUtil.notNull(goodsOrder, ExceptionEnum.GoodsOrderInValid);
//生成支付单信息
String payOrderNo = DateUtils.getTimeString(DateUtils.DATE_YYYYMMDDHHMMSS, new Date()) + RandomStringUtils.randomNumeric(6);
BigDecimal payAmount = goodsOrder.getPayAmount();
boolean payOrderFlag = orderDao.addPayOrder(userId, 1, payOrderNo, payAmount);
AssertUtil.isTrue(payOrderFlag, ExceptionEnum.OrderGoodsFail);
//更新订单交易单号
orderDao.updateGoodsOrderPayOrderNo(userId, payOrderNo, Lists.newArrayList(orderId));
Map<String, String> payInfo = WechatPayUtil.fetchOrder("中广融媒数字科技", "中广融媒数字科技",
payOrderNo, payAmount, clientIp, user.getOpenId(), WechatPayUtil.ORDER_NOTIFY_URL);
return JsonUtil.getInstance().toJsonObj(payInfo, OrderPayDto.class);
}
/**
* 支付回调-更新支付单、订单状态
*
* @param notifyInfo 支付回调信息
* @return 回调处理结果
*/
@Transactional(rollbackFor = Exception.class)
public boolean updatePayStatus(String notifyInfo) {
//TODO 金额校验
try {
Map<String, String> params = XmlUtils.xmlStr2Map(notifyInfo);
System.out.println(params);
String payOrderNo = params.get("out_trade_no");
String outTradeNo = params.get("transaction_id");
boolean payStatus = orderDao.updatePayStatus(payOrderNo, outTradeNo);
if (payStatus) {
List<GoodsOrder> goodsOrders = orderDao.getGoodsOrder(payOrderNo);
if (goodsOrders.size() == 1) {
GoodsOrder goodsOrder = goodsOrders.get(0);
Integer isGroup = goodsOrder.getIsGroup();
if (isGroup == null) {
isGroup = 0;
}
if (isGroup == 1) {
//拼团订单
groupService.excuteGroup(goodsOrder.getUserId(), goodsOrder.getId(), goodsOrder.getGroupId());
}
}
}
return payStatus;
} catch (DocumentException e) {
e.printStackTrace();
}
return false;
}
************************工具类***********************
public class WechatPayUtil {
private static final PropertiesUtil WECHAT_PRO = new PropertiesUtil("/configs/wechat.properties");
public static final String ORDER_NOTIFY_URL;
public static final String LUCKYORDER_NOTIFY_URL; //奖券特殊回调地址
public static final String DEPOSIT_NOTIFY_URL;
public static final String LIFE_ORDER_NOTIFY_URL;
public static final String HOTEL_ORDER_NOTIFY_URL;
private static final String APP_ID;
private static final String MCH_ID;
private static final String PAY_SECRET;
static {
APP_ID = WECHAT_PRO.getProperty("app.id");
MCH_ID = WECHAT_PRO.getProperty("mch.id");
ORDER_NOTIFY_URL = WECHAT_PRO.getProperty("order.notify.url");
LUCKYORDER_NOTIFY_URL = WECHAT_PRO.getProperty("luckyorder.notify.url");
DEPOSIT_NOTIFY_URL = WECHAT_PRO.getProperty("deposit.notify.url");
LIFE_ORDER_NOTIFY_URL = WECHAT_PRO.getProperty("life.order.notify.url");
HOTEL_ORDER_NOTIFY_URL = WECHAT_PRO.getProperty("hotel.order.notify.url");
PAY_SECRET = WECHAT_PRO.getProperty("pay.secret");
}
private static final String TRADE_STATUS_SUCCESS = "SUCCESS";
/**
* 微信JSAPI支付统一下单 预支付交易单 xml字符串
*
* @param body 商品简单描述
* @param detail 商品详细描述
* @param orderNo 内部订单号
* @param money 订单金额 (单位: 元)
* @param clientIp 客户端IP
* @param openId 用户openId
* @return 微信JSAPI支付预支付交易单 xml字符串
*/
private static String generateUnifiedOrder(String body, String detail, @Nonnull String orderNo,
@Nonnull BigDecimal money, String clientIp, @Nonnull String openId, @Nonnull String notifyUrl) {
Map<String, String> params = Maps.newHashMap();
params.put("appid", APP_ID);
params.put("mch_id", MCH_ID);
params.put("nonce_str", RandomStringUtils.randomAlphabetic(6));
params.put("body", body);
params.put("detail", detail);
params.put("out_trade_no", orderNo);
params.put("total_fee", money.multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_DOWN).toString());
params.put("spbill_create_ip", clientIp);
params.put("notify_url", notifyUrl);
params.put("trade_type", "JSAPI");
params.put("openid", openId);
params.put("sign", generateWechatPaySign(params));
return XmlUtils.map2XmlStr(MapUtils.mapParamOrderByAsc(params));
}
/**
* 微信JSAPI支付统一下单
*
* @param goodsDesc 商品描述
* @param goodsDetail 商品详情
* @param orderNo 内部订单号
* @param money 订单金额 (单位: 元)
* @param clientIp 客户端IP
* @param openId 用户openId
* @return 客户端JSAPI支付参数
*/
public static Map<String, String> fetchOrder(String goodsDesc, String goodsDetail, String orderNo,
BigDecimal money, String clientIp, String openId, String notifyUrl) {
try {
String unifiedOrder = generateUnifiedOrder(goodsDesc, goodsDetail, orderNo, money, clientIp, openId, notifyUrl);
String unifiedOrderResult = HttpUtil.getResult(WechatConstant.UNIFIED_ORDER, unifiedOrder);
Map<String, String> payResult = XmlUtils.xmlStr2Map(unifiedOrderResult);
log.info(JsonUtil.getInstance().toJsonString(payResult));
Map<String, String> payValue = Maps.newHashMap();
payValue.put("appId", APP_ID);
payValue.put("timeStamp", System.currentTimeMillis() / 1000 + "");
payValue.put("nonceStr", RandomStringUtils.randomAlphabetic(6));
payValue.put("package", "prepay_id=" + payResult.get("prepay_id"));
payValue.put("signType", "MD5");
payValue.put("paySign", generateWechatPaySign(payValue));
return payValue;
} catch (DocumentException e) {
e.printStackTrace();
}
throw new WebException(ExceptionEnum.Exception);
}
private static String generateWechatPaySign(Map<String, String> params) {
String plainValue = MapUtils.mapParamOrderByAscJoinUrlDelimiter(params) + "&key=" + PAY_SECRET;
return CodecUtil.getMD5Cryptography(plainValue).toUpperCase();
}
/**
* 校验微信支付回调信息
*
* @param notifyInfo 微信支付回调信息
* @return true/false
*/
public static boolean checkCallBackWechatPaySign(String notifyInfo) throws DocumentException {
Map<String, String> params = XmlUtils.xmlStr2Map(notifyInfo);
String oldSignStr = params.get("sign");
params.remove("sign");
String newSignStr = generateWechatPaySign(params);
if (!oldSignStr.equals(newSignStr)) {
return false;
}
return StringUtils.equalsIgnoreCase(params.get("return_code"), TRADE_STATUS_SUCCESS) && StringUtils.equalsIgnoreCase(params.get("result_code"), TRADE_STATUS_SUCCESS);
}
/**
* 生成微信支付回调响应信息
*
* @param checkFlag 签名校验结果
* @return 微信支付回调响应信息
*/
public static String generateWxCallBackResponse(boolean checkFlag) {
Map<String, String> params = Maps.newHashMap();
String returnCode = "FAIL";
String returnMsg = "校验签名失败";
if (checkFlag) {
returnCode = "SUCCESS";
returnMsg = "OK";
}
params.put("return_code", returnCode);
params.put("return_msg", returnMsg);
return XmlUtils.map2XmlStr(params);
}
网友评论