提交 1de81330 作者: xiaowang

微信支付下单及回调接口

上级 02bb0da8
......@@ -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>
......
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;
}
package com.mmc.payment.constant;
/**
* @Author LW
* @date 2023/7/19 17:10
* 概要:
*/
public interface WechatConstant {
String privateKeyPath = "src/main/resources/apiclient_key.pem";
}
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.OrderRequestParamsVO;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
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 ResultBody orderPay(@RequestBody OrderRequestParamsVO orderRequestParamsVO, HttpServletRequest request) {
return ResultBody.success(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);
}
}
package com.mmc.payment.dao;
import com.mmc.payment.entity.order.WxPrepayLogDO;
import org.apache.ibatis.annotations.Mapper;
/**
* @Author LW
* @date 2023/7/19 17:20
* 概要:
*/
@Mapper
public interface WechatPayDao {
void insertWxPrepayLog(WxPrepayLogDO wxPrepayLogDO);
}
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 WxPrepayLogDO {
private Integer id;
private Integer orderPort;
private String orderNo;
private Integer amount;
private String openId;
private String description;
private String prepayId;
private Integer orderStatus;
private Integer userAccountId;
private Date createTime;
private Date updateTime;
}
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;
}
}
package com.mmc.payment.model.dto.user;
import com.mmc.payment.model.dto.role.RoleInfoDTO;
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 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.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;
}
......@@ -20,7 +20,6 @@ import com.mmc.payment.model.dto.repo.PayCashResultDTO;
import com.mmc.payment.model.dto.repo.RepoCashDTO;
import com.mmc.payment.model.dto.repo.RepoWalletDTO;
import com.mmc.payment.model.dto.user.BaseAccountDTO;
import com.mmc.payment.model.dto.user.UserAccountSimpleDTO;
import com.mmc.payment.model.qo.RepoCashQO;
import com.mmc.payment.model.qo.UserCashQO;
import com.mmc.payment.model.qo.WalletMessageQO;
......
package com.mmc.payment.service.Impl;
import cn.hutool.core.util.RandomUtil;
import com.mmc.payment.constant.UserSystemConstant;
import com.mmc.payment.dao.WechatPayDao;
import com.mmc.payment.entity.order.WxPrepayLogDO;
import com.mmc.payment.feign.UserAppApi;
import com.mmc.payment.model.dto.user.UserAccountSimpleDTO;
import com.mmc.payment.model.vo.order.OrderRequestParamsVO;
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.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
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.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
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
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();
// 构建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();
prepayRequest.setPayer(payer);
payer.setOpenid(userSimpleInfo.getOpenid());
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();
WxPrepayLogDO wxPrepayLogDO = new WxPrepayLogDO();
wxPrepayLogDO.setOrderPort(orderRequestParamsVO.getOrderPort());
wxPrepayLogDO.setOrderNo(orderRequestParamsVO.getOrderNo());
wxPrepayLogDO.setDescription(orderRequestParamsVO.getDescription());
wxPrepayLogDO.setUserAccountId(userAccountId);
wxPrepayLogDO.setAmount(orderRequestParamsVO.getAmount());
wxPrepayLogDO.setPrepayId(prepayId);
// 往数据库插入下单的日志信息
wechatPayDao.insertWxPrepayLog(wxPrepayLogDO);
// 获取时间戳
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
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);
result.put("code", "SUCCESS");
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
package com.mmc.payment.service;
import com.mmc.payment.model.vo.order.OrderRequestParamsVO;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* @Author LW
* @date 2023/7/19 16:56
* 概要:
*/
public interface WechatPayService {
Map orderPay(OrderRequestParamsVO orderRequestParamsVO, Integer userAccountId, HttpServletRequest request);
Map payCallback(HttpServletRequest request);
}
package com.mmc.payment.util;
import com.mmc.payment.constant.UserSystemConstant;
import com.mmc.payment.constant.WechatConstant;
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.context.annotation.Bean;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @Author LW
* @date 2023/7/20 10:36
* 概要:
*/
@Component
public class WxConfigUtils {
@Resource
UserSystemConstant userSystemConstant;
@Bean
public Config createConfig() {
// 使用自动更新平台证书的RSA配置
// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
Config config =
new RSAAutoCertificateConfig.Builder()
.merchantId(userSystemConstant.getMchid())
.privateKeyFromPath(WechatConstant.privateKeyPath)
.merchantSerialNumber(userSystemConstant.getMchNumber())
.apiV3Key(userSystemConstant.getApiv3Key())
.build();
return config;
}
@Bean
public NotificationConfig createNotificationConfig() {
// 使用自动更新平台证书的RSA配置
// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
NotificationConfig config =
new RSAAutoCertificateConfig.Builder()
.merchantId(userSystemConstant.getMchid())
.privateKeyFromPath(WechatConstant.privateKeyPath)
.merchantSerialNumber(userSystemConstant.getMchNumber())
.apiV3Key(userSystemConstant.getApiv3Key())
.build();
return config;
}
}
-----BEGIN PRIVATE KEY-----
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==
-----END PRIVATE KEY-----
......@@ -27,6 +27,23 @@ 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
mmcflying:
download:
path: /ossservlet/upload/download/
......
......@@ -19,6 +19,21 @@ 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密钥
aliyun:
oss:
......@@ -37,6 +52,10 @@ mount:
userapp:
url: http://localhost:35150/userapp/
iuav:
userapp:
url: http://127.0.0.1:35150
oms:
url: http://localhost:8077/oms/
......
......@@ -27,6 +27,23 @@ 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
mmcflying:
download:
path: /ossservlet/upload/download/
......
<?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="insertWxPrepayLog">
insert into wx_prepay_log (order_port,
order_no,
amount,
description,
order_status,
user_account_id,
prepay_id,
open_id)
values (#{orderPort}, #{orderNo}, #{amount}, #{description},
#{orderStatus}, #{userAccountId}, #{prepayId}, #{openId})
</insert>
</mapper>
\ No newline at end of file
package com.mmc.payment;
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.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import org.junit.Test;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author: zj
* @Date: 2023/7/19 14:52
*/
@Component
public class QuickStart {
@Resource
private UserSystemConstant userSystemConstant;
/**
* 商户API私钥路径
*/
public static String privateKeyPath = "src/main/resources/apiclient_key.pem";
@Test
public void test() {
// 使用自动更新平台证书的RSA配置
// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
Config config =
new RSAAutoCertificateConfig.Builder()
.merchantId(userSystemConstant.getMchid())
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(userSystemConstant.getMchNumber())
.apiV3Key(userSystemConstant.getApiv3Key())
.build();
// 构建service
NativePayService service = new NativePayService.Builder().config(config).build();
// request.setXxx(val)设置所需参数,具体参数可见Request定义
PrepayRequest request = new PrepayRequest();
Amount amount = new Amount();
amount.setTotal(100);
request.setAmount(amount);
request.setAppid("wx18b7883acd204278");
request.setMchid("1648653533");
request.setDescription("测试商品标题");
request.setNotifyUrl("https://notify_url");
request.setOutTradeNo(System.currentTimeMillis()+"");
// 调用下单方法,得到应答
PrepayResponse response = service.prepay(request);
// 使用微信扫描 code_url 对应的二维码,即可体验Native支付
System.out.println(response.getCodeUrl());
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论