12 files modified
33 files added
| New file |
| | |
| | | package org.springblade.common.config; |
| | | |
| | | import lombok.Data; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | @Configuration |
| | | @ConfigurationProperties(prefix = "wxmini") //读取wxmini节点 |
| | | @Data //使用set方法将wxpay节点中的值填充到当前类的属性中 |
| | | @Slf4j |
| | | public class WxMiniConfig { |
| | | |
| | | // appid |
| | | private String appid; |
| | | |
| | | // 小程序appSecret key |
| | | private String secret; |
| | | |
| | | private String jscode2sessionUrl; |
| | | } |
| | |
| | | import java.security.PrivateKey; |
| | | |
| | | |
| | | //@Configuration |
| | | @Configuration |
| | | // @PropertySource("classpath:wxpay.properties") //读取配置文件 |
| | | //@ConfigurationProperties(prefix = "wxpay") //读取wxpay节点 |
| | | @ConfigurationProperties(prefix = "wxpay") //读取wxpay节点 |
| | | @Data //使用set方法将wxpay节点中的值填充到当前类的属性中 |
| | | @Slf4j |
| | | public class WxPayConfig { |
| | |
| | | * |
| | | * @return |
| | | */ |
| | | // @Bean |
| | | public ScheduledUpdateCertificatesVerifier getVerifier(String privateKeyPath, String mchSerialNo, String mchId, String apiV3Key) { |
| | | @Bean |
| | | public ScheduledUpdateCertificatesVerifier getVerifier() { |
| | | |
| | | log.info("获取签名验证器"); |
| | | |
| | |
| | | * @param verifier |
| | | * @return |
| | | */ |
| | | // @Bean(name = "wxPayClient") |
| | | public CloseableHttpClient getWxPayClient(String privateKeyPath, String mchSerialNo, String mchId, String apiV3Key) { |
| | | @Bean(name = "wxPayClient") |
| | | public CloseableHttpClient getWxPayClient(ScheduledUpdateCertificatesVerifier verifier) { |
| | | |
| | | log.info("获取httpClient"); |
| | | |
| | |
| | | |
| | | WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create() |
| | | .withMerchant(mchId, mchSerialNo, privateKey) |
| | | .withValidator(new WechatPay2Validator(getVerifier(privateKeyPath, mchSerialNo, mchId, apiV3Key))); |
| | | .withValidator(new WechatPay2Validator(verifier)); |
| | | // ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient |
| | | |
| | | // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新 |
| | |
| | | return httpClient; |
| | | } |
| | | |
| | | /** |
| | | * 获取HttpClient,无需进行应答签名验证,跳过验签的流程 |
| | | */ |
| | | @Bean(name = "wxPayNoSignClient") |
| | | public CloseableHttpClient getWxPayNoSignClient() { |
| | | |
| | | //获取商户私钥 |
| | | PrivateKey privateKey = getPrivateKey(privateKeyPath); |
| | | |
| | | //用于构造HttpClient |
| | | WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create() |
| | | //设置商户信息 |
| | | .withMerchant(mchId, mchSerialNo, privateKey) |
| | | //无需进行签名验证、通过withValidator((response) -> true)实现 |
| | | .withValidator((response) -> true); |
| | | |
| | | // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新 |
| | | CloseableHttpClient httpClient = builder.build(); |
| | | |
| | | log.info("== getWxPayNoSignClient END =="); |
| | | |
| | | return httpClient; |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | |
| | | /** |
| | | * 退款结果通知 |
| | | */ |
| | | REFUND_NOTIFY("/wxPay/refunds/notify"); |
| | | REFUND_NOTIFY("/wxPay/refunds/notify"), |
| | | |
| | | /** |
| | | * 添加分账接收方API |
| | | */ |
| | | RECEIVERS_ADD("/v3/profitsharing/receivers/add"), |
| | | |
| | | /** |
| | | * 创建分账订单API |
| | | * |
| | | */ |
| | | PROFITSHARING_ORDERS("/v3/profitsharing/orders"); |
| | | |
| | | /** |
| | | * 类型 |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.controller; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import io.swagger.annotations.ApiParam; |
| | | import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; |
| | | import lombok.AllArgsConstructor; |
| | | import javax.validation.Valid; |
| | | |
| | | import org.springblade.core.mp.support.Condition; |
| | | import org.springblade.core.mp.support.Query; |
| | | import org.springblade.core.tool.api.R; |
| | | import org.springblade.core.tool.utils.Func; |
| | | import org.springblade.modules.pay.entity.OrderInfoEntity; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import org.springblade.modules.pay.vo.OrderInfoVO; |
| | | import org.springblade.modules.pay.wrapper.OrderInfoWrapper; |
| | | import org.springblade.modules.pay.service.IOrderInfoService; |
| | | import org.springblade.core.boot.ctrl.BladeController; |
| | | |
| | | /** |
| | | * 订单信息 控制器 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @RestController |
| | | @AllArgsConstructor |
| | | @RequestMapping("blade-orderInfo/orderInfo") |
| | | @Api(value = "订单信息", tags = "订单信息接口") |
| | | public class OrderInfoController extends BladeController { |
| | | |
| | | private final IOrderInfoService orderInfoService; |
| | | |
| | | /** |
| | | * 订单信息 详情 |
| | | */ |
| | | @GetMapping("/detail") |
| | | @ApiOperationSupport(order = 1) |
| | | @ApiOperation(value = "详情", notes = "传入orderInfo") |
| | | public R<OrderInfoVO> detail(OrderInfoEntity orderInfo) { |
| | | OrderInfoEntity detail = orderInfoService.getOne(Condition.getQueryWrapper(orderInfo)); |
| | | return R.data(OrderInfoWrapper.build().entityVO(detail)); |
| | | } |
| | | /** |
| | | * 订单信息 分页 |
| | | */ |
| | | @GetMapping("/list") |
| | | @ApiOperationSupport(order = 2) |
| | | @ApiOperation(value = "分页", notes = "传入orderInfo") |
| | | public R<IPage<OrderInfoVO>> list(OrderInfoEntity orderInfo, Query query) { |
| | | IPage<OrderInfoEntity> pages = orderInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(orderInfo)); |
| | | return R.data(OrderInfoWrapper.build().pageVO(pages)); |
| | | } |
| | | |
| | | /** |
| | | * 订单信息 自定义分页 |
| | | */ |
| | | @GetMapping("/page") |
| | | @ApiOperationSupport(order = 3) |
| | | @ApiOperation(value = "分页", notes = "传入orderInfo") |
| | | public R<IPage<OrderInfoVO>> page(OrderInfoVO orderInfo, Query query) { |
| | | IPage<OrderInfoVO> pages = orderInfoService.selectOrderInfoPage(Condition.getPage(query), orderInfo); |
| | | return R.data(pages); |
| | | } |
| | | |
| | | /** |
| | | * 订单信息 新增 |
| | | */ |
| | | @PostMapping("/save") |
| | | @ApiOperationSupport(order = 4) |
| | | @ApiOperation(value = "新增", notes = "传入orderInfo") |
| | | public R save(@Valid @RequestBody OrderInfoEntity orderInfo) { |
| | | return R.status(orderInfoService.save(orderInfo)); |
| | | } |
| | | |
| | | /** |
| | | * 创建订单信息 |
| | | */ |
| | | @PostMapping("/save") |
| | | @ApiOperationSupport(order = 4) |
| | | @ApiOperation(value = "新增", notes = "传入orderInfo") |
| | | public R save(@RequestParam Long propertyChargeRecordId) { |
| | | return R.data(orderInfoService.createOrderByPropertyChargeRecordId(propertyChargeRecordId)); |
| | | } |
| | | |
| | | /** |
| | | * 订单信息 修改 |
| | | */ |
| | | @PostMapping("/update") |
| | | @ApiOperationSupport(order = 5) |
| | | @ApiOperation(value = "修改", notes = "传入orderInfo") |
| | | public R update(@Valid @RequestBody OrderInfoEntity orderInfo) { |
| | | return R.status(orderInfoService.updateById(orderInfo)); |
| | | } |
| | | |
| | | /** |
| | | * 订单信息 新增或修改 |
| | | */ |
| | | @PostMapping("/submit") |
| | | @ApiOperationSupport(order = 6) |
| | | @ApiOperation(value = "新增或修改", notes = "传入orderInfo") |
| | | public R submit(@Valid @RequestBody OrderInfoEntity orderInfo) { |
| | | return R.status(orderInfoService.saveOrUpdate(orderInfo)); |
| | | } |
| | | |
| | | /** |
| | | * 订单信息 删除 |
| | | */ |
| | | @PostMapping("/remove") |
| | | @ApiOperationSupport(order = 7) |
| | | @ApiOperation(value = "逻辑删除", notes = "传入ids") |
| | | public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) { |
| | | return R.status(orderInfoService.removeBatchByIds(Func.toLongList(ids))); |
| | | } |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.controller; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import io.swagger.annotations.ApiParam; |
| | | import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; |
| | | import lombok.AllArgsConstructor; |
| | | import javax.validation.Valid; |
| | | |
| | | import org.springblade.core.mp.support.Condition; |
| | | import org.springblade.core.mp.support.Query; |
| | | import org.springblade.core.tool.api.R; |
| | | import org.springblade.core.tool.utils.Func; |
| | | import org.springblade.modules.pay.entity.PaymentInfoEntity; |
| | | import org.springblade.modules.pay.vo.PaymentInfoVO; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import org.springblade.modules.pay.wrapper.PaymentInfoWrapper; |
| | | import org.springblade.modules.pay.service.IPaymentInfoService; |
| | | import org.springblade.core.boot.ctrl.BladeController; |
| | | |
| | | /** |
| | | * 支付信息 控制器 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @RestController |
| | | @AllArgsConstructor |
| | | @RequestMapping("blade-paymentInfo/paymentInfo") |
| | | @Api(value = "支付信息", tags = "支付信息接口") |
| | | public class PaymentInfoController extends BladeController { |
| | | |
| | | private final IPaymentInfoService paymentInfoService; |
| | | |
| | | /** |
| | | * 支付信息 详情 |
| | | */ |
| | | @GetMapping("/detail") |
| | | @ApiOperationSupport(order = 1) |
| | | @ApiOperation(value = "详情", notes = "传入paymentInfo") |
| | | public R<PaymentInfoVO> detail(PaymentInfoEntity paymentInfo) { |
| | | PaymentInfoEntity detail = paymentInfoService.getOne(Condition.getQueryWrapper(paymentInfo)); |
| | | return R.data(PaymentInfoWrapper.build().entityVO(detail)); |
| | | } |
| | | /** |
| | | * 支付信息 分页 |
| | | */ |
| | | @GetMapping("/list") |
| | | @ApiOperationSupport(order = 2) |
| | | @ApiOperation(value = "分页", notes = "传入paymentInfo") |
| | | public R<IPage<PaymentInfoVO>> list(PaymentInfoEntity paymentInfo, Query query) { |
| | | IPage<PaymentInfoEntity> pages = paymentInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(paymentInfo)); |
| | | return R.data(PaymentInfoWrapper.build().pageVO(pages)); |
| | | } |
| | | |
| | | /** |
| | | * 支付信息 自定义分页 |
| | | */ |
| | | @GetMapping("/page") |
| | | @ApiOperationSupport(order = 3) |
| | | @ApiOperation(value = "分页", notes = "传入paymentInfo") |
| | | public R<IPage<PaymentInfoVO>> page(PaymentInfoVO paymentInfo, Query query) { |
| | | IPage<PaymentInfoVO> pages = paymentInfoService.selectPaymentInfoPage(Condition.getPage(query), paymentInfo); |
| | | return R.data(pages); |
| | | } |
| | | |
| | | /** |
| | | * 支付信息 新增 |
| | | */ |
| | | @PostMapping("/save") |
| | | @ApiOperationSupport(order = 4) |
| | | @ApiOperation(value = "新增", notes = "传入paymentInfo") |
| | | public R save(@Valid @RequestBody PaymentInfoEntity paymentInfo) { |
| | | return R.status(paymentInfoService.save(paymentInfo)); |
| | | } |
| | | |
| | | /** |
| | | * 支付信息 修改 |
| | | */ |
| | | @PostMapping("/update") |
| | | @ApiOperationSupport(order = 5) |
| | | @ApiOperation(value = "修改", notes = "传入paymentInfo") |
| | | public R update(@Valid @RequestBody PaymentInfoEntity paymentInfo) { |
| | | return R.status(paymentInfoService.updateById(paymentInfo)); |
| | | } |
| | | |
| | | /** |
| | | * 支付信息 新增或修改 |
| | | */ |
| | | @PostMapping("/submit") |
| | | @ApiOperationSupport(order = 6) |
| | | @ApiOperation(value = "新增或修改", notes = "传入paymentInfo") |
| | | public R submit(@Valid @RequestBody PaymentInfoEntity paymentInfo) { |
| | | return R.status(paymentInfoService.saveOrUpdate(paymentInfo)); |
| | | } |
| | | |
| | | /** |
| | | * 支付信息 删除 |
| | | */ |
| | | @PostMapping("/remove") |
| | | @ApiOperationSupport(order = 7) |
| | | @ApiOperation(value = "逻辑删除", notes = "传入ids") |
| | | public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) { |
| | | return R.status(paymentInfoService.removeBatchByIds(Func.toLongList(ids))); |
| | | } |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.controller; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import io.swagger.annotations.ApiParam; |
| | | import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; |
| | | import lombok.AllArgsConstructor; |
| | | import javax.validation.Valid; |
| | | |
| | | import org.springblade.core.mp.support.Condition; |
| | | import org.springblade.core.mp.support.Query; |
| | | import org.springblade.core.tool.api.R; |
| | | import org.springblade.core.tool.utils.Func; |
| | | import org.springblade.modules.pay.entity.RefundInfoEntity; |
| | | import org.springblade.modules.pay.service.IRefundInfoService; |
| | | import org.springblade.modules.pay.vo.RefundInfoVO; |
| | | import org.springblade.modules.pay.wrapper.RefundInfoWrapper; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import org.springblade.core.boot.ctrl.BladeController; |
| | | |
| | | /** |
| | | * 退款信息 控制器 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @RestController |
| | | @AllArgsConstructor |
| | | @RequestMapping("blade-refundInfo/refundInfo") |
| | | @Api(value = "退款信息", tags = "退款信息接口") |
| | | public class RefundInfoController extends BladeController { |
| | | |
| | | private final IRefundInfoService refundInfoService; |
| | | |
| | | /** |
| | | * 退款信息 详情 |
| | | */ |
| | | @GetMapping("/detail") |
| | | @ApiOperationSupport(order = 1) |
| | | @ApiOperation(value = "详情", notes = "传入refundInfo") |
| | | public R<RefundInfoVO> detail(RefundInfoEntity refundInfo) { |
| | | RefundInfoEntity detail = refundInfoService.getOne(Condition.getQueryWrapper(refundInfo)); |
| | | return R.data(RefundInfoWrapper.build().entityVO(detail)); |
| | | } |
| | | /** |
| | | * 退款信息 分页 |
| | | */ |
| | | @GetMapping("/list") |
| | | @ApiOperationSupport(order = 2) |
| | | @ApiOperation(value = "分页", notes = "传入refundInfo") |
| | | public R<IPage<RefundInfoVO>> list(RefundInfoEntity refundInfo, Query query) { |
| | | IPage<RefundInfoEntity> pages = refundInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(refundInfo)); |
| | | return R.data(RefundInfoWrapper.build().pageVO(pages)); |
| | | } |
| | | |
| | | /** |
| | | * 退款信息 自定义分页 |
| | | */ |
| | | @GetMapping("/page") |
| | | @ApiOperationSupport(order = 3) |
| | | @ApiOperation(value = "分页", notes = "传入refundInfo") |
| | | public R<IPage<RefundInfoVO>> page(RefundInfoVO refundInfo, Query query) { |
| | | IPage<RefundInfoVO> pages = refundInfoService.selectRefundInfoPage(Condition.getPage(query), refundInfo); |
| | | return R.data(pages); |
| | | } |
| | | |
| | | /** |
| | | * 退款信息 新增 |
| | | */ |
| | | @PostMapping("/save") |
| | | @ApiOperationSupport(order = 4) |
| | | @ApiOperation(value = "新增", notes = "传入refundInfo") |
| | | public R save(@Valid @RequestBody RefundInfoEntity refundInfo) { |
| | | return R.status(refundInfoService.save(refundInfo)); |
| | | } |
| | | |
| | | /** |
| | | * 退款信息 修改 |
| | | */ |
| | | @PostMapping("/update") |
| | | @ApiOperationSupport(order = 5) |
| | | @ApiOperation(value = "修改", notes = "传入refundInfo") |
| | | public R update(@Valid @RequestBody RefundInfoEntity refundInfo) { |
| | | return R.status(refundInfoService.updateById(refundInfo)); |
| | | } |
| | | |
| | | /** |
| | | * 退款信息 新增或修改 |
| | | */ |
| | | @PostMapping("/submit") |
| | | @ApiOperationSupport(order = 6) |
| | | @ApiOperation(value = "新增或修改", notes = "传入refundInfo") |
| | | public R submit(@Valid @RequestBody RefundInfoEntity refundInfo) { |
| | | return R.status(refundInfoService.saveOrUpdate(refundInfo)); |
| | | } |
| | | |
| | | /** |
| | | * 退款信息 删除 |
| | | */ |
| | | @PostMapping("/remove") |
| | | @ApiOperationSupport(order = 7) |
| | | @ApiOperation(value = "逻辑删除", notes = "传入ids") |
| | | public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) { |
| | | return R.status(refundInfoService.removeBatchByIds(Func.toLongList(ids))); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | package org.springblade.modules.pay.controller; |
| | | |
| | | import com.google.gson.Gson; |
| | | import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.AllArgsConstructor; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springblade.common.config.WxPayConfig; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.common.utils.HttpUtils; |
| | | import org.springblade.common.utils.WechatPay2ValidatorForRequest; |
| | | import org.springblade.core.boot.ctrl.BladeController; |
| | | import org.springblade.core.tool.api.R; |
| | | import org.springblade.modules.pay.entity.WxPayInfo; |
| | | import org.springblade.modules.pay.service.IWxPayService; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | @CrossOrigin //跨域 |
| | | @RestController |
| | | @AllArgsConstructor |
| | | @RequestMapping("/wxpay") |
| | | @Api(value = "微信支付接口", tags = "微信支付接口") |
| | | public class WxPayController extends BladeController { |
| | | @RequestMapping("/wxPay") |
| | | @Api(tags = "网站微信支付APIv3") |
| | | @Slf4j |
| | | public class WxPayController { |
| | | |
| | | private static final Logger logger = LoggerFactory.getLogger(WxPayController.class); |
| | | |
| | | @Resource |
| | | private IWxPayService wxPayService; |
| | | |
| | | |
| | | @PostMapping("/save") |
| | | public R save(@RequestBody WxPayInfo wxPayInfo) { |
| | |
| | | return R.data(wxPayService.getOpenId(code)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * jsapi下单 |
| | | * |
| | | * @param productId |
| | | * @param properChargeRecordId |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | @ApiOperation("调用jsapi统一下单API") |
| | | @GetMapping("/jsapiPay") |
| | | public R jsapiPay(@RequestParam("productId") Long productId) throws Exception { |
| | | public R jsapiPay(@RequestParam("properChargeRecordId") Long properChargeRecordId) throws Exception { |
| | | |
| | | logger.info("发起支付请求 v3"); |
| | | log.info("发起支付请求 v3"); |
| | | |
| | | //返回支付二维码连接和订单号 |
| | | Map<String, String> map = wxPayService.jsapiPay(productId); |
| | | Map<String, String> map = wxPayService.jsapiPay(properChargeRecordId); |
| | | |
| | | return R.data(map); |
| | | } |
| | |
| | | @ApiOperation("支付通知") |
| | | @PostMapping("/native/notify") |
| | | public String nativeNotify(HttpServletRequest request, HttpServletResponse response) { |
| | | return wxPayService.nativeNotify(request, response); |
| | | } |
| | | |
| | | Gson gson = new Gson(); |
| | | Map<String, String> map = new HashMap<>();//应答对象 |
| | | /** |
| | | * 用户取消订单 |
| | | * |
| | | * @param orderNo |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | @ApiOperation("用户取消订单") |
| | | @PostMapping("/cancel/{orderNo}") |
| | | public R cancel(@PathVariable String orderNo) throws Exception { |
| | | |
| | | try { |
| | | log.info("取消订单"); |
| | | |
| | | //处理通知参数 |
| | | String body = HttpUtils.readData(request); |
| | | Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class); |
| | | String requestId = (String) bodyMap.get("id"); |
| | | logger.info("支付通知的id ===> {}", requestId); |
| | | logger.info("支付通知的完整数据 ===> {}", body); |
| | | //int a = 9 / 0; |
| | | ScheduledUpdateCertificatesVerifier verifier = new WxPayConfig().getVerifier("111", "111", "111", "111"); |
| | | //签名的验证 |
| | | WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest |
| | | = new WechatPay2ValidatorForRequest(verifier, requestId, body); |
| | | if (!wechatPay2ValidatorForRequest.validate(request)) { |
| | | logger.error("通知验签失败"); |
| | | //失败应答 |
| | | response.setStatus(500); |
| | | map.put("code", "ERROR"); |
| | | map.put("message", "通知验签失败"); |
| | | return gson.toJson(map); |
| | | } |
| | | logger.info("通知验签成功"); |
| | | wxPayService.cancelOrder(orderNo); |
| | | return R.data("订单已取消"); |
| | | } |
| | | |
| | | //处理订单 |
| | | wxPayService.processOrder(bodyMap); |
| | | /** |
| | | * 查询订单 |
| | | * |
| | | * @param orderNo |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | @ApiOperation("查询订单") |
| | | @GetMapping("/query/{orderNo}") |
| | | public R queryOrder(@PathVariable String orderNo) throws Exception { |
| | | |
| | | //应答超时 |
| | | //模拟接收微信端的重复通知 |
| | | // TimeUnit.SECONDS.sleep(5); |
| | | log.info("查询订单"); |
| | | |
| | | //成功应答 |
| | | response.setStatus(200); |
| | | map.put("code", "SUCCESS"); |
| | | map.put("message", "成功"); |
| | | return gson.toJson(map); |
| | | String result = wxPayService.queryOrder(orderNo); |
| | | return R.data("result", result); |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | //失败应答 |
| | | response.setStatus(500); |
| | | map.put("code", "ERROR"); |
| | | map.put("message", "失败"); |
| | | return gson.toJson(map); |
| | | } |
| | | } |
| | | |
| | | |
| | | @ApiOperation("申请退款") |
| | | @PostMapping("/refunds/{orderNo}/{reason}") |
| | | public R refunds(@PathVariable String orderNo, @PathVariable String reason) throws Exception { |
| | | |
| | | log.info("申请退款"); |
| | | wxPayService.refund(orderNo, reason); |
| | | return R.success("退款申请成功"); |
| | | } |
| | | |
| | | /** |
| | | * 查询退款 |
| | | * |
| | | * @param refundNo |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | @ApiOperation("查询退款") |
| | | @GetMapping("/query-refund/{refundNo}") |
| | | public R queryRefund(@PathVariable String refundNo) throws Exception { |
| | | |
| | | log.info("查询退款"); |
| | | |
| | | String result = wxPayService.queryRefund(refundNo); |
| | | return R.data("result", result); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 退款结果通知 |
| | | * 退款状态改变后,微信会把相关退款结果发送给商户。 |
| | | */ |
| | | @ApiOperation("退款结果通知") |
| | | @PostMapping("/refunds/notify") |
| | | public String refundsNotify(HttpServletRequest request, HttpServletResponse response) { |
| | | |
| | | log.info("退款通知执行"); |
| | | return wxPayService.refundsNotify(request, response); |
| | | } |
| | | |
| | | |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.dto; |
| | | |
| | | import org.springblade.modules.pay.entity.OrderInfoEntity; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 订单信息 数据传输对象实体类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class OrderInfoDTO extends OrderInfoEntity { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.dto; |
| | | |
| | | import org.springblade.modules.pay.entity.PaymentInfoEntity; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 支付信息 数据传输对象实体类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class PaymentInfoDTO extends PaymentInfoEntity { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.dto; |
| | | |
| | | import org.springblade.modules.pay.entity.RefundInfoEntity; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 退款信息 数据传输对象实体类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class RefundInfoDTO extends RefundInfoEntity { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.entity; |
| | | |
| | | 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; |
| | | import lombok.Data; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.springblade.core.tenant.mp.TenantEntity; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 订单信息 实体类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Data |
| | | @TableName("jczz_order_info") |
| | | @ApiModel(value = "OrderInfo对象", description = "订单信息") |
| | | public class OrderInfoEntity { |
| | | |
| | | |
| | | /** id */ |
| | | @ApiModelProperty(value = "主键ID", example = "") |
| | | @TableId(value = "id", type = IdType.ASSIGN_ID) |
| | | private Long id; |
| | | |
| | | /** 订单标题 */ |
| | | @ApiModelProperty(value = "订单标题", example = "") |
| | | @TableField("title") |
| | | private String title; |
| | | |
| | | /** 商户订单编号 */ |
| | | @ApiModelProperty(value = "商户订单编号", example = "") |
| | | @TableField("order_no") |
| | | private String orderNo; |
| | | |
| | | /** 用户id */ |
| | | @ApiModelProperty(value = "用户id", example = "") |
| | | @TableField("user_id") |
| | | private Long userId; |
| | | |
| | | /** 支付产品id */ |
| | | @ApiModelProperty(value = "支付产品id", example = "") |
| | | @TableField("proper_charge_record_id") |
| | | private Long properChargeRecordId; |
| | | |
| | | /** 订单二维码连接 */ |
| | | @ApiModelProperty(value = "订单二维码连接", example = "") |
| | | @TableField("code_url") |
| | | private String codeUrl; |
| | | |
| | | /** 订单金额(分) */ |
| | | @ApiModelProperty(value = "订单金额(分)", example = "") |
| | | @TableField("total_fee") |
| | | private Integer totalFee; |
| | | |
| | | /** 订单状态 */ |
| | | @ApiModelProperty(value = "订单状态", example = "") |
| | | @TableField("order_status") |
| | | private String orderStatus; |
| | | |
| | | /** 创建时间 */ |
| | | @ApiModelProperty(value = "创建时间", example = "") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("create_time") |
| | | private Date createTime; |
| | | |
| | | /** 更新时间 */ |
| | | @ApiModelProperty(value = "更新时间", example = "") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("update_time") |
| | | private Date updateTime; |
| | | |
| | | /** 物业id */ |
| | | @ApiModelProperty(value = "物业id", example = "") |
| | | @TableId("proper_id") |
| | | private Long properId; |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.entity; |
| | | |
| | | 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; |
| | | import lombok.Data; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.springblade.core.tenant.mp.TenantEntity; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 支付信息 实体类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Data |
| | | @TableName("jczz_payment_info") |
| | | @ApiModel(value = "PaymentInfo对象", description = "支付信息") |
| | | public class PaymentInfoEntity { |
| | | |
| | | |
| | | /** id */ |
| | | @ApiModelProperty(value = "主键ID", example = "") |
| | | @TableId(value = "id", type = IdType.ASSIGN_ID) |
| | | private Long id; |
| | | |
| | | /** 订单编号 */ |
| | | @ApiModelProperty(value = "订单编号", example = "") |
| | | @TableField("order_no") |
| | | private String orderNo; |
| | | |
| | | /** 支付系统交易编号 */ |
| | | @ApiModelProperty(value = "支付系统交易编号", example = "") |
| | | @TableField("transaction_id") |
| | | private String transactionId; |
| | | |
| | | /** 支付类型 */ |
| | | @ApiModelProperty(value = "支付类型", example = "") |
| | | @TableField("payment_type") |
| | | private String paymentType; |
| | | |
| | | /** 交易类型 */ |
| | | @ApiModelProperty(value = "交易类型", example = "") |
| | | @TableField("trade_type") |
| | | private String tradeType; |
| | | |
| | | /** 交易状态 */ |
| | | @ApiModelProperty(value = "交易状态", example = "") |
| | | @TableField("trade_state") |
| | | private String tradeState; |
| | | |
| | | /** 支付金额(分) */ |
| | | @ApiModelProperty(value = "支付金额(分)", example = "") |
| | | @TableField("payer_total") |
| | | private Integer payerTotal; |
| | | |
| | | /** 通知参数 */ |
| | | @ApiModelProperty(value = "通知参数", example = "") |
| | | @TableField("content") |
| | | private String content; |
| | | |
| | | /** 创建时间 */ |
| | | @ApiModelProperty(value = "创建时间", example = "") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("create_time") |
| | | private Date createTime; |
| | | |
| | | /** 更新时间 */ |
| | | @ApiModelProperty(value = "更新时间", example = "") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("update_time") |
| | | private Date updateTime; |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.springblade.core.tenant.mp.TenantEntity; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 退款信息 实体类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Data |
| | | @TableName("jczz_refund_info") |
| | | @ApiModel(value = "RefundInfo对象", description = "退款信息") |
| | | public class RefundInfoEntity { |
| | | |
| | | /** id */ |
| | | @ApiModelProperty(value = "主键ID", example = "") |
| | | @TableId(value = "id", type = IdType.ASSIGN_ID) |
| | | private Long id; |
| | | |
| | | /** 订单编号 */ |
| | | @ApiModelProperty(value = "订单编号", example = "") |
| | | @TableField("order_no") |
| | | private String orderNo; |
| | | |
| | | /** 退款单编号 */ |
| | | @ApiModelProperty(value = "退款单编号", example = "") |
| | | @TableField("refund_no") |
| | | private String refundNo; |
| | | |
| | | /** 支付系统退款单号 */ |
| | | @ApiModelProperty(value = "支付系统退款单号", example = "") |
| | | @TableField("refund_id") |
| | | private String refundId; |
| | | |
| | | /** 原订单金额(分) */ |
| | | @ApiModelProperty(value = "原订单金额(分)", example = "") |
| | | @TableField("total_fee") |
| | | private Integer totalFee; |
| | | |
| | | /** 退款金额(分) */ |
| | | @ApiModelProperty(value = "退款金额(分)", example = "") |
| | | @TableField("refund") |
| | | private Integer refund; |
| | | |
| | | /** 退款原因 */ |
| | | @ApiModelProperty(value = "退款原因", example = "") |
| | | @TableField("reason") |
| | | private String reason; |
| | | |
| | | /** 退款单状态 */ |
| | | @ApiModelProperty(value = "退款单状态", example = "") |
| | | @TableField("refund_status") |
| | | private String refundStatus; |
| | | |
| | | /** 申请退款返回参数 */ |
| | | @ApiModelProperty(value = "申请退款返回参数", example = "") |
| | | @TableField("content_return") |
| | | private String contentReturn; |
| | | |
| | | /** 退款结果通知参数 */ |
| | | @ApiModelProperty(value = "退款结果通知参数", example = "") |
| | | @TableField("content_notify") |
| | | private String contentNotify; |
| | | |
| | | /** 创建时间 */ |
| | | @ApiModelProperty(value = "创建时间", example = "") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField(value = "create_time",fill = FieldFill.INSERT) |
| | | private Date createTime; |
| | | |
| | | /** 更新时间 */ |
| | | @ApiModelProperty(value = "更新时间", example = "") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField(value = "update_time",fill = FieldFill.UPDATE) |
| | | private Date updateTime; |
| | | |
| | | } |
| New file |
| | |
| | | package org.springblade.modules.pay.entity; |
| | | |
| | | import com.alibaba.fastjson.annotation.JSONField; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @Accessors(chain = true) |
| | | @ApiModel(value="WeChatMiniAuthorizeVo对象", description="微信小程序用户授权返回数据") |
| | | public class WeChatMiniAuthorizeVo implements Serializable { |
| | | |
| | | private static final long serialVersionUID=1L; |
| | | |
| | | @ApiModelProperty(value = "会话密钥") |
| | | @JSONField(name = "session_key") |
| | | private String sessionKey; |
| | | |
| | | @ApiModelProperty(value = "用户唯一标识") |
| | | @JSONField(name = "openid") |
| | | private String openId; |
| | | |
| | | @ApiModelProperty(value = "用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回") |
| | | @JSONField(name = "unionid") |
| | | private String unionId; |
| | | |
| | | @ApiModelProperty(value = "错误码") |
| | | @JSONField(name = "errcode") |
| | | private String errCode; |
| | | |
| | | @ApiModelProperty(value = "错误信息") |
| | | @JSONField(name = "errmsg") |
| | | private String errMsg; |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.mapper; |
| | | |
| | | import org.springblade.modules.pay.entity.OrderInfoEntity; |
| | | import org.springblade.modules.pay.vo.OrderInfoVO; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 订单信息 Mapper 接口 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | public interface OrderInfoMapper extends BaseMapper<OrderInfoEntity> { |
| | | |
| | | /** |
| | | * 自定义分页 |
| | | * |
| | | * @param page |
| | | * @param orderInfo |
| | | * @return |
| | | */ |
| | | List<OrderInfoVO> selectOrderInfoPage(IPage page, OrderInfoVO orderInfo); |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="org.springblade.modules.pay.mapper.OrderInfoMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="orderInfoResultMap" type="org.springblade.modules.pay.entity.OrderInfoEntity"> |
| | | </resultMap> |
| | | |
| | | |
| | | <select id="selectOrderInfoPage" resultMap="orderInfoResultMap"> |
| | | select * from jczz_order_info where is_deleted = 0 |
| | | </select> |
| | | |
| | | |
| | | </mapper> |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.mapper; |
| | | |
| | | import org.springblade.modules.pay.dto.PaymentInfoDTO; |
| | | import org.springblade.modules.pay.entity.PaymentInfoEntity; |
| | | import org.springblade.modules.pay.vo.PaymentInfoVO; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 支付信息 Mapper 接口 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | public interface PaymentInfoMapper extends BaseMapper<PaymentInfoEntity> { |
| | | |
| | | /** |
| | | * 自定义分页 |
| | | * |
| | | * @param page |
| | | * @param paymentInfo |
| | | * @return |
| | | */ |
| | | List<PaymentInfoVO> selectPaymentInfoPage(IPage page, PaymentInfoVO paymentInfo); |
| | | |
| | | |
| | | /** |
| | | * 查询支付信息 |
| | | * |
| | | * @param id 支付信息ID |
| | | * @return 支付信息 |
| | | */ |
| | | public PaymentInfoDTO selectPaymentInfoById(Long id); |
| | | |
| | | /** |
| | | * 查询支付信息列表 |
| | | * |
| | | * @param paymentInfoDTO 支付信息 |
| | | * @return 支付信息集合 |
| | | */ |
| | | public List<PaymentInfoDTO> selectPaymentInfoList(PaymentInfoDTO paymentInfoDTO); |
| | | } |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="org.springblade.modules.pay.mapper.PaymentInfoMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="paymentInfoResultMap" type="org.springblade.modules.pay.entity.PaymentInfoEntity"> |
| | | </resultMap> |
| | | |
| | | |
| | | <select id="selectPaymentInfoPage" resultMap="paymentInfoResultMap"> |
| | | select * from jczz_payment_info where is_deleted = 0 |
| | | </select> |
| | | |
| | | <resultMap type="org.springblade.modules.pay.dto.PaymentInfoDTO" id="PaymentInfoDTOResult"> |
| | | <result property="id" column="id" /> |
| | | <result property="orderNo" column="order_no" /> |
| | | <result property="transactionId" column="transaction_id" /> |
| | | <result property="paymentType" column="payment_type" /> |
| | | <result property="tradeType" column="trade_type" /> |
| | | <result property="tradeState" column="trade_state" /> |
| | | <result property="payerTotal" column="payer_total" /> |
| | | <result property="content" column="content" /> |
| | | <result property="createTime" column="create_time" /> |
| | | <result property="updateTime" column="update_time" /> |
| | | </resultMap> |
| | | |
| | | <sql id="selectPaymentInfo"> |
| | | select |
| | | id, |
| | | order_no, |
| | | transaction_id, |
| | | payment_type, |
| | | trade_type, |
| | | trade_state, |
| | | payer_total, |
| | | content, |
| | | create_time, |
| | | update_time |
| | | from |
| | | jczz_payment_info |
| | | </sql> |
| | | |
| | | <select id="selectPaymentInfoById" parameterType="long" resultMap="PaymentInfoDTOResult"> |
| | | <include refid="selectPaymentInfo"/> |
| | | where |
| | | id = #{id} |
| | | </select> |
| | | |
| | | <select id="selectPaymentInfoList" parameterType="org.springblade.modules.pay.dto.PaymentInfoDTO" resultMap="PaymentInfoDTOResult"> |
| | | <include refid="selectPaymentInfo"/> |
| | | <where> |
| | | <if test="id != null "> and id = #{id}</if> |
| | | <if test="orderNo != null and orderNo != ''"> and order_no = #{orderNo}</if> |
| | | <if test="transactionId != null and transactionId != ''"> and transaction_id = #{transactionId}</if> |
| | | <if test="paymentType != null and paymentType != ''"> and payment_type = #{paymentType}</if> |
| | | <if test="tradeType != null and tradeType != ''"> and trade_type = #{tradeType}</if> |
| | | <if test="tradeState != null and tradeState != ''"> and trade_state = #{tradeState}</if> |
| | | <if test="payerTotal != null and payerTotal != ''"> and payer_total = #{payerTotal}</if> |
| | | <if test="content != null and content != ''"> and content = #{content}</if> |
| | | <if test="createTime != null "> and create_time = #{createTime}</if> |
| | | <if test="updateTime != null "> and update_time = #{updateTime}</if> |
| | | </where> |
| | | </select> |
| | | </mapper> |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.mapper; |
| | | |
| | | import org.springblade.modules.pay.dto.RefundInfoDTO; |
| | | import org.springblade.modules.pay.entity.RefundInfoEntity; |
| | | import org.springblade.modules.pay.vo.RefundInfoVO; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 退款信息 Mapper 接口 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | public interface RefundInfoMapper extends BaseMapper<RefundInfoEntity> { |
| | | |
| | | /** |
| | | * 自定义分页 |
| | | * |
| | | * @param page |
| | | * @param refundInfo |
| | | * @return |
| | | */ |
| | | List<RefundInfoVO> selectRefundInfoPage(IPage page, RefundInfoVO refundInfo); |
| | | |
| | | /** |
| | | * 查询退款信息 |
| | | * |
| | | * @param id 退款信息ID |
| | | * @return 退款信息 |
| | | */ |
| | | public RefundInfoDTO selectRefundInfoById(Long id); |
| | | |
| | | /** |
| | | * 查询退款信息列表 |
| | | * |
| | | * @param refundInfoDTO 退款信息 |
| | | * @return 退款信息集合 |
| | | */ |
| | | public List<RefundInfoDTO> selectRefundInfoList(RefundInfoDTO refundInfoDTO); |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="org.springblade.modules.pay.mapper.RefundInfoMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="refundInfoResultMap" type="org.springblade.modules.pay.entity.RefundInfoEntity"> |
| | | </resultMap> |
| | | |
| | | |
| | | <select id="selectRefundInfoPage" resultMap="refundInfoResultMap"> |
| | | select * from jczz_refund_info where is_deleted = 0 |
| | | </select> |
| | | <resultMap type="org.springblade.modules.pay.dto.RefundInfoDTO" id="RefundInfoDTOResult"> |
| | | <result property="id" column="id" /> |
| | | <result property="orderNo" column="order_no" /> |
| | | <result property="refundNo" column="refund_no" /> |
| | | <result property="refundId" column="refund_id" /> |
| | | <result property="totalFee" column="total_fee" /> |
| | | <result property="refund" column="refund" /> |
| | | <result property="reason" column="reason" /> |
| | | <result property="refundStatus" column="refund_status" /> |
| | | <result property="contentReturn" column="content_return" /> |
| | | <result property="contentNotify" column="content_notify" /> |
| | | <result property="createTime" column="create_time" /> |
| | | <result property="updateTime" column="update_time" /> |
| | | </resultMap> |
| | | |
| | | <sql id="selectRefundInfo"> |
| | | select |
| | | id, |
| | | order_no, |
| | | refund_no, |
| | | refund_id, |
| | | total_fee, |
| | | refund, |
| | | reason, |
| | | refund_status, |
| | | content_return, |
| | | content_notify, |
| | | create_time, |
| | | update_time |
| | | from |
| | | jczz_refund_info |
| | | </sql> |
| | | |
| | | <select id="selectRefundInfoById" parameterType="long" resultMap="RefundInfoDTOResult"> |
| | | <include refid="selectRefundInfo"/> |
| | | where |
| | | id = #{id} |
| | | </select> |
| | | |
| | | <select id="selectRefundInfoList" parameterType="org.springblade.modules.pay.dto.RefundInfoDTO" resultMap="RefundInfoDTOResult"> |
| | | <include refid="selectRefundInfo"/> |
| | | <where> |
| | | <if test="id != null "> and id = #{id}</if> |
| | | <if test="orderNo != null "> and order_no = #{orderNo}</if> |
| | | <if test="refundNo != null "> and refund_no = #{refundNo}</if> |
| | | <if test="refundId != null "> and refund_id = #{refundId}</if> |
| | | <if test="totalFee != null and totalFee != ''"> and total_fee = #{totalFee}</if> |
| | | <if test="refund != null and refund != ''"> and refund = #{refund}</if> |
| | | <if test="reason != null and reason != ''"> and reason = #{reason}</if> |
| | | <if test="refundStatus != null and refundStatus != ''"> and refund_status = #{refundStatus}</if> |
| | | <if test="contentReturn != null and contentReturn != ''"> and content_return = #{contentReturn}</if> |
| | | <if test="contentNotify != null and contentNotify != ''"> and content_notify = #{contentNotify}</if> |
| | | <if test="createTime != null "> and create_time = #{createTime}</if> |
| | | <if test="updateTime != null "> and update_time = #{updateTime}</if> |
| | | </where> |
| | | </select> |
| | | |
| | | |
| | | </mapper> |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import org.springblade.common.enums.OrderStatus; |
| | | import org.springblade.modules.pay.entity.OrderInfoEntity; |
| | | import org.springblade.modules.pay.vo.OrderInfoVO; |
| | | import org.springblade.core.mp.base.BaseService; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 订单信息 服务类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | public interface IOrderInfoService extends IService<OrderInfoEntity> { |
| | | |
| | | /** |
| | | * 自定义分页 |
| | | * |
| | | * @param page |
| | | * @param orderInfo |
| | | * @return |
| | | */ |
| | | IPage<OrderInfoVO> selectOrderInfoPage(IPage<OrderInfoVO> page, OrderInfoVO orderInfo); |
| | | |
| | | |
| | | OrderInfoEntity createOrderByPropertyChargeRecordId(Long propertyChargeRecordId); |
| | | |
| | | void saveCodeUrl(String orderNo, String codeUrl); |
| | | |
| | | List<OrderInfoEntity> listOrderByCreateTimeDesc(); |
| | | |
| | | void updateStatusByOrderNo(String orderNo, OrderStatus orderStatus); |
| | | |
| | | String getOrderStatus(String orderNo); |
| | | |
| | | List<OrderInfoEntity> getNoPayOrderByDuration(int minutes); |
| | | |
| | | OrderInfoEntity getOrderByOrderNo(String orderNo); |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import org.springblade.modules.pay.entity.PaymentInfoEntity; |
| | | import org.springblade.modules.pay.vo.PaymentInfoVO; |
| | | import org.springblade.core.mp.base.BaseService; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | |
| | | /** |
| | | * 支付信息 服务类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | public interface IPaymentInfoService extends IService<PaymentInfoEntity> { |
| | | |
| | | /** |
| | | * 自定义分页 |
| | | * |
| | | * @param page |
| | | * @param paymentInfo |
| | | * @return |
| | | */ |
| | | IPage<PaymentInfoVO> selectPaymentInfoPage(IPage<PaymentInfoVO> page, PaymentInfoVO paymentInfo); |
| | | |
| | | void createPaymentInfo(String plainText); |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import org.springblade.modules.pay.entity.RefundInfoEntity; |
| | | import org.springblade.modules.pay.vo.RefundInfoVO; |
| | | import org.springblade.core.mp.base.BaseService; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | |
| | | /** |
| | | * 退款信息 服务类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | public interface IRefundInfoService extends IService<RefundInfoEntity> { |
| | | |
| | | /** |
| | | * 自定义分页 |
| | | * |
| | | * @param page |
| | | * @param refundInfo |
| | | * @return |
| | | */ |
| | | IPage<RefundInfoVO> selectRefundInfoPage(IPage<RefundInfoVO> page, RefundInfoVO refundInfo); |
| | | |
| | | |
| | | RefundInfoEntity createRefundByOrderNo(String orderNo, String reason); |
| | | |
| | | void updateRefund(String plainText); |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import org.springblade.modules.pay.entity.WxPayInfo; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.security.GeneralSecurityException; |
| | | import java.util.Map; |
| | | |
| | | public interface IWxPayService extends IService<WxPayInfo> { |
| | | |
| | | /** |
| | | * 获取openId |
| | | * @param code |
| | | * @return |
| | | */ |
| | | Object getOpenId(String code); |
| | | |
| | | Map<String, String> jsapiPay(Long productId) throws IOException; |
| | | Object getOpenId(String code); |
| | | |
| | | void processOrder(Map<String, Object> bodyMap) throws GeneralSecurityException; |
| | | |
| | | void cancelOrder(String orderNo) throws Exception; |
| | | |
| | | String queryOrder(String orderNo) throws Exception; |
| | | |
| | | void checkOrderStatus(String orderNo) throws Exception; |
| | | |
| | | void refund(String orderNo, String reason) throws Exception; |
| | | |
| | | String queryRefund(String orderNo) throws Exception; |
| | | |
| | | void checkRefundStatus(String refundNo) throws Exception; |
| | | |
| | | void processRefund(Map<String, Object> bodyMap) throws Exception; |
| | | |
| | | Map<String, String> jsapiPay(Long productId) throws IOException, Exception; |
| | | |
| | | String refundsNotify(HttpServletRequest request, HttpServletResponse response); |
| | | |
| | | String nativeNotify(HttpServletRequest request, HttpServletResponse response); |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springblade.common.enums.OrderStatus; |
| | | import org.springblade.modules.pay.entity.OrderInfoEntity; |
| | | import org.springblade.modules.pay.vo.OrderInfoVO; |
| | | import org.springblade.modules.pay.mapper.OrderInfoMapper; |
| | | import org.springblade.modules.pay.service.IOrderInfoService; |
| | | import org.springblade.modules.property.entity.PropertyChargeRecord; |
| | | import org.springblade.modules.property.service.IPropertyChargeRecordService; |
| | | import org.springframework.stereotype.Service; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.Duration; |
| | | import java.time.Instant; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Random; |
| | | |
| | | /** |
| | | * 订单信息 服务实现类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Service |
| | | public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfoEntity> implements IOrderInfoService { |
| | | |
| | | private static Logger logger = LoggerFactory.getLogger(OrderInfoServiceImpl.class); |
| | | |
| | | |
| | | @Resource |
| | | private IPropertyChargeRecordService iPropertyChargeRecordService; |
| | | |
| | | @Override |
| | | public IPage<OrderInfoVO> selectOrderInfoPage(IPage<OrderInfoVO> page, OrderInfoVO orderInfo) { |
| | | return page.setRecords(baseMapper.selectOrderInfoPage(page, orderInfo)); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public OrderInfoEntity createOrderByPropertyChargeRecordId(Long propertyChargeRecordId) { |
| | | |
| | | //查找已存在但未支付的订单 |
| | | OrderInfoEntity orderInfo = this.getNoPayOrderByPropertyChargeRecordId(propertyChargeRecordId); |
| | | if( orderInfo != null){ |
| | | return orderInfo; |
| | | } |
| | | //获取商品信息 |
| | | PropertyChargeRecord propertyChargeRecord = iPropertyChargeRecordService.getById(propertyChargeRecordId); |
| | | //生成订单 |
| | | orderInfo = new OrderInfoEntity(); |
| | | orderInfo.setTitle(propertyChargeRecord.getPayContent()); |
| | | orderInfo.setOrderNo(getOrderNoStr()); //订单号 |
| | | orderInfo.setProperChargeRecordId(propertyChargeRecordId); |
| | | orderInfo.setTotalFee(propertyChargeRecord.getPayPrice().intValue()); //分 |
| | | orderInfo.setOrderStatus(OrderStatus.NOTPAY.getType()); |
| | | baseMapper.insert(orderInfo); |
| | | return orderInfo; |
| | | } |
| | | |
| | | /** |
| | | * 存储订单二维码 |
| | | * @param orderNo |
| | | * @param codeUrl |
| | | */ |
| | | @Override |
| | | public void saveCodeUrl(String orderNo, String codeUrl) { |
| | | |
| | | QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.eq("order_no", orderNo); |
| | | |
| | | OrderInfoEntity orderInfo = new OrderInfoEntity(); |
| | | orderInfo.setCodeUrl(codeUrl); |
| | | |
| | | baseMapper.update(orderInfo, queryWrapper); |
| | | } |
| | | |
| | | /** |
| | | * 查询订单列表,并倒序查询 |
| | | * @return |
| | | */ |
| | | @Override |
| | | public List<OrderInfoEntity> listOrderByCreateTimeDesc() { |
| | | |
| | | QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<OrderInfoEntity>().orderByDesc("create_time"); |
| | | return baseMapper.selectList(queryWrapper); |
| | | } |
| | | |
| | | /** |
| | | * 根据订单号更新订单状态 |
| | | * @param orderNo |
| | | * @param orderStatus |
| | | */ |
| | | @Override |
| | | public void updateStatusByOrderNo(String orderNo, OrderStatus orderStatus) { |
| | | |
| | | logger.info("更新订单状态 ===> {}", orderStatus.getType()); |
| | | |
| | | QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.eq("order_no", orderNo); |
| | | |
| | | OrderInfoEntity orderInfo = new OrderInfoEntity(); |
| | | orderInfo.setOrderStatus(orderStatus.getType()); |
| | | |
| | | baseMapper.update(orderInfo, queryWrapper); |
| | | } |
| | | |
| | | /** |
| | | * 根据订单号获取订单状态 |
| | | * @param orderNo |
| | | * @return |
| | | */ |
| | | @Override |
| | | public String getOrderStatus(String orderNo) { |
| | | |
| | | QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.eq("order_no", orderNo); |
| | | OrderInfoEntity orderInfo = baseMapper.selectOne(queryWrapper); |
| | | if(orderInfo == null){ |
| | | return null; |
| | | } |
| | | return orderInfo.getOrderStatus(); |
| | | } |
| | | |
| | | /** |
| | | * 查询创建超过minutes分钟并且未支付的订单 |
| | | * @param minutes |
| | | * @return |
| | | */ |
| | | @Override |
| | | public List<OrderInfoEntity> getNoPayOrderByDuration(int minutes) { |
| | | |
| | | Instant instant = Instant.now().minus(Duration.ofMinutes(minutes)); |
| | | |
| | | QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.eq("order_status", OrderStatus.NOTPAY.getType()); |
| | | queryWrapper.le("create_time", instant); |
| | | |
| | | List<OrderInfoEntity> orderInfoList = baseMapper.selectList(queryWrapper); |
| | | |
| | | return orderInfoList; |
| | | } |
| | | |
| | | /** |
| | | * 根据订单号获取订单 |
| | | * @param orderNo |
| | | * @return |
| | | */ |
| | | @Override |
| | | public OrderInfoEntity getOrderByOrderNo(String orderNo) { |
| | | |
| | | QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.eq("order_no", orderNo); |
| | | OrderInfoEntity orderInfo = baseMapper.selectOne(queryWrapper); |
| | | |
| | | return orderInfo; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 根据商品id查询未支付订单 |
| | | * 防止重复创建订单对象 |
| | | * @param propertyChargeRecordId |
| | | * @return |
| | | */ |
| | | private OrderInfoEntity getNoPayOrderByPropertyChargeRecordId(Long propertyChargeRecordId) { |
| | | |
| | | QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.eq("product_id", propertyChargeRecordId); |
| | | queryWrapper.eq("order_status", OrderStatus.NOTPAY.getType()); |
| | | // queryWrapper.eq("user_id", userId); |
| | | OrderInfoEntity orderInfo = baseMapper.selectOne(queryWrapper); |
| | | return orderInfo; |
| | | } |
| | | |
| | | //生成订单号 |
| | | public static String getOrderNoStr() { |
| | | String order = "pay" + new SimpleDateFormat("yyyyMMdd").format(new Date()); |
| | | Random r = new Random(); |
| | | for (int i = 0; i < 10; i++) { |
| | | order += r.nextInt(9); |
| | | } |
| | | return order; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.google.gson.Gson; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springblade.common.enums.PayType; |
| | | import org.springblade.modules.pay.entity.PaymentInfoEntity; |
| | | import org.springblade.modules.pay.mapper.PaymentInfoMapper; |
| | | import org.springblade.modules.pay.vo.PaymentInfoVO; |
| | | import org.springblade.modules.pay.service.IPaymentInfoService; |
| | | import org.springblade.core.mp.base.BaseServiceImpl; |
| | | import org.springframework.stereotype.Service; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 支付信息 服务实现类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Service |
| | | public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, PaymentInfoEntity> implements IPaymentInfoService { |
| | | |
| | | private static Logger logger = LoggerFactory.getLogger(PaymentInfoServiceImpl.class); |
| | | |
| | | @Override |
| | | public IPage<PaymentInfoVO> selectPaymentInfoPage(IPage<PaymentInfoVO> page, PaymentInfoVO paymentInfo) { |
| | | return page.setRecords(baseMapper.selectPaymentInfoPage(page, paymentInfo)); |
| | | } |
| | | |
| | | /** |
| | | * 记录支付日志 |
| | | * @param plainText |
| | | */ |
| | | @Override |
| | | public void createPaymentInfo(String plainText) { |
| | | |
| | | logger.info("记录支付日志"); |
| | | |
| | | Gson gson = new Gson(); |
| | | HashMap plainTextMap = gson.fromJson(plainText, HashMap.class); |
| | | |
| | | //订单号 |
| | | String orderNo = (String)plainTextMap.get("out_trade_no"); |
| | | //业务编号 |
| | | String transactionId = (String)plainTextMap.get("transaction_id"); |
| | | //支付类型 |
| | | String tradeType = (String)plainTextMap.get("trade_type"); |
| | | //交易状态 |
| | | String tradeState = (String)plainTextMap.get("trade_state"); |
| | | //用户实际支付金额 |
| | | Map<String, Object> amount = (Map)plainTextMap.get("amount"); |
| | | Integer payerTotal = ((Double) amount.get("payer_total")).intValue(); |
| | | |
| | | PaymentInfoEntity paymentInfo = new PaymentInfoEntity(); |
| | | paymentInfo.setOrderNo(orderNo); |
| | | paymentInfo.setPaymentType(PayType.WXPAY.getType()); |
| | | paymentInfo.setTransactionId(transactionId); |
| | | paymentInfo.setTradeType(tradeType); |
| | | paymentInfo.setTradeState(tradeState); |
| | | paymentInfo.setPayerTotal(payerTotal); |
| | | paymentInfo.setContent(plainText); |
| | | |
| | | baseMapper.insert(paymentInfo); |
| | | } |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.google.gson.Gson; |
| | | import org.springblade.modules.pay.entity.OrderInfoEntity; |
| | | import org.springblade.modules.pay.entity.RefundInfoEntity; |
| | | import org.springblade.modules.pay.mapper.RefundInfoMapper; |
| | | import org.springblade.modules.pay.service.IOrderInfoService; |
| | | import org.springblade.modules.pay.service.IRefundInfoService; |
| | | import org.springblade.modules.pay.vo.RefundInfoVO; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.Random; |
| | | |
| | | /** |
| | | * 退款信息 服务实现类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Service |
| | | public class RefundInfoServiceImpl extends ServiceImpl<RefundInfoMapper, RefundInfoEntity> implements IRefundInfoService { |
| | | |
| | | |
| | | @Resource |
| | | private IOrderInfoService orderInfoService; |
| | | @Override |
| | | public IPage<RefundInfoVO> selectRefundInfoPage(IPage<RefundInfoVO> page, RefundInfoVO refundInfo) { |
| | | return page.setRecords(baseMapper.selectRefundInfoPage(page, refundInfo)); |
| | | } |
| | | |
| | | @Override |
| | | public RefundInfoEntity createRefundByOrderNo(String orderNo, String reason) { |
| | | |
| | | //根据订单号获取订单信息 |
| | | OrderInfoEntity orderInfo = orderInfoService.getOne(Wrappers.<OrderInfoEntity>lambdaQuery() |
| | | .eq(OrderInfoEntity::getOrderNo, orderNo)); |
| | | |
| | | //根据订单号生成退款订单 |
| | | RefundInfoEntity refundInfo = new RefundInfoEntity(); |
| | | refundInfo.setOrderNo(orderNo);//订单编号 |
| | | refundInfo.setRefundNo(getOrderNoStr());//退款单编号 |
| | | refundInfo.setTotalFee(orderInfo.getTotalFee());//原订单金额(分) |
| | | refundInfo.setRefund(orderInfo.getTotalFee());//退款金额(分) |
| | | refundInfo.setReason(reason);//退款原因 |
| | | |
| | | //保存退款订单 |
| | | baseMapper.insert(refundInfo); |
| | | |
| | | return refundInfo; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void updateRefund(String content) { |
| | | //将json字符串转换成Map |
| | | Gson gson = new Gson(); |
| | | Map<String, String> resultMap = gson.fromJson(content, HashMap.class); |
| | | |
| | | //根据退款单编号修改退款单 |
| | | QueryWrapper<RefundInfoEntity> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.eq("refund_no", resultMap.get("out_refund_no")); |
| | | |
| | | //设置要修改的字段 |
| | | RefundInfoEntity refundInfo = new RefundInfoEntity(); |
| | | |
| | | refundInfo.setRefundId(resultMap.get("refund_id"));//微信支付退款单号 |
| | | |
| | | //查询退款和申请退款中的返回参数 |
| | | if(resultMap.get("status") != null){ |
| | | refundInfo.setRefundStatus(resultMap.get("status"));//退款状态 |
| | | refundInfo.setContentReturn(content);//将全部响应结果存入数据库的content字段 |
| | | } |
| | | //退款回调中的回调参数 |
| | | if(resultMap.get("refund_status") != null){ |
| | | refundInfo.setRefundStatus(resultMap.get("refund_status"));//退款状态 |
| | | refundInfo.setContentNotify(content);//将全部响应结果存入数据库的content字段 |
| | | } |
| | | |
| | | //更新退款单 |
| | | baseMapper.update(refundInfo, queryWrapper); |
| | | } |
| | | |
| | | |
| | | //生成订单号 |
| | | public static String getOrderNoStr() { |
| | | String order = "refund" + new SimpleDateFormat("yyyyMMdd").format(new Date()); |
| | | Random r = new Random(); |
| | | for (int i = 0; i < 10; i++) { |
| | | order += r.nextInt(9); |
| | | } |
| | | return order; |
| | | } |
| | | } |
| | |
| | | package org.springblade.modules.pay.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.github.wxpay.sdk.WXPayUtil; |
| | | import com.google.gson.Gson; |
| | | import com.wechat.pay.contrib.apache.httpclient.util.AesUtil; |
| | | import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; |
| | | 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.util.EntityUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springblade.common.config.WxPayConfig; |
| | | import org.springblade.common.enums.OrderStatus; |
| | | import org.springblade.common.enums.wxpay.WxApiType; |
| | | import org.springblade.common.enums.wxpay.WxNotifyType; |
| | | import org.springblade.modules.pay.controller.WxPayController; |
| | | import org.springblade.common.enums.wxpay.WxRefundStatus; |
| | | import org.springblade.common.enums.wxpay.WxTradeState; |
| | | import org.springblade.common.utils.HttpUtils; |
| | | import org.springblade.common.utils.SpringUtils; |
| | | import org.springblade.common.utils.WechatPay2ValidatorForRequest; |
| | | import org.springblade.core.secure.utils.AuthUtil; |
| | | import org.springblade.modules.pay.entity.OrderInfoEntity; |
| | | import org.springblade.modules.pay.entity.RefundInfoEntity; |
| | | import org.springblade.modules.pay.entity.WxPayInfo; |
| | | import org.springblade.modules.pay.mapper.WxPayMapper; |
| | | import org.springblade.modules.pay.service.IOrderInfoService; |
| | | import org.springblade.modules.pay.service.IPaymentInfoService; |
| | | import org.springblade.modules.pay.service.IRefundInfoService; |
| | | import org.springblade.modules.pay.service.IWxPayService; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springblade.modules.property.entity.PropertyChargeRecord; |
| | | import org.springblade.modules.property.service.IPropertyChargeService; |
| | | import org.springblade.modules.system.entity.User; |
| | | import org.springblade.modules.system.service.IUserService; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.FileInputStream; |
| | | import java.io.IOException; |
| | | import java.nio.charset.StandardCharsets; |
| | |
| | | |
| | | @Service |
| | | public class WxPayServiceImpl extends ServiceImpl<WxPayMapper,WxPayInfo> implements IWxPayService { |
| | | private static Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class); |
| | | |
| | | private final String MINI_PROGRAM_APP_ID = "wx41aa8a5d2e565a05"; |
| | | private static final Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class); |
| | | |
| | | @Resource |
| | | private WxPayConfig wxPayConfig; |
| | | |
| | | @Resource |
| | | private IPropertyChargeService iPropertyChargeService; |
| | | |
| | | |
| | | @Resource |
| | | private CloseableHttpClient wxPayClient; |
| | | |
| | | @Resource |
| | | private IOrderInfoService orderInfoService; |
| | | |
| | | @Resource |
| | | private IPaymentInfoService paymentInfoService; |
| | | |
| | | @Resource |
| | | private IRefundInfoService refundsInfoService; |
| | | |
| | | private final ReentrantLock lock = new ReentrantLock(); |
| | | |
| | | |
| | | @Override |
| | | public Object getOpenId(String code) { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public Map<String, String> jsapiPay(Long productId) throws IOException { |
| | | |
| | | String prepayId = ""; |
| | | //生成订单 |
| | | // OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId); |
| | | |
| | | |
| | | logger.info("调用统一下单API"); |
| | | |
| | | // //调用统一下单API |
| | | // HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.JSAPI_PAY.getType())); |
| | | // |
| | | // // 请求body参数 |
| | | // |
| | | // Gson gson = new Gson(); |
| | | // Map paramsMap = new HashMap(); |
| | | // paramsMap.put("appid", wxPayConfig.getAppid()); |
| | | // paramsMap.put("mchid", wxPayConfig.getMchId()); |
| | | // paramsMap.put("description", orderInfo.getTitle()); |
| | | // paramsMap.put("out_trade_no", orderInfo.getOrderNo()); |
| | | // paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType())); |
| | | // |
| | | // Map amountMap = new HashMap(); |
| | | // amountMap.put("total", orderInfo.getTotalFee()); |
| | | // amountMap.put("currency", "CNY"); |
| | | // |
| | | // paramsMap.put("amount", amountMap); |
| | | // |
| | | // Map payerMap = new HashMap(); |
| | | // payerMap.put("openid", "oSX3G6OUuGaKJbWzSHUpPbzgtDXo"); |
| | | // |
| | | // paramsMap.put("payer", payerMap); |
| | | // |
| | | // //将参数转换成json字符串 |
| | | // String jsonParams = gson.toJson(paramsMap); |
| | | // logger.info("请求参数 ===> {}" + jsonParams); |
| | | // |
| | | // StringEntity entity = new StringEntity(jsonParams, "utf-8"); |
| | | // entity.setContentType("application/json"); |
| | | // httpPost.setEntity(entity); |
| | | // httpPost.setHeader("Accept", "application/json"); |
| | | // |
| | | // //完成签名并执行请求 |
| | | // CloseableHttpResponse response = wxPayClient.execute(httpPost); |
| | | // |
| | | // try { |
| | | // String bodyAsString = EntityUtils.toString(response.getEntity());//响应体 |
| | | // int statusCode = response.getStatusLine().getStatusCode();//响应状态码 |
| | | // if (statusCode == 200) { //处理成功 |
| | | // logger.info("成功, 返回结果 = " + bodyAsString); |
| | | // } else if (statusCode == 204) { //处理成功,无返回Body |
| | | // logger.info("成功"); |
| | | // } else { |
| | | // logger.info("jszpi下单失败,响应码 = " + statusCode + ",返回结果 = " + bodyAsString); |
| | | // throw new IOException("request failed"); |
| | | // } |
| | | // //响应结果 |
| | | // Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class); |
| | | // //预支付交易会话标识 |
| | | // prepayId = resultMap.get("prepay_id"); |
| | | // |
| | | // //返回预支付交易会话标识 |
| | | // // 组装前端预下单参数 |
| | | // /** 返回给前端所需要的数据 */ |
| | | // SortedMap<String, String> payMap = new TreeMap<>(); |
| | | // String nonceStr = WXPayUtil.generateNonceStr(); |
| | | // String timestamp = String.valueOf(System.currentTimeMillis() / 1000); |
| | | // payMap.put("appId", wxPayConfig.getAppid()); |
| | | // payMap.put("timeStamp", timestamp); |
| | | // payMap.put("nonceStr", nonceStr); |
| | | // payMap.put("signType", "RSA"); |
| | | // payMap.put("package", "prepay_id=" + prepayId); |
| | | // String paySign = getSign(wxPayConfig.getAppid(), prepayId, timestamp, nonceStr); |
| | | // payMap.put("paySign", paySign); |
| | | // logger.info("返回参数 ===> {}" + gson.toJson(payMap)); |
| | | // return payMap; |
| | | // } finally { |
| | | // response.close(); |
| | | // } |
| | | return null; |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public void processOrder(Map<String, Object> bodyMap) throws GeneralSecurityException { |
| | | logger.info("处理订单"); |
| | |
| | | 以避免函数重入造成的数据混乱*/ |
| | | //尝试获取锁: |
| | | // 成功获取则立即返回true,获取失败则立即返回false。不必一直等待锁的释放 |
| | | // if (lock.tryLock()) { |
| | | // try { |
| | | // //处理重复的通知 |
| | | // //接口调用的幂等性:无论接口被调用多少次,产生的结果是一致的。 |
| | | // String orderStatus = orderInfoService.getOrderStatus(orderNo); |
| | | // if (!OrderStatus.NOTPAY.getType().equals(orderStatus)) { |
| | | // return; |
| | | // } |
| | | // |
| | | // //模拟通知并发 |
| | | // try { |
| | | // TimeUnit.SECONDS.sleep(5); |
| | | // } catch (InterruptedException e) { |
| | | // e.printStackTrace(); |
| | | // } |
| | | // |
| | | // //更新订单状态 |
| | | // orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS); |
| | | // |
| | | // //记录支付日志 |
| | | // paymentInfoService.createPaymentInfo(plainText); |
| | | // } finally { |
| | | // //要主动释放锁 |
| | | // lock.unlock(); |
| | | // } |
| | | // } |
| | | if (lock.tryLock()) { |
| | | try { |
| | | //处理重复的通知 |
| | | //接口调用的幂等性:无论接口被调用多少次,产生的结果是一致的。 |
| | | String orderStatus = orderInfoService.getOrderStatus(orderNo); |
| | | if (!OrderStatus.NOTPAY.getType().equals(orderStatus)) { |
| | | return; |
| | | } |
| | | |
| | | //模拟通知并发 |
| | | try { |
| | | TimeUnit.SECONDS.sleep(5); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | //更新订单状态 |
| | | orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS); |
| | | |
| | | //记录支付日志 |
| | | paymentInfoService.createPaymentInfo(plainText); |
| | | } finally { |
| | | //要主动释放锁 |
| | | lock.unlock(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 用户取消订单 |
| | | * |
| | | * @param orderNo |
| | | */ |
| | | @Override |
| | | public void cancelOrder(String orderNo) throws Exception { |
| | | |
| | | //调用微信支付的关单接口 |
| | | this.closeOrder(orderNo); |
| | | |
| | | //更新商户端的订单状态 |
| | | orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.CANCEL); |
| | | } |
| | | |
| | | @Override |
| | | public String queryOrder(String orderNo) throws Exception { |
| | | |
| | | logger.info("查单接口调用 ===> {}", orderNo); |
| | | |
| | | String url = String.format(WxApiType.ORDER_QUERY_BY_NO.getType(), orderNo); |
| | | url = wxPayConfig.getDomain().concat(url).concat("?mchid=").concat(wxPayConfig.getMchId()); |
| | | |
| | | HttpGet httpGet = new HttpGet(url); |
| | | httpGet.setHeader("Accept", "application/json"); |
| | | |
| | | //完成签名并执行请求 |
| | | CloseableHttpResponse response = wxPayClient.execute(httpGet); |
| | | |
| | | try { |
| | | String bodyAsString = EntityUtils.toString(response.getEntity());//响应体 |
| | | int statusCode = response.getStatusLine().getStatusCode();//响应状态码 |
| | | if (statusCode == 200) { //处理成功 |
| | | logger.info("成功, 返回结果 = " + bodyAsString); |
| | | } else if (statusCode == 204) { //处理成功,无返回Body |
| | | logger.info("成功"); |
| | | } else { |
| | | logger.info("查单接口调用,响应码 = " + statusCode + ",返回结果 = " + bodyAsString); |
| | | throw new IOException("request failed"); |
| | | } |
| | | |
| | | return bodyAsString; |
| | | |
| | | } finally { |
| | | response.close(); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 根据订单号查询微信支付查单接口,核实订单状态 |
| | | * 如果订单已支付,则更新商户端订单状态,并记录支付日志 |
| | | * 如果订单未支付,则调用关单接口关闭订单,并更新商户端订单状态 |
| | | * |
| | | * @param orderNo |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public void checkOrderStatus(String orderNo) throws Exception { |
| | | |
| | | logger.info("根据订单号核实订单状态 ===> {}", orderNo); |
| | | |
| | | //调用微信支付查单接口 |
| | | String result = this.queryOrder(orderNo); |
| | | |
| | | Gson gson = new Gson(); |
| | | Map<String, String> resultMap = gson.fromJson(result, HashMap.class); |
| | | |
| | | //获取微信支付端的订单状态 |
| | | String tradeState = resultMap.get("trade_state"); |
| | | |
| | | //判断订单状态 |
| | | if (WxTradeState.SUCCESS.getType().equals(tradeState)) { |
| | | |
| | | logger.info("核实订单已支付 ===> {}", orderNo); |
| | | |
| | | //如果确认订单已支付则更新本地订单状态 |
| | | orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS); |
| | | //记录支付日志 |
| | | paymentInfoService.createPaymentInfo(result); |
| | | } |
| | | |
| | | if (WxTradeState.NOTPAY.getType().equals(tradeState)) { |
| | | logger.info("核实订单未支付 ===> {}", orderNo); |
| | | |
| | | //如果订单未支付,则调用关单接口 |
| | | this.closeOrder(orderNo); |
| | | |
| | | //更新本地订单状态 |
| | | orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.CLOSED); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 退款 |
| | | * |
| | | * @param orderNo |
| | | * @param reason |
| | | * @throws IOException |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public void refund(String orderNo, String reason) throws Exception { |
| | | |
| | | logger.info("创建退款单记录"); |
| | | //根据订单编号创建退款单 |
| | | RefundInfoEntity refundsInfo = refundsInfoService.createRefundByOrderNo(orderNo, reason); |
| | | |
| | | logger.info("调用退款API"); |
| | | |
| | | //调用统一下单API |
| | | String url = wxPayConfig.getDomain().concat(WxApiType.DOMESTIC_REFUNDS.getType()); |
| | | HttpPost httpPost = new HttpPost(url); |
| | | |
| | | // 请求body参数 |
| | | Gson gson = new Gson(); |
| | | Map paramsMap = new HashMap(); |
| | | paramsMap.put("out_trade_no", orderNo);//订单编号 |
| | | paramsMap.put("out_refund_no", refundsInfo.getRefundNo());//退款单编号 |
| | | paramsMap.put("reason", reason);//退款原因 |
| | | paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.REFUND_NOTIFY.getType()));//退款通知地址 |
| | | |
| | | Map amountMap = new HashMap(); |
| | | amountMap.put("refund", refundsInfo.getRefund());//退款金额 |
| | | amountMap.put("total", refundsInfo.getTotalFee());//原订单金额 |
| | | amountMap.put("currency", "CNY");//退款币种 |
| | | paramsMap.put("amount", amountMap); |
| | | |
| | | //将参数转换成json字符串 |
| | | String jsonParams = gson.toJson(paramsMap); |
| | | logger.info("请求参数 ===> {}" + jsonParams); |
| | | |
| | | StringEntity entity = new StringEntity(jsonParams, "utf-8"); |
| | | entity.setContentType("application/json");//设置请求报文格式 |
| | | httpPost.setEntity(entity);//将请求报文放入请求对象 |
| | | httpPost.setHeader("Accept", "application/json");//设置响应报文格式 |
| | | |
| | | //完成签名并执行请求,并完成验签 |
| | | CloseableHttpResponse response = wxPayClient.execute(httpPost); |
| | | |
| | | try { |
| | | |
| | | //解析响应结果 |
| | | String bodyAsString = EntityUtils.toString(response.getEntity()); |
| | | int statusCode = response.getStatusLine().getStatusCode(); |
| | | if (statusCode == 200) { |
| | | logger.info("成功, 退款返回结果 = " + bodyAsString); |
| | | } else if (statusCode == 204) { |
| | | logger.info("成功"); |
| | | } else { |
| | | throw new RuntimeException("退款异常, 响应码 = " + statusCode + ", 退款返回结果 = " + bodyAsString); |
| | | } |
| | | |
| | | //更新订单状态 |
| | | orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_PROCESSING); |
| | | |
| | | //更新退款单 |
| | | refundsInfoService.updateRefund(bodyAsString); |
| | | |
| | | } finally { |
| | | response.close(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 查询退款接口调用 |
| | | * |
| | | * @param refundNo |
| | | * @return |
| | | */ |
| | | @Override |
| | | public String queryRefund(String refundNo) throws Exception { |
| | | |
| | | logger.info("查询退款接口调用 ===> {}", refundNo); |
| | | |
| | | String url = String.format(WxApiType.DOMESTIC_REFUNDS_QUERY.getType(), refundNo); |
| | | url = wxPayConfig.getDomain().concat(url); |
| | | |
| | | //创建远程Get 请求对象 |
| | | HttpGet httpGet = new HttpGet(url); |
| | | httpGet.setHeader("Accept", "application/json"); |
| | | |
| | | //完成签名并执行请求 |
| | | CloseableHttpResponse response = wxPayClient.execute(httpGet); |
| | | |
| | | try { |
| | | String bodyAsString = EntityUtils.toString(response.getEntity()); |
| | | int statusCode = response.getStatusLine().getStatusCode(); |
| | | if (statusCode == 200) { |
| | | logger.info("成功, 查询退款返回结果 = " + bodyAsString); |
| | | } else if (statusCode == 204) { |
| | | logger.info("成功"); |
| | | } else { |
| | | throw new RuntimeException("查询退款异常, 响应码 = " + statusCode + ", 查询退款返回结果 = " + bodyAsString); |
| | | } |
| | | |
| | | return bodyAsString; |
| | | |
| | | } finally { |
| | | response.close(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据退款单号核实退款单状态 |
| | | * |
| | | * @param refundNo |
| | | * @return |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public void checkRefundStatus(String refundNo) throws Exception { |
| | | |
| | | logger.info("根据退款单号核实退款单状态 ===> {}", refundNo); |
| | | |
| | | //调用查询退款单接口 |
| | | String result = this.queryRefund(refundNo); |
| | | |
| | | //组装json请求体字符串 |
| | | Gson gson = new Gson(); |
| | | Map<String, String> resultMap = gson.fromJson(result, HashMap.class); |
| | | |
| | | //获取微信支付端退款状态 |
| | | String status = resultMap.get("status"); |
| | | |
| | | String orderNo = resultMap.get("out_trade_no"); |
| | | |
| | | if (WxRefundStatus.SUCCESS.getType().equals(status)) { |
| | | |
| | | logger.info("核实订单已退款成功 ===> {}", refundNo); |
| | | |
| | | //如果确认退款成功,则更新订单状态 |
| | | orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_SUCCESS); |
| | | |
| | | //更新退款单 |
| | | refundsInfoService.updateRefund(result); |
| | | } |
| | | |
| | | if (WxRefundStatus.ABNORMAL.getType().equals(status)) { |
| | | |
| | | logger.info("核实订单退款异常 ===> {}", refundNo); |
| | | |
| | | //如果确认退款成功,则更新订单状态 |
| | | orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_ABNORMAL); |
| | | |
| | | //更新退款单 |
| | | refundsInfoService.updateRefund(result); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理退款单 |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public void processRefund(Map<String, Object> bodyMap) throws Exception { |
| | | |
| | | logger.info("退款单"); |
| | | |
| | | //解密报文 |
| | | String plainText = decryptFromResource(bodyMap); |
| | | |
| | | //将明文转换成map |
| | | Gson gson = new Gson(); |
| | | HashMap plainTextMap = gson.fromJson(plainText, HashMap.class); |
| | | String orderNo = (String) plainTextMap.get("out_trade_no"); |
| | | |
| | | if (lock.tryLock()) { |
| | | try { |
| | | |
| | | String orderStatus = orderInfoService.getOrderStatus(orderNo); |
| | | if (!OrderStatus.REFUND_PROCESSING.getType().equals(orderStatus)) { |
| | | return; |
| | | } |
| | | |
| | | //更新订单状态 |
| | | orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_SUCCESS); |
| | | |
| | | //更新退款单 |
| | | refundsInfoService.updateRefund(plainText); |
| | | |
| | | } finally { |
| | | //要主动释放锁 |
| | | lock.unlock(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public Map<String, String> jsapiPay(Long properChargeRecordId) throws Exception { |
| | | |
| | | String prepayId = ""; |
| | | //生成订单 |
| | | OrderInfoEntity orderInfo = orderInfoService.getOne(Wrappers.<OrderInfoEntity>lambdaQuery().eq(OrderInfoEntity::getProperChargeRecordId,properChargeRecordId)); |
| | | IUserService userService = SpringUtils.getBean(IUserService.class); |
| | | User serviceOne = userService.getOne(Wrappers.<User>lambdaQuery().eq(User::getId, AuthUtil.getUserId())); |
| | | |
| | | logger.info("调用统一下单API"); |
| | | |
| | | //调用统一下单API |
| | | HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.JSAPI_PAY.getType())); |
| | | |
| | | // 请求body参数 |
| | | |
| | | Gson gson = new Gson(); |
| | | Map paramsMap = new HashMap(); |
| | | paramsMap.put("appid", wxPayConfig.getAppid()); |
| | | paramsMap.put("mchid", wxPayConfig.getMchId()); |
| | | paramsMap.put("description", orderInfo.getTitle()); |
| | | paramsMap.put("out_trade_no", orderInfo.getOrderNo()); |
| | | paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType())); |
| | | |
| | | Map amountMap = new HashMap(); |
| | | amountMap.put("total", orderInfo.getTotalFee()); |
| | | amountMap.put("currency", "CNY"); |
| | | |
| | | paramsMap.put("amount", amountMap); |
| | | |
| | | Map payerMap = new HashMap(); |
| | | payerMap.put("openid", serviceOne.getMiniOpenId()); |
| | | |
| | | paramsMap.put("payer", payerMap); |
| | | |
| | | // 是否指定分账,枚举值 true:是 false:否 |
| | | paramsMap.put("profit_sharing", true); |
| | | |
| | | //将参数转换成json字符串 |
| | | String jsonParams = gson.toJson(paramsMap); |
| | | logger.info("请求参数 ===> {}" + jsonParams); |
| | | |
| | | StringEntity entity = new StringEntity(jsonParams, "utf-8"); |
| | | entity.setContentType("application/json"); |
| | | httpPost.setEntity(entity); |
| | | httpPost.setHeader("Accept", "application/json"); |
| | | |
| | | //完成签名并执行请求 |
| | | CloseableHttpResponse response = wxPayClient.execute(httpPost); |
| | | |
| | | try { |
| | | String bodyAsString = EntityUtils.toString(response.getEntity());//响应体 |
| | | int statusCode = response.getStatusLine().getStatusCode();//响应状态码 |
| | | if (statusCode == 200) { //处理成功 |
| | | logger.info("成功, 返回结果 = " + bodyAsString); |
| | | } else if (statusCode == 204) { //处理成功,无返回Body |
| | | logger.info("成功"); |
| | | } else { |
| | | logger.info("jszpi下单失败,响应码 = " + statusCode + ",返回结果 = " + bodyAsString); |
| | | throw new IOException("request failed"); |
| | | } |
| | | //响应结果 |
| | | Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class); |
| | | //预支付交易会话标识 |
| | | prepayId = resultMap.get("prepay_id"); |
| | | |
| | | //返回预支付交易会话标识 |
| | | // 组装前端预下单参数 |
| | | /** 返回给前端所需要的数据 */ |
| | | SortedMap<String, String> payMap = new TreeMap<>(); |
| | | String nonceStr = WXPayUtil.generateNonceStr(); |
| | | String timestamp = String.valueOf(System.currentTimeMillis() / 1000); |
| | | payMap.put("appId", wxPayConfig.getAppid()); |
| | | payMap.put("timeStamp", timestamp); |
| | | payMap.put("nonceStr", nonceStr); |
| | | payMap.put("signType", "RSA"); |
| | | payMap.put("package", "prepay_id=" + prepayId); |
| | | String paySign = getSign(wxPayConfig.getAppid(), prepayId, timestamp, nonceStr); |
| | | payMap.put("paySign", paySign); |
| | | logger.info("返回参数 ===> {}" + gson.toJson(payMap)); |
| | | return payMap; |
| | | } finally { |
| | | response.close(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | //签名方式 |
| | | Signature sign = Signature.getInstance("SHA256withRSA"); |
| | | //私钥,通过MyPrivateKey来获取,这是个静态类可以接调用方法 ,需要的是_key.pem文件的绝对路径配上文件名 |
| | | // sign.initSign(getPrivateKey(wxPayConfig.getPrivateKeyPath())); |
| | | sign.initSign(getPrivateKey(wxPayConfig.getPrivateKeyPath())); |
| | | sign.update(message); |
| | | |
| | | return Base64.getEncoder().encodeToString(sign.sign()); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 关单接口的调用 |
| | | * |
| | | * @param orderNo |
| | | */ |
| | | private void closeOrder(String orderNo) throws Exception { |
| | | |
| | | logger.info("关单接口的调用,订单号 ===> {}", orderNo); |
| | | //创建远程请求对象 |
| | | String url = String.format(WxApiType.CLOSE_ORDER_BY_NO.getType(), orderNo); |
| | | url = wxPayConfig.getDomain().concat(url); |
| | | HttpPost httpPost = new HttpPost(url); |
| | | |
| | | //组装json请求体 |
| | | Gson gson = new Gson(); |
| | | Map<String, String> paramsMap = new HashMap<>(); |
| | | paramsMap.put("mchid", wxPayConfig.getMchId()); |
| | | String jsonParams = gson.toJson(paramsMap); |
| | | logger.info("请求参数 ===> {}", jsonParams); |
| | | |
| | | //将请求参数设置到请求对象中 |
| | | StringEntity entity = new StringEntity(jsonParams, "utf-8"); |
| | | entity.setContentType("application/json"); |
| | | httpPost.setEntity(entity); |
| | | httpPost.setHeader("Accept", "application/json"); |
| | | |
| | | //完成签名并执行请求 |
| | | CloseableHttpResponse response = wxPayClient.execute(httpPost); |
| | | |
| | | try { |
| | | int statusCode = response.getStatusLine().getStatusCode();//响应状态码 |
| | | if (statusCode == 200) { //处理成功 |
| | | logger.info("成功200"); |
| | | } else if (statusCode == 204) { //处理成功,无返回Body |
| | | logger.info("成功204"); |
| | | } else { |
| | | logger.info("Native下单失败,响应码 = " + statusCode); |
| | | throw new IOException("request failed"); |
| | | } |
| | | |
| | | } finally { |
| | | response.close(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 对称解密 |
| | | * |
| | |
| | | String associatedData = resourceMap.get("associated_data"); |
| | | |
| | | logger.info("密文 ===> {}", ciphertext); |
| | | // AesUtil aesUtil = new AesUtil(wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8)); |
| | | // String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), |
| | | // nonce.getBytes(StandardCharsets.UTF_8), |
| | | // ciphertext); |
| | | AesUtil aesUtil = new AesUtil(wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8)); |
| | | String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), |
| | | nonce.getBytes(StandardCharsets.UTF_8), |
| | | ciphertext); |
| | | |
| | | // logger.info("明文 ===> {}", plainText); |
| | | logger.info("明文 ===> {}", plainText); |
| | | |
| | | // return plainText; |
| | | return null; |
| | | return plainText; |
| | | } |
| | | |
| | | @Override |
| | | public String nativeNotify(HttpServletRequest request, HttpServletResponse response) { |
| | | Gson gson = new Gson(); |
| | | Map<String, String> map = new HashMap<>();//应答对象 |
| | | |
| | | try { |
| | | |
| | | //处理通知参数 |
| | | String body = HttpUtils.readData(request); |
| | | Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class); |
| | | String requestId = (String) bodyMap.get("id"); |
| | | logger.info("支付通知的id ===> {}", requestId); |
| | | logger.info("支付通知的完整数据 ===> {}", body); |
| | | //int a = 9 / 0; |
| | | |
| | | //签名的验证 |
| | | WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest |
| | | = new WechatPay2ValidatorForRequest(wxPayConfig.getVerifier(), requestId, body); |
| | | if (!wechatPay2ValidatorForRequest.validate(request)) { |
| | | |
| | | logger.error("通知验签失败"); |
| | | //失败应答 |
| | | response.setStatus(500); |
| | | map.put("code", "ERROR"); |
| | | map.put("message", "通知验签失败"); |
| | | return gson.toJson(map); |
| | | } |
| | | logger.info("通知验签成功"); |
| | | |
| | | //处理订单 |
| | | processOrder(bodyMap); |
| | | |
| | | //成功应答 |
| | | response.setStatus(200); |
| | | map.put("code", "SUCCESS"); |
| | | map.put("message", "成功"); |
| | | return gson.toJson(map); |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | //失败应答 |
| | | response.setStatus(500); |
| | | map.put("code", "ERROR"); |
| | | map.put("message", "失败"); |
| | | return gson.toJson(map); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public String refundsNotify(HttpServletRequest request, HttpServletResponse response) { |
| | | Gson gson = new Gson(); |
| | | Map<String, String> map = new HashMap<>();//应答对象 |
| | | |
| | | try { |
| | | //处理通知参数 |
| | | String body = HttpUtils.readData(request); |
| | | Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class); |
| | | String requestId = (String) bodyMap.get("id"); |
| | | logger.info("支付通知的id ===> {}", requestId); |
| | | |
| | | //签名的验证 |
| | | WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest |
| | | = new WechatPay2ValidatorForRequest(wxPayConfig.getVerifier(), requestId, body); |
| | | if (!wechatPay2ValidatorForRequest.validate(request)) { |
| | | |
| | | logger.error("通知验签失败"); |
| | | //失败应答 |
| | | response.setStatus(500); |
| | | map.put("code", "ERROR"); |
| | | map.put("message", "通知验签失败"); |
| | | return gson.toJson(map); |
| | | } |
| | | logger.info("通知验签成功"); |
| | | |
| | | //处理退款单 |
| | | processRefund(bodyMap); |
| | | |
| | | //成功应答 |
| | | response.setStatus(200); |
| | | map.put("code", "SUCCESS"); |
| | | map.put("message", "成功"); |
| | | return gson.toJson(map); |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | //失败应答 |
| | | response.setStatus(500); |
| | | map.put("code", "ERROR"); |
| | | map.put("message", "失败"); |
| | | return gson.toJson(map); |
| | | } |
| | | } |
| | | |
| | | |
| | | //创建签名所需要的参数xml格式 |
| | | // public static String createXML(Map<String, Object> map) { |
| | | // String xml = "<xml>"; |
| | | // Set<String> set = map.keySet(); |
| | | // Iterator<String> i = set.iterator(); |
| | | // while (i.hasNext()) { |
| | | // String str = i.next(); |
| | | // xml += "<" + str + ">" + "<![CDATA[" + map.get(str) + "]]>" + "</" + str + ">"; |
| | | // } |
| | | // xml += "</xml>"; |
| | | // return xml; |
| | | // } |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.vo; |
| | | |
| | | import org.springblade.modules.pay.entity.OrderInfoEntity; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 订单信息 视图实体类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class OrderInfoVO extends OrderInfoEntity { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.vo; |
| | | |
| | | import org.springblade.modules.pay.entity.PaymentInfoEntity; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 支付信息 视图实体类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class PaymentInfoVO extends PaymentInfoEntity { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.vo; |
| | | |
| | | import org.springblade.modules.pay.entity.RefundInfoEntity; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 退款信息 视图实体类 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class RefundInfoVO extends RefundInfoEntity { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.wrapper; |
| | | |
| | | import org.springblade.core.mp.support.BaseEntityWrapper; |
| | | import org.springblade.core.tool.utils.BeanUtil; |
| | | import org.springblade.modules.pay.entity.OrderInfoEntity; |
| | | import org.springblade.modules.pay.vo.OrderInfoVO; |
| | | |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * 订单信息 包装类,返回视图层所需的字段 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | public class OrderInfoWrapper extends BaseEntityWrapper<OrderInfoEntity, OrderInfoVO> { |
| | | |
| | | public static OrderInfoWrapper build() { |
| | | return new OrderInfoWrapper(); |
| | | } |
| | | |
| | | @Override |
| | | public OrderInfoVO entityVO(OrderInfoEntity orderInfo) { |
| | | OrderInfoVO orderInfoVO = Objects.requireNonNull(BeanUtil.copy(orderInfo, OrderInfoVO.class)); |
| | | |
| | | //User createUser = UserCache.getUser(orderInfo.getCreateUser()); |
| | | //User updateUser = UserCache.getUser(orderInfo.getUpdateUser()); |
| | | //orderInfoVO.setCreateUserName(createUser.getName()); |
| | | //orderInfoVO.setUpdateUserName(updateUser.getName()); |
| | | |
| | | return orderInfoVO; |
| | | } |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.wrapper; |
| | | |
| | | import org.springblade.core.mp.support.BaseEntityWrapper; |
| | | import org.springblade.core.tool.utils.BeanUtil; |
| | | import org.springblade.modules.pay.entity.PaymentInfoEntity; |
| | | import org.springblade.modules.pay.vo.PaymentInfoVO; |
| | | |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * 支付信息 包装类,返回视图层所需的字段 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | public class PaymentInfoWrapper extends BaseEntityWrapper<PaymentInfoEntity, PaymentInfoVO> { |
| | | |
| | | public static PaymentInfoWrapper build() { |
| | | return new PaymentInfoWrapper(); |
| | | } |
| | | |
| | | @Override |
| | | public PaymentInfoVO entityVO(PaymentInfoEntity paymentInfo) { |
| | | PaymentInfoVO paymentInfoVO = Objects.requireNonNull(BeanUtil.copy(paymentInfo, PaymentInfoVO.class)); |
| | | |
| | | //User createUser = UserCache.getUser(paymentInfo.getCreateUser()); |
| | | //User updateUser = UserCache.getUser(paymentInfo.getUpdateUser()); |
| | | //paymentInfoVO.setCreateUserName(createUser.getName()); |
| | | //paymentInfoVO.setUpdateUserName(updateUser.getName()); |
| | | |
| | | return paymentInfoVO; |
| | | } |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.springblade.modules.pay.wrapper; |
| | | |
| | | import org.springblade.core.mp.support.BaseEntityWrapper; |
| | | import org.springblade.core.tool.utils.BeanUtil; |
| | | import org.springblade.modules.pay.entity.RefundInfoEntity; |
| | | import org.springblade.modules.pay.vo.RefundInfoVO; |
| | | |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * 退款信息 包装类,返回视图层所需的字段 |
| | | * |
| | | * @author BladeX |
| | | * @since 2024-04-07 |
| | | */ |
| | | public class RefundInfoWrapper extends BaseEntityWrapper<RefundInfoEntity, RefundInfoVO> { |
| | | |
| | | public static RefundInfoWrapper build() { |
| | | return new RefundInfoWrapper(); |
| | | } |
| | | |
| | | @Override |
| | | public RefundInfoVO entityVO(RefundInfoEntity refundInfo) { |
| | | RefundInfoVO refundInfoVO = Objects.requireNonNull(BeanUtil.copy(refundInfo, RefundInfoVO.class)); |
| | | |
| | | //User createUser = UserCache.getUser(refundInfo.getCreateUser()); |
| | | //User updateUser = UserCache.getUser(refundInfo.getUpdateUser()); |
| | | //refundInfoVO.setCreateUserName(createUser.getName()); |
| | | //refundInfoVO.setUpdateUserName(updateUser.getName()); |
| | | |
| | | return refundInfoVO; |
| | | } |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package org.springblade.modules.property.dto; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import lombok.Data; |
| | | import org.springblade.modules.property.entity.PropertyChargeRecord; |
| | | |
| | | /** |
| | | * 缴费记录表对象 jczz_property_charge_record |
| | | * |
| | | * @author ${context.author} |
| | | * @date 2024-04-07 15:44:09 |
| | | */ |
| | | @ApiModel(value = "PropertyChargeRecordDTO对象") |
| | | @Data |
| | | public class PropertyChargeRecordDTO extends PropertyChargeRecord |
| | | { |
| | | |
| | | } |
| | |
| | | package org.springblade.modules.property.entity; |
| | | |
| | | 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; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import org.springblade.core.mp.base.BaseEntity; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.Date; |
| | | |
| | | @Data |
| | | @TableName("jczz_property_charge_record") |
| | | @ApiModel(value = "PropertyChargeRecord", description = "物业缴费记录") |
| | | public class PropertyChargeRecord extends BaseEntity { |
| | | public class PropertyChargeRecord { |
| | | |
| | | |
| | | //物业公司的deptId |
| | | /** 主键 */ |
| | | @ApiModelProperty(value = "主键ID", example = "") |
| | | @TableId(value = "id", type = IdType.ASSIGN_ID) |
| | | private Long id; |
| | | |
| | | /** 物业公司id */ |
| | | @ApiModelProperty(value = "物业公司id", example = "") |
| | | @TableField("property_id") |
| | | private String propertyId; |
| | | |
| | | /** 订单号 */ |
| | | @ApiModelProperty(value = "订单号", example = "") |
| | | @TableField("order_no") |
| | | private String orderNo; |
| | | |
| | | //缴费项id |
| | | /** 缴费项id */ |
| | | @ApiModelProperty(value = "缴费项id", example = "") |
| | | @TableField("charge_id") |
| | | private String chargeId; |
| | | |
| | | //编号 |
| | | /** 缴费单号 */ |
| | | @ApiModelProperty(value = "缴费单号", example = "") |
| | | @TableField("no") |
| | | private String no; |
| | | |
| | | //付款人id |
| | | /** 付款人id */ |
| | | @ApiModelProperty(value = "付款人id", example = "") |
| | | @TableField("pay_user") |
| | | private String payUser; |
| | | |
| | | //付款时间 |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | /** 付费时间 */ |
| | | @ApiModelProperty(value = "付费时间", example = "") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("pay_time") |
| | | private Date payTime; |
| | | |
| | | //缴费方式 |
| | | /** 付款方式 */ |
| | | @ApiModelProperty(value = "付款方式", example = "") |
| | | @TableField("pay_func") |
| | | private String payFunc; |
| | | |
| | | //付款金额 |
| | | private String payPrice; |
| | | /** 付款金额 */ |
| | | @ApiModelProperty(value = "付款金额(分)", example = "") |
| | | @TableField("pay_price") |
| | | private BigDecimal payPrice; |
| | | |
| | | //付款房屋的houseCode |
| | | private String payHouse; |
| | | /** 房屋编码 */ |
| | | @ApiModelProperty(value = "房屋编码", example = "") |
| | | @TableField("house_code") |
| | | private String houseCode; |
| | | |
| | | //缴费内容 |
| | | /** 缴费内容 */ |
| | | @ApiModelProperty(value = "缴费内容", example = "") |
| | | @TableField("pay_content") |
| | | private String payContent; |
| | | |
| | | /** 创建时间 */ |
| | | @ApiModelProperty(value = "创建时间", example = "") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("create_time") |
| | | private Date createTime; |
| | | |
| | | /** 创建人 */ |
| | | @ApiModelProperty(value = "创建人", example = "") |
| | | @TableField("create_user") |
| | | private Long createUser; |
| | | |
| | | /** 创建部门 */ |
| | | @ApiModelProperty(value = "创建部门", example = "") |
| | | @TableField("create_dept") |
| | | private Long createDept; |
| | | |
| | | /** 修改人 */ |
| | | @ApiModelProperty(value = "修改人", example = "") |
| | | @TableField("update_user") |
| | | private Long updateUser; |
| | | |
| | | /** 修改时间 */ |
| | | @ApiModelProperty(value = "修改时间", example = "") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("update_time") |
| | | private Date updateTime; |
| | | |
| | | /** 状态(1、待支付;2、已支付;99取消支付) */ |
| | | @ApiModelProperty(value = "状态(1、待支付;2、已支付;99取消支付)", example = "") |
| | | @TableField("status") |
| | | private Integer status; |
| | | |
| | | /** 是否已删除 */ |
| | | @ApiModelProperty(value = "是否已删除", example = "") |
| | | @TableField("is_deleted") |
| | | private Integer isDeleted; |
| | | |
| | | /** 开始时间 */ |
| | | @ApiModelProperty(value = "开始时间", example = "") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("start_time") |
| | | private Date startTime; |
| | | |
| | | /** 到期时间 */ |
| | | @ApiModelProperty(value = "到期时间", example = "") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("end_time") |
| | | private Date endTime; |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.springblade.modules.property.dto.PropertyChargeRecordDTO; |
| | | import org.springblade.modules.property.entity.PropertyCharge; |
| | | import org.springblade.modules.property.entity.PropertyChargeRecord; |
| | | import org.springblade.modules.property.vo.PropertyChargeRecordVO; |
| | |
| | | |
| | | |
| | | List<PropertyChargeRecordVO> getPage(IPage<PropertyChargeRecordVO> page, @Param("vo") PropertyChargeRecordVO vo); |
| | | |
| | | |
| | | /** |
| | | * 查询缴费记录表 |
| | | * |
| | | * @param id 缴费记录表ID |
| | | * @return 缴费记录表 |
| | | */ |
| | | public PropertyChargeRecordDTO selectPropertyChargeRecordById(Long id); |
| | | |
| | | /** |
| | | * 查询缴费记录表列表 |
| | | * |
| | | * @param propertyChargeRecordDTO 缴费记录表 |
| | | * @return 缴费记录表集合 |
| | | */ |
| | | public List<PropertyChargeRecordDTO> selectPropertyChargeRecordList(PropertyChargeRecordDTO propertyChargeRecordDTO); |
| | | } |
| | |
| | | <select id="getPage" resultType="org.springblade.modules.property.vo.PropertyChargeRecordVO"> |
| | | SELECT * FROM jczz_property_charge_record where is_deleted = 0 |
| | | </select> |
| | | |
| | | |
| | | <resultMap type="org.springblade.modules.property.dto.PropertyChargeRecordDTO" id="PropertyChargeRecordDTOResult"> |
| | | <result property="id" column="id" /> |
| | | <result property="propertyId" column="property_id" /> |
| | | <result property="chargeId" column="charge_id" /> |
| | | <result property="no" column="no" /> |
| | | <result property="payUser" column="pay_user" /> |
| | | <result property="payTime" column="pay_time" /> |
| | | <result property="payFunc" column="pay_func" /> |
| | | <result property="payPrice" column="pay_price" /> |
| | | <result property="houseCode" column="house_code" /> |
| | | <result property="payContent" column="pay_content" /> |
| | | <result property="createTime" column="create_time" /> |
| | | <result property="createUser" column="create_user" /> |
| | | <result property="createDept" column="create_dept" /> |
| | | <result property="updateUser" column="update_user" /> |
| | | <result property="updateTime" column="update_time" /> |
| | | <result property="status" column="status" /> |
| | | <result property="isDeleted" column="is_deleted" /> |
| | | <result property="startTime" column="start_time" /> |
| | | <result property="endTime" column="end_time" /> |
| | | </resultMap> |
| | | |
| | | <sql id="selectPropertyChargeRecord"> |
| | | select |
| | | id, |
| | | property_id, |
| | | charge_id, |
| | | no, |
| | | pay_user, |
| | | pay_time, |
| | | pay_func, |
| | | pay_price, |
| | | house_code, |
| | | pay_content, |
| | | create_time, |
| | | create_user, |
| | | create_dept, |
| | | update_user, |
| | | update_time, |
| | | status, |
| | | is_deleted, |
| | | start_time, |
| | | end_time |
| | | from |
| | | jczz_property_charge_record |
| | | </sql> |
| | | |
| | | <select id="selectPropertyChargeRecordById" parameterType="long" resultMap="PropertyChargeRecordDTOResult"> |
| | | <include refid="selectPropertyChargeRecord"/> |
| | | where |
| | | id = #{id} |
| | | </select> |
| | | |
| | | <select id="selectPropertyChargeRecordList" parameterType="org.springblade.modules.property.dto.PropertyChargeRecordDTO" resultMap="PropertyChargeRecordDTOResult"> |
| | | <include refid="selectPropertyChargeRecord"/> |
| | | <where> |
| | | <if test="id != null "> and id = #{id}</if> |
| | | <if test="propertyId != null and propertyId != ''"> and property_id = #{propertyId}</if> |
| | | <if test="chargeId != null and chargeId != ''"> and charge_id = #{chargeId}</if> |
| | | <if test="no != null and no != ''"> and no = #{no}</if> |
| | | <if test="payUser != null and payUser != ''"> and pay_user = #{payUser}</if> |
| | | <if test="payTime != null "> and pay_time = #{payTime}</if> |
| | | <if test="payFunc != null and payFunc != ''"> and pay_func = #{payFunc}</if> |
| | | <if test="payPrice != null "> and pay_price = #{payPrice}</if> |
| | | <if test="houseCode != null and houseCode != ''"> and house_code = #{houseCode}</if> |
| | | <if test="payContent != null and payContent != ''"> and pay_content = #{payContent}</if> |
| | | <if test="createTime != null "> and create_time = #{createTime}</if> |
| | | <if test="createUser != null "> and create_user = #{createUser}</if> |
| | | <if test="createDept != null "> and create_dept = #{createDept}</if> |
| | | <if test="updateUser != null "> and update_user = #{updateUser}</if> |
| | | <if test="updateTime != null "> and update_time = #{updateTime}</if> |
| | | <if test="status != null "> and status = #{status}</if> |
| | | <if test="isDeleted != null "> and is_deleted = #{isDeleted}</if> |
| | | <if test="startTime != null "> and start_time = #{startTime}</if> |
| | | <if test="endTime != null "> and end_time = #{endTime}</if> |
| | | </where> |
| | | </select> |
| | | </mapper> |
| | |
| | | package org.springblade.modules.property.service; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import org.springblade.core.mp.base.BaseService; |
| | | import org.springblade.modules.property.entity.PropertyCharge; |
| | | import org.springblade.modules.property.entity.PropertyChargeRecord; |
| | |
| | | * @author BladeX |
| | | * @since 2023-11-23 |
| | | */ |
| | | public interface IPropertyChargeRecordService extends BaseService<PropertyChargeRecord> { |
| | | public interface IPropertyChargeRecordService extends IService<PropertyChargeRecord> { |
| | | |
| | | |
| | | IPage<PropertyChargeRecordVO> getPage(IPage<PropertyChargeRecordVO> page, PropertyChargeRecordVO vo); |
| | |
| | | package org.springblade.modules.property.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import org.springblade.core.mp.base.BaseServiceImpl; |
| | | import org.springblade.modules.property.entity.PropertyCharge; |
| | | import org.springblade.modules.property.entity.PropertyChargeRecord; |
| | |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | @Service |
| | | public class PropertyChargeRecordServiceImpl extends BaseServiceImpl<PropertyChargeRecordMapper, PropertyChargeRecord> implements IPropertyChargeRecordService { |
| | | public class PropertyChargeRecordServiceImpl extends ServiceImpl<PropertyChargeRecordMapper, PropertyChargeRecord> implements IPropertyChargeRecordService { |
| | | @Override |
| | | public IPage<PropertyChargeRecordVO> getPage(IPage<PropertyChargeRecordVO> page, PropertyChargeRecordVO vo) { |
| | | return page.setRecords(baseMapper.getPage(page, vo)); |
| | |
| | | @TableField("lat") |
| | | private String lat; |
| | | |
| | | @ApiModelProperty(value = "小程序openid", example = "") |
| | | @TableField("mini_open_id") |
| | | private String miniOpenId; |
| | | |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package org.springblade.modules.wechat.controller; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.tool.api.R; |
| | | import org.springblade.modules.pay.entity.WeChatMiniAuthorizeVo; |
| | | import org.springblade.modules.wechat.service.WechatService; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestMethod; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | @Slf4j |
| | | @RestController |
| | | @RequestMapping("blade-wechat/wechat/") |
| | | @Api(tags = "用户 -- 登录注册") |
| | | public class WechatController { |
| | | @Resource |
| | | private WechatService wechatService; |
| | | |
| | | @ApiOperation(value = "微信小程序授权") |
| | | @RequestMapping(value = "/getOpenId", method = RequestMethod.GET) |
| | | public R<WeChatMiniAuthorizeVo> wechatRoutineLogin(String code) throws Exception { |
| | | return R.data(wechatService.miniAuthCode(code)); |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | |
| | | |
| New file |
| | |
| | | package org.springblade.modules.wechat.service; |
| | | |
| | | import org.springblade.modules.pay.entity.WeChatMiniAuthorizeVo; |
| | | |
| | | public interface WechatService { |
| | | /** |
| | | * 小程序登录凭证校验 |
| | | * |
| | | * @return 小程序登录校验对象 |
| | | */ |
| | | WeChatMiniAuthorizeVo miniAuthCode(String code) throws Exception; |
| | | } |
| New file |
| | |
| | | package org.springblade.modules.wechat.service.impl; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springblade.common.config.WxMiniConfig; |
| | | import org.springblade.common.utils.HttpClientUtils; |
| | | import org.springblade.common.utils.SpringUtils; |
| | | import org.springblade.core.secure.utils.AuthUtil; |
| | | import org.springblade.modules.pay.entity.WeChatMiniAuthorizeVo; |
| | | import org.springblade.modules.system.entity.User; |
| | | import org.springblade.modules.system.service.IUserService; |
| | | import org.springblade.modules.wechat.service.WechatService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | @Service |
| | | public class WechatServiceImpl implements WechatService { |
| | | |
| | | private static final Logger logger = LoggerFactory.getLogger(WechatServiceImpl.class); |
| | | |
| | | @Resource |
| | | private WxMiniConfig wxMiniConfig; |
| | | |
| | | /** |
| | | * 小程序登录凭证校验 |
| | | * |
| | | * @return 小程序登录校验对象 |
| | | */ |
| | | @Override |
| | | public WeChatMiniAuthorizeVo miniAuthCode(String code) throws Exception { |
| | | String url = StrUtil.format(wxMiniConfig.getJscode2sessionUrl(), wxMiniConfig.getAppid(), wxMiniConfig.getSecret(), code); |
| | | JSONObject data = JSON.parseObject(HttpClientUtils.doGet(url)); |
| | | if (ObjectUtil.isNull(data)) { |
| | | logger.error("微信平台接口异常,没任何数据返回!"); |
| | | throw new Exception("微信平台接口异常,没任何数据返回!"); |
| | | } |
| | | if (data.containsKey("errcode") && !data.getString("errcode").equals("0")) { |
| | | if (data.containsKey("errmsg")) { |
| | | logger.error("微信接口调用失败:" + data.getString("errcode") + data.getString("errmsg")); |
| | | throw new Exception("微信接口调用失败:" + data.getString("errcode") + data.getString("errmsg")); |
| | | } |
| | | } |
| | | WeChatMiniAuthorizeVo weChatMiniAuthorizeVo = JSONObject.parseObject(data.toJSONString(), WeChatMiniAuthorizeVo.class); |
| | | // 绑定用户openid |
| | | Long userId = AuthUtil.getUserId(); |
| | | IUserService userService = SpringUtils.getBean(IUserService.class); |
| | | userService.update(Wrappers.<User>lambdaUpdate().set(User::getMiniOpenId, weChatMiniAuthorizeVo.getOpenId()).eq(User::getId, userId)); |
| | | return weChatMiniAuthorizeVo; |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | |
| | | appId: 202403288666059313538996533 |
| | | privateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCCL4tz9BbUz+z3vs/eFwmUmQhsTiP3ZLwruTMJuEhsTEsT58PrdUOKGipwhKF88zj8SCk/Tn8izvDXj5IzqHEWjSEkfivYHx/6cE3VdHc6vvpvpeC06264d5NN4T6hwYH9CYz9iSmx9HFxADlg5zxj0lHqLSFf25cmEPF3F7PvAzj1cmYrKjet1HtCKaAyKADD+ojHHRjNLXZg3E5CINUqRYlLi+OKQph3VdrfokkO8efe8CR2wdiGU78mV1/UtTaiSYOEwv7pkbGECkqIXp+xYzaAVNCxikIWkc+qKmvvJXKsQVOKqv5b7/FQ/ag8trWPe8JLcQCN/Zg7DXSTc9YHAgMBAAECggEAENI73punZ5AGOmy5RyUK49xyLixakVi+x5eCdLsPAI9LFCNaOU5Jj8qZuTgp9Y8nydE5IyjtXH4IuJGgfnRBSHyrz59N4vsCksV4CSCnVzvd+Bci1b2l7MfmjKWSBiyOszdMtGXIsWm4TrWMtGysbOl8FBoIue4RtaVyzcSOR0+gDCIkn2XGqh3FhSIIApYm+eTOPDLZuSOsrgoTrppTOVUCXGN+/cSBAegWQnCES0b49F2EIRCAtSybc52N7zFPB9f8Kzzmgozilf00uS27HLZplwyLA6FMargdOi619x3T/XY52a55r4ldu/aZF2EbD1RpvMi9aGH/O77HtmLfAQKBgQC/32H0ibR5BgqfUjOWS0v+GRqG0gXr4x2R/oY9Pym16F5gEFKDYauBfEK4GYDtTEahB0Wo0n57StSZ3fX6yy9uBsPxywy0yUvzkxwe2th8fBg5czEBbLzHz4RMqo7LkfwKBatKMJLCOLdecSV2uJlDt/AIRFx5ymypiVLyYHb4IQKBgQCtsjv0ThHMM861CEfe9FZ2B4LFGfCptcek95ilARc7r3RpZpSSi+K0mF2992JVen+dkPh3FuG5NM5VSJeFyReNj5RxVz8A+4d9w3fxrqi2qfC1TFHR7IRv4JzPeZ+7wkMSc7rwkJ9UBSOdecXm2FV7BOivtnf7bGWIGLJNUb7pJwKBgCu0ZkudUk5+4cyInNePLzAh57jt/gtNIF8w6sLosEePNnALR8BFbxt/gnMM3CExTqU/Us6xo73RvbuOo4kM3zDguaFJ7wr/Dx3cVHtyvf0dByeO5Yq9igK5chlEgGI+Tnq579pmVgeHg70vaKkyQzb5nuNDLw1O3pF/hjVPY8oBAoGAFLW5nElqqdRLgx43o4eyf2Qp3WJYZYO9CBhVZOcaZA1pbd/DOy3em/XGx42lddejO6A7X8ekpjZ7m4OKPXNakZBa/KCQbIeRAhe6R2Cx0QW2I4e0AbmXmNdJGxu/Rd3FrX+K/H/h31y1gGMyi3Gjz4UoUTsKVzn3aSC4satbfeUCgYEAmpIo2ZO4hQ9THCOdgR5udXRG5s5JjGEct2QSxXntRyJm3RAkPA3/mEDVlI6X5UNIn7BKeThCFo5eM2bbFFF4sFeNV0W4uP8p9dsOnpwU7FzT++16WNiBopQpff72MNzjnt/k/KLlX/zV60zbMJ1R6McYsv0LP9Zuv9RAo8v8ZDU= |
| | | sopCreateBy: 106575361457 |
| | | |
| | | wxpay: |
| | | api-v3-key: qqwuMJcCPRhcNcmFlqb6ucxdHKqVxp9U |
| | | appid: wxeeab25f4f176f1fc |
| | | domain: https://api.mch.weixin.qq.com |
| | | mch-id: 1600701071 |
| | | mch-serial-no: 4C19EAFA9E0AD598DDE3D7399B47C3D5C85EB7C9 |
| | | notify-domain: https://wx.nkjj88.com |
| | | partnerKey: qqwuMJcCPRhcNcmFlqb6ucxdHKqVxp9U |
| | | private-key-path: /www/wwwroot/apiclient_key.pem |
| | | private-cert-path: /www/wwwroot/apiclient_cert.p12 |
| | | wxmini: |
| | | appid: wxeeab25f4f176f1fc |
| | | secret: 0a0e0d0a0c0b0a09080706050403020100 |
| | | jscode2sessionUrl: https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code |