diff --git a/src/main/java/com/ycwl/basic/config/WechatConfig.java b/src/main/java/com/ycwl/basic/config/WechatConfig.java deleted file mode 100644 index ee83f8e..0000000 --- a/src/main/java/com/ycwl/basic/config/WechatConfig.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.ycwl.basic.config; - -import lombok.Data; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -/** - * 微信小程序配置 - * - * @author songmingsong - **/ -@Data -@Component -@ConfigurationProperties(prefix = "wx") -public class WechatConfig { - - /** - * 公众号的appId - */ - private String appId; - - /** - * 公众号的密钥 - */ - private String appSecret; - - - /** - * 小程序的AppId - */ - private String miniProgramAppId; - - /** - * 小程序的secret - */ - private String miniProgramSecret; - - /** - * 申请openid授权 - */ - private String grandType; - - /** - * 商户号 - */ - private String mchId; - - /** - * 商户证书序列号 - */ - private String mchSerialNo; - - /** - * 支付回调接口地址 - */ - private String payNotifyUrl; - /** - * 退款回调接口地址 - */ - private String refundNotifyUrl; - - /** - * 商户API私钥路径 - */ - private String keyPath; - - /** - * 商户APIV3密钥 - */ - private String apiV3; - -} diff --git a/src/main/java/com/ycwl/basic/controller/mobile/AppOrderController.java b/src/main/java/com/ycwl/basic/controller/mobile/AppOrderController.java index 77387c8..262e77b 100644 --- a/src/main/java/com/ycwl/basic/controller/mobile/AppOrderController.java +++ b/src/main/java/com/ycwl/basic/controller/mobile/AppOrderController.java @@ -6,7 +6,6 @@ import com.ycwl.basic.biz.PriceBiz; import com.ycwl.basic.constant.BaseContextHandler; import com.ycwl.basic.mapper.FaceMapper; import com.ycwl.basic.model.jwt.JwtInfo; -import com.ycwl.basic.model.mobile.goods.GoodsPriceQueryReq; import com.ycwl.basic.model.mobile.order.IsBuyBatchRespVO; import com.ycwl.basic.model.mobile.order.IsBuyRespVO; import com.ycwl.basic.model.mobile.order.OrderAppPageReq; @@ -14,12 +13,7 @@ import com.ycwl.basic.model.mobile.order.RefundOrderReq; import com.ycwl.basic.model.pc.face.resp.FaceRespVO; import com.ycwl.basic.model.pc.order.req.CreateBatchOrderReqVO; import com.ycwl.basic.model.pc.order.req.CreateOrderReqVO; -import com.ycwl.basic.model.pc.order.req.OrderAddReq; import com.ycwl.basic.model.pc.order.resp.OrderAppRespVO; -import com.ycwl.basic.model.wx.WxPayRespVO; -import com.ycwl.basic.repository.OrderRepository; -import com.ycwl.basic.repository.PriceRepository; -import com.ycwl.basic.service.mobile.GoodsService; import com.ycwl.basic.service.pc.OrderService; import com.ycwl.basic.utils.ApiResponse; import com.ycwl.basic.utils.JwtTokenUtil; @@ -28,6 +22,8 @@ import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.Map; + /** * @Author:longbinbin * @Date:2024/12/4 17:16 @@ -62,7 +58,7 @@ public class AppOrderController { @ApiOperation("用户端订单新增") @PostMapping("/addOrder") - public ApiResponse addOrder(@RequestBody CreateOrderReqVO orderAddReq) throws Exception { + public ApiResponse> addOrder(@RequestBody CreateOrderReqVO orderAddReq) throws Exception { JwtInfo worker = JwtTokenUtil.getWorker(); return orderService.createOrder(worker.getUserId(), orderAddReq); } @@ -70,7 +66,7 @@ public class AppOrderController { @ApiOperation("用户端打包订单新增") @PostMapping("/addBatchOrder") - public ApiResponse addOrder(@RequestBody CreateBatchOrderReqVO batchOrderReqVO) throws Exception { + public ApiResponse> addOrder(@RequestBody CreateBatchOrderReqVO batchOrderReqVO) throws Exception { JwtInfo worker = JwtTokenUtil.getWorker(); return orderService.createBatchOrder(worker.getUserId(), batchOrderReqVO); } diff --git a/src/main/java/com/ycwl/basic/controller/mobile/AppScenicController.java b/src/main/java/com/ycwl/basic/controller/mobile/AppScenicController.java index d3c9160..faa952e 100644 --- a/src/main/java/com/ycwl/basic/controller/mobile/AppScenicController.java +++ b/src/main/java/com/ycwl/basic/controller/mobile/AppScenicController.java @@ -8,6 +8,7 @@ import com.ycwl.basic.model.mobile.scenic.ScenicDeviceCountVO; import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO; import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity; import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; +import com.ycwl.basic.model.pc.scenic.resp.ScenicConfigResp; import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO; import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.service.mobile.AppScenicService; @@ -51,9 +52,24 @@ public class AppScenicController { @GetMapping("/{id}/config") @IgnoreToken - public ApiResponse getConfig(@PathVariable Long id){ + public ApiResponse getConfig(@PathVariable Long id){ ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(id); - return ApiResponse.success(scenicConfig); + ScenicConfigResp resp = new ScenicConfigResp(); + resp.setBookRoutine(scenicConfig.getBookRoutine()); + resp.setForceFinishTime(scenicConfig.getForceFinishTime()); + resp.setTourTime(scenicConfig.getTourTime()); + resp.setSampleStoreDay(scenicConfig.getSampleStoreDay()); + resp.setFaceStoreDay(scenicConfig.getFaceStoreDay()); + resp.setVideoStoreDay(scenicConfig.getVideoStoreDay()); + resp.setAllFree(scenicConfig.getAllFree()); + resp.setDisableSourceVideo(scenicConfig.getDisableSourceVideo()); + resp.setDisableSourceImage(scenicConfig.getDisableSourceImage()); + resp.setAntiScreenRecordType(scenicConfig.getAntiScreenRecordType()); + resp.setVideoSourceStoreDay(scenicConfig.getVideoSourceStoreDay()); + resp.setImageSourceStoreDay(scenicConfig.getImageSourceStoreDay()); + resp.setUserSourceExpireDay(scenicConfig.getUserSourceExpireDay()); + resp.setBrokerDirectRate(scenicConfig.getBrokerDirectRate()); + return ApiResponse.success(resp); } @ApiOperation("查询景区设备总数和拍到用户的机位数量") diff --git a/src/main/java/com/ycwl/basic/controller/mobile/AppWxPayController.java b/src/main/java/com/ycwl/basic/controller/mobile/AppWxPayController.java index 050803e..1d21f4a 100644 --- a/src/main/java/com/ycwl/basic/controller/mobile/AppWxPayController.java +++ b/src/main/java/com/ycwl/basic/controller/mobile/AppWxPayController.java @@ -10,6 +10,7 @@ import com.ycwl.basic.utils.ApiResponse; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -33,12 +34,6 @@ public class AppWxPayController { @Autowired private WxPayService wxPayService; - @ApiOperation(value = "微信预支付", notes = "微信预支付") - @PostMapping("/createOrder") - public ApiResponse createOrder(@RequestBody WXPayOrderReqVO req) throws Exception { - return ApiResponse.success(wxPayService.createOrder(req)); - } - @ApiOperation(value = "微信支付回调", notes = "微信支付回调") @PostMapping("/payNotify") @IgnoreToken @@ -46,29 +41,19 @@ public class AppWxPayController { wxPayService.payNotify(request); return ApiResponse.success(BizCodeEnum.REQUEST_OK); } - - @ApiOperation(value = "微信退款", notes = "微信退款") - @PostMapping("/refundOrder") - public ApiResponse refundOrder(@RequestBody String orderId) throws Exception { - return ApiResponse.buildResult(wxPayService.refundOrder(orderId) ? - BizCodeEnum.SUCCESS : - BizCodeEnum.ADVANCE_PAYMENT_REFUND_FAILED); + @PostMapping("/{scenicId}/payNotify") + @IgnoreToken + public ApiResponse payNotifyByScenicId(@PathVariable Long scenicId, HttpServletRequest request) { + wxPayService.payNotify(scenicId, request); + return ApiResponse.success(BizCodeEnum.REQUEST_OK); } @ApiOperation(value = "微信支付退款回调", notes = "微信支付退款回调") - @PostMapping("/refundNotify") + @PostMapping("/{scenicId}/refundNotify") @IgnoreToken - public ApiResponse refundNotify(@RequestBody String refundResult) throws GeneralSecurityException, IOException { - return ApiResponse.buildResult(wxPayService.refundNotify(refundResult) ? + public ApiResponse refundNotify(@PathVariable Long scenicId, HttpServletRequest request) throws GeneralSecurityException, IOException { + return ApiResponse.buildResult(wxPayService.refundNotify(scenicId, request) ? BizCodeEnum.SUCCESS : BizCodeEnum.ADVANCE_PAYMENT_CALLBACK_REFUND_FAILED); } - - @ApiOperation(value = "微信关闭订单", notes = "微信关闭订单") - @PostMapping("/closeOrder") - @IgnoreToken - public ApiResponse closeOrder(@RequestBody String orderId) { - wxPayService.closeOrder(orderId); - return ApiResponse.buildResult(BizCodeEnum.REQUEST_OK); - } } diff --git a/src/main/java/com/ycwl/basic/model/pc/scenic/entity/ScenicConfigEntity.java b/src/main/java/com/ycwl/basic/model/pc/scenic/entity/ScenicConfigEntity.java index d97dee8..98189ab 100644 --- a/src/main/java/com/ycwl/basic/model/pc/scenic/entity/ScenicConfigEntity.java +++ b/src/main/java/com/ycwl/basic/model/pc/scenic/entity/ScenicConfigEntity.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import com.ycwl.basic.facebody.enums.FaceBodyAdapterType; +import com.ycwl.basic.pay.enums.PayAdapterType; import com.ycwl.basic.storage.enums.StorageType; import lombok.Data; @@ -84,4 +85,7 @@ public class ScenicConfigEntity { private FaceBodyAdapterType faceType; private String faceConfigJson; + + private PayAdapterType payType; + private String payConfigJson; } diff --git a/src/main/java/com/ycwl/basic/model/pc/scenic/resp/ScenicConfigResp.java b/src/main/java/com/ycwl/basic/model/pc/scenic/resp/ScenicConfigResp.java new file mode 100644 index 0000000..92da7eb --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/pc/scenic/resp/ScenicConfigResp.java @@ -0,0 +1,45 @@ +package com.ycwl.basic.model.pc.scenic.resp; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ycwl.basic.facebody.enums.FaceBodyAdapterType; +import com.ycwl.basic.pay.enums.PayAdapterType; +import com.ycwl.basic.storage.enums.StorageType; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @Author:longbinbin + * @Date:2024/12/2 10:53 + * 景区配置 + */ +@Data +public class ScenicConfigResp { + + /** + * 预约流程,1-预约,2-在线,3-全部 + */ + private Integer bookRoutine; + private Integer forceFinishTime; + private Integer tourTime; + /** + * 样本保存时间 + */ + private Integer sampleStoreDay; + private Integer faceStoreDay; + /** + * 视频保存时间 + */ + private Integer videoStoreDay; + private Integer allFree; + private Integer disableSourceVideo; + private Integer disableSourceImage; + private Integer antiScreenRecordType; + private Integer videoSourceStoreDay; + private Integer imageSourceStoreDay; + private Integer userSourceExpireDay; + private BigDecimal brokerDirectRate; +} diff --git a/src/main/java/com/ycwl/basic/service/mobile/WxPayService.java b/src/main/java/com/ycwl/basic/service/mobile/WxPayService.java index 2a58862..d70fb6d 100644 --- a/src/main/java/com/ycwl/basic/service/mobile/WxPayService.java +++ b/src/main/java/com/ycwl/basic/service/mobile/WxPayService.java @@ -1,24 +1,26 @@ package com.ycwl.basic.service.mobile; import com.ycwl.basic.model.wx.WXPayOrderReqVO; -import com.ycwl.basic.model.wx.WxPayRespVO; import com.ycwl.basic.model.wx.WxchatCallbackSuccessData; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.security.GeneralSecurityException; +import java.util.Map; public interface WxPayService { /** * 微信预支付 */ - WxPayRespVO createOrder(WXPayOrderReqVO req) throws Exception; + Map createOrder(Long scenicId, WXPayOrderReqVO req) throws Exception; /** * 微信支付回调 */ - void payNotify(HttpServletRequest xml); + void payNotify(HttpServletRequest request); + + void payNotify(Long scenicId, HttpServletRequest request); /** @@ -38,7 +40,7 @@ public interface WxPayService { /** * 微信退款回调 */ - boolean refundNotify(String refundResult) throws IOException, GeneralSecurityException; + boolean refundNotify(Long scenicId, HttpServletRequest request) throws IOException; /** * 关闭订单 @@ -46,4 +48,5 @@ public interface WxPayService { * @param orderId 订单id(订单编号) */ void closeOrder(String orderId) ; + } diff --git a/src/main/java/com/ycwl/basic/service/mobile/impl/AppMemberServiceImpl.java b/src/main/java/com/ycwl/basic/service/mobile/impl/AppMemberServiceImpl.java index 248942a..dba4647 100644 --- a/src/main/java/com/ycwl/basic/service/mobile/impl/AppMemberServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/mobile/impl/AppMemberServiceImpl.java @@ -3,7 +3,6 @@ package com.ycwl.basic.service.mobile.impl; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.databind.ObjectMapper; -import com.ycwl.basic.config.WechatConfig; import com.ycwl.basic.constant.BaseContextHandler; import com.ycwl.basic.constant.NumberConstant; import com.ycwl.basic.constant.WeiXinConstant; diff --git a/src/main/java/com/ycwl/basic/service/mobile/impl/WxPayServiceImpl.java b/src/main/java/com/ycwl/basic/service/mobile/impl/WxPayServiceImpl.java index 224ad37..6d195fe 100644 --- a/src/main/java/com/ycwl/basic/service/mobile/impl/WxPayServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/mobile/impl/WxPayServiceImpl.java @@ -1,28 +1,8 @@ package com.ycwl.basic.service.mobile.impl; -import com.alibaba.fastjson.JSONObject; -import com.aliyuncs.utils.StringUtils; -import com.wechat.pay.java.core.Config; -import com.wechat.pay.java.core.RSAAutoCertificateConfig; -import com.wechat.pay.java.core.exception.ServiceException; -import com.wechat.pay.java.core.notification.NotificationConfig; -import com.wechat.pay.java.core.notification.NotificationParser; -import com.wechat.pay.java.core.notification.RequestParam; -import com.wechat.pay.java.core.util.PemUtil; -import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction; -import com.wechat.pay.java.service.payments.jsapi.JsapiService; -import com.wechat.pay.java.service.payments.jsapi.model.*; -import com.wechat.pay.java.service.payments.model.TransactionAmount; -import com.wechat.pay.java.service.refund.RefundService; -import com.wechat.pay.java.service.refund.model.AmountReq; -import com.wechat.pay.java.service.refund.model.CreateRequest; -import com.wechat.pay.java.service.refund.model.Refund; import com.ycwl.basic.biz.OrderBiz; -import com.ycwl.basic.config.WechatConfig; -import com.ycwl.basic.constant.HttpConstant; import com.ycwl.basic.constant.NumberConstant; -import com.ycwl.basic.constant.WeiXinConstant; import com.ycwl.basic.enums.BizCodeEnum; import com.ycwl.basic.enums.OrderStateEnum; import com.ycwl.basic.enums.StatisticEnum; @@ -35,37 +15,28 @@ import com.ycwl.basic.model.pc.order.entity.OrderEntity; import com.ycwl.basic.model.pc.order.req.OrderUpdateReq; import com.ycwl.basic.model.pc.payment.entity.PaymentEntity; import com.ycwl.basic.model.wx.WXPayOrderReqVO; -import com.ycwl.basic.model.wx.WxPayRespVO; import com.ycwl.basic.model.wx.WxchatCallbackSuccessData; +import com.ycwl.basic.pay.adapter.IPayAdapter; +import com.ycwl.basic.pay.entity.CancelOrderRequest; +import com.ycwl.basic.pay.entity.CreateOrderRequest; +import com.ycwl.basic.pay.entity.CreateOrderResponse; +import com.ycwl.basic.pay.entity.PayResponse; +import com.ycwl.basic.pay.entity.RefundResponse; +import com.ycwl.basic.pay.entity.RefundOrderRequest; +import com.ycwl.basic.pay.entity.RefundOrderResponse; import com.ycwl.basic.repository.OrderRepository; import com.ycwl.basic.service.mobile.WxPayService; +import com.ycwl.basic.service.pc.ScenicService; import com.ycwl.basic.utils.SnowFlakeUtil; -import com.ycwl.basic.utils.WXPayUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import javax.crypto.Cipher; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.spec.GCMParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.security.*; import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static com.wechat.pay.java.core.http.Constant.*; -import static com.wechat.pay.java.service.refund.model.Status.SUCCESS; -import static com.ycwl.basic.constant.WeiXinConstant.*; /** * @Author: songmingsong @@ -77,8 +48,6 @@ import static com.ycwl.basic.constant.WeiXinConstant.*; @Service public class WxPayServiceImpl implements WxPayService { - @Autowired - private WechatConfig wechatConfig; @Autowired private PaymentMapper paymentMapper; @Autowired @@ -89,116 +58,50 @@ public class WxPayServiceImpl implements WxPayService { private OrderBiz orderBiz; @Autowired private OrderMapper orderMapper; + @Autowired + private ScenicService scenicService; @Override - public WxPayRespVO createOrder(WXPayOrderReqVO req) { + public Map createOrder(Long scenicId, WXPayOrderReqVO req) { PaymentEntity entity = new PaymentEntity(); entity.setOrderId(req.getOrderSn()); entity.setMemberId(req.getMemberId()); entity.setPayPrice(new BigDecimal(BigInteger.valueOf(req.getTotalPrice()), 2)); Long entityId = paymentMapper.addGetId(entity); + IPayAdapter scenicPayAdapter = scenicService.getScenicPayAdapter(scenicId); try { - // 使用自动更新平台证书的RSA配置 - Config config = getInstance(wechatConfig); - // 构建service - JsapiService service = new JsapiService.Builder().config(config).build(); - - // request.setXxx(val)设置所需参数,具体参数可见Request定义 - PrepayRequest request = new PrepayRequest(); - Amount amount = new Amount(); - amount.setTotal(req.getTotalPrice()); - request.setAmount(amount); - request.setAppid(wechatConfig.getMiniProgramAppId()); - request.setMchid(wechatConfig.getMchId()); - request.setDescription(req.getGoodsName()); - request.setNotifyUrl(wechatConfig.getPayNotifyUrl()); - request.setOutTradeNo(req.getOrderSn().toString()); - request.setDescription(req.getDescription()); - - Payer payer = new Payer(); - payer.setOpenid(req.getOpenId()); - request.setPayer(payer); -// SettleInfo settleInfo = new SettleInfo(); -// settleInfo.setProfitSharing(true); -// request.setSettleInfo(settleInfo); - - // 调用下单方法,得到应答 - PrepayResponse response = service.prepay(request); - WxPayRespVO vo = new WxPayRespVO(); - Long timeStamp = System.currentTimeMillis() / NumberConstant.THOUSAND; - vo.setTimeStamp(timeStamp); - String substring = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32); - vo.setNonceStr(substring); - String signatureStr = Stream.of(wechatConfig.getMiniProgramAppId(), String.valueOf(timeStamp), substring, "prepay_id=" + response.getPrepayId()) - .collect(Collectors.joining("\n", "", "\n")); - String sign = WXPayUtil.getSign(signatureStr, wechatConfig.getKeyPath()); - vo.setPaySign(sign); - vo.setSignType("RSA-SHA256"); - vo.setPrepayId("prepay_id=" + response.getPrepayId()); - return vo; - } catch (ServiceException e) { - JSONObject parse = JSONObject.parseObject(e.getResponseBody()); - throw new AppException(BizCodeEnum.ADVANCE_PAYMENT_FAILED, parse.getString(HttpConstant.Message)); + CreateOrderRequest request = new CreateOrderRequest() + .setOrderNo(String.valueOf(req.getOrderSn())) + .setPriceInCents(req.getTotalPrice()) + .setDescription(req.getDescription()) + .setGoodsName(req.getGoodsName()) + .setUserIdentify(req.getOpenId()) + .setNotifyUrl("https://zhentuai.com/api/mobile/wx/pay/v1/"+scenicId+"/payNotify"); + CreateOrderResponse order = scenicPayAdapter.createOrder(request); + Map paymentParams = scenicPayAdapter.getPaymentParams(order); + paymentParams.put("needPay", !order.isSkipPay()); + return paymentParams; } catch (Exception e) { throw new AppException(BizCodeEnum.ADVANCE_PAYMENT_FAILED, e.toString()); } } @Override - public void payNotify(HttpServletRequest request) { + public void payNotify(Long scenicId, HttpServletRequest request) { + IPayAdapter scenicPayAdapter = scenicService.getScenicPayAdapter(scenicId); try { - // 读取请求体的信息 - ServletInputStream inputStream = request.getInputStream(); - StringBuffer stringBuffer = new StringBuffer(); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); - String s; - // 读取回调请求体 - while ((s = bufferedReader.readLine()) != null) { - stringBuffer.append(s); - } - String s1 = stringBuffer.toString(); - log.warn("微信支付回调:{}", s1); - String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP); - String nonce = request.getHeader(WECHAT_PAY_NONCE); - String signType = request.getHeader(WeiXinConstant.WECHATPAY_SIGNATURE_TYPE); - String serialNo = request.getHeader(WECHAT_PAY_SERIAL); - String signature = request.getHeader(WECHAT_PAY_SIGNATURE); - - NotificationConfig config = new RSAAutoCertificateConfig.Builder() - .merchantId(wechatConfig.getMchId()) - .privateKey(wechatConfig.getKeyPath()) - .merchantSerialNumber(wechatConfig.getMchSerialNo()) - .apiV3Key(wechatConfig.getApiV3()) - .build(); - // 初始化 NotificationParser - NotificationParser parser = new NotificationParser(config); - RequestParam requestParam = new RequestParam.Builder() - .serialNumber(serialNo) - .nonce(nonce) - .signature(signature) - .timestamp(timestamp) - // 若未设置signType,默认值为 WECHATPAY2-SHA256-RSA2048 - .signType(signType) - .body(s1) - .build(); - Transaction parse = parser.parse(requestParam, Transaction.class); - log.info("[微信支付]parse = {}", parse); + PayResponse callbackResponse = scenicPayAdapter.handleCallback(request); + log.info("[微信支付]parse = {}", callbackResponse); // 更新订单信息 new Thread(() -> { - long orderId = Long.parseLong(parse.getOutTradeNo()); - switch (parse.getTradeState()) { - case SUCCESS: - orderBiz.paidOrder(orderId); - break; - case NOTPAY: - case CLOSED: - case REVOKED: - orderBiz.cancelOrder(orderId); - break; - case REFUND: - orderBiz.refundOrder(orderId); - break; + long orderId = Long.parseLong(callbackResponse.getOrderNo()); + if (callbackResponse.isPay()) { + orderBiz.paidOrder(orderId); + } else if (callbackResponse.isCancel()) { + orderBiz.cancelOrder(orderId); + } else if (callbackResponse.isRefund()) { + orderBiz.refundOrder(orderId); } }).start(); } catch (Exception e) { @@ -207,59 +110,29 @@ public class WxPayServiceImpl implements WxPayService { } @Override - public WxchatCallbackSuccessData queryPay(Long orderId) { - WxchatCallbackSuccessData wxchatCallbackSuccessData = new WxchatCallbackSuccessData(); - QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest(); - queryRequest.setMchid(wechatConfig.getMchId()); - queryRequest.setOutTradeNo(orderId.toString()); - Config config = getInstance(wechatConfig); - // 构建service - JsapiService service = new JsapiService.Builder().config(config).build(); - try { - com.wechat.pay.java.service.payments.model.Transaction transaction = service.queryOrderByOutTradeNo(queryRequest); - String successTime = transaction.getSuccessTime(); + public void payNotify(HttpServletRequest request) { + payNotify(0L, request); + } - wxchatCallbackSuccessData.setOrderId(orderId.toString()); - wxchatCallbackSuccessData.setSuccessTime(successTime); - wxchatCallbackSuccessData.setTradetype(WeiXinConstant.getDescriptionType(transaction.getTradeType())); - wxchatCallbackSuccessData.setTradestate(WeiXinConstant.getDescriptionState(transaction.getTradeState())); - TransactionAmount amount = transaction.getAmount(); - Integer total = amount.getTotal(); - wxchatCallbackSuccessData.setTotalMoney(new BigDecimal(total).movePointLeft(2)); - } catch (ServiceException e) { - // API返回失败, 例如ORDER_NOT_EXISTS - log.error("[微信退款] code={}, message={}", e.getErrorCode(), e.getErrorMessage()); - log.error("[微信退款] Response_body={}", e.getResponseBody()); - } - return wxchatCallbackSuccessData; + @Override + public WxchatCallbackSuccessData queryPay(Long orderId) { + return null; } @Override public Boolean refundOrder(String orderId) { OrderEntity order = orderRepository.getOrder(Long.parseLong(orderId)); + IPayAdapter scenicPayAdapter = scenicService.getScenicPayAdapter(order.getScenicId()); BigDecimal payPrice = order.getPayPrice(); - long priceInCents = payPrice.multiply(new BigDecimal(NumberConstant.HUNDRED)).longValue(); // 转换为分(int) - - Config config = - new RSAAutoCertificateConfig.Builder() - .merchantId(wechatConfig.getMchId()) - // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名 - .privateKey(wechatConfig.getKeyPath()) - .merchantSerialNumber(wechatConfig.getMchSerialNo()) - .apiV3Key(wechatConfig.getApiV3()) - .build(); - RefundService service = new RefundService.Builder().config(config).build(); - CreateRequest request = new CreateRequest(); - request.setNotifyUrl(wechatConfig.getRefundNotifyUrl()); - AmountReq amountReq = new AmountReq(); - amountReq.setTotal(priceInCents); - amountReq.setRefund(priceInCents); - amountReq.setCurrency(WECHATPAY_CURRENCY_CNY); - request.setAmount(amountReq); - request.setOutTradeNo(orderId); - request.setOutRefundNo(SnowFlakeUtil.getId()); - Refund refundResult = service.create(request); - if (refundResult.getStatus() == SUCCESS) { + int priceInCents = payPrice.multiply(new BigDecimal(NumberConstant.HUNDRED)).intValue(); // 转换为分(int) + RefundOrderRequest request = new RefundOrderRequest() + .setOrderNo(orderId) + .setPrice(priceInCents) + .setRefundNo(SnowFlakeUtil.getId()) + .setRefundPrice(priceInCents) + .setNotifyUrl("https://zhentuai.com/api/mobile/wx/pay/v1/"+order.getScenicId()+"/refundNotify"); + RefundOrderResponse response = scenicPayAdapter.refund(request); + if (response.isSuccess()) { OrderUpdateReq orderUpdateReq = new OrderUpdateReq(); orderUpdateReq.setId(Long.parseLong(orderId)); orderUpdateReq.setRefundStatus(OrderStateEnum.REFUNDED.getType()); @@ -272,31 +145,14 @@ public class WxPayServiceImpl implements WxPayService { } @Override - public boolean refundNotify(String refundResult) throws IOException, GeneralSecurityException { - // 转为map格式 - Map jsonMap = JSONObject.parseObject(refundResult, Map.class); + public boolean refundNotify(Long scenicId, HttpServletRequest request) throws IOException { + IPayAdapter scenicPayAdapter = scenicService.getScenicPayAdapter(scenicId); + try { + RefundResponse callbackResponse = scenicPayAdapter.handleRefundCallback(request); + log.info("[微信支付]parse = {}", callbackResponse); - /* - * 退款成功后返回一个加密字段resource,以下为解密 - * 解密需要从resource参数中,获取到ciphertext,nonce,associated_data这三个参数进行解密 - */ - String resource = JSONObject.toJSONString(jsonMap.get(REFUNDS_RESOURCE)); - JSONObject object = JSONObject.parseObject(resource); - - String ciphertext = String.valueOf(object.get(REFUNDS_CIPHERTEXT)); - String nonce = String.valueOf(object.get(REFUNDS_NONCE)); - String associated_data = String.valueOf(object.get(REFUNDS_ASSOCIATED_DATA)); - - String resultStr = decryptToString(associated_data.getBytes(String.valueOf(StandardCharsets.UTF_8)), - nonce.getBytes(String.valueOf(StandardCharsets.UTF_8)), - ciphertext); - Map reqInfo = JSONObject.parseObject(resultStr, Map.class); - - String refund_status = reqInfo.get(REFUNDS_REFUND_STATUS);// 退款状态 - String out_trade_no = reqInfo.get(WECHATPAY_OUT_TRADE_NO); // 订单号 - - if (!StringUtils.isEmpty(refund_status) && WECHATPAY_SUCCESS.equals(refund_status)) { - long orderId = Long.parseLong(out_trade_no); + // 更新订单信息 + long orderId = Long.parseLong(callbackResponse.getOrderNo()); orderBiz.refundOrder(orderId); OrderEntity order = orderRepository.getOrder(orderId); @@ -306,117 +162,19 @@ public class WxPayServiceImpl implements WxPayService { statisticsRecordAddReq.setScenicId(order.getScenicId()); statisticsRecordAddReq.setMorphId(orderId); statisticsMapper.addStatisticsRecord(statisticsRecordAddReq); - - log.info("[微信退款回调]退款成功"); return true; - } else { - log.error("[微信退款回调]退款失败"); + } catch (Exception e) { + log.error("微信退款回调失败!", e); return false; } } @Override public void closeOrder(String orderId) { - CloseOrderRequest closeOrderRequest = new CloseOrderRequest(); - closeOrderRequest.setOutTradeNo(orderId); - closeOrderRequest.setMchid(wechatConfig.getMchId()); - Config config = getInstance(wechatConfig); - // 构建service - JsapiService service = new JsapiService.Builder().config(config).build(); - service.closeOrder(closeOrderRequest); - } - - - /** - * 退款回调 解密数据 - * - * @param associatedData - * @param nonce - * @param ciphertext - * @return - * @throws GeneralSecurityException - * @throws IOException - */ - public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext) throws GeneralSecurityException, IOException { - try { - Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); - SecretKeySpec key = new SecretKeySpec(wechatConfig.getApiV3().getBytes(), "AES"); - GCMParameterSpec spec = new GCMParameterSpec(128, nonce); - cipher.init(Cipher.DECRYPT_MODE, key, spec); - cipher.updateAAD(associatedData); - return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), StandardCharsets.UTF_8); - } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { - throw new IllegalStateException(e); - } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { - throw new IllegalArgumentException(e); - } - } - - - /** - * 生成退款请求token - * - * @param method - * @param orderId - * @param body - * @return - * @throws InvalidKeyException - * @throws NoSuchAlgorithmException - * @throws UnsupportedEncodingException - * @throws SignatureException - */ - public String getToken(String method, String orderId, String body) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException, SignatureException { - String nonceStr = WXPayUtil.generateNonceStr(); - long timestamp = System.currentTimeMillis() / NumberConstant.THOUSAND; // 生成时间戳 - - String parameter = method + "\n" - + REFUNDS_URi + orderId + "\n" - + timestamp + "\n" - + nonceStr + "\n" - + body + "\n"; - - // 对参数进行加密 - byte[] bytes = parameter.getBytes(String.valueOf(StandardCharsets.UTF_8)); - Signature sign = Signature.getInstance("SHA256withRSA"); - PrivateKey privateKey = PemUtil.loadPrivateKeyFromString(wechatConfig.getKeyPath()); // privateKeyPath是商户证书密钥的位置apiclient_key.pem - sign.initSign(privateKey); // 商户密钥文件路径 - sign.update(bytes); - String signature = Base64.getEncoder().encodeToString(sign.sign()); - - // 获取token - String token = "mchid=\"" + wechatConfig.getMchId() + "\"," // 商户号 - + "nonce_str=\"" + nonceStr + "\"," - + "timestamp=\"" + timestamp + "\"," - + "serial_no=\"" + wechatConfig.getMchSerialNo() + "\"," // merchantSerialNumber是微信支付中申请的证书序列号 - + "signature=\"" + signature + "\""; - - return REFUNDS_SCHEMA + token; - } - - /** - * 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错 - */ - private static class Holder { - private static volatile Config instance; - - static void init(WechatConfig wechatConfig) { - instance = new RSAAutoCertificateConfig.Builder() - .merchantId(wechatConfig.getMchId()) - .privateKey(wechatConfig.getKeyPath()) - .merchantSerialNumber(wechatConfig.getMchSerialNo()) - .apiV3Key(wechatConfig.getApiV3()) - .build(); - } - } - - public static Config getInstance(WechatConfig wechatConfig) { - if (Holder.instance == null) { - synchronized (Holder.class) { - if (Holder.instance == null) { - Holder.init(wechatConfig); - } - } - } - return Holder.instance; + OrderEntity order = orderRepository.getOrder(Long.parseLong(orderId)); + IPayAdapter scenicPayAdapter = scenicService.getScenicPayAdapter(order.getScenicId()); + CancelOrderRequest request = new CancelOrderRequest() + .setOrderNo(orderId); + scenicPayAdapter.cancelOrder(request); } } diff --git a/src/main/java/com/ycwl/basic/service/pc/OrderService.java b/src/main/java/com/ycwl/basic/service/pc/OrderService.java index fb72c7d..60602df 100644 --- a/src/main/java/com/ycwl/basic/service/pc/OrderService.java +++ b/src/main/java/com/ycwl/basic/service/pc/OrderService.java @@ -8,14 +8,13 @@ import com.ycwl.basic.model.pc.order.entity.OrderEntity; import com.ycwl.basic.model.pc.order.req.CreateBatchOrderReqVO; import com.ycwl.basic.model.pc.order.req.CreateOrderReqVO; import com.ycwl.basic.model.pc.order.req.OrderUpdateReq; -import com.ycwl.basic.model.pc.order.req.OrderAddReq; import com.ycwl.basic.model.pc.order.req.OrderReqQuery; import com.ycwl.basic.model.pc.order.resp.OrderAppRespVO; import com.ycwl.basic.model.pc.order.resp.OrderRespVO; -import com.ycwl.basic.model.wx.WxPayRespVO; import com.ycwl.basic.utils.ApiResponse; import java.util.List; +import java.util.Map; /** * @Author:longbinbin @@ -63,7 +62,7 @@ public interface OrderService { ApiResponse> refundPageQuery(OrderReqQuery query); - ApiResponse createOrder(Long userId, CreateOrderReqVO orderAddReq) throws Exception; + ApiResponse> createOrder(Long userId, CreateOrderReqVO orderAddReq) throws Exception; - ApiResponse createBatchOrder(Long userId, CreateBatchOrderReqVO batchOrderReqVO) throws Exception; + ApiResponse> createBatchOrder(Long userId, CreateBatchOrderReqVO batchOrderReqVO) throws Exception; } diff --git a/src/main/java/com/ycwl/basic/service/pc/ScenicService.java b/src/main/java/com/ycwl/basic/service/pc/ScenicService.java index d456315..15ea13d 100644 --- a/src/main/java/com/ycwl/basic/service/pc/ScenicService.java +++ b/src/main/java/com/ycwl/basic/service/pc/ScenicService.java @@ -6,6 +6,7 @@ import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity; import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq; import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO; +import com.ycwl.basic.pay.adapter.IPayAdapter; import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.utils.ApiResponse; @@ -41,4 +42,6 @@ public interface ScenicService { IStorageAdapter getScenicLocalStorageAdapter(Long scenicId); IFaceBodyAdapter getScenicFaceBodyAdapter(Long scenicId); + + IPayAdapter getScenicPayAdapter(Long scenicId); } diff --git a/src/main/java/com/ycwl/basic/service/pc/impl/OrderServiceImpl.java b/src/main/java/com/ycwl/basic/service/pc/impl/OrderServiceImpl.java index a760831..8caf9e0 100644 --- a/src/main/java/com/ycwl/basic/service/pc/impl/OrderServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/pc/impl/OrderServiceImpl.java @@ -33,7 +33,6 @@ import com.ycwl.basic.model.pc.source.entity.SourceEntity; import com.ycwl.basic.model.pc.task.entity.TaskEntity; import com.ycwl.basic.model.pc.video.entity.VideoEntity; import com.ycwl.basic.model.wx.WXPayOrderReqVO; -import com.ycwl.basic.model.wx.WxPayRespVO; import com.ycwl.basic.repository.FaceRepository; import com.ycwl.basic.repository.PriceRepository; import com.ycwl.basic.repository.VideoRepository; @@ -52,7 +51,9 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @@ -167,11 +168,12 @@ public class OrderServiceImpl implements OrderService { /** * 发起支付 - * @param order 订单 + * + * @param order 订单 * @param orderItems 商品详情 * @return 支付请求结果 */ - private WxPayRespVO initiatePayment(OrderEntity order, List orderItems) throws Exception { + private Map initiatePayment(OrderEntity order, List orderItems) throws Exception { WXPayOrderReqVO wxPayOrderReqVO = new WXPayOrderReqVO(); String goodsName = null; if (orderItems.size() > 1) { @@ -186,12 +188,6 @@ public class OrderServiceImpl implements OrderService { goodsName = "景区照片包"; } } - if (order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) { - // 0元支付 - WxPayRespVO wxPayRespVO = new WxPayRespVO(); - wxPayRespVO.setNeedPay(false); - return wxPayRespVO; - } wxPayOrderReqVO.setOpenId(order.getOpenId()) .setMemberId(order.getMemberId()) .setOrderSn(order.getId()) @@ -199,7 +195,7 @@ public class OrderServiceImpl implements OrderService { .setGoodsName(goodsName) .setDescription(goodsName); - return wxPayService.createOrder(wxPayOrderReqVO); + return wxPayService.createOrder(order.getScenicId(), wxPayOrderReqVO); } @Override @@ -360,7 +356,7 @@ public class OrderServiceImpl implements OrderService { @Override @Transactional(rollbackFor = Exception.class) - public ApiResponse createOrder(Long userId, CreateOrderReqVO createOrderReqVO) throws Exception { + public ApiResponse> createOrder(Long userId, CreateOrderReqVO createOrderReqVO) throws Exception { IsBuyRespVO isBuy = orderBiz.isBuy(userId, createOrderReqVO.getScenicId(), createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId()); if (isBuy.isBuy()) { return ApiResponse.fail("您已购买此内容,无需重复购买!"); @@ -442,16 +438,18 @@ public class OrderServiceImpl implements OrderService { } if (order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) { orderBiz.paidOrder(order.getId()); - return ApiResponse.success(new WxPayRespVO()); + HashMap data = new HashMap<>(); + data.put("needPay", false); + return ApiResponse.success(data); } else { - WxPayRespVO wxPayRespVO = initiatePayment(order, orderItems); + Map wxPayRespVO = initiatePayment(order, orderItems); return ApiResponse.success(wxPayRespVO); } } @Override @Transactional(rollbackFor = Exception.class) - public ApiResponse createBatchOrder(Long userId, CreateBatchOrderReqVO batchOrderReqVO) throws Exception { + public ApiResponse> createBatchOrder(Long userId, CreateBatchOrderReqVO batchOrderReqVO) throws Exception { PriceConfigEntity priceConfig = priceRepository.getPriceConfigByScenicTypeGoods(batchOrderReqVO.getScenicId(), batchOrderReqVO.getType(), batchOrderReqVO.getGoodsId()); if (priceConfig == null) { return ApiResponse.fail("该套餐暂未开放购买"); @@ -504,9 +502,11 @@ public class OrderServiceImpl implements OrderService { } if (order.getPayPrice().equals(BigDecimal.ZERO)) { orderBiz.paidOrder(order.getId()); - return ApiResponse.success(new WxPayRespVO()); + HashMap data = new HashMap<>(); + data.put("needPay", false); + return ApiResponse.success(data); } else { - WxPayRespVO wxPayRespVO = initiatePayment(order, orderItems); + Map wxPayRespVO = initiatePayment(order, orderItems); return ApiResponse.success(wxPayRespVO); } } diff --git a/src/main/java/com/ycwl/basic/service/pc/impl/ScenicServiceImpl.java b/src/main/java/com/ycwl/basic/service/pc/impl/ScenicServiceImpl.java index bc90eb6..8f0d5e2 100644 --- a/src/main/java/com/ycwl/basic/service/pc/impl/ScenicServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/pc/impl/ScenicServiceImpl.java @@ -12,6 +12,8 @@ import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity; import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq; import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO; +import com.ycwl.basic.pay.PayFactory; +import com.ycwl.basic.pay.adapter.IPayAdapter; import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.service.pc.ScenicService; import com.ycwl.basic.service.task.TaskFaceService; @@ -106,6 +108,7 @@ public class ScenicServiceImpl implements ScenicService { scenicRepository.clearCache(id); scenicFaceBodyAdapterMap.remove(id); scenicStorageAdapterMap.remove(id); + scenicPayAdapterMap.remove(id); return ApiResponse.success(true); }else { return ApiResponse.fail("景区删除失败"); @@ -200,6 +203,7 @@ public class ScenicServiceImpl implements ScenicService { scenicStorageAdapterMap.remove(config.getScenicId()); scenicTmpStorageAdapterMap.remove(config.getScenicId()); scenicLocalStorageAdapterMap.remove(config.getScenicId()); + scenicPayAdapterMap.remove(config.getScenicId()); } @@ -276,4 +280,20 @@ public class ScenicServiceImpl implements ScenicService { return adapter; }); } + + private static final Map scenicPayAdapterMap = new ConcurrentHashMap<>(); + @Override + public IPayAdapter getScenicPayAdapter(Long scenicId) { + return scenicPayAdapterMap.computeIfAbsent(scenicId, (key) -> { + IPayAdapter adapter; + ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId); + if (scenicConfig != null && scenicConfig.getPayType() != null) { + adapter = PayFactory.getAdapter(scenicConfig.getPayType()); + adapter.loadConfig(JSONObject.parseObject(scenicConfig.getPayConfigJson(), Map.class)); + } else { + adapter = PayFactory.use(); + } + return adapter; + }); + } } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 20703da..67f4aa7 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -49,60 +49,6 @@ mybatis-plus: # 指定使用的日志配置文件 logging: config: classpath:logback-spring.xml -# 微信小程序相关配置 -wx: - # 公众号的appId - appId: fix - # 公众号的密钥 - appSecret: fix - # 小程序的AppId - miniProgramAppId: wxe7ff26af70bfc37c - # 小程序的secret - miniProgramSecret: 5252fbbc68513bc77b7cc0052b9f9695 - # 申请openid授权 - grandType: authorization_code - # 推送模板 - push: - templateId: 5b8vTm7kvwYubqDxb3dxBqFIhc3Swt5l7QHSK5r-ZRI - # 商户号 - mchId: 1700540331 - # 商户证书序列号 - mchSerialNo: 2AD248A1D15F0056D6AEC20B4EEF53F3C32CBFF0 - # 支付回调接口地址 - payNotifyUrl: https://zhentuai.com/api/mobile/wx/pay/v1/payNotify - # 退款回调接口地址 - refundNotifyUrl: https://zhentuai.com/api/mobile/wx/pay/v1/refundNotify - # 商户API私钥路径 - keyPath: "-----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHwDoab8iRX4vn -Ta3a+gh5Z3wcyTM3VkWhkAPJGNJhaNgzOBI9b4v1x+uSZ4To2uXhQE5hvcxWSfNZ -F7H6yp+6estADeZLpdXLBDBvPDOjEGhG7YUHJjWnFh5eY2Rtnx4/7x+xCsRS+Mtq -Mx6KMrb4UZYNIq14peTQgfICkDBdqnUIkFjDmChUy0LlsSFW8AyJIqrBec5VZWf/ -QqsIBf9vsTVxrqlX+5owYZuPYoFOIQJFUW8dfU20qk//BxiDjPFZBLNa02aIEbNF -SXZE2TlKD7zD0Qv/w95Hf1V+a/cxP2B6LNtqwioIdHbU6Axu7uHkr0RSPXPsvOWY -eUIpGP4bAgMBAAECggEBALm34w3TYtKu2D/tfDh9gkWGTuHgu6q2nrTxVmOxnWEN -/v3YIzVVsfaJs2ACuZNaeqNsi7PaqNKNnSD3o/X+UHYsVy8t/THWdSl1sqapfYUd -6yYPDkEwaG/6Y6/0j1pQt+pPpNKRpSlTwqTx9HIfZvkHuhBqbokfDNhECUQS1bUu -8pmyALIkuXu38B/xCs/EH+Lp1N69IA0mwalT/2zi9ZJhGNg5OWBzNbkMKf2Tck+9 -SnS6s+pAT6YxB9qYhg645H3dRKXdeSYbjI+uiIe/7cJvTxfQDLD/oDap2TJQH3iM -SVbSfNFbR1tH6PiYx9eXeElEg2QXEPztbf8NcUlGOGkCgYEA8PewLVzUdHD20KkX -tZP+JCvSTy2f0kPHTc3+BU+MOlG8uZzsK06efo+X5BGkMRj8P+MPp9rJQr5IJqJl -GpeA1XpF54v2DIcNcjrQHIJ9XWoWirZjMWRVn4D5laQTI+FEV8pyFfJJOLIgBe9b -c6hBHNnAB4Y6JZ/s+US4ymK4wQ0CgYEA1DZMcuyiUgjnprUsOIokpg8RxGLIvB5+ -2FyCffa/CikMRU8bRtHdpJLguArrR9rEILU6fICPARdlCg8r0XMrvniiAaS3YlDj -tSxbfrrS6xySvVFdNusv/j3i5/76IedsSArJLeQpIZMZ3n6q/dmq4kbWh+bT/5z+ -MVpjWixpYccCgYBtaEh5kDh2VgP6YYv+SZ+OVMc8Y/64vUV0sh6v0ppcsFf7/p/M -WfnkhNX2G3xtPmbpqvKkx9WxlCu2Pu2g0UERrF6o7wdcUMVuI/3xs92v2Ec72+vV -tTSbIzgvFTwLgnBBXA3IoSVVtKqNh0wCi1Zk/wkNYYhtJNu3odg1K/Wu0QKBgBOv -IbI7TucrGkm1Xm+0KKgal7xOqW4BqiRpmFUU0S2hFxlKuC3+g3+jfCK2KJLWsQCT -ruQjjKA+Skn/lEHuW+1kBSr/217MQALrJWWA8NWMJfRXmrzgXehIV0bLuOnyLHIW -Rgjys/oAShMATt4TFa29gmLCv4FjT5TGXJbdrby7AoGBAOqER71Vi90UV84sYLWx -DSW/3q5/QrndmeeaQALslA6sidnTZWqlhMsNPl8dfBKl6xnrCdcaeY5xk/xmVOqP -0KedJgT+IjLwY1yJ9QOBd02ejAY3qNlKt2NiSWv2GBY1cZxqhkHNaI/UWI9CAyH5 -YfkdFNxtYLdVAwuylMoV3fKI ------END PRIVATE KEY-----" - # 商户APIV3密钥 - apiV3: ZHENTUAIzhentuaiZHENTUAIzhentuai # 存储 storage: @@ -168,7 +114,45 @@ facebody: accessKeyId: "LTAI5tMwrmxVcUEKoH5QzLHx" accessKeySecret: "ZCIP8aKx1jwX1wkeYIPQEDZ8fPtN1c" region: "cn-shanghai" - +#支付 +pay: + default-use: zt + configs: + - name: zt + type: WX_MP_PAY + config: + merchantId: "1700540331" + appId: "wxe7ff26af70bfc37c" + privateKey: "-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHwDoab8iRX4vn +Ta3a+gh5Z3wcyTM3VkWhkAPJGNJhaNgzOBI9b4v1x+uSZ4To2uXhQE5hvcxWSfNZ +F7H6yp+6estADeZLpdXLBDBvPDOjEGhG7YUHJjWnFh5eY2Rtnx4/7x+xCsRS+Mtq +Mx6KMrb4UZYNIq14peTQgfICkDBdqnUIkFjDmChUy0LlsSFW8AyJIqrBec5VZWf/ +QqsIBf9vsTVxrqlX+5owYZuPYoFOIQJFUW8dfU20qk//BxiDjPFZBLNa02aIEbNF +SXZE2TlKD7zD0Qv/w95Hf1V+a/cxP2B6LNtqwioIdHbU6Axu7uHkr0RSPXPsvOWY +eUIpGP4bAgMBAAECggEBALm34w3TYtKu2D/tfDh9gkWGTuHgu6q2nrTxVmOxnWEN +/v3YIzVVsfaJs2ACuZNaeqNsi7PaqNKNnSD3o/X+UHYsVy8t/THWdSl1sqapfYUd +6yYPDkEwaG/6Y6/0j1pQt+pPpNKRpSlTwqTx9HIfZvkHuhBqbokfDNhECUQS1bUu +8pmyALIkuXu38B/xCs/EH+Lp1N69IA0mwalT/2zi9ZJhGNg5OWBzNbkMKf2Tck+9 +SnS6s+pAT6YxB9qYhg645H3dRKXdeSYbjI+uiIe/7cJvTxfQDLD/oDap2TJQH3iM +SVbSfNFbR1tH6PiYx9eXeElEg2QXEPztbf8NcUlGOGkCgYEA8PewLVzUdHD20KkX +tZP+JCvSTy2f0kPHTc3+BU+MOlG8uZzsK06efo+X5BGkMRj8P+MPp9rJQr5IJqJl +GpeA1XpF54v2DIcNcjrQHIJ9XWoWirZjMWRVn4D5laQTI+FEV8pyFfJJOLIgBe9b +c6hBHNnAB4Y6JZ/s+US4ymK4wQ0CgYEA1DZMcuyiUgjnprUsOIokpg8RxGLIvB5+ +2FyCffa/CikMRU8bRtHdpJLguArrR9rEILU6fICPARdlCg8r0XMrvniiAaS3YlDj +tSxbfrrS6xySvVFdNusv/j3i5/76IedsSArJLeQpIZMZ3n6q/dmq4kbWh+bT/5z+ +MVpjWixpYccCgYBtaEh5kDh2VgP6YYv+SZ+OVMc8Y/64vUV0sh6v0ppcsFf7/p/M +WfnkhNX2G3xtPmbpqvKkx9WxlCu2Pu2g0UERrF6o7wdcUMVuI/3xs92v2Ec72+vV +tTSbIzgvFTwLgnBBXA3IoSVVtKqNh0wCi1Zk/wkNYYhtJNu3odg1K/Wu0QKBgBOv +IbI7TucrGkm1Xm+0KKgal7xOqW4BqiRpmFUU0S2hFxlKuC3+g3+jfCK2KJLWsQCT +ruQjjKA+Skn/lEHuW+1kBSr/217MQALrJWWA8NWMJfRXmrzgXehIV0bLuOnyLHIW +Rgjys/oAShMATt4TFa29gmLCv4FjT5TGXJbdrby7AoGBAOqER71Vi90UV84sYLWx +DSW/3q5/QrndmeeaQALslA6sidnTZWqlhMsNPl8dfBKl6xnrCdcaeY5xk/xmVOqP +0KedJgT+IjLwY1yJ9QOBd02ejAY3qNlKt2NiSWv2GBY1cZxqhkHNaI/UWI9CAyH5 +YfkdFNxtYLdVAwuylMoV3fKI +-----END PRIVATE KEY-----" + serialNumber: "2AD248A1D15F0056D6AEC20B4EEF53F3C32CBFF0" + apiV3Key: ZHENTUAIzhentuaiZHENTUAIzhentuai notify: defaultUse: "" configs: diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 3ddc212..e91b6fc 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -54,57 +54,6 @@ mybatis-plus: # 指定使用的日志配置文件 logging: config: classpath:logback-spring-prod.xml -# 微信小程序相关配置 -wx: - # 公众号的appId - appId: fix - # 公众号的密钥 - appSecret: fix - # 小程序的AppId - miniProgramAppId: wxe7ff26af70bfc37c - # 小程序的secret - miniProgramSecret: 5252fbbc68513bc77b7cc0052b9f9695 - # 申请openid授权 - grandType: authorization_code - # 商户号 - mchId: 1700540331 - # 商户证书序列号 - mchSerialNo: 2AD248A1D15F0056D6AEC20B4EEF53F3C32CBFF0 - # 支付回调接口地址 - payNotifyUrl: https://zhentuai.com/api/mobile/wx/pay/v1/payNotify - # 退款回调接口地址 - refundNotifyUrl: https://zhentuai.com/api/mobile/wx/pay/v1/refundNotify - # 商户API私钥路径 - keyPath: "-----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHwDoab8iRX4vn -Ta3a+gh5Z3wcyTM3VkWhkAPJGNJhaNgzOBI9b4v1x+uSZ4To2uXhQE5hvcxWSfNZ -F7H6yp+6estADeZLpdXLBDBvPDOjEGhG7YUHJjWnFh5eY2Rtnx4/7x+xCsRS+Mtq -Mx6KMrb4UZYNIq14peTQgfICkDBdqnUIkFjDmChUy0LlsSFW8AyJIqrBec5VZWf/ -QqsIBf9vsTVxrqlX+5owYZuPYoFOIQJFUW8dfU20qk//BxiDjPFZBLNa02aIEbNF -SXZE2TlKD7zD0Qv/w95Hf1V+a/cxP2B6LNtqwioIdHbU6Axu7uHkr0RSPXPsvOWY -eUIpGP4bAgMBAAECggEBALm34w3TYtKu2D/tfDh9gkWGTuHgu6q2nrTxVmOxnWEN -/v3YIzVVsfaJs2ACuZNaeqNsi7PaqNKNnSD3o/X+UHYsVy8t/THWdSl1sqapfYUd -6yYPDkEwaG/6Y6/0j1pQt+pPpNKRpSlTwqTx9HIfZvkHuhBqbokfDNhECUQS1bUu -8pmyALIkuXu38B/xCs/EH+Lp1N69IA0mwalT/2zi9ZJhGNg5OWBzNbkMKf2Tck+9 -SnS6s+pAT6YxB9qYhg645H3dRKXdeSYbjI+uiIe/7cJvTxfQDLD/oDap2TJQH3iM -SVbSfNFbR1tH6PiYx9eXeElEg2QXEPztbf8NcUlGOGkCgYEA8PewLVzUdHD20KkX -tZP+JCvSTy2f0kPHTc3+BU+MOlG8uZzsK06efo+X5BGkMRj8P+MPp9rJQr5IJqJl -GpeA1XpF54v2DIcNcjrQHIJ9XWoWirZjMWRVn4D5laQTI+FEV8pyFfJJOLIgBe9b -c6hBHNnAB4Y6JZ/s+US4ymK4wQ0CgYEA1DZMcuyiUgjnprUsOIokpg8RxGLIvB5+ -2FyCffa/CikMRU8bRtHdpJLguArrR9rEILU6fICPARdlCg8r0XMrvniiAaS3YlDj -tSxbfrrS6xySvVFdNusv/j3i5/76IedsSArJLeQpIZMZ3n6q/dmq4kbWh+bT/5z+ -MVpjWixpYccCgYBtaEh5kDh2VgP6YYv+SZ+OVMc8Y/64vUV0sh6v0ppcsFf7/p/M -WfnkhNX2G3xtPmbpqvKkx9WxlCu2Pu2g0UERrF6o7wdcUMVuI/3xs92v2Ec72+vV -tTSbIzgvFTwLgnBBXA3IoSVVtKqNh0wCi1Zk/wkNYYhtJNu3odg1K/Wu0QKBgBOv -IbI7TucrGkm1Xm+0KKgal7xOqW4BqiRpmFUU0S2hFxlKuC3+g3+jfCK2KJLWsQCT -ruQjjKA+Skn/lEHuW+1kBSr/217MQALrJWWA8NWMJfRXmrzgXehIV0bLuOnyLHIW -Rgjys/oAShMATt4TFa29gmLCv4FjT5TGXJbdrby7AoGBAOqER71Vi90UV84sYLWx -DSW/3q5/QrndmeeaQALslA6sidnTZWqlhMsNPl8dfBKl6xnrCdcaeY5xk/xmVOqP -0KedJgT+IjLwY1yJ9QOBd02ejAY3qNlKt2NiSWv2GBY1cZxqhkHNaI/UWI9CAyH5 -YfkdFNxtYLdVAwuylMoV3fKI ------END PRIVATE KEY-----" - # 商户APIV3密钥 - apiV3: ZHENTUAIzhentuaiZHENTUAIzhentuai # 存储 storage: @@ -171,7 +120,45 @@ facebody: accessKeyId: "LTAI5tMwrmxVcUEKoH5QzLHx" accessKeySecret: "ZCIP8aKx1jwX1wkeYIPQEDZ8fPtN1c" region: "cn-shanghai" - +#支付 +pay: + default-use: zt + configs: + - name: zt + type: WX_MP_PAY + config: + merchantId: "1700540331" + appId: "wxe7ff26af70bfc37c" + privateKey: "-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHwDoab8iRX4vn +Ta3a+gh5Z3wcyTM3VkWhkAPJGNJhaNgzOBI9b4v1x+uSZ4To2uXhQE5hvcxWSfNZ +F7H6yp+6estADeZLpdXLBDBvPDOjEGhG7YUHJjWnFh5eY2Rtnx4/7x+xCsRS+Mtq +Mx6KMrb4UZYNIq14peTQgfICkDBdqnUIkFjDmChUy0LlsSFW8AyJIqrBec5VZWf/ +QqsIBf9vsTVxrqlX+5owYZuPYoFOIQJFUW8dfU20qk//BxiDjPFZBLNa02aIEbNF +SXZE2TlKD7zD0Qv/w95Hf1V+a/cxP2B6LNtqwioIdHbU6Axu7uHkr0RSPXPsvOWY +eUIpGP4bAgMBAAECggEBALm34w3TYtKu2D/tfDh9gkWGTuHgu6q2nrTxVmOxnWEN +/v3YIzVVsfaJs2ACuZNaeqNsi7PaqNKNnSD3o/X+UHYsVy8t/THWdSl1sqapfYUd +6yYPDkEwaG/6Y6/0j1pQt+pPpNKRpSlTwqTx9HIfZvkHuhBqbokfDNhECUQS1bUu +8pmyALIkuXu38B/xCs/EH+Lp1N69IA0mwalT/2zi9ZJhGNg5OWBzNbkMKf2Tck+9 +SnS6s+pAT6YxB9qYhg645H3dRKXdeSYbjI+uiIe/7cJvTxfQDLD/oDap2TJQH3iM +SVbSfNFbR1tH6PiYx9eXeElEg2QXEPztbf8NcUlGOGkCgYEA8PewLVzUdHD20KkX +tZP+JCvSTy2f0kPHTc3+BU+MOlG8uZzsK06efo+X5BGkMRj8P+MPp9rJQr5IJqJl +GpeA1XpF54v2DIcNcjrQHIJ9XWoWirZjMWRVn4D5laQTI+FEV8pyFfJJOLIgBe9b +c6hBHNnAB4Y6JZ/s+US4ymK4wQ0CgYEA1DZMcuyiUgjnprUsOIokpg8RxGLIvB5+ +2FyCffa/CikMRU8bRtHdpJLguArrR9rEILU6fICPARdlCg8r0XMrvniiAaS3YlDj +tSxbfrrS6xySvVFdNusv/j3i5/76IedsSArJLeQpIZMZ3n6q/dmq4kbWh+bT/5z+ +MVpjWixpYccCgYBtaEh5kDh2VgP6YYv+SZ+OVMc8Y/64vUV0sh6v0ppcsFf7/p/M +WfnkhNX2G3xtPmbpqvKkx9WxlCu2Pu2g0UERrF6o7wdcUMVuI/3xs92v2Ec72+vV +tTSbIzgvFTwLgnBBXA3IoSVVtKqNh0wCi1Zk/wkNYYhtJNu3odg1K/Wu0QKBgBOv +IbI7TucrGkm1Xm+0KKgal7xOqW4BqiRpmFUU0S2hFxlKuC3+g3+jfCK2KJLWsQCT +ruQjjKA+Skn/lEHuW+1kBSr/217MQALrJWWA8NWMJfRXmrzgXehIV0bLuOnyLHIW +Rgjys/oAShMATt4TFa29gmLCv4FjT5TGXJbdrby7AoGBAOqER71Vi90UV84sYLWx +DSW/3q5/QrndmeeaQALslA6sidnTZWqlhMsNPl8dfBKl6xnrCdcaeY5xk/xmVOqP +0KedJgT+IjLwY1yJ9QOBd02ejAY3qNlKt2NiSWv2GBY1cZxqhkHNaI/UWI9CAyH5 +YfkdFNxtYLdVAwuylMoV3fKI +-----END PRIVATE KEY-----" + serialNumber: "2AD248A1D15F0056D6AEC20B4EEF53F3C32CBFF0" + apiV3Key: ZHENTUAIzhentuaiZHENTUAIzhentuai # 通知到人 notify: defaultUse: "developer" diff --git a/src/main/resources/mapper/ScenicMapper.xml b/src/main/resources/mapper/ScenicMapper.xml index 1092602..5c7f8d9 100644 --- a/src/main/resources/mapper/ScenicMapper.xml +++ b/src/main/resources/mapper/ScenicMapper.xml @@ -118,7 +118,9 @@ watermark_scenic_text=#{watermarkScenicText}, watermark_dt_format=#{watermarkDtFormat}, face_type=#{faceType}, - face_config_json=#{faceConfigJson} + face_config_json=#{faceConfigJson}, + pay_type=#{payType}, + pay_config_json=#{payConfigJson} where id = #{id}