diff --git a/gather-app/src/main/java/com/ruoyi/database/controller/AlipayNotifyController.java b/gather-app/src/main/java/com/ruoyi/database/controller/AlipayNotifyController.java index 0b61e33..131d872 100644 --- a/gather-app/src/main/java/com/ruoyi/database/controller/AlipayNotifyController.java +++ b/gather-app/src/main/java/com/ruoyi/database/controller/AlipayNotifyController.java @@ -1,11 +1,13 @@ package com.ruoyi.database.controller; +import cn.hutool.json.JSONObject; import com.alipay.api.internal.util.AlipaySignature; import com.ruoyi.config.AlipayRYConfig; import com.ruoyi.database.domain.ParkingBillInfo; import com.ruoyi.database.domain.ParkingBillPaymentInfo; import com.ruoyi.database.service.ParkingBillInfoService; import com.ruoyi.database.service.ParkingBillPaymentInfoService; +import com.ruoyi.database.util.HaiKangApiUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -26,6 +28,9 @@ public class AlipayNotifyController { @Autowired private ParkingBillInfoService parkingBillInfoService; + @Autowired + private HaiKangApiUtils haiKangApiUtils; + public AlipayNotifyController(AlipayRYConfig alipayConfig) { @@ -91,6 +96,12 @@ public class AlipayNotifyController { if (parkingBillInfo == null) { return "failure"; } + String notice = haiKangApiUtils.notice(one, parkingBillInfo, 2); + JSONObject jsonObject = new JSONObject(notice); + String msg = jsonObject.getStr("msg"); + if ("SUCCESS".equals(msg)) { + parkingBillInfo.setIsNotify(1); + } parkingBillInfo.setIsPay(1); boolean b1 = parkingBillInfoService.updateById(parkingBillInfo); if (!b1) { diff --git a/gather-app/src/main/java/com/ruoyi/database/controller/SmallProgramController.java b/gather-app/src/main/java/com/ruoyi/database/controller/SmallProgramController.java index 75e2285..955bce0 100644 --- a/gather-app/src/main/java/com/ruoyi/database/controller/SmallProgramController.java +++ b/gather-app/src/main/java/com/ruoyi/database/controller/SmallProgramController.java @@ -18,8 +18,6 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.time.Instant; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -35,8 +33,7 @@ public class SmallProgramController extends BaseController { private final ParkingBillInfoService parkingBillInfoService; private final AlipayService alipayService; - private final WechatPhoneService wechatPhoneService; - private final AlipayPhoneService alipayPhoneService; + private final BaseCustomerInfoService baseCustomerInfoService; private final WechatMiniProgramPayService wechatMiniProgramPayService; private final ParkingBillPaymentInfoService parkingBillPaymentInfoService; private final CustomerPlateNoInfoService customerPlateNoInfoService; @@ -48,15 +45,15 @@ public class SmallProgramController extends BaseController { @ApiOperation("根据车牌号查询缴费订单") @Transactional public AjaxResult getOrder(String plateNo) { -// ParkingBillInfo b = parkingBillInfoService.saveOrUpdateParkingBillInfo(plateNo); - ParkingBillInfo one = parkingBillInfoService.lambdaQuery() - .eq(ParkingBillInfo::getPlateNo, plateNo) - .orderByDesc(ParkingBillInfo::getCreateTime) - .last("limit 1") - .one(); + ParkingBillInfo one = parkingBillInfoService.saveOrUpdateParkingBillInfo(plateNo); +// ParkingBillInfo one = parkingBillInfoService.lambdaQuery() +// .eq(ParkingBillInfo::getPlateNo, plateNo) +// .orderByDesc(ParkingBillInfo::getCreateTime) +// .last("limit 1") +// .one(); if (one == null) { - return AjaxResult.error("未查询到订单"); + return AjaxResult.error("未查询到停车记录"); }else { ParkingBillInfoVO parkingBillInfoVO = new ParkingBillInfoVO(); BeanUtils.copyProperties(one, parkingBillInfoVO); @@ -73,6 +70,9 @@ public class SmallProgramController extends BaseController { @ApiOperation("历史缴费车牌列表") public AjaxResult getHistoryOrder(HttpServletRequest request){ LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); + if (loginUserByPhone == null) { + return AjaxResult.error("用户未登录"); + } String phone = loginUserByPhone.getPhone(); List list = parkingBillPaymentInfoService.lambdaQuery() .eq(ParkingBillPaymentInfo::getPhone, phone) @@ -101,6 +101,9 @@ public class SmallProgramController extends BaseController { @ApiOperation("查询历史未缴费订单") public AjaxResult getHistoryNoPayOrder(HttpServletRequest request){ LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); + if (loginUserByPhone == null) { + return AjaxResult.error("用户未登录"); + } List list = customerPlateNoInfoService.lambdaQuery() .eq(CustomerPlateNoInfo::getPhone, loginUserByPhone.getPhone()) .list(); @@ -131,6 +134,9 @@ public class SmallProgramController extends BaseController { @ApiOperation("查询已绑定车辆") public AjaxResult getBindTheVehicle(HttpServletRequest request){ LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); + if (loginUserByPhone == null) { + return AjaxResult.error("用户未登录"); + } List list = customerPlateNoInfoService.lambdaQuery() .eq(CustomerPlateNoInfo::getPhone, loginUserByPhone.getPhone()) .list(); @@ -178,14 +184,30 @@ public class SmallProgramController extends BaseController { .last("limit 1") .one(); if (one == null) { - return AjaxResult.error("订单查询失败"); + return AjaxResult.error("停车记录查询失败"); + } + ParkingBillInfo parkingBillInfo = parkingBillInfoService.saveOrUpdateParkingBillInfo(one.getPlateNo()); + if (parkingBillInfo != null) { + one = parkingBillInfo; } -// one = parkingBillInfoService.saveOrUpdateParkingBillInfo(one.getPlateNo()); -// if (one == null) { -// return AjaxResult.error("订单查询失败"); -// } String generate = generate(loginUserByPhone.getPhone()); - String openId = getOpenId(payFees); + BaseCustomerInfo one1 = baseCustomerInfoService.lambdaQuery() + .eq(BaseCustomerInfo::getPhone, loginUserByPhone.getPhone()) + .last("limit 1") + .one(); + if (one1 == null) { + return AjaxResult.error("用户信息出错"); + } + String openId = null; + PayType payType = PayType.getByCode(payFees.getPayType()); + switch (payType) { + case WECHAT: + openId = one1.getOpenId(); + break; + case ALIPAY: + openId = one1.getAlipayUserId(); + break; + } String clientIp = wechatMiniProgramPayService.getClientIpAddress(request); Map order = createOrder(payFees, generate, openId, one, clientIp); @@ -208,25 +230,7 @@ public class SmallProgramController extends BaseController { } - /** - * 获取用户openid - * @param payFees - * @return - */ - private String getOpenId(PayFees payFees) { - PayType payType = PayType.getByCode(payFees.getPayType()); - switch (payType) { - case WECHAT: - return wechatPhoneService.getOpenId(payFees.getCode()); - - case ALIPAY: - return alipayPhoneService.getAlipayUserId(payFees.getCode()); - - default: - throw new IllegalArgumentException("不支持的登录方式: " + payType); - } - } /** * 创建支付宝 微信 订单 diff --git a/gather-app/src/main/java/com/ruoyi/database/controller/WxPayNotifyController.java b/gather-app/src/main/java/com/ruoyi/database/controller/WxPayNotifyController.java index 5331b55..b4387ae 100644 --- a/gather-app/src/main/java/com/ruoyi/database/controller/WxPayNotifyController.java +++ b/gather-app/src/main/java/com/ruoyi/database/controller/WxPayNotifyController.java @@ -1,5 +1,6 @@ package com.ruoyi.database.controller; +import cn.hutool.json.JSONObject; import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.github.binarywang.wxpay.service.WxPayService; @@ -8,6 +9,7 @@ import com.ruoyi.database.domain.ParkingBillPaymentInfo; import com.ruoyi.database.service.ParkingBillInfoService; import com.ruoyi.database.service.ParkingBillPaymentInfoService; import com.ruoyi.database.service.WechatMiniProgramPayService; +import com.ruoyi.database.util.HaiKangApiUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -27,6 +29,9 @@ public class WxPayNotifyController { @Autowired private ParkingBillInfoService parkingBillInfoService; + @Autowired + private HaiKangApiUtils haiKangApiUtils; + /** * 微信支付结果通知回调 @@ -74,6 +79,12 @@ public class WxPayNotifyController { if (parkingBillInfo == null) { return WxPayNotifyResponse.fail("处理失败"); } + String notice = haiKangApiUtils.notice(one, parkingBillInfo, 3); + JSONObject jsonObject = new JSONObject(notice); + String msg = jsonObject.getStr("msg"); + if ("SUCCESS".equals(msg)) { + parkingBillInfo.setIsNotify(1); + } parkingBillInfo.setIsPay(1); boolean b1 = parkingBillInfoService.updateById(parkingBillInfo); if (!b1){ diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/BaseCustomerInfo.java b/gather-app/src/main/java/com/ruoyi/database/domain/BaseCustomerInfo.java index 8611eeb..33ffba1 100644 --- a/gather-app/src/main/java/com/ruoyi/database/domain/BaseCustomerInfo.java +++ b/gather-app/src/main/java/com/ruoyi/database/domain/BaseCustomerInfo.java @@ -2,6 +2,7 @@ package com.ruoyi.database.domain; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; @@ -113,4 +114,8 @@ public class BaseCustomerInfo { private Integer memberLevel; + @TableField(exist = false) + private String wxMchId; + + } diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/LoginRequest.java b/gather-app/src/main/java/com/ruoyi/database/domain/LoginRequest.java index 4c1e54d..57c280a 100644 --- a/gather-app/src/main/java/com/ruoyi/database/domain/LoginRequest.java +++ b/gather-app/src/main/java/com/ruoyi/database/domain/LoginRequest.java @@ -21,4 +21,9 @@ public class LoginRequest { @NotBlank(message = "授权code不能为空") private String code; + + + @ApiModelProperty("支付宝的授权code") + private String authCode; + } diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBill.java b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBill.java index 340565d..52ff238 100644 --- a/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBill.java +++ b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBill.java @@ -1,5 +1,6 @@ package com.ruoyi.database.domain; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -10,6 +11,7 @@ import java.util.Date; * 停车场账单信息 */ @Data +@JsonIgnoreProperties(ignoreUnknown = true) public class ParkingBill { /** diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBillInfo.java b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBillInfo.java index 6da3b8c..07c595e 100644 --- a/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBillInfo.java +++ b/gather-app/src/main/java/com/ruoyi/database/domain/ParkingBillInfo.java @@ -170,4 +170,9 @@ public class ParkingBillInfo { @ApiModelProperty("是否支付") @Excel(name = "是否支付") private Integer isPay; + + + @ApiModelProperty("是否通知") + @Excel(name = "是否通知") + private Integer isNotify; } diff --git a/gather-app/src/main/java/com/ruoyi/database/domain/PayFees.java b/gather-app/src/main/java/com/ruoyi/database/domain/PayFees.java index 2445d33..8df5725 100644 --- a/gather-app/src/main/java/com/ruoyi/database/domain/PayFees.java +++ b/gather-app/src/main/java/com/ruoyi/database/domain/PayFees.java @@ -15,8 +15,4 @@ public class PayFees { @ApiModelProperty("支付方式: wechat 或 alipay") @NotBlank(message = "支付方式不能为空") private String payType; - - @ApiModelProperty("微信或支付宝的授权code") - @NotBlank(message = "code不能为空") - private String code; } diff --git a/gather-app/src/main/java/com/ruoyi/database/service/AlipayPhoneService.java b/gather-app/src/main/java/com/ruoyi/database/service/AlipayPhoneService.java index 2ea671b..bd0c2ef 100644 --- a/gather-app/src/main/java/com/ruoyi/database/service/AlipayPhoneService.java +++ b/gather-app/src/main/java/com/ruoyi/database/service/AlipayPhoneService.java @@ -329,11 +329,11 @@ public class AlipayPhoneService { */ public String getAlipayUserId(String authCode) { try { - String phoneNumber = getPhoneNumber(authCode); + String openId = getOpenId(authCode); // 在实际业务中,你可能需要根据手机号关联用户ID // 这里返回手机号作为示例,实际应该返回支付宝用户ID - return phoneNumber; + return openId; } catch (Exception e) { log.error("获取支付宝用户ID异常", e); diff --git a/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingBillInfoServiceImpl.java b/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingBillInfoServiceImpl.java index 8638cab..3d79829 100644 --- a/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingBillInfoServiceImpl.java +++ b/gather-app/src/main/java/com/ruoyi/database/service/impl/ParkingBillInfoServiceImpl.java @@ -50,7 +50,7 @@ public class ParkingBillInfoServiceImpl extends ServiceImpl updateWrapper = new LambdaUpdateWrapper<>(); - updateWrapper.eq(ParkingBillInfo::getBillCode,parkingBillInfo.getBillCode()); + updateWrapper.eq(ParkingBillInfo::getInUnid,parkingBillInfo.getInUnid()); boolean b = saveOrUpdate(parkingBillInfo, updateWrapper); if (b) { return parkingBillInfo; diff --git a/gather-app/src/main/java/com/ruoyi/database/util/HaiKangApiUtils.java b/gather-app/src/main/java/com/ruoyi/database/util/HaiKangApiUtils.java index 37fc68e..a3c0a83 100644 --- a/gather-app/src/main/java/com/ruoyi/database/util/HaiKangApiUtils.java +++ b/gather-app/src/main/java/com/ruoyi/database/util/HaiKangApiUtils.java @@ -4,19 +4,28 @@ import cn.hutool.json.JSONObject; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.database.domain.ParkingBillInfo; +import com.ruoyi.database.domain.ParkingBillPaymentInfo; import lombok.RequiredArgsConstructor; import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; import org.apache.http.client.config.RequestConfig; +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.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.springframework.stereotype.Component; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Base64; import java.util.HashMap; +import java.util.List; import java.util.concurrent.TimeUnit; @@ -73,26 +82,35 @@ public class HaiKangApiUtils { * 调用海康云平台 * 获取accessToken接口 */ - public String getHikAccessToken(){ + public String getHikAccessToken() { try (CloseableHttpClient client = createHttpClient()) { HttpPost httpPost = new HttpPost(HIK_URL + "/artemis/oauth/token"); - HashMap map = new HashMap<>(); - map.put("client_id", client_id); - map.put("client_secret", client_secret); - String json = gson.toJson(map); - StringEntity entity = new StringEntity(json, "UTF-8"); + + // 1. 使用List构建表单参数 + List params = new ArrayList<>(); + params.add(new BasicNameValuePair("client_id", client_id)); + params.add(new BasicNameValuePair("client_secret", client_secret)); + + // 2. 创建UrlEncodedFormEntity + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8"); httpPost.setEntity(entity); + + // 3. 设置正确的Content-Type httpPost.setHeader("Content-type", "application/x-www-form-urlencoded"); - CloseableHttpResponse response = client.execute(httpPost); - HttpEntity entityResponse = response.getEntity(); - if (entityResponse != null) { - String res = EntityUtils.toString(entityResponse, "UTF-8"); - System.out.println(res); - return res; - } else { - // 处理空响应的情况 - System.err.println("Received empty response from server"); - return null; + + // 4. 如果API需要Basic认证 + String auth = client_id + ":" + client_secret; + String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8)); + httpPost.setHeader("Authorization", "Basic " + encodedAuth); + + try (CloseableHttpResponse response = client.execute(httpPost)) { + HttpEntity entityResponse = response.getEntity(); + if (entityResponse != null) { + return EntityUtils.toString(entityResponse, "UTF-8"); + } else { + System.err.println("Received empty response from server"); + return null; + } } } catch (Exception e) { e.printStackTrace(); @@ -157,4 +175,38 @@ public class HaiKangApiUtils { } } + + + public String notice(ParkingBillPaymentInfo billPaymentInfo,ParkingBillInfo parkingBillInfo,int payType){ + try (CloseableHttpClient client = createHttpClient()) { + HttpPost httpPost = new HttpPost(HIK_URL + "/artemis/api/v1/charge/payment/notice"); + HashMap map = new HashMap<>(); + map.put("billNo", billPaymentInfo.getBillCode()); + map.put("thirdBillNo", billPaymentInfo.getTransactionId()); + map.put("payTime", billPaymentInfo.getPayTime()); + map.put("payType", payType); + map.put("payMoney", parkingBillInfo.getPayMoney()); + map.put("thirdUserId", billPaymentInfo.getOpenId()); + String json = gson.toJson(map); + StringEntity entity = new StringEntity(json, "UTF-8"); + httpPost.setEntity(entity); + httpPost.setHeader("Content-type", "application/json"); + httpPost.setHeader("access_token", getAccessToken()); + CloseableHttpResponse response = client.execute(httpPost); + HttpEntity entityResponse = response.getEntity(); + if (entityResponse != null) { + String res = EntityUtils.toString(entityResponse, "UTF-8"); + System.out.println(res); + return res; + } else { + // 处理空响应的情况 + System.err.println("Received empty response from server"); + return null; + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java index a369d0c..211bc35 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -22,6 +22,7 @@ import com.ruoyi.system.service.ISysMenuService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -58,6 +59,9 @@ public class SysLoginController { @Autowired private AlipayPhoneService alipayPhoneService; + @Value("${wx.pay.mchId}") + public String wxMchId; + /** * 登录方法 * @@ -97,22 +101,35 @@ public class SysLoginController { String phoneNumber = getPhoneNumberByLoginType(request); LoginBodyByPhone loginBodyByPhone = new LoginBodyByPhone(); loginBodyByPhone.setPhone(phoneNumber); + String openId = getOpenId(request); + LoginType loginType = LoginType.getByCode(request.getLoginType()); AjaxResult ajax = AjaxResult.success(); // 生成令牌 BaseCustomerInfo one = baseCustomerInfoService.lambdaQuery() .eq(BaseCustomerInfo::getPhone, loginBodyByPhone.getPhone()) .last("limit 1") .one(); + switch (loginType) { + case WECHAT: + one.setOpenId(openId); + break; + case ALIPAY: + one.setAlipayUserId(openId); + break; + } if (one == null) { BaseCustomerInfo baseCustomerInfo = new BaseCustomerInfo(); baseCustomerInfo.setPhone(loginBodyByPhone.getPhone()); baseCustomerInfo.setNickname(loginBodyByPhone.getPhone()); baseCustomerInfoService.save(baseCustomerInfo); + }else { + baseCustomerInfoService.updateById(one); } String token = loginService.loginByPhone(loginBodyByPhone.getPhone()); ajax.put(Constants.TOKEN, token); return ajax; + } @@ -149,6 +166,26 @@ public class SysLoginController { throw new IllegalArgumentException("不支持的登录方式: " + loginType); } } + + /** + * 获取用户openid + * @param request + * @return + */ + private String getOpenId(LoginRequest request) { + LoginType loginType = LoginType.getByCode(request.getLoginType()); + + switch (loginType) { + case WECHAT: + return wechatPhoneService.getOpenId(request.getAuthCode()); + + case ALIPAY: + return alipayPhoneService.getAlipayUserId(request.getAuthCode()); + + default: + throw new IllegalArgumentException("不支持的登录方式: " + loginType); + } + } /** * 获取用户信息 * @@ -188,6 +225,7 @@ public class SysLoginController { .last("limit 1") .one(); one.setPhone(DesensitizedUtil.mobilePhone(one.getPhone())); + one.setWxMchId(wxMchId); return AjaxResult.success(one); } return AjaxResult.success(loginUser); diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 78bee77..591d335 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -138,7 +138,7 @@ wx: appId: wxea120f6f0e955dc2 # 你的小程序AppID mchId: 1251484401 # 你的商户号 mchKey: QloRc8RZcKpOVb4hKPFJKRG9stmqSfxD # 你的API密钥(32位) - keyPath: classpath:cert/apiclient_cert.p12 # 证书路径 + keyPath: /home/project/wisdomPark/config/apiclient_cert.p12 # 证书路径 notifyUrl: https://tingche.csckl.com/wisdomPark/wxpay/notify alipay: