提交 24c167a4 作者: zhenjie

Merge branch 'develop'

......@@ -19,9 +19,9 @@ spec:
- name: payment
image: REGISTRY/NAMESPACE/IMAGE:TAG
readinessProbe:
initialDelaySeconds: 480
periodSeconds: 10
failureThreshold: 20
initialDelaySeconds: 15
periodSeconds: 5
failureThreshold: 10
httpGet:
path: /payment/actuator/health/readiness
port: payment-port
......@@ -31,9 +31,7 @@ spec:
- name: localtime
mountPath: /etc/localtime
readOnly: true
resources:
limits:
cpu: 100m
resources: { }
ports:
- containerPort: 8088
name: payment-port
......
......@@ -14,4 +14,4 @@ patches:
images:
- name: REGISTRY/NAMESPACE/IMAGE:TAG
newName: mmc-registry.cn-shenzhen.cr.aliyuncs.com/sharefly-dev/payment
newTag: bf09b8fcc929d18f19e3d92b52a9eb85cdc3b5c9
newTag: 01f38f32f51899d7bdc6a4ec9743138ad2011e65
......@@ -14,8 +14,10 @@
<name>payment</name>
<description>Demo project for Spring Boot</description>
<properties>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
......@@ -23,6 +25,31 @@
<scope>test</scope>
</dependency>
<!-- 微信支付相关 -->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.9</version>
</dependency>
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.10</version>
</dependency>
<!-- 工具类 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
......@@ -80,7 +107,43 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 引入 Feign, 可以以声明的方式调用微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 使用okhttp-feign-连接池技术 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<!-- 引入服务容错 Hystrix 的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!-- 标识 SpringCloud 的版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
......
......@@ -2,8 +2,10 @@ package com.mmc.payment;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients(basePackages = "com.mmc.payment.feign")
public class PayMentApplication {
public static void main(String[] args) {
......
package com.mmc.payment.common.publicinterface;
/**
* @author: zj
* @Date: 2023/5/16 16:32
*/
public interface Insert {
}
\ No newline at end of file
package com.mmc.payment.constant;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author: zj
* @Date: 2023/5/16 13:34
*/
@Data
@Component
public class UserSystemConstant {
@Value("${wx.app.id}")
private String wxAppId;
@Value("${wx.app.secret}")
private String wxAppSecret;
@Value("${wx.app.miniprogram-state}")
private String miniProgramState;
@Value("${wx.app.env-version}")
private String envVersion;
@Value("${wx.sub.appid}")
private String wxSubAppId;
@Value("${wx.sub.secret}")
private String wxSubSecret;
@Value("${wx.pay.mchid}")
private String mchid;
@Value("${wx.pay.api-v3-key}")
private String apiv3Key;
@Value("${wx.pay.mch-number}")
private String mchNumber;
@Value("${wx.pay.notify-url}")
private String notifyUrl;
@Value("${data.file.url}")
private String privateKeyFromPath;
@Value("${wx.pay.refund-notify-url}")
private String refundNotifyUrl;
}
package com.mmc.payment.constant;
/**
* @Author LW
* @date 2023/7/19 17:10
* 概要:
*/
public interface WechatConstant {
String privateKeyPath = "src/main/resources/apiclient_key.pem";
Integer ORDER_PAY_SUCCESS_STATUS_CODE = 200;
}
package com.mmc.payment.controller;
import com.alibaba.fastjson2.JSONObject;
import com.mmc.payment.common.result.ResultEnum;
import com.mmc.payment.exception.BizException;
import com.mmc.payment.model.dto.user.LoginSuccessDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import javax.servlet.http.HttpServletRequest;
/**
* @author: zj
* @Date: 2023/5/25 18:11
*/
public abstract class BaseController {
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 使用token从redis获取用户信息
*
* @param request
* @return
*/
public LoginSuccessDTO getUserLoginInfoFromRedis(HttpServletRequest request) {
String token = request.getHeader("token");
if (StringUtils.isBlank(token)) {
throw new BizException(ResultEnum.LOGIN_ACCOUNT_STATUS_ERROR);
}
String json = stringRedisTemplate.opsForValue().get(token);
if (StringUtils.isBlank(json)) {
throw new BizException(ResultEnum.LOGIN_ACCOUNT_STATUS_ERROR);
}
LoginSuccessDTO loginSuccessDTO = JSONObject.parseObject(json, LoginSuccessDTO.class);
return loginSuccessDTO;
}
}
package com.mmc.payment.controller;
import com.mmc.payment.common.result.ResultBody;
import com.mmc.payment.model.vo.order.ApplyRefundVO;
import com.mmc.payment.model.vo.order.OrderRequestParamsVO;
import com.mmc.payment.model.vo.order.UserPayInfoVO;
import com.mmc.payment.service.WechatPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
/**
* @Author LW
* @date 2023/7/19 14:26
* 概要:
*/
@Api(tags = {"微信支付-相关接口"})
@RestController
@RequestMapping("/wechat/")
public class WechatPayController extends BaseController {
@Resource
WechatPayService wechatPayService;
@ApiOperation(value = "小程序调起支付API")
@ApiResponses({@ApiResponse(code = 200, message = "OK", response = ResultBody.class)})
@PostMapping("pay")
public Map orderPay(@RequestBody OrderRequestParamsVO orderRequestParamsVO, HttpServletRequest request) throws IOException {
return wechatPayService.orderPay(orderRequestParamsVO, this.getUserLoginInfoFromRedis(request).getUserAccountId(), request);
}
@ApiOperation(value = "支付异步通知")
@ApiResponses({@ApiResponse(code = 200, message = "OK", response = ResultBody.class)})
@PostMapping("payCallback")
public Map payCallback(HttpServletRequest request) {
return wechatPayService.payCallback(request);
}
@ApiOperation(value = "关闭订单")
@ApiResponses({@ApiResponse(code = 200, message = "OK", response = ResultBody.class)})
@GetMapping("closeOrder")
public ResultBody closeOrder(String orderNo) {
return wechatPayService.closeOrder(orderNo);
}
@ApiOperation(value = "根据交易号或订单编号查询订单")
@ApiResponses({@ApiResponse(code = 200, message = "OK", response = ResultBody.class)})
@GetMapping("queryOrder")
public ResultBody queryOrder(@RequestParam(required = false) String transactionId,
@RequestParam(required = false) String orderNo) {
return wechatPayService.queryOrder(transactionId, orderNo);
}
@ApiOperation(value = "申请退款")
@ApiResponses({@ApiResponse(code = 200, message = "OK", response = ResultBody.class)})
@PostMapping("applyRefund")
public ResultBody applyRefund(@RequestBody ApplyRefundVO applyRefundVO) {
return wechatPayService.applyRefund(applyRefundVO);
}
@ApiOperation(value = "退款异步通知")
@ApiResponses({@ApiResponse(code = 200, message = "OK", response = ResultBody.class)})
@PostMapping("refundCallback")
public Map refundCallback(HttpServletRequest request) {
return wechatPayService.refundCallback(request);
}
@ApiOperation(value = "查询退款")
@ApiResponses({@ApiResponse(code = 200, message = "OK", response = ResultBody.class)})
@PostMapping("queryRefund")
public ResultBody queryRefund(String outRefundNo) {
return wechatPayService.queryRefund(outRefundNo);
}
@ApiOperation(value = "订单编号查询订单")
@ApiResponses({@ApiResponse(code = 200, message = "OK", response = UserPayInfoVO.class)})
@GetMapping("queryUserPayInfo")
public UserPayInfoVO queryUserPayInfo(@RequestParam(required = false) String orderNo) {
return wechatPayService.queryUserPayInfo(orderNo);
}
}
package com.mmc.payment.dao;
import com.mmc.payment.entity.order.ApplyRefundLogDO;
import com.mmc.payment.entity.order.WxPayLogDO;
import org.apache.ibatis.annotations.Mapper;
/**
* @Author LW
* @date 2023/7/19 17:20
* 概要:
*/
@Mapper
public interface WechatPayDao {
void insertWxPayLog(WxPayLogDO wxPayLogDO);
WxPayLogDO selectWxPayInfoByOrderNo(String orderNo);
void updateWxPayLog(WxPayLogDO wxPayLogDO);
void deleteWxPayLogByOrderNo(String orderNo);
void insertApplyRefundLog(ApplyRefundLogDO applyRefundLogDO);
void updateApplyRefundLog(ApplyRefundLogDO applyRefundLogDO);
}
package com.mmc.payment.entity.order;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author LW
* @date 2023/7/22 16:23
* 概要:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApplyRefundLogDO {
private Integer id;
private String orderNo;
private String transactionId;
private String outRefundNo;
private String reason;
private Integer total;
private Long refund;
private String currency;
private String refundId;
private String channel;
private String userReceivedAccount;
private String successTime;
private String createTime;
private String refundStatus;
private String fundsAccount;
private String notifyRefundStatus;
}
package com.mmc.payment.entity.order;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @Author LW
* @date 2023/7/19 17:16
* 概要:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class WxPayLogDO {
private Integer id;
private Integer orderPort;
private String orderNo;
private Integer amount;
private String openId;
private String description;
private String prepayId;
private Integer userAccountId;
private String outTradeNo;
private String transactionId;
private String bankType;
private String attach;
private String successTime;
private String wxNotifyOpenid;
private Integer wxNotifyTotal;
private Integer wxNotifyPayerTotal;
private String tradeType;
private String tradeState;
private String tradeStateDesc;
private Date createTime;
private Date updateTime;
}
package com.mmc.payment.enums;
/**
* @author 作者 geDuo
* @version 创建时间:2021年10月14日 下午4:08:18
* @explain 0下单初始化->100待分配运营->200需求确认->300订单确认->400待支付->500调度中->600作业中->700验收通过->900订单关闭
*/
/**
* 0下单成功-> 100(待分配运营)已分配运营-> 200(待需求确认)已经需求确认-> 300(待确认订单)已确认订单->
* 400(待预支付)已预支付-> 500(调度中)调度完成-> 600(作业中)作业完成-> 700(待验收结算)验收通过-> 900订单关闭
*
* @author geDuo
*/
public enum OrderPayStatus {
WAIT("WAIT", "待支付"),
SUCCESS("SUCCESS", "支付成功"),
REFUND("REFUND", "转入退款"),
NOTPAY("NOTPAY", "未支付"),
CLOSED("CLOSED", "已关闭"),
REVOKED("REVOKED", "已撤销(付款码支付)"),
USERPAYING("USERPAYING", "用户支付中(付款码支付)"),
PAYERROR("PAYERROR", "支付失败(其他原因,如银行返回失败)");
private String status;
private String doing;
OrderPayStatus(String status, String doing) {
this.status = status;
this.doing = doing;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getDoing() {
return doing;
}
public void setDoing(String doing) {
this.doing = doing;
}
}
package com.mmc.payment.feign;
import com.mmc.payment.feign.hystrix.UserAppApiHystrix;
import com.mmc.payment.model.dto.user.UserAccountSimpleDTO;
import com.mmc.payment.model.qo.UserAccountQO;
import com.mmc.payment.model.vo.user.BUserAccountQO;
import io.swagger.annotations.ApiParam;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author: zj
* @Date: 2023/5/18 17:06
*/
//@FeignClient(name = "cms-svc", fallback = UserAppApiHystrix.class)
@FeignClient(url = "${iuav.userapp.url}", name = "cms-svc", fallback = UserAppApiHystrix.class)
public interface UserAppApi {
/**
* 根据用户id获取基本信息
*
* @param userAccountId
* @return
*/
@RequestMapping(value = "/userapp/user-account/feignGetUserSimpleInfo", method = RequestMethod.GET)
public UserAccountSimpleDTO feignGetUserSimpleInfo(@RequestParam Integer userAccountId, @RequestHeader("token") String token);
/**
* 根据地区信息查询用户id
*
* @param provinceCode
* @param cityCode
* @param districtCode
* @return
*/
@GetMapping("/userapp/user-account/feignListUserAccountIds")
List<Integer> feignListUserAccountIds(@RequestParam Integer provinceCode, @RequestParam(required = false) Integer cityCode,
@RequestParam(required = false) Integer districtCode, @RequestHeader(value = "token", required = false) String token);
/**
* 获取后台用户集合列表页面
*
* @param bUserAccountQO 问:b用户帐户
* @return {@link List}<{@link UserAccountSimpleDTO}>
*/
@PostMapping("/userapp/back-user/feignListBAccountPage")
List<UserAccountSimpleDTO> feignListBAccountPage(@ApiParam(value = "账号查询QO", required = true) @RequestBody BUserAccountQO bUserAccountQO, @RequestHeader("token") String token);
/**
* 获取小程序用户集合列表页面
*
* @param userAccountQO
* @param token
* @return
*/
@PostMapping("/userapp/user-account/feignListAppUserAccount")
List<UserAccountSimpleDTO> feignListAppUserAccount(@ApiParam(value = "账号查询QO", required = true) @RequestBody UserAccountQO userAccountQO, @RequestHeader("token") String token);
}
package com.mmc.payment.feign.config;
import com.mmc.payment.feign.hystrix.UserAppApiHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @author: zj
* @Date: 2023/5/18 18:21
*/
@ComponentScan(basePackages = "com.mmc.payment.feign")
@Configuration
public class FeignConfiguration {
@Bean(name = "userAppApiHystrix")
public UserAppApiHystrix userAppApi() {
return new UserAppApiHystrix();
}
}
package com.mmc.payment.feign.hystrix;
import com.mmc.payment.feign.UserAppApi;
import com.mmc.payment.model.dto.user.UserAccountSimpleDTO;
import com.mmc.payment.model.qo.UserAccountQO;
import com.mmc.payment.model.vo.user.BUserAccountQO;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
/**
* @author: zj
* @Date: 2023/5/18 17:08
*/
@Slf4j
public class UserAppApiHystrix implements UserAppApi {
@Override
public UserAccountSimpleDTO feignGetUserSimpleInfo(Integer userAccountId, String token) {
log.error("熔断:feignGetUserSimpleInfo:{}", userAccountId);
return null;
}
@Override
public List<Integer> feignListUserAccountIds(Integer provinceCode, Integer cityCode, Integer districtCode, String token) {
log.error("熔断:feignListUserAccountIds:{}, {}, {}", provinceCode, cityCode, districtCode);
return null;
}
@Override
public List<UserAccountSimpleDTO> feignListBAccountPage(BUserAccountQO bUserAccountQO, String token) {
log.error("熔断:feignListBAccountPage:{}", bUserAccountQO);
return null;
}
@Override
public List<UserAccountSimpleDTO> feignListAppUserAccount(UserAccountQO userAccountQO, String token) {
log.error("熔断:feignListAppUserAccount:{}", userAccountQO);
return null;
}
}
......@@ -39,7 +39,8 @@ public class AuthSignatureFilter implements AuthFilter {
* 无需登录白名单
*/
private static final String[] IGNORE_URLS = {"/payment/swagger-resources"
, "/payment/v2/api-docs", "/payment/repocash/walletUsers", "/payment/doc.html","/payment/actuator/health/readiness"};
, "/payment/v2/api-docs", "/payment/repocash/walletUsers", "/payment/doc.html",
"/payment/actuator/health/readiness", "/payment/wechat/payCallback", "/payment/wechat/refundCallback"};
/*无需加密狗无需登录白名单*/
private static final String[] USE_KEY = {"/oms/account/loginByUsbKey"};
......
package com.mmc.payment.model.dto.user;
import com.mmc.payment.model.dto.role.RoleInfoDTO;
import com.mmc.payment.model.vo.user.CompanyInfoVO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author 作者 geDuo
* @version 创建时间:2021年8月31日 下午8:06:14
* @explain 类说明
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginSuccessDTO implements Serializable {
private static final long serialVersionUID = -1200834589953161925L;
private String token;
private Integer userAccountId;
private String accountNo;
private Integer portType;
private String uid;
private String phoneNum;
private String userName;
private String nickName;
private CompanyInfoVO companyInfoVO;
private RoleInfoDTO roleInfo;
}
package com.mmc.payment.model.dto.user;
import com.mmc.payment.model.vo.user.CooperationTagVO;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
......@@ -7,18 +8,18 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* @Author small
* @Date 2023/5/25 17:50
* @Version 1.0
* @author: zj
* @Date: 2023/5/18 17:25
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UserAccountSimpleDTO implements Serializable {
private static final long serialVersionUID = 3451336520607073343L;
private static final long serialVersionUID = -4408363798593041955L;
@ApiModelProperty(value = "用户id")
private Integer id;
@ApiModelProperty(value = "用户类型")
......@@ -33,6 +34,8 @@ public class UserAccountSimpleDTO implements Serializable {
private String nickName;
@ApiModelProperty(value = "用户头像")
private String userImg;
@ApiModelProperty(value = "openid")
private String openid;
@ApiModelProperty(value = "用户性别:0未知、1男、2女")
private Integer userSex;
@ApiModelProperty(value = "用户邮箱")
......@@ -45,6 +48,6 @@ public class UserAccountSimpleDTO implements Serializable {
private Integer portType;
@ApiModelProperty(value = "企业认证状态, 0未通过,1通过")
private Integer companyAuthStatus;
@ApiModelProperty(value = "账号")
private String accountNo;
@ApiModelProperty(value = "用户合作标签")
private List<CooperationTagVO> cooperationTagVOS;
}
package com.mmc.payment.model.vo.order;
import com.wechat.pay.java.service.refund.model.GoodsDetail;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @Author LW
* @date 2023/7/22 14:51
* 概要:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApplyRefundVO {
@ApiModelProperty(value = "商户订单号", required = true)
private String outTradeNo;
@ApiModelProperty(value = "退款原因")
private String reason;
@ApiModelProperty(value = "退款金额", required = true)
private Long refund;
@ApiModelProperty(value = "商品信息(可填可不填)")
private List<GoodsDetail> goodsDetail;
}
package com.mmc.payment.model.vo.order;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @Author LW
* @date 2023/7/19 16:20
* 概要:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrderRequestParamsVO implements Serializable {
@ApiModelProperty(value = "订单编号")
private String orderNo;
@ApiModelProperty(value = "商品描述")
private String description;
@ApiModelProperty(value = "订单金额(分为单位)")
private Integer amount;
@ApiModelProperty(value = "订单来源 0:产品商城 1:租赁订单 2:培训订单 ...其他后续加")
private Integer orderPort;
}
package com.mmc.payment.model.vo.order;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author LW
* @date 2023/7/19 17:16
* 概要:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserPayInfoVO {
@ApiModelProperty("订单号")
private String outTradeNo;
@ApiModelProperty("支付成功时间")
private String successTime;
@ApiModelProperty("用户支付金额")
private Integer wxNotifyPayerTotal;
@ApiModelProperty("交易状态")
private String tradeState;
@ApiModelProperty("用户id")
private Integer userAccountId;
}
package com.mmc.payment.model.vo.order;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author LW
* @date 2023/7/19 17:16
* 概要:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class WxPayLogVO {
@ApiModelProperty("订单号")
private String outTradeNo;
@ApiModelProperty("付款银行")
private String bankType;
@ApiModelProperty("附加信息")
private String attach;
@ApiModelProperty("支付成功时间")
private String successTime;
@ApiModelProperty("支付者openid")
private String wxNotifyOpenid;
@ApiModelProperty("总金额")
private Integer wxNotifyTotal;
@ApiModelProperty("用户支付金额")
private Integer wxNotifyPayerTotal;
@ApiModelProperty("交易类型")
private String tradeType;
@ApiModelProperty("交易状态")
private String tradeState;
@ApiModelProperty("交易状态描述")
private String tradeStateDesc;
}
package com.mmc.payment.model.vo.user;
import com.mmc.payment.common.publicinterface.Page;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
/**
* @author: zj
* @Date: 2023/5/25 13:32
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BUserAccountQO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "关键字", required = false)
private String keyword;
@ApiModelProperty(value = "地区", required = false)
private String area;
@ApiModelProperty(value = "省份编码", required = false)
private Integer provinceCode;
@ApiModelProperty(value = "城市编码", required = false)
private Integer cityCode;
@ApiModelProperty(value = "县区编码", required = false)
private Integer districtCode;
@ApiModelProperty(value = "角色id", required = false)
private Integer roleId;
@ApiModelProperty(value = "账号状态:0禁用 1可用")
private Integer accountStatus;
@ApiModelProperty(value = "账号状态:0合伙人 1员工")
private Integer userType;
@ApiModelProperty(value = "用户id集合")
private List<Integer> userIds;
@ApiModelProperty(value = "推荐单位id")
private Integer rcdCompanyId;
@ApiModelProperty(value = "单位集合", hidden = true)
private List<Integer> companys;
@ApiModelProperty(value = "页码", required = true)
@NotNull(message = "页码不能为空", groups = Page.class)
@Min(value = 1, groups = Page.class)
private Integer pageNo;
@ApiModelProperty(value = "每页显示数", required = true)
@NotNull(message = "每页显示数不能为空", groups = Page.class)
@Min(value = 1, groups = Page.class)
private Integer pageSize;
public void buildCurrentPage() {
this.pageNo = (pageNo - 1) * pageSize;
}
}
package com.mmc.payment.model.vo.user;
import com.mmc.payment.common.publicinterface.Insert;
import com.mmc.payment.common.publicinterface.Update;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @author: zj
* @Date: 2023/7/3 16:04
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CompanyInfoVO implements Serializable {
private static final long serialVersionUID = 3247519744829926132L;
@ApiModelProperty(value = "id")
@NotNull(message = "id不能为空", groups = {Update.class})
private Integer id;
@ApiModelProperty(value = "单位类型,0科比特,1加盟公司", example = "0")
@NotNull(message = "单位类型不能为空", groups = {Insert.class})
private Integer companyType;
@ApiModelProperty(value = "单位名称", example = "科比特")
@NotNull(message = "单位名称不能为空", groups = {Insert.class})
private String companyName;
@ApiModelProperty(value = "单位全称", example = "浙江科比特创新科技有限公司")
private String fullName;
@ApiModelProperty(value = "省份名称", example = "广东省")
@NotNull(message = "省份名称不能为空", groups = {Insert.class})
private String province;
@ApiModelProperty(value = "城市名称", example = "深圳市")
@NotNull(message = "城市名称不能为空", groups = {Insert.class})
private String city;
@ApiModelProperty(value = "县区名称", example = "南山区")
@NotNull(message = "县区名称不能为空", groups = {Insert.class})
private String district;
@ApiModelProperty(value = "详细地址", example = "西丽街道万科云城国际创新谷6栋")
@NotNull(message = "详细地址不能为空", groups = {Insert.class})
private String address;
@ApiModelProperty(value = "联系人", example = "lx")
private String companyUserName;
@ApiModelProperty(value = "联系电话", example = "13925255742")
private String phoneNum;
@ApiModelProperty(value = "备注")
private String remark;
}
package com.mmc.payment.model.vo.user;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* @author: zj
* @Date: 2023/5/17 21:27
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CooperationTagVO implements Serializable {
private static final long serialVersionUID = 8884567706797525506L;
@ApiModelProperty(value = "id")
private Integer id;
@ApiModelProperty(value = "合作标签名称")
private String tagName;
@ApiModelProperty(value = "合作标签img")
private String tagImg;
@ApiModelProperty(value = "合作标签描述")
private String tagDescription;
@ApiModelProperty(value = "注意事项")
private String tagRequire;
@ApiModelProperty(value = "创建时间")
private Date createTime;
}
......@@ -99,7 +99,7 @@ public class RepoCashServiceImpl implements RepoCashService {
UserAccountSimpleDTO account = JSON.parseObject(responseEntity.getBody(), UserAccountSimpleDTO.class);
list.stream().forEach(t -> {
if (t.getCreateUser().equals(account.getId())) {
t.setAccountName(account.getAccountNo());
t.setAccountName(account.getUserName());
t.setUserName(account.getUserName());
}
});
......
package com.mmc.payment.service.Impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSONObject;
import com.mmc.payment.common.result.ResultBody;
import com.mmc.payment.common.util.CodeUtil;
import com.mmc.payment.common.util.TDateUtil;
import com.mmc.payment.constant.UserSystemConstant;
import com.mmc.payment.dao.WechatPayDao;
import com.mmc.payment.entity.order.ApplyRefundLogDO;
import com.mmc.payment.entity.order.WxPayLogDO;
import com.mmc.payment.enums.OrderPayStatus;
import com.mmc.payment.feign.UserAppApi;
import com.mmc.payment.model.dto.user.UserAccountSimpleDTO;
import com.mmc.payment.model.vo.order.ApplyRefundVO;
import com.mmc.payment.model.vo.order.OrderRequestParamsVO;
import com.mmc.payment.model.vo.order.UserPayInfoVO;
import com.mmc.payment.model.vo.order.WxPayLogVO;
import com.mmc.payment.service.WechatPayService;
import com.mmc.payment.util.WxConfigUtils;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.cipher.SignatureResult;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
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.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @Author LW
* @date 2023/7/19 16:56
* 概要:
*/
@Service
@Slf4j
public class WechatPayServiceImpl implements WechatPayService {
@Resource
UserSystemConstant userSystemConstant;
@Resource
WechatPayDao wechatPayDao;
@Resource
UserAppApi userAppApi;
@Resource
WxConfigUtils wxConfigUtils;
@Override
@Transactional(rollbackFor = Exception.class)
public Map orderPay(OrderRequestParamsVO orderRequestParamsVO, Integer userAccountId, HttpServletRequest request) {
UserAccountSimpleDTO userSimpleInfo = userAppApi.feignGetUserSimpleInfo(userAccountId, request.getHeader("token"));
if (userSimpleInfo == null) {
throw new RuntimeException("服务器内部错误!");
}
Config config = wxConfigUtils.createConfig();
// 查询该订单是否已下单
WxPayLogDO wxPayLogDO = wechatPayDao.selectWxPayInfoByOrderNo(orderRequestParamsVO.getOrderNo());
if (wxPayLogDO != null && wxPayLogDO.getTradeState().equals(OrderPayStatus.SUCCESS.getStatus())) {
throw new RuntimeException("订单已支付!");
} else if (wxPayLogDO == null) {
// 构建service
JsapiService jsapiService = new JsapiService.Builder().config(config).build();
// request.setXxx(val)设置所需参数,具体参数可见Request定义
PrepayRequest prepayRequest = new PrepayRequest();
Amount amount = new Amount();
amount.setTotal(orderRequestParamsVO.getAmount());
prepayRequest.setAmount(amount);
Payer payer = new Payer();
payer.setOpenid(userSimpleInfo.getOpenid());
prepayRequest.setPayer(payer);
prepayRequest.setAppid(userSystemConstant.getWxAppId());
prepayRequest.setMchid(userSystemConstant.getMchid());
prepayRequest.setDescription(orderRequestParamsVO.getDescription());
prepayRequest.setNotifyUrl(userSystemConstant.getNotifyUrl());
prepayRequest.setOutTradeNo(orderRequestParamsVO.getOrderNo());
// 调用下单方法,得到应答
PrepayResponse prepay = jsapiService.prepay(prepayRequest);
String prepayId = prepay.getPrepayId();
// 录入数据库记录数据
WxPayLogDO wxPrepayLogDO = new WxPayLogDO();
wxPrepayLogDO.setOrderPort(orderRequestParamsVO.getOrderPort());
wxPrepayLogDO.setOrderNo(orderRequestParamsVO.getOrderNo());
wxPrepayLogDO.setDescription(orderRequestParamsVO.getDescription());
wxPrepayLogDO.setUserAccountId(userAccountId);
wxPrepayLogDO.setAmount(orderRequestParamsVO.getAmount());
wxPrepayLogDO.setPrepayId(prepayId);
wxPrepayLogDO.setOpenId(userSimpleInfo.getOpenid());
wxPrepayLogDO.setTradeState(OrderPayStatus.WAIT.getStatus());
// 往数据库插入下单的日志信息
wechatPayDao.insertWxPayLog(wxPrepayLogDO);
Map<String, Object> map = getSignInfoMap(config, prepayId);
return map;
} else {
Map<String, Object> map = getSignInfoMap(config, wxPayLogDO.getPrepayId());
return map;
}
}
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> getSignInfoMap(Config config, String prepayId) {
// 获取时间戳
String timeStamp = System.currentTimeMillis() / 1000 + "";
// 获取随机字符串
String nonceStr = RandomUtil.randomString(32);
// 签名方式
String signType = "RSA";
// 订单详情扩展字符串
String prepayPackage = "prepay_id=" + prepayId;
// 构造签名串
StringBuilder sb = new StringBuilder();
sb.append(userSystemConstant.getWxAppId()).append("\n");
sb.append(timeStamp).append("\n");
sb.append(nonceStr).append("\n");
sb.append(prepayPackage).append("\n");
// 生成签名
SignatureResult sign = config.createSigner().sign(sb.toString());
Map<String, Object> map = new HashMap<>(16);
map.put("timeStamp", timeStamp);
map.put("nonceStr", nonceStr);
map.put("package", prepayPackage);
map.put("signType", signType);
map.put("paySign", sign);
return map;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Map payCallback(HttpServletRequest request) {
Map<String, String> result = new HashMap(16);
result.put("code", "FAIL");
// 获取应答时间戳
String timestamp = request.getHeader("Wechatpay-Timestamp");
// 获取应答随机串
String nonce = request.getHeader("Wechatpay-Nonce");
// 获取应答签名
String signature = request.getHeader("Wechatpay-Signature");
// 获取应答序列号
String serialNumber = request.getHeader("Wechatpay-Serial");
log.info("应答时间戳: {},应答随机串:{},应答签名:{},应答序列号{}", timestamp, nonce, signature, serialNumber);
try {
// 获取body请求报文
BufferedReader br = request.getReader();
String str = null;
StringBuilder sb = new StringBuilder();
while ((str = br.readLine()) != null) {
sb.append(str);
}
log.info("请求体数据:{}", sb);
NotificationConfig config = wxConfigUtils.createNotificationConfig();
// 构造 RequestParam
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(serialNumber)
.nonce(nonce)
.signature(signature)
.timestamp(timestamp)
.body(sb.toString())
.build();
// 初始化 NotificationParser
NotificationParser parser = new NotificationParser(config);
// 以支付通知回调为例,验签、解密并转换成 Transaction
Transaction transaction = parser.parse(requestParam, Transaction.class);
log.info("解密resource数据:{}", transaction);
WxPayLogDO wxPayLogDO = new WxPayLogDO();
wxPayLogDO.setOutTradeNo(transaction.getOutTradeNo());
wxPayLogDO.setTransactionId(transaction.getTransactionId());
wxPayLogDO.setBankType(transaction.getBankType());
wxPayLogDO.setAttach(transaction.getAttach());
wxPayLogDO.setSuccessTime(transaction.getSuccessTime());
wxPayLogDO.setWxNotifyOpenid(transaction.getPayer().getOpenid());
wxPayLogDO.setWxNotifyTotal(transaction.getAmount().getTotal());
wxPayLogDO.setWxNotifyPayerTotal(transaction.getAmount().getPayerTotal());
wxPayLogDO.setTradeType(transaction.getTradeType().toString());
wxPayLogDO.setTradeState(transaction.getTradeState().toString());
wxPayLogDO.setTradeStateDesc(transaction.getTradeStateDesc());
wechatPayDao.updateWxPayLog(wxPayLogDO);
result.put("code", "SUCCESS");
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
public ResultBody closeOrder(String orderNo) {
Config config = wxConfigUtils.createConfig();
// 构建service
JsapiService jsapiService = new JsapiService.Builder().config(config).build();
CloseOrderRequest closeRequest = new CloseOrderRequest();
closeRequest.setMchid(userSystemConstant.getMchid());
closeRequest.setOutTradeNo(orderNo);
// 方法没有返回值,意味着成功时API返回204 No Content
jsapiService.closeOrder(closeRequest);
// 删除数据库记录
wechatPayDao.deleteWxPayLogByOrderNo(orderNo);
return ResultBody.success();
}
@Override
public ResultBody queryOrder(String transactionId, String orderNo) {
try {
Config config = wxConfigUtils.createConfig();
// 构建service
JsapiService service = new JsapiService.Builder().config(config).build();
if (orderNo != null) {
QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
queryRequest.setOutTradeNo(orderNo);
queryRequest.setMchid(userSystemConstant.getMchid());
Transaction result = service.queryOrderByOutTradeNo(queryRequest);
return getTransactionInfo(result);
}
if (transactionId != null) {
QueryOrderByIdRequest queryRequest = new QueryOrderByIdRequest();
queryRequest.setTransactionId(transactionId);
queryRequest.setMchid(userSystemConstant.getMchid());
Transaction result = service.queryOrderById(queryRequest);
return getTransactionInfo(result);
}
} catch (ServiceException e) {
String responseBody = e.getResponseBody();
JSONObject jsonObject = JSONObject.parseObject(responseBody);
return ResultBody.error(jsonObject.getString("message"));
}
return ResultBody.success();
}
private ResultBody getTransactionInfo(Transaction result) {
WxPayLogVO wxPayLogVO = new WxPayLogVO();
wxPayLogVO.setOutTradeNo(result.getOutTradeNo());
wxPayLogVO.setBankType(result.getBankType());
wxPayLogVO.setAttach(result.getAttach());
wxPayLogVO.setSuccessTime(result.getSuccessTime());
wxPayLogVO.setWxNotifyOpenid(result.getPayer() == null ? null : result.getPayer().getOpenid());
wxPayLogVO.setWxNotifyTotal(result.getAmount() == null ? null : result.getAmount().getTotal());
wxPayLogVO.setWxNotifyPayerTotal(result.getAmount() == null ? null : result.getAmount().getPayerTotal());
wxPayLogVO.setTradeType(result.getTradeType() == null ? null : result.getTradeType().toString());
wxPayLogVO.setTradeState(result.getTradeState() == null ? null : result.getTradeState().toString());
wxPayLogVO.setTradeStateDesc(result.getTradeStateDesc());
return ResultBody.success(wxPayLogVO);
}
@Override
public Map refundCallback(HttpServletRequest request) {
Map<String, String> result = new HashMap(16);
result.put("code", "FAIL");
// 获取应答时间戳
String timestamp = request.getHeader("Wechatpay-Timestamp");
// 获取应答随机串
String nonce = request.getHeader("Wechatpay-Nonce");
// 获取应答签名
String signature = request.getHeader("Wechatpay-Signature");
// 获取应答序列号
String serialNumber = request.getHeader("Wechatpay-Serial");
log.info("应答时间戳: {},应答随机串:{},应答签名:{},应答序列号{}", timestamp, nonce, signature, serialNumber);
try {
// 获取body请求报文
BufferedReader br = request.getReader();
String str = null;
StringBuilder sb = new StringBuilder();
while ((str = br.readLine()) != null) {
sb.append(str);
}
log.info("请求体数据:{}", sb);
NotificationConfig config = wxConfigUtils.createNotificationConfig();
// 构造 RequestParam
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(serialNumber)
.nonce(nonce)
.signature(signature)
.timestamp(timestamp)
.body(sb.toString())
.build();
// 初始化 NotificationParser
NotificationParser parser = new NotificationParser(config);
// 验签、解密并转换成 Refund
RefundNotification parse = parser.parse(requestParam, RefundNotification.class);
log.info("解密resource数据:{}", parser);
ApplyRefundLogDO applyRefundLogDO = new ApplyRefundLogDO();
applyRefundLogDO.setNotifyRefundStatus(parse.getRefundStatus().toString());
applyRefundLogDO.setOrderNo(parse.getOutTradeNo());
applyRefundLogDO.setSuccessTime(parse.getSuccessTime());
wechatPayDao.updateApplyRefundLog(applyRefundLogDO);
result.put("code", "SUCCESS");
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public ResultBody applyRefund(ApplyRefundVO applyRefundVO) {
log.info("=======申请退款信息入库=======");
ApplyRefundLogDO refundInfo = this.createRefundInfo(applyRefundVO);
Config config = wxConfigUtils.createConfig();
log.info("========调用微信退款接口=========");
// 初始化服务
RefundService service = new RefundService.Builder().config(config).build();
try {
CreateRequest request = new CreateRequest();
request.setOutTradeNo(applyRefundVO.getOutTradeNo());
request.setOutRefundNo(refundInfo.getOutRefundNo());
request.setReason(refundInfo.getReason());
// 创建退款金额对象
AmountReq amountReq = new AmountReq();
amountReq.setTotal(Long.valueOf(refundInfo.getTotal()));
amountReq.setRefund(applyRefundVO.getRefund());
amountReq.setCurrency("CNY");
request.setNotifyUrl(userSystemConstant.getRefundNotifyUrl());
request.setAmount(amountReq);
if (CollectionUtil.isNotEmpty(applyRefundVO.getGoodsDetail())) {
request.setGoodsDetail(applyRefundVO.getGoodsDetail());
}
Refund refund = service.create(request);
this.updateRefundInfo(refund);
return ResultBody.success();
} catch (HttpException e) {
log.info("申请退款HttpException日志打印:{}", e.getHttpRequest());
return ResultBody.error("申请退款出错,请联系技术人员上服务器查询日志!");
} catch (ServiceException e) {
log.info("申请退款ServiceException日志打印:{}", e.getResponseBody());
return ResultBody.error("申请退款出错,请联系技术人员上服务器查询日志!");
} catch (MalformedMessageException e) {
log.info("申请退款MalformedMessageException日志打印:{}", e.getMessage());
return ResultBody.error("申请退款出错,请联系技术人员上服务器查询日志!");
}
}
private void updateRefundInfo(Refund refund) {
ApplyRefundLogDO applyRefundLogDO = new ApplyRefundLogDO();
applyRefundLogDO.setRefundId(refund.getRefundId());
applyRefundLogDO.setTransactionId(refund.getTransactionId());
applyRefundLogDO.setChannel(refund.getChannel().toString());
applyRefundLogDO.setUserReceivedAccount(refund.getUserReceivedAccount());
applyRefundLogDO.setSuccessTime(refund.getSuccessTime());
applyRefundLogDO.setCreateTime(refund.getCreateTime());
applyRefundLogDO.setRefundStatus(refund.getStatus() == null ? null : refund.getStatus().toString());
applyRefundLogDO.setFundsAccount(refund.getFundsAccount() == null ? null : refund.getFundsAccount().toString());
applyRefundLogDO.setOrderNo(refund.getOutTradeNo());
wechatPayDao.updateApplyRefundLog(applyRefundLogDO);
}
@Transactional(rollbackFor = Exception.class)
public ApplyRefundLogDO createRefundInfo(ApplyRefundVO applyRefundVO) {
// 生成商户退款订单号
String outRefundNo = "RF" + TDateUtil.getDateStr(new Date(), "yyyyMMddHHmmss") + CodeUtil.getRandomNum(4);
// 查询订单信息
WxPayLogDO wxPayLogDO = wechatPayDao.selectWxPayInfoByOrderNo(applyRefundVO.getOutTradeNo());
ApplyRefundLogDO applyRefundLogDO = new ApplyRefundLogDO();
applyRefundLogDO.setReason(applyRefundVO.getReason());
applyRefundLogDO.setOrderNo(applyRefundVO.getOutTradeNo());
applyRefundLogDO.setOutRefundNo(outRefundNo);
applyRefundLogDO.setRefund(applyRefundVO.getRefund());
applyRefundLogDO.setTotal(wxPayLogDO.getAmount());
applyRefundLogDO.setCurrency("CNY");
wechatPayDao.insertApplyRefundLog(applyRefundLogDO);
return applyRefundLogDO;
}
@Override
public ResultBody queryRefund(String outRefundNo) {
Config config = wxConfigUtils.createConfig();
// 初始化服务
RefundService service = new RefundService.Builder().config(config).build();
QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
request.setOutRefundNo(outRefundNo);
Refund refund = service.queryByOutRefundNo(request);
ApplyRefundLogDO applyRefundLogDO = new ApplyRefundLogDO();
applyRefundLogDO.setRefundId(refund.getRefundId());
applyRefundLogDO.setOutRefundNo(refund.getOutRefundNo());
applyRefundLogDO.setTransactionId(refund.getTransactionId());
applyRefundLogDO.setOrderNo(refund.getOutTradeNo());
applyRefundLogDO.setChannel(refund.getChannel().toString());
applyRefundLogDO.setUserReceivedAccount(refund.getUserReceivedAccount());
applyRefundLogDO.setSuccessTime(refund.getSuccessTime() == null ? null : refund.getSuccessTime());
applyRefundLogDO.setCreateTime(refund.getCreateTime());
applyRefundLogDO.setRefundStatus(refund.getStatus().toString());
applyRefundLogDO.setTotal(Math.toIntExact(refund.getAmount().getTotal()));
applyRefundLogDO.setRefund(refund.getAmount().getRefund());
applyRefundLogDO.setCurrency(refund.getAmount().getCurrency());
return ResultBody.success(applyRefundLogDO);
}
@Override
public UserPayInfoVO queryUserPayInfo(String orderNo) {
WxPayLogDO wxPayLogDO = wechatPayDao.selectWxPayInfoByOrderNo(orderNo);
UserPayInfoVO userPayInfoVO = new UserPayInfoVO();
userPayInfoVO.setOutTradeNo(wxPayLogDO.getOutTradeNo());
userPayInfoVO.setSuccessTime(wxPayLogDO.getSuccessTime());
userPayInfoVO.setWxNotifyPayerTotal(wxPayLogDO.getWxNotifyPayerTotal());
userPayInfoVO.setUserAccountId(wxPayLogDO.getUserAccountId());
userPayInfoVO.setTradeState(wxPayLogDO.getTradeState());
return userPayInfoVO;
}
}
package com.mmc.payment.service;
import com.mmc.payment.common.result.ResultBody;
import com.mmc.payment.model.vo.order.ApplyRefundVO;
import com.mmc.payment.model.vo.order.OrderRequestParamsVO;
import com.mmc.payment.model.vo.order.UserPayInfoVO;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
/**
* @Author LW
* @date 2023/7/19 16:56
* 概要:
*/
public interface WechatPayService {
Map orderPay(OrderRequestParamsVO orderRequestParamsVO, Integer userAccountId, HttpServletRequest request) throws IOException;
Map payCallback(HttpServletRequest request);
ResultBody closeOrder(String orderNo);
ResultBody queryOrder(String transactionId, String orderNo);
ResultBody applyRefund(ApplyRefundVO applyRefundVO);
Map refundCallback(HttpServletRequest request);
ResultBody queryRefund(String outRefundNo);
UserPayInfoVO queryUserPayInfo(String orderNo);
}
package com.mmc.payment.util;
import com.mmc.payment.constant.UserSystemConstant;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @Author LW
* @date 2023/7/20 10:36
* 概要:
*/
@Component
public class WxConfigUtils {
@Resource
UserSystemConstant userSystemConstant;
public Config createConfig() {
// 使用自动更新平台证书的RSA配置
// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
Config config =
new RSAAutoCertificateConfig.Builder()
.merchantId(userSystemConstant.getMchid())
.privateKey(userSystemConstant.getPrivateKeyFromPath())
.merchantSerialNumber(userSystemConstant.getMchNumber())
.apiV3Key(userSystemConstant.getApiv3Key())
.build();
return config;
}
public NotificationConfig createNotificationConfig() {
// 使用自动更新平台证书的RSA配置
// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
NotificationConfig config =
new RSAAutoCertificateConfig.Builder()
.merchantId(userSystemConstant.getMchid())
.privateKey(userSystemConstant.getPrivateKeyFromPath())
.merchantSerialNumber(userSystemConstant.getMchNumber())
.apiV3Key(userSystemConstant.getApiv3Key())
.build();
return config;
}
}
......@@ -27,6 +27,24 @@ aliyun:
access-key-secret: ${OSS_ACCESS_KEY_SECRET}
bucket: pad-video-x
wx:
sub:
appid: wx5c6a105a0ddca4c5
secret: 96c75255dd26f82f8d55e15b59e101c7
app:
id: wx18b7883acd204278
secret: 28afe74ba373830237a8133a7431ee82
miniprogram-state: trial
env-version: trial
token-path: /userservlet/wechat/getAppletUserAccessToken
port: user
pay:
mchid: 1648653533 #商户id
mch-number: 7BF5931E5A177A94E2F3A41C839A616ECBA86718 #商户序列号
api-v3-key: MMcaFDcly5Eb5o0nTNZdu3ek8DDh4K1B #apiv3密钥
notify-url: https://test.iuav.shop/payment/wechat/payCallback
refund-notify-url: https://test.iuav.shop/payment/wechat/refundCallback
mmcflying:
download:
path: /ossservlet/upload/download/
......@@ -39,4 +57,38 @@ userapp:
oms:
url: https://test.iuav.shop/oms/
iuav:
userapp:
url: http://cms-svc:35150
data:
file:
# url: classpath:apiclient_key.pem
url: "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCpxxR1ZZCLlLn+
XWCX90UrJE6iT9S4Fbf28WMIdqgtsk9IHuIFEy4jfKc/GayxKasFA7r5/csTeZuS
hGPhvtj8mDru6EFg/nKVwW9z26d3a9oYoq5MTNEl5PbrS9wsupULIKDwkd4unIPA
IISBFV/o3UBwAP0TU6jLHG7tgryuIIau5HHNDwkIbuxn/vj0A0HY1ZhvWD1xs1XW
F+TzBybUzPAlEyzGYhhZR+Z/xjtUFWPXxdmC+MD1/qSvMqVpDNpSjTkJZXw7cYHf
GluLlP0Q2ZQI8uOG+uXXhcHUpi61OpmXSyIgST+FGynq28y28aiOUs/6e0i7SnZe
lsODEzqXAgMBAAECggEADvKSIIvioAdmILkD6h1BH71AlxXEOrjey4URHQulXvCV
/lmJuLypkUJGT03pYGe0wOpFKgFoQbyxL8MsMBHndMXKWoJkTy/X0suHDoJGSkNa
nlSkV99jgpyYCLtTFTUQLjyfLs8I6r2o899pCxxgp1XjeHj9zxfMgqVsNskN556c
wWsiICcpZFFEolXXswLDw3WM1n7Ktq7tpCZZksIPCI0s5V0lMcezd284lkV4AkyQ
oXy1viwf2COjT7QqsKR7SAMIRsIsk0RlkPJar3o4FmaD9GA5EUfuC0etSxypbkH7
J8eaCVwv9ns23hUvjR89Fs4HTYxWr0/svi0hMSyY8QKBgQDX71HdH8fwhCPMnjOq
gYrFp/9I3ghoFyswupPQv5cVmEzqrweI4E/tZNJrM70Z1V+0tI8rGc2hmgPTB3HS
A8zFyXj8eU3Up/hXjhVkdi9qzF89ImLA9LT0MFMx38NEHoPUkO6wxTAFuF4Wvhi/
S6dnag3uNjJ5xLlNjrQhLNR4UwKBgQDJR1eA67CfJo9oZBU4lJzruHRVmX3sARpd
lXAgOD7q4DTjL3/bq/+n19sVAh34mTdI0vAVIGlp4oZVohjsByOwPkL8rt0HyhdA
+RYyMD5H+Azp5Qvx4MJhUQxhg2WCjPqthU6bunqCWu2kSZkvkX/t/sX8fqS6NvYj
IOflwwscLQKBgH+PbeHd02Qe+3L2Bfl0u0DWZHVsTLUI8se/gHCxrZPhO5brvNy7
/ht0EuWnU89+ACKlA2pnvNT5QccZP8Db48z3ntQu6K52Z7t5QOPu+UXy41QfCw2H
wZn7LjppQFXuXNxmncqpQhwu9M4kkEP5cjQiL4aIV7sdXoYVhg2PCRjnAoGAf3Pg
ce9MsQp+xrCRS3m3gAAWEloWhYoRQu8syAo1tQ7yDmX2hYh9Y6/ot33WsqN6gW+o
vQgAGB9rxu/U7ih7Lc/PJSgpKBSM8wSHTJKF7Zahvr3d+XTEQVFMELdeYPOajKQc
KbpEdyTS1DQSfy+YHYE1p3QeJRhGdeoRTcla0KUCgYA+HSr6b3q/vU+/LGujNJls
656gtZHTlAobfjqOzA1vbNalHT26/Ikv7cPzAXO1mHsxcxUa9zeS2V+RDzy+RF15
kfWTgY4GaDbhQhFg0KrcbloH+p8oNWpqvyynoJxP1IFQWn+VJW2tN1uSAtlD2dBQ
+Z56YzbOQlvvml7ajzxzSg=="
......@@ -19,6 +19,23 @@ springfox:
swagger-ui:
enabled: false
enabled: true #开启文档
wx:
sub:
appid: wx5c6a105a0ddca4c5
secret: 96c75255dd26f82f8d55e15b59e101c7
app:
id: wx18b7883acd204278
secret: 28afe74ba373830237a8133a7431ee82
miniprogram-state: trial
env-version: trial
token-path: /userservlet/wechat/getAppletUserAccessToken
port: user
pay:
mchid: 1648653533 #商户id
mch-number: 7BF5931E5A177A94E2F3A41C839A616ECBA86718 #商户序列号
api-v3-key: MMcaFDcly5Eb5o0nTNZdu3ek8DDh4K1B #apiv3密钥
notify-url: https://test.iuav.shop/payment/wechat/payCallback
refund-notify-url: https://test.iuav.shop/payment/wechat/refundCallback
aliyun:
oss:
......@@ -37,8 +54,40 @@ mount:
userapp:
url: http://localhost:35150/userapp/
iuav:
userapp:
url: http://127.0.0.1:35150
oms:
url: http://localhost:8077/oms/
data:
file:
# url: classpath:apiclient_key.pem
url: "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCpxxR1ZZCLlLn+
XWCX90UrJE6iT9S4Fbf28WMIdqgtsk9IHuIFEy4jfKc/GayxKasFA7r5/csTeZuS
hGPhvtj8mDru6EFg/nKVwW9z26d3a9oYoq5MTNEl5PbrS9wsupULIKDwkd4unIPA
IISBFV/o3UBwAP0TU6jLHG7tgryuIIau5HHNDwkIbuxn/vj0A0HY1ZhvWD1xs1XW
F+TzBybUzPAlEyzGYhhZR+Z/xjtUFWPXxdmC+MD1/qSvMqVpDNpSjTkJZXw7cYHf
GluLlP0Q2ZQI8uOG+uXXhcHUpi61OpmXSyIgST+FGynq28y28aiOUs/6e0i7SnZe
lsODEzqXAgMBAAECggEADvKSIIvioAdmILkD6h1BH71AlxXEOrjey4URHQulXvCV
/lmJuLypkUJGT03pYGe0wOpFKgFoQbyxL8MsMBHndMXKWoJkTy/X0suHDoJGSkNa
nlSkV99jgpyYCLtTFTUQLjyfLs8I6r2o899pCxxgp1XjeHj9zxfMgqVsNskN556c
wWsiICcpZFFEolXXswLDw3WM1n7Ktq7tpCZZksIPCI0s5V0lMcezd284lkV4AkyQ
oXy1viwf2COjT7QqsKR7SAMIRsIsk0RlkPJar3o4FmaD9GA5EUfuC0etSxypbkH7
J8eaCVwv9ns23hUvjR89Fs4HTYxWr0/svi0hMSyY8QKBgQDX71HdH8fwhCPMnjOq
gYrFp/9I3ghoFyswupPQv5cVmEzqrweI4E/tZNJrM70Z1V+0tI8rGc2hmgPTB3HS
A8zFyXj8eU3Up/hXjhVkdi9qzF89ImLA9LT0MFMx38NEHoPUkO6wxTAFuF4Wvhi/
S6dnag3uNjJ5xLlNjrQhLNR4UwKBgQDJR1eA67CfJo9oZBU4lJzruHRVmX3sARpd
lXAgOD7q4DTjL3/bq/+n19sVAh34mTdI0vAVIGlp4oZVohjsByOwPkL8rt0HyhdA
+RYyMD5H+Azp5Qvx4MJhUQxhg2WCjPqthU6bunqCWu2kSZkvkX/t/sX8fqS6NvYj
IOflwwscLQKBgH+PbeHd02Qe+3L2Bfl0u0DWZHVsTLUI8se/gHCxrZPhO5brvNy7
/ht0EuWnU89+ACKlA2pnvNT5QccZP8Db48z3ntQu6K52Z7t5QOPu+UXy41QfCw2H
wZn7LjppQFXuXNxmncqpQhwu9M4kkEP5cjQiL4aIV7sdXoYVhg2PCRjnAoGAf3Pg
ce9MsQp+xrCRS3m3gAAWEloWhYoRQu8syAo1tQ7yDmX2hYh9Y6/ot33WsqN6gW+o
vQgAGB9rxu/U7ih7Lc/PJSgpKBSM8wSHTJKF7Zahvr3d+XTEQVFMELdeYPOajKQc
KbpEdyTS1DQSfy+YHYE1p3QeJRhGdeoRTcla0KUCgYA+HSr6b3q/vU+/LGujNJls
656gtZHTlAobfjqOzA1vbNalHT26/Ikv7cPzAXO1mHsxcxUa9zeS2V+RDzy+RF15
kfWTgY4GaDbhQhFg0KrcbloH+p8oNWpqvyynoJxP1IFQWn+VJW2tN1uSAtlD2dBQ
+Z56YzbOQlvvml7ajzxzSg=="
......@@ -27,6 +27,24 @@ aliyun:
access-key-secret: ${OSS_ACCESS_KEY_SECRET}
bucket: pad-video-x
wx:
sub:
appid: wx5c6a105a0ddca4c5
secret: 96c75255dd26f82f8d55e15b59e101c7
app:
id: wx18b7883acd204278
secret: 28afe74ba373830237a8133a7431ee82
miniprogram-state: formal
env-version: release
token-path: /userservlet/wechat/getAppletUserAccessToken
port: user
pay:
mchid: 1648653533 #商户id
mch-number: 7BF5931E5A177A94E2F3A41C839A616ECBA86718 #商户序列号
api-v3-key: MMcaFDcly5Eb5o0nTNZdu3ek8DDh4K1B #apiv3密钥
notify-url: https://www.iuav.shop/payment/wechat/payCallback
refund-notify-url: https://www.iuav.shop/payment/wechat/refundCallback
mmcflying:
download:
path: /ossservlet/upload/download/
......@@ -38,3 +56,40 @@ userapp:
oms:
url: https://www.iuav.shop/oms/
iuav:
userapp:
url: http://cms-svc:35150
pmsapp:
url: http://pms-svc:8099
data:
file:
# url: classpath:apiclient_key.pem
url: "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCpxxR1ZZCLlLn+
XWCX90UrJE6iT9S4Fbf28WMIdqgtsk9IHuIFEy4jfKc/GayxKasFA7r5/csTeZuS
hGPhvtj8mDru6EFg/nKVwW9z26d3a9oYoq5MTNEl5PbrS9wsupULIKDwkd4unIPA
IISBFV/o3UBwAP0TU6jLHG7tgryuIIau5HHNDwkIbuxn/vj0A0HY1ZhvWD1xs1XW
F+TzBybUzPAlEyzGYhhZR+Z/xjtUFWPXxdmC+MD1/qSvMqVpDNpSjTkJZXw7cYHf
GluLlP0Q2ZQI8uOG+uXXhcHUpi61OpmXSyIgST+FGynq28y28aiOUs/6e0i7SnZe
lsODEzqXAgMBAAECggEADvKSIIvioAdmILkD6h1BH71AlxXEOrjey4URHQulXvCV
/lmJuLypkUJGT03pYGe0wOpFKgFoQbyxL8MsMBHndMXKWoJkTy/X0suHDoJGSkNa
nlSkV99jgpyYCLtTFTUQLjyfLs8I6r2o899pCxxgp1XjeHj9zxfMgqVsNskN556c
wWsiICcpZFFEolXXswLDw3WM1n7Ktq7tpCZZksIPCI0s5V0lMcezd284lkV4AkyQ
oXy1viwf2COjT7QqsKR7SAMIRsIsk0RlkPJar3o4FmaD9GA5EUfuC0etSxypbkH7
J8eaCVwv9ns23hUvjR89Fs4HTYxWr0/svi0hMSyY8QKBgQDX71HdH8fwhCPMnjOq
gYrFp/9I3ghoFyswupPQv5cVmEzqrweI4E/tZNJrM70Z1V+0tI8rGc2hmgPTB3HS
A8zFyXj8eU3Up/hXjhVkdi9qzF89ImLA9LT0MFMx38NEHoPUkO6wxTAFuF4Wvhi/
S6dnag3uNjJ5xLlNjrQhLNR4UwKBgQDJR1eA67CfJo9oZBU4lJzruHRVmX3sARpd
lXAgOD7q4DTjL3/bq/+n19sVAh34mTdI0vAVIGlp4oZVohjsByOwPkL8rt0HyhdA
+RYyMD5H+Azp5Qvx4MJhUQxhg2WCjPqthU6bunqCWu2kSZkvkX/t/sX8fqS6NvYj
IOflwwscLQKBgH+PbeHd02Qe+3L2Bfl0u0DWZHVsTLUI8se/gHCxrZPhO5brvNy7
/ht0EuWnU89+ACKlA2pnvNT5QccZP8Db48z3ntQu6K52Z7t5QOPu+UXy41QfCw2H
wZn7LjppQFXuXNxmncqpQhwu9M4kkEP5cjQiL4aIV7sdXoYVhg2PCRjnAoGAf3Pg
ce9MsQp+xrCRS3m3gAAWEloWhYoRQu8syAo1tQ7yDmX2hYh9Y6/ot33WsqN6gW+o
vQgAGB9rxu/U7ih7Lc/PJSgpKBSM8wSHTJKF7Zahvr3d+XTEQVFMELdeYPOajKQc
KbpEdyTS1DQSfy+YHYE1p3QeJRhGdeoRTcla0KUCgYA+HSr6b3q/vU+/LGujNJls
656gtZHTlAobfjqOzA1vbNalHT26/Ikv7cPzAXO1mHsxcxUa9zeS2V+RDzy+RF15
kfWTgY4GaDbhQhFg0KrcbloH+p8oNWpqvyynoJxP1IFQWn+VJW2tN1uSAtlD2dBQ
+Z56YzbOQlvvml7ajzxzSg=="
<?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="com.mmc.payment.dao.WechatPayDao">
<insert id="insertWxPayLog">
insert into wx_pay_log (order_port,
order_no,
amount,
description,
trade_state,
user_account_id,
prepay_id,
open_id)
values (#{orderPort}, #{orderNo}, #{amount}, #{description},
#{tradeState}, #{userAccountId}, #{prepayId}, #{openId})
</insert>
<insert id="insertApplyRefundLog">
insert into apply_refund_log (order_no,
total,
refund,
currency,
out_refund_no,
reason)
values (#{orderNo}, #{total}, #{refund}, #{currency}, #{outRefundNo}, #{reason})
</insert>
<update id="updateWxPayLog">
update wx_pay_log
set out_trade_no = #{outTradeNo},
transaction_id = #{transactionId},
bank_type = #{bankType},
attach = #{attach},
success_time = #{successTime},
wx_notify_openid = #{wxNotifyOpenid},
wx_notify_total = #{wxNotifyTotal},
wx_notify_payer_total = #{wxNotifyPayerTotal},
trade_type = #{tradeType},
trade_state = #{tradeState},
trade_state_desc = #{tradeStateDesc}
where order_no = #{outTradeNo}
</update>
<update id="updateApplyRefundLog">
update apply_refund_log
<set>
<if test="refundId != null">
refund_id = #{refundId},
</if>
<if test="transactionId != null">
transaction_id = #{transactionId},
</if>
<if test="channel != null">
channel = #{channel},
</if>
<if test="userReceivedAccount != null">
user_received_account = #{userReceivedAccount},
</if>
<if test="successTime != null">
success_time = #{successTime},
</if>
<if test="createTime != null">
create_time = #{createTime},
</if>
<if test="refundStatus != null">
refund_status = #{refundStatus},
</if>
<if test="fundsAccount != null">
funds_account = #{fundsAccount}
</if>
<if test="notifyRefundStatus != null">
notify_refund_status = #{notifyRefundStatus}
</if>
</set>
where order_no = #{orderNo}
</update>
<delete id="deleteWxPayLogByOrderNo">
delete
from wx_pay_log
where order_no = #{orderNo}
</delete>
<select id="selectWxPayInfoByOrderNo" resultType="com.mmc.payment.entity.order.WxPayLogDO">
SELECT id,
order_port,
order_no,
amount,
open_id,
description,
prepay_id,
user_account_id,
out_trade_no,
transaction_id,
bank_type,
attach,
success_time,
wx_notify_openid,
wx_notify_total,
wx_notify_payer_total,
trade_type,
trade_state,
trade_state_desc,
create_time,
update_time
FROM wx_pay_log
where order_no = #{orderNo}
</select>
</mapper>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论