From 6b53b5915b10b0568bb5b44ee35679ece3c476ce Mon Sep 17 00:00:00 2001 From: puzhibing <393733352@qq.com> Date: 星期三, 21 八月 2024 17:05:21 +0800 Subject: [PATCH] Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/java/mx_charging_pile --- ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java | 227 +++++++++++ ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/controller/WxPayController.java | 76 ++- ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/NotifyV3PayDecodeRespBody.java | 222 +++++++++++ ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ChargingPileClient.java | 5 ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/WxPaymentFallbackFactory.java | 51 ++ ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TAppUserVipDetail.java | 10 ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/AppUserVipDetailClient.java | 27 + ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyChargingOrderList.java | 2 ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserVipDetailController.java | 41 ++ ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TExchangeOrderController.java | 6 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java | 41 + ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java | 18 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/PreChargeCheck.java | 20 + ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/utils/WxAbstractPay.java | 32 + ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java | 104 +++++ ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/model/WxCloseOrderModel.java | 22 + ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/PaymentOrder.java | 33 + ruoyi-service/ruoyi-payment/pom.xml | 5 ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/utils/WxV3Pay.java | 24 ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/WxPaymentClient.java | 62 +++ ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddChargingOrder.java | 26 + ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java | 42 ++ ruoyi-service/ruoyi-order/pom.xml | 4 /dev/null | 15 ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/vo/GetAppUserVipDetail.java | 19 ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/AppUserVipDetailFallbackFactory.java | 33 + ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java | 13 ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java | 2 28 files changed, 1,119 insertions(+), 63 deletions(-) diff --git a/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/AppUserVipDetailFallbackFactory.java b/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/AppUserVipDetailFallbackFactory.java new file mode 100644 index 0000000..f22b61a --- /dev/null +++ b/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/AppUserVipDetailFallbackFactory.java @@ -0,0 +1,33 @@ +package com.ruoyi.account.api.factory; + +import com.ruoyi.account.api.feignClient.AppUserVipDetailClient; +import com.ruoyi.account.api.model.TAppUserVipDetail; +import com.ruoyi.account.api.vo.GetAppUserVipDetail; +import com.ruoyi.common.core.domain.R; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.openfeign.FallbackFactory; +import org.springframework.stereotype.Component; + + +/** + * + * @author ruoyi + */ +@Component +public class AppUserVipDetailFallbackFactory implements FallbackFactory<AppUserVipDetailClient> +{ + private static final Logger log = LoggerFactory.getLogger(AppUserVipDetailFallbackFactory.class); + + @Override + public AppUserVipDetailClient create(Throwable throwable) { + log.error("用户会员明细调用失败:{}", throwable.getMessage()); + return new AppUserVipDetailClient() { + + @Override + public R<TAppUserVipDetail> getAppUserVipDetail(GetAppUserVipDetail getAppUserVipDetail) { + return R.fail("获取用户当前有效的VIP明细调用失败:" + throwable.getMessage()); + } + }; + } +} diff --git a/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/AppUserVipDetailClient.java b/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/AppUserVipDetailClient.java new file mode 100644 index 0000000..37f0dbb --- /dev/null +++ b/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/AppUserVipDetailClient.java @@ -0,0 +1,27 @@ +package com.ruoyi.account.api.feignClient; + +import com.ruoyi.account.api.factory.AppUserVipDetailFallbackFactory; +import com.ruoyi.account.api.model.TAppUserVipDetail; +import com.ruoyi.account.api.vo.GetAppUserVipDetail; +import com.ruoyi.common.core.constant.ServiceNameConstants; +import com.ruoyi.common.core.domain.R; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; + +/** + * @author zhibing.pu + * @Date 2024/8/21 10:27 + */ +@FeignClient(contextId = "AppUserVipDetailClient", value = ServiceNameConstants.ACCOUNT_SERVICE, fallbackFactory = AppUserVipDetailFallbackFactory.class) +public interface AppUserVipDetailClient { + + /** + * 获取用户当前有效的VIP明细 + * @param getAppUserVipDetail + * @return + */ + @PostMapping("/appUserVipDetail/getAppUserVipDetail") + R<TAppUserVipDetail> getAppUserVipDetail(GetAppUserVipDetail getAppUserVipDetail); + + +} diff --git a/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TAppUserVipDetail.java b/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TAppUserVipDetail.java index 577fc54..ed91fc3 100644 --- a/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TAppUserVipDetail.java +++ b/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TAppUserVipDetail.java @@ -38,10 +38,12 @@ @ApiModelProperty(value = "剩余充电次数") @TableField("charge_num") private Integer chargeNum; - - - - @ApiModelProperty(value = "购买时折扣金额") + + @ApiModelProperty(value = "折扣") + @TableField("discount") + private BigDecimal discount; + + @ApiModelProperty(value = "最高优惠金额") @TableField("discount_money") private BigDecimal discountMoney; diff --git a/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/vo/GetAppUserVipDetail.java b/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/vo/GetAppUserVipDetail.java new file mode 100644 index 0000000..a1ce8a5 --- /dev/null +++ b/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/vo/GetAppUserVipDetail.java @@ -0,0 +1,19 @@ +package com.ruoyi.account.api.vo; + +import lombok.Data; + +/** + * @author zhibing.pu + * @Date 2024/8/21 10:30 + */ +@Data +public class GetAppUserVipDetail { + /** + * 用户id + */ + private Long appUserId; + /** + * vipid + */ + private Integer vipId; +} diff --git a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ChargingPileClient.java b/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ChargingPileClient.java index b2e13b0..ff0b238 100644 --- a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ChargingPileClient.java +++ b/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ChargingPileClient.java @@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.R; import io.swagger.annotations.ApiOperation; import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -37,4 +38,8 @@ @PostMapping("/site/getSiteInfoByNumber") @ApiOperation(value = "扫一扫后通过桩编号获取电站信息", tags = {"小程序-扫一扫"}) R<SiteInfoVO> getSiteInfoByNumber(@RequestParam("number") String number); + + + @PostMapping("/t-charging-pile/getChargingPileById/{id}") + R<TChargingPile> getChargingPileById(@PathVariable("id") Integer id); } diff --git a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java b/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java index e730372..2d71dfa 100644 --- a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java +++ b/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/vo/SiteInfoVO.java @@ -14,6 +14,8 @@ private String name; @ApiModelProperty(value = "桩编号") private String number; + @ApiModelProperty(value = "充电枪id") + private Integer chargingGunId; @ApiModelProperty(value = "普通电价") private BigDecimal electrovalence; @ApiModelProperty(value = "会员电价") diff --git a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/ChargingOrderFallbackFactory.java b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/ChargingOrderFallbackFactory.java deleted file mode 100644 index ea8f590..0000000 --- a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/ChargingOrderFallbackFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.ruoyi.payment.api.factory; - -import com.ruoyi.payment.api.feignClient.ChargingOrderClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cloud.openfeign.FallbackFactory; -import org.springframework.stereotype.Component; - -/** - * 充电订单服务降级处理 - * - * @author ruoyi - */ -@Component -public class ChargingOrderFallbackFactory implements FallbackFactory<ChargingOrderClient> -{ - private static final Logger log = LoggerFactory.getLogger(ChargingOrderFallbackFactory.class); - - @Override - public ChargingOrderClient create(Throwable throwable) { - log.error("充电订单调用失败:{}", throwable.getMessage()); - return new ChargingOrderClient() { - - }; - } -} diff --git a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/WxPaymentFallbackFactory.java b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/WxPaymentFallbackFactory.java new file mode 100644 index 0000000..bad2cf8 --- /dev/null +++ b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/factory/WxPaymentFallbackFactory.java @@ -0,0 +1,51 @@ +package com.ruoyi.payment.api.factory; + +import com.ruoyi.common.core.domain.R; +import com.ruoyi.payment.api.feignClient.WxPaymentClient; +import com.ruoyi.payment.api.vo.NotifyV3PayDecodeRespBody; +import com.ruoyi.payment.api.vo.PaymentOrder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.openfeign.FallbackFactory; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +/** + * 充电订单服务降级处理 + * + * @author ruoyi + */ +@Component +public class WxPaymentFallbackFactory implements FallbackFactory<WxPaymentClient> +{ + private static final Logger log = LoggerFactory.getLogger(WxPaymentFallbackFactory.class); + + @Override + public WxPaymentClient create(Throwable throwable) { + log.error("微信支付调用失败:{}", throwable.getMessage()); + return new WxPaymentClient() { + + @Override + public R<NotifyV3PayDecodeRespBody> queryOrderInfo(String orderId) { + return R.fail("查询支付订单信息失败:" + throwable.getMessage()); + } + + @Override + public R<Map<String, Object>> orderPay(PaymentOrder paymentOrder) { + throw new RuntimeException("调起微信支付失败:" + throwable.getMessage()); + } + + @Override + public R<Map<String, Object>> payNotify(HttpServletRequest request) { + return R.fail("微信支付回调失败:" + throwable.getMessage()); + } + + @Override + public void ack() { + + } + }; + } +} diff --git a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/ChargingOrderClient.java b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/ChargingOrderClient.java deleted file mode 100644 index d9f4240..0000000 --- a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/ChargingOrderClient.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.ruoyi.payment.api.feignClient; - -import com.ruoyi.common.core.constant.ServiceNameConstants; -import com.ruoyi.payment.api.factory.ChargingOrderFallbackFactory; -import org.springframework.cloud.openfeign.FeignClient; - -/** - * 充电订单服务 - * @author ruoyi - */ -@FeignClient(contextId = "ChargingOrderClient", value = ServiceNameConstants.PAYMENT_SERVICE, fallbackFactory = ChargingOrderFallbackFactory.class) -public interface ChargingOrderClient { - - -} diff --git a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/WxPaymentClient.java b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/WxPaymentClient.java new file mode 100644 index 0000000..7c8f21f --- /dev/null +++ b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/feignClient/WxPaymentClient.java @@ -0,0 +1,62 @@ +package com.ruoyi.payment.api.feignClient; + +import com.ruoyi.common.core.constant.ServiceNameConstants; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.payment.api.factory.WxPaymentFallbackFactory; +import com.ruoyi.payment.api.vo.NotifyV3PayDecodeRespBody; +import com.ruoyi.payment.api.vo.PaymentOrder; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +/** + * 充电订单服务 + * @author ruoyi + */ +@FeignClient(contextId = "WxPaymentClient", value = ServiceNameConstants.PAYMENT_SERVICE, fallbackFactory = WxPaymentFallbackFactory.class) +public interface WxPaymentClient { + + /** + * 查询支付订单信息 + * @param orderId + * @return + */ + @PostMapping("/wx/query/queryOrderInfo") + R<NotifyV3PayDecodeRespBody> queryOrderInfo(String orderId); + + + /** + * 订单支付 + * @param paymentOrder + * @return + */ + @PostMapping("/wx/orderPay") + R<Map<String, Object>> orderPay(@RequestBody PaymentOrder paymentOrder); + + + /** + * 支付回调 + * @param request + * @return + */ + @PostMapping("/wx/pay/notify") + R<Map<String, Object>> payNotify(HttpServletRequest request); + + /** + * 支付回调成功后的成功应答 + */ + @PostMapping("/wx/pay/ack") + void ack(); + + + /** + * 关闭订单 + * @param outTradeNo + */ + @PostMapping("/wx/pay/close") + void close(String outTradeNo); +} diff --git a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/NotifyV3PayDecodeRespBody.java b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/NotifyV3PayDecodeRespBody.java new file mode 100644 index 0000000..3eb2cda --- /dev/null +++ b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/NotifyV3PayDecodeRespBody.java @@ -0,0 +1,222 @@ +package com.ruoyi.payment.api.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * @author xiaochen + * @ClassName FacilV3PayNotifyRespBody + * @Description + */ +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Data +public class NotifyV3PayDecodeRespBody implements Serializable { + // 合单--开始 + private String combine_appid; + private String combine_mchid; + private String combine_out_trade_no; + private List<SubOrders> sub_orders; + // 合单--结束 + /** + * 服务商应用ID + */ + private String sp_appid; + /** + * 服务商户号 + */ + private String sp_mchid; + /** + * 商户号 + */ + private String mchid; + /** + * 子商户应用ID + */ + private String sub_appid; + /** + * 子商户号 + */ + private String sub_mchid; + /** + * 商户订单号 + */ + private String out_trade_no; + /** + * 交易状态描述 + */ + private String trade_state_desc; + /** + * 交易类型,枚举值: + * JSAPI:公众号支付 + * NATIVE:扫码支付 + * APP:APP支付 + * MICROPAY:付款码支付 + * MWEB:H5支付 + * FACEPAY:刷脸支付 + */ + private String trade_type; + /** + * 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用 + */ + private String attach; + /** + * 微信支付订单号 + */ + private String transaction_id; + /** + * 交易状态,枚举值: + * SUCCESS:支付成功 + * REFUND:转入退款 + * NOTPAY:未支付 + * CLOSED:已关闭 + * REVOKED:已撤销(付款码支付) + * USERPAYING:用户支付中(付款码支付) + * PAYERROR:支付失败(其他原因,如银行返回失败) + */ + private String trade_state; + /** + * 银行类型,采用字符串类型的银行标识。银行标识请参考《银行类型对照表》 + * https://pay.weixin.qq.com/wiki/doc/apiv3_partner/terms_definition/chapter1_1_3.shtml#part-6 + */ + private String bank_type; + /** + * 支付完成时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE, + * YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒, + * TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。 + * 例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。 + * 示例值:2018-06-08T10:34:56+08:00 + */ + private String success_time; + /** + * 支付者信息 + */ + private Payer payer; + + /** + * 支付者 + */ + private Payer combine_payer_info; + + /** + * 订单金额信息 + */ + private Amount amount; + /** + * 场景信息 + */ + private SceneInfo scene_info; + /** + * 优惠功能,享受优惠时返回该字段 + */ + private List<PromotionDetail> promotion_detail; + + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Data + public static class Amount implements Serializable{ + /** + * 用户支付金额 + */ + private int payer_total; + /** + * 总金额 + */ + private int total; + /** + * 标价金额 + */ + private int total_amount; + /** + * 现金支付金额 + */ + private int payer_amount; + private String currency; + private String payer_currency; + } + + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Data + public static class GoodsDetail implements Serializable{ + private String goods_id; + private int quantity; + private int unit_price; + private int discount_amount; + private String goods_remark; + + } + + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Data + public static class Payer implements Serializable{ + private String openid; + private String sp_openid; + private String sub_openid; + } + + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Data + public static class PromotionDetail implements Serializable{ + private String coupon_id; + private String name; + private String scope; + private String type; + private int amount; + private String stock_id; + private int wechatpay_contribute; + + private int merchant_contribute; + private int other_contribute; + private String currency; + + private List<GoodsDetail> goods_detail; + + } + + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Data + public static class SceneInfo implements Serializable{ + /** + * 商户端设备号 + */ + private String device_id; + } + + + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Data + public static class SubOrders implements Serializable{ + private String mchid; + private String trade_type; + private String trade_state; + private String trade_state_desc; + private String bank_type; + private String attach; + private String success_time; + private String transaction_id; + private String out_trade_no; + private String sub_mchid; + private Amount amount; + /** + * 优惠功能,享受优惠时返回该字段 + */ + private List<PromotionDetail> promotion_detail; + } +} diff --git a/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/PaymentOrder.java b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/PaymentOrder.java new file mode 100644 index 0000000..a998845 --- /dev/null +++ b/ruoyi-api/ruoyi-api-payment/src/main/java/com/ruoyi/payment/api/vo/PaymentOrder.java @@ -0,0 +1,33 @@ +package com.ruoyi.payment.api.vo; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author zhibing.pu + * @Date 2024/8/21 9:06 + */ +@Data +public class PaymentOrder { + /** + * 订单流水号 + */ + private String code; + /** + * 支付金额 + */ + private BigDecimal amount; + /** + * openid + */ + private String openId; + /** + * 描述 + */ + private String description; + /** + * 回调地址 + */ + private String notifyUrl; +} diff --git a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java index d623721..c8ae422 100644 --- a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java +++ b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppCouponController.java @@ -7,6 +7,9 @@ import com.ruoyi.account.api.model.TAppCoupon; import com.ruoyi.account.api.model.TAppUserCar; import com.ruoyi.account.api.query.ExchangeRecordGoodsQuery; +import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient; +import com.ruoyi.chargingPile.api.model.TChargingGun; +import com.ruoyi.chargingPile.api.model.TChargingPile; import com.ruoyi.other.api.vo.CouponListVOVO; import com.ruoyi.account.api.vo.ExchangeRecordVO; import com.ruoyi.account.service.TAppCouponService; @@ -26,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; @@ -54,6 +58,11 @@ private ChargingPileClient chargingPileClient; @Autowired private ChargingOrderClient chargingOrderClient; + + @Resource + private ChargingGunClient chargingGunClient; + + /** * 小程序扫一扫 添加车辆 * @param dto @@ -70,10 +79,13 @@ * 查询用户可用优惠券数量 * @return */ - @ApiOperation(value = "通过桩编号和预付金额获取电站详情", tags = {"小程序-扫一扫"}) + @ApiOperation(value = "通过充电枪id和预付金额获取电站详情", tags = {"小程序-扫一扫"}) @GetMapping(value = "/scan/siteInfo") - public AjaxResult<SiteInfoVO> siteInfo(String number,BigDecimal money) { - SiteInfoVO data = chargingPileClient.getSiteInfoByNumber(number).getData(); + public AjaxResult<SiteInfoVO> siteInfo(Integer id, BigDecimal money) { + TChargingGun chargingGun = chargingGunClient.getChargingGunById(id).getData(); + TChargingPile chargingPile = chargingPileClient.getChargingPileById(chargingGun.getChargingPileId()).getData(); + SiteInfoVO data = chargingPileClient.getSiteInfoByNumber(chargingPile.getNumber().toString()).getData(); + data.setChargingGunId(id); List<TAppUserCar> cars = appUserCarService.list(new QueryWrapper<TAppUserCar>() .eq("app_user_id",tokenService.getLoginUserApplet().getUserId()) .orderByDesc("create_time")); diff --git a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserVipDetailController.java b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserVipDetailController.java new file mode 100644 index 0000000..898a5eb --- /dev/null +++ b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserVipDetailController.java @@ -0,0 +1,41 @@ +package com.ruoyi.account.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.account.api.model.TAppUserVipDetail; +import com.ruoyi.account.api.vo.GetAppUserVipDetail; +import com.ruoyi.account.service.TAppUserVipDetailService; +import com.ruoyi.common.core.domain.R; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @author zhibing.pu + * @Date 2024/8/21 10:35 + */ +@RestController +@RequestMapping("/appUserVipDetail") +public class TAppUserVipDetailController { + + @Resource + private TAppUserVipDetailService appUserVipDetailService; + + /** + * 获取用户当前有效的vip明细 + * @param getAppUserVipDetail + * @return + */ + @PostMapping("/getAppUserVipDetail") + public R<TAppUserVipDetail> getAppUserVipDetail(@RequestBody GetAppUserVipDetail getAppUserVipDetail){ + TAppUserVipDetail one = appUserVipDetailService.getOne(new LambdaQueryWrapper<TAppUserVipDetail>() + .eq(TAppUserVipDetail::getAppUserId, getAppUserVipDetail.getAppUserId()) + .eq(TAppUserVipDetail::getVipId, getAppUserVipDetail.getVipId()) + .last(" and now() between start_time and end_time")); + return R.ok(one); + } + + +} diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java index 5e4d424..b876d46 100644 --- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java +++ b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java @@ -162,5 +162,18 @@ PageInfo<ChargingGunMonitoring> chargingGunMonitoring = chargingPileService.getChargingGunMonitoring(query); return AjaxResult.success(chargingGunMonitoring); } + + + /** + * 根据id获取充电桩信息 + * @param id + * @return + */ + @ResponseBody + @PostMapping("/getChargingPileById/{id}") + public R<TChargingPile> getChargingPileById(@PathVariable Integer id){ + TChargingPile chargingPile = chargingPileService.getById(id); + return R.ok(chargingPile); + } } diff --git a/ruoyi-service/ruoyi-order/pom.xml b/ruoyi-service/ruoyi-order/pom.xml index aee7399..c3c837a 100644 --- a/ruoyi-service/ruoyi-order/pom.xml +++ b/ruoyi-service/ruoyi-order/pom.xml @@ -33,6 +33,10 @@ <groupId>com.ruoyi</groupId> <artifactId>ruoyi-api-chargingPile</artifactId> </dependency> + <dependency> + <groupId>com.ruoyi</groupId> + <artifactId>ruoyi-api-payment</artifactId> + </dependency> <!-- SpringCloud Alibaba Nacos --> diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java index eac5cd5..d8c37ed 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.chargingPile.api.vo.SiteVO; import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.redis.service.RedisService; import com.ruoyi.common.security.service.TokenService; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.BasePage; @@ -17,15 +18,21 @@ import com.ruoyi.order.dto.MyChargingOrderInfo; import com.ruoyi.order.dto.MyChargingOrderList; import com.ruoyi.order.dto.OrderEvaluateVo; +import com.ruoyi.order.dto.*; import com.ruoyi.order.service.TChargingOrderService; import com.ruoyi.order.service.TOrderEvaluateService; import com.ruoyi.order.service.TOrderEvaluateTagService; +import com.ruoyi.payment.api.feignClient.WxPaymentClient; import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; import org.springframework.beans.factory.annotation.Autowired; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.util.List; import java.util.Map; import java.util.List; @@ -51,6 +58,15 @@ private TOrderEvaluateService orderEvaluateService; @Autowired private TOrderEvaluateTagService orderEvaluateTagService; + + @Resource + private WxPaymentClient wxPaymentClient; + + @Resource + private RedisService redisService; + + + @ResponseBody @PostMapping(value = "/chargingOrder") @@ -150,10 +166,96 @@ @ResponseBody @GetMapping(value = "/getNoInvoicedOrder") @ApiOperation(value = "获取未开票的订单数据", tags = {"小程序-充电发票"}) - public AjaxResult<List<MyChargingOrderList>> getNoInvoicedOrder(@RequestBody GetNoInvoicedOrder query){ + public AjaxResult<List<MyChargingOrderList>> getNoInvoicedOrder(GetNoInvoicedOrder query){ List<MyChargingOrderList> list = chargingOrderService.getNoInvoicedOrder(query); return AjaxResult.success(list); } + + + @ResponseBody + @PostMapping(value = "/paymentChargingOrder") + @ApiOperation(value = "支付充电充值费用", tags = {"小程序-扫一扫"}) + public AjaxResult paymentChargingOrder(AddChargingOrder addChargingOrder){ + return chargingOrderService.paymentChargingOrder(addChargingOrder); + } + + /** + * 充电充值支付回调 + * @param request + */ + @ResponseBody + @PostMapping(value = "/chargingOrderWXCallback") + public void chargingOrderWXCallback(HttpServletRequest request){ + Map<String, Object> data = wxPaymentClient.payNotify(request).getData(); + if(null != data){ + String out_trade_no = data.get("out_trade_no").toString(); + String transaction_id = data.get("transaction_id").toString(); + String attach = data.get("attach").toString(); + AjaxResult ajaxResult = chargingOrderService.chargingOrderCallback(1, out_trade_no, transaction_id, attach); + if(ajaxResult.isSuccess()){ + wxPaymentClient.ack(); + } + } + } + + + /** + * 支付宝支付成功后的回调 + * @param request + */ + @ResponseBody + @PostMapping(value = "/chargingOrderALICallback") + public void chargingOrderALICallback(HttpServletRequest request){ + Map<String, Object> data = wxPaymentClient.payNotify(request).getData(); + if(null != data){ + String out_trade_no = data.get("out_trade_no").toString(); + String transaction_id = data.get("transaction_id").toString(); + String attach = data.get("attach").toString(); + AjaxResult ajaxResult = chargingOrderService.chargingOrderCallback(2, out_trade_no, transaction_id, attach); + if(ajaxResult.isSuccess()){ + + } + } + } + + + + @ResponseBody + @GetMapping(value = "/preChargeCheck/{id}") + @ApiOperation(value = "获取安全检测数据", tags = {"小程序-扫一扫"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "充电枪id", required = true) + }) + public AjaxResult<PreChargeCheck> preChargeCheck(@PathVariable Integer id){ + String key = "AQJC_" + id; + Object cacheObject = redisService.getCacheObject(key); + return AjaxResult.success(cacheObject); + } + + + + @ResponseBody + @GetMapping(value = "/getChargingDetails/{id}") + @ApiOperation(value = "获取充电中页面数据", tags = {"小程序-扫一扫"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "充电枪id", required = true) + }) + public AjaxResult<ChargingDetails> getChargingDetails(@PathVariable Integer id){ + ChargingDetails chargingDetails = chargingOrderService.getChargingDetails(id); + return AjaxResult.success(chargingDetails); + } + + + + @ResponseBody + @PutMapping(value = "/stopCharging/{id}") + @ApiOperation(value = "手动停止充电", tags = {"小程序-扫一扫"}) + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true) + }) + public AjaxResult stopCharging(@PathVariable String id){ + return chargingOrderService.stopCharging(id); + } } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TExchangeOrderController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TExchangeOrderController.java index 9535840..690d828 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TExchangeOrderController.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TExchangeOrderController.java @@ -1,4 +1,5 @@ package com.ruoyi.order.controller; +import java.text.SimpleDateFormat; import java.time.LocalDateTime; @@ -27,6 +28,7 @@ import javax.annotation.Resource; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.stream.Collectors; @@ -158,7 +160,9 @@ @PostMapping("/create") public R<Long> exchangeCreate(@RequestBody ExchangeDto exchangeDto){ TExchangeOrder tExchangeOrder = new TExchangeOrder(); - tExchangeOrder.setCode(""); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + String code = "DH" + Math.random() * 1000 + sdf.format(new Date()); + tExchangeOrder.setCode(code); tExchangeOrder.setAppUserId(exchangeDto.getUserId()); tExchangeOrder.setOrderType(0); tExchangeOrder.setGoodsId(0); diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddChargingOrder.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddChargingOrder.java new file mode 100644 index 0000000..eddec93 --- /dev/null +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddChargingOrder.java @@ -0,0 +1,26 @@ +package com.ruoyi.order.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author zhibing.pu + * @Date 2024/8/20 13:54 + */ +@Data +@ApiModel +public class AddChargingOrder { + @ApiModelProperty("充电枪id") + public Integer id; + @ApiModelProperty("支付金额") + private BigDecimal paymentAmount; + @ApiModelProperty("优惠券id") + private Long appUserCouponId; + @ApiModelProperty("车辆id") + private Long appUserCarId; + @ApiModelProperty("支付方式(1=微信,2=支付宝)") + private Integer paymentType; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java new file mode 100644 index 0000000..6dd6614 --- /dev/null +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/ChargingDetails.java @@ -0,0 +1,42 @@ +package com.ruoyi.order.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author zhibing.pu + * @Date 2024/8/21 14:09 + */ +@Data +@ApiModel +public class ChargingDetails { + @ApiModelProperty("订单id") + private String id; + @ApiModelProperty("充电电流") + private BigDecimal chargeCurrent; + @ApiModelProperty("充电电压") + private BigDecimal ChargeVoltage; + @ApiModelProperty("充电功率") + private BigDecimal ChargePower; + @ApiModelProperty("完成比例") + private Integer completionRatio; + @ApiModelProperty("续航") + private BigDecimal endurance; + @ApiModelProperty("剩余充电时间") + private Long remainingChargeTime; + @ApiModelProperty("充电枪名") + private String name; + @ApiModelProperty("订单编号") + private String code; + @ApiModelProperty("已充电度数") + private BigDecimal chargedDegrees; + @ApiModelProperty("已充电时间") + private Long chargedTime; + @ApiModelProperty("充电费用") + private BigDecimal ChargingCost; + @ApiModelProperty("充电状态(0=未知,1=等待中,2=启动中,3=充电中,4=停止中,5=已结束)") + private Integer status; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyChargingOrderList.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyChargingOrderList.java index e38ea6e..9c1613b 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyChargingOrderList.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyChargingOrderList.java @@ -21,6 +21,8 @@ private String title; @ApiModelProperty("充电度数") private BigDecimal chargingDegree; + @ApiModelProperty("充电枪id") + private Integer chargingGunId; @ApiModelProperty("充电桩枪名称") private String name; @ApiModelProperty("结束方式(0=异常终止,1=主动终止,2=满电终止,3=费用不足终止)") diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/PreChargeCheck.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/PreChargeCheck.java new file mode 100644 index 0000000..3620ddf --- /dev/null +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/PreChargeCheck.java @@ -0,0 +1,20 @@ +package com.ruoyi.order.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author zhibing.pu + * @Date 2024/8/21 13:47 + */ +@Data +@ApiModel +public class PreChargeCheck { + @ApiModelProperty("安全连接检测") + private Boolean secureConnectionDetection; + @ApiModelProperty("绝缘检测") + private Boolean insulationTesting; + @ApiModelProperty("电子锁锁止") + private Boolean electronicLockLock; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java index d4b0897..25c5c91 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java @@ -1,12 +1,10 @@ package com.ruoyi.order.service; import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.BasePage; import com.ruoyi.order.api.model.TChargingOrder; -import com.ruoyi.order.dto.GetMyChargingOrderList; -import com.ruoyi.order.dto.GetNoInvoicedOrder; -import com.ruoyi.order.dto.MyChargingOrderInfo; -import com.ruoyi.order.dto.MyChargingOrderList; +import com.ruoyi.order.dto.*; import org.springframework.web.bind.annotation.RequestBody; import java.util.List; @@ -45,4 +43,39 @@ * @return */ List<MyChargingOrderList> getNoInvoicedOrder(GetNoInvoicedOrder query); + + + /** + * 充电支付 + * @param addChargingOrder + * @return + */ + AjaxResult paymentChargingOrder(AddChargingOrder addChargingOrder); + + + /** + * 支付成功后的回调处理逻辑 + * @param paymentType 支付方式:1=微信,2=支付宝 + * @param out_trade_no 业务流水号 + * @param transaction_id 三方支付流水号 + * @param attach 附加数据 + * @return + */ + AjaxResult chargingOrderCallback(Integer paymentType, String out_trade_no, String transaction_id, String attach); + + + /** + * 获取充电中的详情 + * @param id + * @return + */ + ChargingDetails getChargingDetails(Integer id); + + + /** + * 停止充电 + * @param id + * @return + */ + AjaxResult stopCharging(String id); } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java index d22e59a..d5521a8 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java @@ -3,24 +3,33 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.account.api.feignClient.AppUserCarClient; +import com.ruoyi.account.api.feignClient.AppUserClient; +import com.ruoyi.account.api.feignClient.AppUserVipDetailClient; +import com.ruoyi.account.api.model.TAppUser; import com.ruoyi.account.api.model.TAppUserCar; +import com.ruoyi.account.api.model.TAppUserVipDetail; +import com.ruoyi.account.api.vo.GetAppUserVipDetail; import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient; import com.ruoyi.chargingPile.api.feignClient.ChargingPileClient; import com.ruoyi.chargingPile.api.feignClient.SiteClient; import com.ruoyi.chargingPile.api.model.Site; import com.ruoyi.chargingPile.api.model.TChargingGun; +import com.ruoyi.chargingPile.api.model.TChargingPile; +import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.BasePage; +import com.ruoyi.common.redis.service.RedisService; import com.ruoyi.common.security.service.TokenService; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.order.api.model.TChargingOrder; import com.ruoyi.order.api.model.TChargingOrderAccountingStrategy; -import com.ruoyi.order.dto.GetMyChargingOrderList; -import com.ruoyi.order.dto.GetNoInvoicedOrder; -import com.ruoyi.order.dto.MyChargingOrderInfo; -import com.ruoyi.order.dto.MyChargingOrderList; +import com.ruoyi.order.dto.*; import com.ruoyi.order.mapper.TChargingOrderMapper; import com.ruoyi.order.service.TChargingOrderAccountingStrategyService; import com.ruoyi.order.service.TChargingOrderService; +import com.ruoyi.payment.api.feignClient.WxPaymentClient; +import com.ruoyi.payment.api.vo.NotifyV3PayDecodeRespBody; +import com.ruoyi.payment.api.vo.PaymentOrder; +import io.seata.spring.annotation.GlobalTransactional; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -29,6 +38,7 @@ import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.stream.Collectors; /** * <p> @@ -56,6 +66,21 @@ @Resource private TokenService tokenService; + @Resource + private WxPaymentClient wxPaymentClient; + + @Resource + private ChargingPileClient chargingPileClient; + + @Resource + private AppUserClient appUserClient; + + @Resource + private AppUserVipDetailClient appUserVipDetailClient; + + @Resource + private RedisService redisService; + @@ -80,6 +105,7 @@ myChargingOrderList.setTitle(site.getName()); myChargingOrderList.setChargingDegree(tChargingOrder.getChargingCapacity()); String name = chargingGunClient.getAllName(tChargingOrder.getChargingGunId()).getData(); + myChargingOrderList.setChargingGunId(tChargingOrder.getChargingGunId()); myChargingOrderList.setName(name); myChargingOrderList.setEndMode(tChargingOrder.getEndMode()); BigDecimal payMoney = tChargingOrder.getStatus() < 4 ? tChargingOrder.getRechargeAmount() : tChargingOrder.getPaymentAmount(); @@ -167,4 +193,197 @@ } return list; } + + + /** + * 充电支付 + * @param addChargingOrder + * @return + */ + @Override + @GlobalTransactional(rollbackFor = Exception.class) + public AjaxResult paymentChargingOrder(AddChargingOrder addChargingOrder) { + Long userId = tokenService.getLoginUserApplet().getUserId(); + TAppUser appUser = appUserClient.getUserById(userId).getData(); + //查询待支付状态的订单,没有支付则删除订单 + List<TChargingOrder> list = this.list(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getAppUserId, userId) + .eq(TChargingOrder::getRechargePaymentStatus, 1).eq(TChargingOrder::getDelFlag, 0)); + for (TChargingOrder tChargingOrder : list) { + Integer rechargePaymentType = tChargingOrder.getRechargePaymentType(); + if(1 == rechargePaymentType){ + NotifyV3PayDecodeRespBody data = wxPaymentClient.queryOrderInfo(tChargingOrder.getCode()).getData(); + if(null != data){ + String trade_state = data.getTrade_state(); + //支付失败,删除无效的订单 + if(trade_state.equals("REFUND") || trade_state.equals("NOTPAY") || trade_state.equals("REVOKED") || trade_state.equals("PAYERROR")){ + this.removeById(tChargingOrder.getId()); + } + } + } + if(2 == rechargePaymentType){ + + } + } + + //检查当前枪是否是正在使用中 + TChargingOrder one = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getChargingGunId, addChargingOrder.getId()) + .in(TChargingOrder::getStatus, Arrays.asList(1, 2, 3)).eq(TChargingOrder::getDelFlag, 0)); + if(null != one){ + return AjaxResult.error("充电枪正在充电桩中,启动失败"); + } + //查询当前充电枪是否有正在支付的订单 + one = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getChargingGunId, addChargingOrder.getId()) + .eq(TChargingOrder::getAppUserCarId, userId).eq(TChargingOrder::getRechargePaymentStatus, 1).eq(TChargingOrder::getDelFlag, 0)); + if(null != one){ + //查询三方支付数据,支付中直接结束三方订单 + if(1 == one.getRechargePaymentType()){ + NotifyV3PayDecodeRespBody data = wxPaymentClient.queryOrderInfo(one.getCode()).getData(); + if(null != data){ + String trade_state = data.getTrade_state(); + //支付失败,删除无效的订单 + if(trade_state.equals("REFUND") || trade_state.equals("NOTPAY") || trade_state.equals("REVOKED") || trade_state.equals("PAYERROR")){ + this.removeById(one.getId()); + }else{ + //结束第三方支付,删除订单 + wxPaymentClient.close(one.getCode()); + this.removeById(one.getId()); + } + } + } + if(2 == one.getRechargePaymentType()){ + + } + } + + + //构建新的待支付订单 + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + TChargingOrder chargingOrder = new TChargingOrder(); + String code = "CD" + Math.random() * 1000 + sdf.format(new Date()); + chargingOrder.setCode(code); + chargingOrder.setOrderType(1); + chargingOrder.setOrderClassification(1); + chargingOrder.setAppUserId(userId); + chargingOrder.setAppUserCarId(addChargingOrder.getAppUserCarId()); + TChargingGun tChargingGun = chargingGunClient.getChargingGunById(addChargingOrder.getId()).getData(); + chargingOrder.setSiteId(tChargingGun.getSiteId()); + chargingOrder.setChargingPileId(tChargingGun.getChargingPileId()); + chargingOrder.setChargingGunId(addChargingOrder.getId()); + chargingOrder.setRechargePaymentType(addChargingOrder.getPaymentType()); + chargingOrder.setRechargePaymentStatus(1); + chargingOrder.setRechargeAmount(addChargingOrder.getPaymentAmount()); + chargingOrder.setAppCouponId(addChargingOrder.getAppUserCouponId()); + if(null != appUser.getVipId()){ + GetAppUserVipDetail getAppUserVipDetail = new GetAppUserVipDetail(); + getAppUserVipDetail.setAppUserId(appUser.getId()); + getAppUserVipDetail.setVipId(appUser.getVipId()); + TAppUserVipDetail vipDetail = appUserVipDetailClient.getAppUserVipDetail(getAppUserVipDetail).getData(); + if(null != vipDetail){ + Integer chargeNum = vipDetail.getChargeNum(); + if(0 > chargeNum){ + chargingOrder.setVipDiscount(vipDetail.getDiscount()); + BigDecimal discountAmount = addChargingOrder.getPaymentAmount().multiply((new BigDecimal(10) + .subtract(vipDetail.getDiscount())).divide(new BigDecimal(10))).setScale(4, BigDecimal.ROUND_HALF_EVEN); + chargingOrder.setVipDiscountAmount(discountAmount); + } + } + + } + this.save(chargingOrder); + //会员优惠折扣将其计入增加充电时长(增加总充电金额) + //如果充电总金额未使用完,则需要退回费用=(原金额/总金额)*(总金额-实际充电金额) + if(1 == addChargingOrder.getPaymentType()){ + PaymentOrder paymentOrder = new PaymentOrder(); + paymentOrder.setCode(chargingOrder.getCode()); + paymentOrder.setAmount(addChargingOrder.getPaymentAmount()); + paymentOrder.setOpenId(appUser.getWxOpenid()); + paymentOrder.setDescription("充电充值"); + paymentOrder.setNotifyUrl("/order/t-charging-order/chargingOrderWXCallback"); + Map<String, Object> data = wxPaymentClient.orderPay(paymentOrder).getData(); + return AjaxResult.success(data); + } + if(2 == addChargingOrder.getPaymentType()){ + + } + throw new RuntimeException("无效的支付方式"); + } + + + /** + * 支付成功后的回调处理逻辑 + * @param paymentType 支付方式:1=微信,2=支付宝 + * @param out_trade_no 业务流水号 + * @param transaction_id 三方支付流水号 + * @param attach 附加数据 + * @return + */ + @Override + public AjaxResult chargingOrderCallback(Integer paymentType, String out_trade_no, String transaction_id, String attach) { + TChargingOrder chargingOrder = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getCode, out_trade_no)); + if(chargingOrder.getRechargePaymentStatus() == 2){ + return AjaxResult.success(); + } + chargingOrder.setRechargePaymentStatus(2); + chargingOrder.setRechargeSerialNumber(transaction_id); + this.updateById(chargingOrder); + //添加安全检测数据到缓存中,每步安全检测完成后需要更新缓存数据 + PreChargeCheck preChargeCheck = new PreChargeCheck(); + preChargeCheck.setElectronicLockLock(false); + preChargeCheck.setInsulationTesting(false); + preChargeCheck.setSecureConnectionDetection(false); + String key = "AQJC_" + chargingOrder.getChargingGunId(); + redisService.setCacheObject(key, preChargeCheck); + //开始检测充电桩状,将检查状态写入缓存。检测完成后开始开启充电 + //充电结束后需要计算退款剩余金额 + // todo 需要完善 + + return AjaxResult.success(); + } + + + /** + * 获取充电中的详情 + * @param id + * @return + */ + @Override + public ChargingDetails getChargingDetails(Integer id) { + Long userId = tokenService.getLoginUserApplet().getUserId(); + TChargingOrder one = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getAppUserId, userId).eq(TChargingOrder::getChargingGunId, id) + .in(TChargingOrder::getStatus, Arrays.asList(1, 2, 3)).eq(TChargingOrder::getRechargePaymentStatus, 2).eq(TChargingOrder::getDelFlag, 0)); + if(null == one){ + return null; + } + // todo 需要完善充电实时数据 + ChargingDetails chargingDetails = new ChargingDetails(); + chargingDetails.setId(one.getId().toString()); + TChargingGun chargingGun = chargingGunClient.getChargingGunById(id).getData(); + TChargingPile chargingPile = chargingPileClient.getChargingPileById(chargingGun.getChargingPileId()).getData(); + Site site = siteClient.getSiteByIds(Arrays.asList(chargingPile.getSiteId())).getData().get(0); + chargingDetails.setName(site.getName() + "-" + chargingPile.getName()); + chargingDetails.setCode(one.getCode()); + chargingDetails.setStatus(one.getStatus()); + return chargingDetails; + } + + + /** + * 停止充电操作 + * @param id 订单id + * @return + */ + @Override + public AjaxResult stopCharging(String id) { + TChargingOrder chargingOrder = this.getById(id); + Integer status = chargingOrder.getStatus(); + if(status == 4 || status == 5){ + return AjaxResult.error("不能重复操作"); + } + chargingOrder.setStatus(4); + chargingOrder.setEndMode(1); + this.updateById(chargingOrder); + //调用硬件停止充电,停止成功后开始计算费用退款 + // todo 待完善 + return AjaxResult.success(); + } } diff --git a/ruoyi-service/ruoyi-payment/pom.xml b/ruoyi-service/ruoyi-payment/pom.xml index 639a394..cb8466b 100644 --- a/ruoyi-service/ruoyi-payment/pom.xml +++ b/ruoyi-service/ruoyi-payment/pom.xml @@ -112,6 +112,11 @@ <artifactId>joda-time</artifactId> <version>2.10.10</version> </dependency> + + <dependency> + <groupId>com.ruoyi</groupId> + <artifactId>ruoyi-api-payment</artifactId> + </dependency> </dependencies> <build> diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/controller/WxPayController.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/controller/WxPayController.java index 30c22cb..adeb678 100644 --- a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/controller/WxPayController.java +++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/controller/WxPayController.java @@ -1,9 +1,12 @@ package com.ruoyi.payment.wx.controller; import com.fasterxml.jackson.core.type.TypeReference; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.payment.api.vo.PaymentOrder; import com.ruoyi.payment.wx.enums.RefundEnum; import com.ruoyi.payment.wx.model.WxPaymentRefundModel; +import com.ruoyi.payment.wx.resp.NotifyV3PayDecodeRespBody; import com.ruoyi.payment.wx.utils.WxV3Pay; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -13,6 +16,7 @@ import javax.servlet.http.HttpServletRequest; import java.io.IOException; +import java.math.BigDecimal; import java.util.Map; import java.util.Objects; @@ -32,22 +36,22 @@ /** * 按实际修改 */ - @PostMapping("order") + @PostMapping("orderPay") @ApiOperation("订单支付") - public AjaxResult<Map<String, Object>> orderPay(@RequestParam Long orderId) { + public R<Map<String, Object>> orderPay(@RequestBody PaymentOrder paymentOrder) { // 查询订单 // 0元订单不走支付 // 价格 - Integer totalPrice = 0; + Integer totalPrice = paymentOrder.getAmount().multiply(new BigDecimal(100)).intValue(); // 生成订单号 - String orderNo = ""; + String orderNo = paymentOrder.getCode(); // 查询用户信息 用户openid - String openId = ""; + String openId = paymentOrder.getOpenId(); // 订单做修改 // 调用支付方法 - Map<String, Object> result = wxV3Pay.jsApi(orderNo, totalPrice, openId,""); + Map<String, Object> result = wxV3Pay.jsApi(orderNo, totalPrice, openId, paymentOrder.getNotifyUrl(),paymentOrder.getDescription()); log.info("支付参数:{}", result); - return AjaxResult.ok(result); + return R.ok(result); } /** @@ -80,31 +84,33 @@ * 支付回调 */ @PostMapping("pay/notify") - public void payNotify(HttpServletRequest request) throws IOException { + public R<Map<String, Object>> payNotify(HttpServletRequest request) throws Exception { try { - Map<String, Object> params = wxV3Pay.verifyNotify(request, new TypeReference<Map<String, Object>>() { - }); + Map<String, Object> params = wxV3Pay.verifyNotify(request, new TypeReference<Map<String, Object>>() {}); log.info("支付回调:{}", params); - // 商户订单号 - String tradeNo = params.get("out_trade_no").toString(); - // 交易状态 - String trade_state = params.get("trade_state").toString(); - // 交易状态描述 - String trade_state_desc = params.get("trade_state_desc").toString(); - // 微信支付订单号 - String transaction_id = params.get("transaction_id").toString(); - // 支付完成时间 - // 时间不对的话,可以调用 WxTimeUtils.toRfc3339Date(success_time)转换一下 - String success_time = params.get("success_time").toString(); - // 附加数据 - Integer attach = Integer.parseInt(params.get("attach").toString()); - // TODO 业务处理 + return R.ok(params); } catch (Exception e) { log.error("支付回调异常:{}", e, e); wxV3Pay.ack(false, e.getMessage()); + return R.fail("回调异常"); } } + + /** + * 支付回调成功后 + */ + @PostMapping("pay/ack") + public void ack(){ + try { + wxV3Pay.ack(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + /** * 退款回调 @@ -138,5 +144,25 @@ } } - + + /** + * 查询订单信息 + * @param orderId + * @return + */ + @PostMapping("query/queryOrderInfo") + public R<NotifyV3PayDecodeRespBody> queryOrderInfo(@RequestParam("orderId") String orderId){ + NotifyV3PayDecodeRespBody query = wxV3Pay.query(orderId); + return R.ok(query); + } + + + /** + * 关闭订单 + * @param outTradeNo + */ + @PostMapping("pay/close") + public void close(@RequestParam("outTradeNo") String outTradeNo){ + wxV3Pay.close(outTradeNo); + } } diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/model/WxCloseOrderModel.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/model/WxCloseOrderModel.java new file mode 100644 index 0000000..b01f282 --- /dev/null +++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/model/WxCloseOrderModel.java @@ -0,0 +1,22 @@ +package com.ruoyi.payment.wx.model; + +import lombok.*; + +import java.util.List; + +/** + * @author xiaochen + * @ClassName WxPaymentRefundModel + * @Description + */ +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@ToString +public class WxCloseOrderModel { + private String mchid; + + private String out_trade_no; +} diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/utils/WxAbstractPay.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/utils/WxAbstractPay.java index a17e3bd..dbbae3a 100644 --- a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/utils/WxAbstractPay.java +++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/utils/WxAbstractPay.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.ruoyi.common.core.utils.WebUtils; +import com.ruoyi.payment.wx.model.WxCloseOrderModel; import com.ruoyi.payment.wx.model.WxPaymentInfoModel; import com.ruoyi.payment.wx.model.WxPaymentRefundModel; import com.ruoyi.payment.wx.resp.NotifyV3PayDecodeRespBody; @@ -210,7 +211,7 @@ * @param mchid * @return */ - public abstract NotifyV3PayDecodeRespBody query(String out_trade_no, String mchid); + public abstract NotifyV3PayDecodeRespBody query(String out_trade_no); /** @@ -220,6 +221,10 @@ * @return */ public abstract Map<String, Object> refund(WxPaymentRefundModel refundModel); + + + + public abstract String close(String out_trade_no); /** * 订单退款 @@ -329,5 +334,30 @@ writer.close(); } } + + + /** + * 关闭订单 + * @param httpClient + * @param uri + * @param httpReadTimeoutMs + * @param httpConnectTimeoutMs + * @param closeModel + * @return + */ + public String close(CloseableHttpClient httpClient, + String uri, + int httpReadTimeoutMs, + int httpConnectTimeoutMs, + WxCloseOrderModel closeModel) { + String reqBody = WxJsonUtils.toJsonString(closeModel); + //请求URL + HttpEntityEnclosingRequestBase httpPost = requestPost( + uri + , httpReadTimeoutMs + , httpConnectTimeoutMs, reqBody); + String repBody = result(httpClient, httpPost); + return repBody; + } } diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/utils/WxV3Pay.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/utils/WxV3Pay.java index b76bbfd..4e01120 100644 --- a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/utils/WxV3Pay.java +++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/wx/utils/WxV3Pay.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.ruoyi.payment.wx.model.WeixinProperties; +import com.ruoyi.payment.wx.model.WxCloseOrderModel; import com.ruoyi.payment.wx.model.WxPaymentInfoModel; import com.ruoyi.payment.wx.model.WxPaymentRefundModel; import com.ruoyi.payment.wx.resp.NotifyV3PayDecodeRespBody; @@ -120,12 +121,13 @@ * @author xiaochen * @date 2022-03-22 12:47 */ - public Map<String, Object> jsApi(String tradeNo, Integer amount, String openid, String description) { + public Map<String, Object> jsApi(String tradeNo, Integer amount, String openid, String notify_url, String description) { WxPaymentInfoModel requestBody = WxPaymentInfoModel.builder() .mchid(this.config.getMchId()) .appid(this.config.getAppId()) .description(description) .out_trade_no(tradeNo) + .notify_url(notify_url) // .attach("") .amount(WxPaymentInfoModel.Amount.builder().total(amount).build()) .payer(WxPaymentInfoModel.Payer.builder().openid(openid).build()) @@ -169,15 +171,14 @@ * 订单查询 * * @param out_trade_no - * @param mchid * @return com.abl.biz.center.payment.wx.v3.NotifyV3PayDecodeRespBody * @author xiaochen * @date 2021-12-20 16:47 */ @Override - public NotifyV3PayDecodeRespBody query(String out_trade_no, String mchid) { + public NotifyV3PayDecodeRespBody query(String out_trade_no) { String url = - String.format("/v3/pay/transactions/out-trade-no/%s", out_trade_no) + String.format("?mchid=%s", mchid); + String.format("/v3/pay/transactions/out-trade-no/%s", out_trade_no) + String.format("?mchid=%s", this.getConfig().getMchId()); return query(this.httpClient, this.config.getHttpReadTimeoutMs(), this.config.getHttpConnectTimeoutMs(), url); } @@ -193,5 +194,18 @@ // refundModel.setNotify_url(this.config.getV3().getNotifyRefundUrl()); return refund(this.httpClient, "/v3/refund/domestic/refunds", this.config.getHttpReadTimeoutMs(), this.config.getHttpConnectTimeoutMs(), refundModel); } - + + + /** + * 关闭订单 + * @param out_trade_no + * @return + */ + @Override + public String close(String out_trade_no) { + String uri = String.format("/v3/pay/transactions/out-trade-no/%s/close", out_trade_no); + WxCloseOrderModel wxCloseOrderModel = new WxCloseOrderModel(); + wxCloseOrderModel.setMchid(this.config.getMchId()); + return close(this.httpClient, uri, this.config.getHttpReadTimeoutMs(), this.config.getHttpConnectTimeoutMs(), wxCloseOrderModel); + } } -- Gitblit v1.7.1