Commit c47aeba4 by 郑云飞

支付功能完善

parent e86b0ede
......@@ -176,6 +176,7 @@ wx:
subAppId: #服务商模式下的子商户公众账号ID
subMchId: #服务商模式下的子商户号
keyPath: C:\\ProgramData\\certKey\xinrenli\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
notifyUrl: http://xinrenli.nyinhong.com/api//xinrenli/order/notify # 微信支付回调接口
# mp:
# useRedis: false
# redisConfig:
......
......@@ -31,6 +31,7 @@ public class WxPayConfiguration {
payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
payConfig.setNotifyUrl(StringUtils.trimToNull(this.properties.getNotifyUrl()));
// 可以指定是否使用沙箱环境
payConfig.setUseSandboxEnv(false);
......
......@@ -41,4 +41,9 @@ public class WxPayProperties {
*/
private String keyPath;
/**
* 支付回调接口
*/
private String notifyUrl;
}
......@@ -12,6 +12,10 @@ import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* 获取地址类
*
......@@ -57,4 +61,46 @@ public class AddressUtils {
}
return UNKNOWN;
}
/**
* 获取ip
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request) {
String ipAddress;
try {
ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if (ipAddress.equals("127.0.0.1")) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
log.error(e.getMessage(), e);
}
ipAddress = inet.getHostAddress();
}
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
// = 15
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
} catch (Exception e) {
ipAddress = "";
}
return ipAddress;
}
}
package com.yongqi.common.utils.redis;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.yongqi.common.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import java.time.Duration;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@Slf4j
public class CodeUtils {
public static String next(String type) {
return next(type, 4);
}
public static String next(String type, int limit) {
return type + DateUtils.dateTimeNow("yyyyMMdd") + autoGenericCode(RandomUtil.randomInt(getMax(limit)), limit);
}
private static String autoGenericCode(int code, int num) {
// System.out.println(code);
String result = "";
// 保留num的位数
// num 代表长度为4
// d 代表参数为正数型
result = String.format("%0" + num + "d", code);
return result;
}
private static Integer getMax(int limit) {
String a = "";
for (int i = 0; i < limit; i++) {
a = a + "9";
}
return Integer.valueOf(a);
}
private static String random(){
Random random = new Random();
int ends = random.nextInt(99);
return autoGenericCode(ends, 2);
}
public static String createSerialNumber(String type) {
Object object = RedisUtils.getCacheObject(type);
int num = 0;
if (ObjectUtil.isEmpty(object)) {
RedisUtils.setCacheObject(type, 1, Duration.ofMillis(-1));
num = 1;
}else {
num = Integer.parseInt(object.toString());
}
log.info("redis中的编码为:{}", num);
String code = autoGenericCode(num, 4);
RedisUtils.setCacheObject(type, num + 1);
return type + DateUtils.dateTimeNow("yyMMdd") + code + random();
}
public static void main(String[] args) {
// System.out.println(next("KBHMD"));
// createSerialNumber("KBHMD");
System.out.println(createSerialNumber("KBHMD"));
}
}
......@@ -5,15 +5,18 @@ import java.util.Arrays;
import com.yongqi.common.core.domain.model.LoginUser;
import com.yongqi.common.helper.LoginHelper;
import com.yongqi.common.utils.ip.AddressUtils;
import com.yongqi.xinrenli.domain.DbOrder;
import com.yongqi.xinrenli.domain.bo.DbOrderEditBo;
import com.yongqi.xinrenli.domain.vo.ReportFormsVo;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.aspectj.weaver.ast.Var;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.yongqi.common.annotation.RepeatSubmit;
......@@ -146,10 +149,23 @@ public class DbOrderController extends BaseController {
@Log(title = "下单", businessType = BusinessType.DELETE)
@RequestMapping("/orderPay")
public R orderPay(@NotNull(message = "主键不能为空") @RequestParam("id") Long orderId
, @RequestParam(value = "id", required = false) Long couponId) {
, @RequestParam(value = "id", required = false) Long couponId
, HttpServletRequest request) {
LoginUser loginUser = LoginHelper.getLoginUser();
return iDbOrderService.orderPay(orderId, couponId, loginUser);
String ipAddr = AddressUtils.getIpAddr(request);
return iDbOrderService.orderPay(orderId, couponId, loginUser, ipAddr);
}
/**
* 下单
*/
@SaCheckPermission("xinrenli:order:notify")
@Log(title = "下单", businessType = BusinessType.DELETE)
@RequestMapping("/notify")
public R payCallback(@RequestBody String xmlData) {
return iDbOrderService.payCallback(xmlData);
}
/**
* 报表
*/
......
package com.yongqi.xinrenli.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
/**
* @author Administrator
*/
@Data
public class WxPayOrderResult {
/**
* 微信生成的预支付会话标识
*/
private String prepayId;
/**
* 交易类型
*/
private String tradeType;
private String timeStamp;
/**
* 随机字符串
*/
private String nonceStr;
/**
* 签名
*/
private String sign;
/**
* 签名方式
*/
private String signType = "MD5";
/**
* 支付时间
*/
@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss")
@JsonFormat(pattern = "yyyy/MM/dd HH:mm:ss")
private LocalDateTime createTime;
}
......@@ -10,11 +10,10 @@ public enum OrderStatusEnum {
PUBLISHED(0, "已发布"),
REJECTED(1, "已驳回"),
TO_BE_PAID(2, "待支付"),
PAYMENT_IN_PROGRESS(3, "支付中"),
RECEIVED_ORDER(4, "已接单"),
FINISHED(5, "已完成"),
REFUBD_IN_PROGRESS(6, "退款中"),
REFUNDED(7, "已退款"),
RECEIVED_ORDER(3, "已接单"),
FINISHED(4, "已完成"),
REFUBD_IN_PROGRESS(5, "退款中"),
REFUNDED(6, "已退款"),
;
private final Integer code;
......
package com.yongqi.xinrenli.service;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.yongqi.common.core.domain.R;
import com.yongqi.common.core.domain.model.LoginUser;
import com.yongqi.xinrenli.domain.DbOrder;
import com.yongqi.xinrenli.domain.bo.DbOrderEditBo;
import com.yongqi.xinrenli.domain.vo.DbOrderVo;
import com.yongqi.xinrenli.domain.bo.DbOrderBo;
......@@ -10,7 +10,6 @@ import com.yongqi.common.core.page.TableDataInfo;
import com.yongqi.common.core.domain.PageQuery;
import com.yongqi.xinrenli.domain.vo.ReportFormsVo;
import java.util.Collection;
import java.util.List;
/**
......@@ -69,7 +68,7 @@ public interface IDbOrderService {
*/
TableDataInfo<DbOrderVo> homeList(DbOrderBo bo, PageQuery pageQuery);
R orderPay(Long id, Long couponId, LoginUser loginUser);
R orderPay(Long id, Long couponId, LoginUser loginUser, String ipAddr);
ReportFormsVo reportForms();
......@@ -80,4 +79,11 @@ public interface IDbOrderService {
* @return
*/
Integer unpaidJob();
/**
* 支付回调
* @param xmlData
* @return
*/
R payCallback(String xmlData) throws WxPayException;
}
package com.yongqi.xinrenli.service.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.yongqi.common.core.domain.R;
import com.yongqi.common.core.domain.entity.SysUser;
import com.yongqi.common.core.domain.model.LoginUser;
import com.yongqi.common.utils.StringUtils;
import com.yongqi.common.core.page.TableDataInfo;
......@@ -16,19 +16,20 @@ import com.yongqi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yongqi.common.utils.redis.CodeUtils;
import com.yongqi.xinrenli.domain.DbCoupon;
import com.yongqi.xinrenli.domain.DbFile;
import com.yongqi.xinrenli.domain.bo.DbFileBo;
import com.yongqi.xinrenli.domain.bo.DbOrderEditBo;
import com.yongqi.xinrenli.domain.vo.DbFileVo;
import com.yongqi.xinrenli.domain.vo.ReportFormsVo;
import com.yongqi.xinrenli.domain.vo.WxPayOrderResult;
import com.yongqi.xinrenli.enums.DeleteStatusEnum;
import com.yongqi.xinrenli.enums.FileEnumServiceType;
import com.yongqi.xinrenli.enums.OrderStatusEnum;
import com.yongqi.xinrenli.mapper.DbCouponMapper;
import com.yongqi.xinrenli.mapper.DbFileMapper;
import com.yongqi.xinrenli.service.IDbCouponService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yongqi.xinrenli.domain.bo.DbOrderBo;
......@@ -47,6 +48,7 @@ import java.util.*;
* @author zyf
* @date 2023-03-09
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class DbOrderServiceImpl implements IDbOrderService {
......@@ -278,13 +280,15 @@ public class DbOrderServiceImpl implements IDbOrderService {
/**
* 下单
* @param orderId 订单id
*
* @param orderId 订单id
* @param couponId 优惠券id
* @param loginUser 当前登录用户
* @param ipAddr
* @return
*/
@Override
public R orderPay(Long orderId, Long couponId, LoginUser loginUser) {
public R orderPay(Long orderId, Long couponId, LoginUser loginUser, String ipAddr) {
// 1.根据订单id获取订单信息
DbOrder dbOrder = this.baseMapper.selectById(orderId);
// 2.根据卡券id获取卡券信息
......@@ -296,7 +300,8 @@ public class DbOrderServiceImpl implements IDbOrderService {
BigDecimal payAmount = dbOrder.getActualAmount().subtract(dbCoupon.getFullSubtraction());
dbOrder.setPayAmount(payAmount);
dbOrder.setUseCouponId(couponId);
dbOrder.setStatus();
String orderNo = CodeUtils.createSerialNumber("XQ");
dbOrder.setOrderNo(orderNo);
// 4.组装支付数据
WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
// 需求标题
......@@ -306,30 +311,30 @@ public class DbOrderServiceImpl implements IDbOrderService {
}
request.setBody(join);
// 商户订单号
request.setOutTradeNo(consumerOrder.getOrderCode());
// 子商户号
request.setSubMchId(dealer.getWxShopNo());
BigDecimal actualPrice = consumerOrder.getFinalPrice().multiply(BigDecimal.valueOf(100));
request.setOutTradeNo(orderNo);
BigDecimal actualPrice = payAmount.multiply(BigDecimal.valueOf(100));
// 标价金额
request.setTotalFee((actualPrice.intValue()));
// 客户端IP
request.setSpbillCreateIp(ip);
request.setSpbillCreateIp(ipAddr);
// 交易类型
request.setTradeType(WxPayConstants.TradeType.JSAPI);
// 签名类型,默认为MD5,支持HMAC-SHA256和MD5。
request.setSignType(WxPayConstants.SignType.MD5);
// 用户标识
request.setOpenid(wxUser.getOpenId());
request.setOpenid(loginUser.getOpenId());
// 5.调用微信统一下单接口
try {
wxPayService.createOrder(request);
Object order = wxPayService.createOrder(request);
String json = JSON.toJSONString(order);
WxPayOrderResult result = JSON.parseObject(json, WxPayOrderResult.class);
// 6.返回支付所需数据
return R.ok(result);
} catch (WxPayException e) {
throw new RuntimeException(e);
}
return null;
}
/**
......@@ -353,4 +358,17 @@ public class DbOrderServiceImpl implements IDbOrderService {
public Integer unpaidJob() {
return baseMapper.unpaidJob();
}
/**
* 支付回调
* @param xmlData
* @return
*/
@Override
public R payCallback(String xmlData) throws WxPayException {
final WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
log.info("支付回调参数解析:{}", notifyResult);
// 1.查询订单信息
return null;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment