This commit is contained in:
2026-07-20 11:48:06 +08:00
parent 7119dc76a9
commit f379291e4f
409 changed files with 150227 additions and 8557 deletions
@@ -23,6 +23,10 @@ public class WxPayConfig {
// 商户私钥文件
private String privateKeyPath;
private String pubKeyId;
private String pubKeyPath;
// APIv3秘钥
private String apiV3Key;
@@ -2,12 +2,6 @@ package com.gxwebsoft.shop.controller;
//import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import cn.binarywang.wx.miniapp.util.WxMaConfigHolder;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
@@ -47,11 +41,9 @@ import java.util.stream.Collectors;
import static com.gxwebsoft.common.core.constants.RedisConstants.ACCESS_TOKEN_KEY;
@RestController
@RequestMapping("/api/shop/wx-login")
@RequestMapping("/api/wx-login")
@Api(tags = "微信小程序登录API")
public class WxLoginController extends BaseController {
@Resource
private SettingService settingService;
@Resource
private UserService userService;
@Resource
@@ -88,7 +80,7 @@ public class WxLoginController extends BaseController {
User user = userOauthService.getByOauthId(openid);
// 3.存在则签发token并返回登录成功,不存在则注册新用户
if (user == null) {
user = addUser(userParam);
user = addUser(userParam, userParam.getPhone());
// 添加第三方用户信息
UserOauth uo = new UserOauth();
uo.setUserId(user.getUserId());
@@ -109,6 +101,8 @@ public class WxLoginController extends BaseController {
@PostMapping("/loginByMpWxPhone")
public ApiResult<LoginResult> loginByMpWxPhone(@RequestBody UserParam userParam, HttpServletRequest request) throws WxErrorException {
// 获取手机号码
JSONObject result = getOpenIdByCode(userParam);
String openid = result.getString("openid");
String phone = getPhoneByCode(userParam);
System.out.println("phone:" + phone);
@@ -117,7 +111,17 @@ public class WxLoginController extends BaseController {
System.out.println("用户:" + user);
// 不存在
if (user == null) {
return fail("该用户不存在", new LoginResult());
user = addUser(userParam, phone);
user.setPhone(phone);
user.setOpenId(openid);
userService.updateById(user);
// 添加第三方用户信息
UserOauth uo = new UserOauth();
uo.setUserId(user.getUserId());
uo.setTenantId(user.getTenantId());
uo.setOauthType("MP-WEIXIN");
uo.setOauthId(openid);
userOauthService.save(uo);
}
// 签发token
String access_token = JwtUtil.buildToken(new JwtSubject(user.getUsername(), user.getTenantId()),
@@ -145,15 +149,19 @@ public class WxLoginController extends BaseController {
/**
* 新用户注册
*/
private User addUser(UserParam userParam) {
private User addUser(UserParam userParam, String phone) {
User addUser = new User();
// 注册用户
addUser.setStatus(0);
addUser.setUsername(createUsername("wx_"));
addUser.setNickname("微信用户");
addUser.setPassword(userService.encodePassword(CommonUtil.randomUUID16()));
String rawPassword = CommonUtil.randomUUID16();
if (phone != null && phone.length() >= 6) {
rawPassword = phone.substring(phone.length() - 6);
}
addUser.setPassword(userService.encodePassword(rawPassword));
addUser.setTenantId(getTenantId());
Role role = roleService.getOne(new QueryWrapper<Role>().eq("role_code", "user"), false);
Role role = roleService.getOne(new QueryWrapper<Role>().eq("role_code", "student"), false);
addUser.setRoleId(role.getRoleId());
if (userService.saveUser(addUser)) {
// 添加用户角色
@@ -168,10 +176,9 @@ public class WxLoginController extends BaseController {
// 获取openid
private JSONObject getOpenIdByCode(UserParam userParam) {
// 获取微信小程序配置信息
JSONObject setting = settingService.getBySettingKey("mp-weixin");
WxMaProperties.Config config = getDefaultMiniappConfig();
// 获取openId
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + setting.getString("appId") + "&secret=" + setting.getString("appSecret") + "&js_code=" + userParam.getCode() + "&grant_type=authorization_code";
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + config.getAppid() + "&secret=" + config.getSecret() + "&js_code=" + userParam.getCode() + "&grant_type=authorization_code";
// 执行get请求
String result = HttpUtil.get(apiUrl);
System.out.println("result = " + result);
@@ -180,6 +187,14 @@ public class WxLoginController extends BaseController {
// return wxMaService.getUserService().getSessionInfo(userParam.getCode());
}
private WxMaProperties.Config getDefaultMiniappConfig() {
List<WxMaProperties.Config> configs = wxMaProperties.getConfigs();
if (configs == null || configs.isEmpty()) {
throw new WxRuntimeException("请先在yml中配置wx.miniapp.configs");
}
return configs.get(0);
}
/**
* 获取微信手机号码
*
@@ -221,10 +236,9 @@ public class WxLoginController extends BaseController {
*/
public String getAccessToken() {
System.out.println(getTenantId());
// 获取微信小程序配置信息
// JSONObject setting = settingService.getBySettingKey("mp-weixin");
String appid = "wx7bdcb7c68d53062b";
String secret = "8d747742fa81da3211da1d504e494531";
WxMaProperties.Config config = getDefaultMiniappConfig();
String appid = config.getAppid();
String secret = config.getSecret();
// 从缓存获取access_token
String value = redisTemplate.opsForValue().get(ACCESS_TOKEN_KEY.concat(getTenantId().toString()));
// if (value != null) {
@@ -235,7 +249,6 @@ public class WxLoginController extends BaseController {
// 微信获取凭证接口
String apiUrl = "https://api.weixin.qq.com/cgi-bin/token";
// 组装url参数
// String url = apiUrl.concat("?grant_type=client_credential").concat("&appid=").concat(setting.getString("appId")).concat("&secret=").concat(setting.getString("appSecret"));
String url = apiUrl.concat("?grant_type=client_credential").concat("&appid=").concat(appid).concat("&secret=").concat(secret);
// 执行get请求
String result = HttpUtil.get(url);
@@ -250,25 +263,4 @@ public class WxLoginController extends BaseController {
// return null;
}
public WxMaService wxMaService() {
List<WxMaProperties.Config> configs = wxMaProperties.getConfigs();
if (configs == null) {
throw new WxRuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!");
}
WxMaService maService = new WxMaServiceImpl();
maService.setMultiConfigs(
configs.stream()
.map(a -> {
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
config.setAppid(a.getAppid());
config.setSecret(a.getSecret());
config.setToken(a.getToken());
config.setAesKey(a.getAesKey());
config.setMsgDataFormat(a.getMsgDataFormat());
return config;
}).collect(Collectors.toMap(WxMaDefaultConfigImpl::getAppid, a -> a, (o, n) -> o)));
return maService;
}
}
@@ -4,13 +4,12 @@ import cn.hutool.core.date.DateUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.DictData;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.DictDataService;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.shop.constants.OrderConstants;
import com.gxwebsoft.shop.entity.*;
import com.gxwebsoft.shop.service.*;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.RSAConfig;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
@@ -20,6 +19,9 @@ import com.wechat.pay.java.service.partnerpayments.nativepay.model.Transaction;
import com.wechat.pay.java.service.partnerpayments.model.TransactionAmount;
import com.wechat.pay.java.service.partnerpayments.nativepay.NativePayService;
import com.wechat.pay.java.service.partnerpayments.nativepay.model.PrepayResponse;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
@@ -39,6 +41,7 @@ import com.wechat.pay.java.core.Config;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
@RestController
@@ -52,8 +55,8 @@ public class WxPayController extends BaseController {
private DictDataService dictDataService;
@Resource
private OrderRefundService orderRefundService;
@Autowired
private UserBalanceLogController userBalanceLogController;
@Resource
private UserService userService;
private final Integer tenantId = 10036;
@@ -63,88 +66,69 @@ public class WxPayController extends BaseController {
* 商户号
*/
@Value("${wxpay.mch-id}")
public String merchantId;
public String mchId;
/**
* 商户API私钥路径
*/
@Value("${wxpay.private-key-path}")
public String privateKeyPath;
/**
* 商户证书序列号
*/
@Value("${wxpay.pub-key-path}")
public String publicKeyPath;
@Value("${wxpay.pub-key-id}")
public String publicKeyId;
@Value("${wxpay.mch-serial-no}")
public String merchantSerialNumber;
public String serialNo;
/**
* 商户APIV3密钥
*/
@Value("${wxpay.api-v3-key}")
public String apiV3key;
@Value("${wxpay.notify-domain}")
public String notifyUrl;
@Value("${wxpay.cert-path}")
public String wechatPayCertificatePath;
private final String spAppId = "wxa67c676fc445590e";
private final String spMerchantId = "1615739384";
public String nativePay(String orderNo, Integer payAmount, String title) {
Config config = new RSAAutoCertificateConfig.Builder()
.merchantId(spMerchantId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.apiV3Key(apiV3key)
.build();
// 构建service
NativePayService service = new NativePayService.Builder().config(config).build();
PrepayRequest request = new PrepayRequest();
Amount amount = new Amount();
DictData dictData = dictDataService.getByDictCodeAndName("PAY_TEST_MODE", "模式");
if (Integer.valueOf(dictData.getDictDataCode()).equals(0)) {
amount.setTotal(1);
}else {
public HashMap<String, String> makePay(String openId, String orderNo, Integer payAmount, String title, String notifyUrl) {
try {
Config config = new RSAPublicKeyConfig.Builder()
.merchantId(mchId)
.privateKeyFromPath(privateKeyPath)
.publicKeyFromPath(publicKeyPath)
.publicKeyId(publicKeyId)
.apiV3Key(apiV3key)
.merchantSerialNumber(serialNo)
.build();
JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(config).build();
// 跟之前下单示例一样,填充预下单参数
com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest();
com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount();
amount.setTotal(payAmount);
amount.setCurrency("CNY");
request.setAmount(amount);
request.setAppid(appId);
request.setMchid(mchId);
request.setDescription(title);
request.setOutTradeNo(orderNo);
request.setAttach(getTenantId().toString());
final Payer payer = new Payer();
payer.setOpenid(openId);
request.setPayer(payer);
request.setNotifyUrl(notifyUrl);
System.out.println("request = " + request);
PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
final HashMap<String, String> orderInfo = new HashMap<>();
orderInfo.put("provider", "wxpay");
orderInfo.put("timeStamp", response.getTimeStamp());
orderInfo.put("nonceStr", response.getNonceStr());
orderInfo.put("package", response.getPackageVal());
orderInfo.put("signType", "RSA");
orderInfo.put("paySign", response.getPaySign());
return orderInfo;
} catch (Exception e) {
System.out.println(e);
System.out.println(e.getMessage());
}
request.setSpAppid(spAppId);
request.setSpMchid(spMerchantId);
request.setSubAppid(appId);
request.setSubMchid(merchantId);
request.setAmount(amount);
request.setDescription(title);
request.setNotifyUrl(notifyUrl);
request.setOutTradeNo(orderNo);
PrepayResponse response = service.prepay(request);
// 调用下单方法,得到应答
return response.getCodeUrl();
}
/***
* 退款申请
* @param orderRefund
*/
public void refund(OrderRefund orderRefund) {
Config config = new RSAAutoCertificateConfig.Builder()
.merchantId(spMerchantId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.apiV3Key(apiV3key)
.build();
RefundService service = new RefundService.Builder().config(config).build();
CreateRequest request = new CreateRequest();
// 金额
AmountReq amount = new AmountReq();
amount.setTotal(orderRefund.getRefundMoney().multiply(BigDecimal.valueOf(100)).longValue());
amount.setRefund(orderRefund.getRefundMoney().multiply(BigDecimal.valueOf(100)).longValue());
amount.setCurrency("CNY");
request.setSubMchid(merchantId);
request.setAmount(amount);
request.setOutTradeNo(orderRefund.getOrder().getOrderNo());
request.setOutRefundNo("R" + orderRefund.getOrder().getOrderNo());
String wechatRefundNotifyUrl = "https://vivo-server.gxwebsoft.com/api/shop/wx-pay/refund-notify";
request.setNotifyUrl(wechatRefundNotifyUrl);
service.create(request);
return null;
}
@PostMapping("/notify")
@@ -156,11 +140,13 @@ public class WxPayController extends BaseController {
.timestamp(header.get("wechatpay-timestamp").toString())
.body(body)
.build();
NotificationConfig config = new RSAAutoCertificateConfig.Builder()
.merchantId(spMerchantId)
NotificationConfig config = new RSAPublicKeyConfig.Builder()
.merchantId(mchId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.publicKeyFromPath(publicKeyPath)
.publicKeyId(publicKeyId)
.apiV3Key(apiV3key)
.merchantSerialNumber(serialNo)
.build();
// 初始化 NotificationParser
NotificationParser parser = new NotificationParser(config);
@@ -178,45 +164,9 @@ public class WxPayController extends BaseController {
Transaction.TradeStateEnum tradeStateEnum = transaction.getTradeState();
System.out.println("支付结果:" + transaction);
if (tradeStateEnum == Transaction.TradeStateEnum.SUCCESS) {
Order order = orderService.getByOutTradeNo(orderNo);
order.setOrderStatus(OrderConstants.ORDER_STATUS_PAID);
order.setPayMethod(OrderConstants.ORDER_PAY_METHOD_WECHAT.toString());
order.setTradeId(transactionId);
order.setReceiptAmount(userPaid);
order.setPayTime(DateUtil.date());
orderService.updateById(order);
}
return success();
}
@PostMapping("/refund-notify")
public ApiResult<?> refundNotify(@RequestBody String body, @RequestHeader Map<String, Object> header) throws ParseException {
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(header.get("wechatpay-serial").toString())
.nonce(header.get("wechatpay-nonce").toString())
.signature(header.get("wechatpay-signature").toString())
.timestamp(header.get("wechatpay-timestamp").toString())
.body(body)
.build();
NotificationConfig config = new RSAAutoCertificateConfig.Builder()
.merchantId(spMerchantId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.apiV3Key(apiV3key)
.build();
// 初始化 NotificationParser
NotificationParser parser = new NotificationParser(config);
RefundNotification notification = parser.parse(requestParam, RefundNotification.class);
String orderNo = notification.getOutTradeNo();
if (notification.getRefundStatus().equals(Status.SUCCESS)) {
Order order = orderService.getByOutTradeNo(orderNo);
OrderRefund orderRefund = orderRefundService.getByOrderId(order.getOrderId());
if (orderRefund.getRefundStatus().equals(0)) {
orderRefund.setRefundStatus(1);
orderRefundService.updateById(orderRefund);
}
}
return success();
}
}