feat(新增): 完成
This commit is contained in:
parent
abdd193d2d
commit
b3a2d42e24
|
@ -28,6 +28,7 @@
|
||||||
<file url="file://$PROJECT_DIR$/service/service-cart/src/main/java" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/service/service-cart/src/main/java" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/service/service-home/src/main/java" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/service/service-home/src/main/java" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/service/service-order/src/main/java" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/service/service-order/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/service/service-payment/src/main/java" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/service/service-product/src/main/java" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/service/service-product/src/main/java" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/service/service-search/src/main/java" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/service/service-search/src/main/java" charset="UTF-8" />
|
||||||
<file url="file://$PROJECT_DIR$/service/service-sys/src/main/java" charset="UTF-8" />
|
<file url="file://$PROJECT_DIR$/service/service-sys/src/main/java" charset="UTF-8" />
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
<module>service-home</module>
|
<module>service-home</module>
|
||||||
<module>service-cart</module>
|
<module>service-cart</module>
|
||||||
<module>service-order</module>
|
<module>service-order</module>
|
||||||
|
<module>service-payment</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.atguigu.ssyx.home.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
|
import springfox.documentation.builders.ParameterBuilder;
|
||||||
|
import springfox.documentation.builders.PathSelectors;
|
||||||
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
|
import springfox.documentation.schema.ModelRef;
|
||||||
|
import springfox.documentation.service.ApiInfo;
|
||||||
|
import springfox.documentation.service.Contact;
|
||||||
|
import springfox.documentation.service.Parameter;
|
||||||
|
import springfox.documentation.spi.DocumentationType;
|
||||||
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableSwagger2WebMvc
|
||||||
|
public class Knife4jConfig {
|
||||||
|
@Bean
|
||||||
|
public Docket adminApiConfig() {
|
||||||
|
List<Parameter> pars = new ArrayList<>();
|
||||||
|
ParameterBuilder tokenPar = new ParameterBuilder();
|
||||||
|
tokenPar.name("adminId")
|
||||||
|
.description("用户token")
|
||||||
|
.defaultValue("1")
|
||||||
|
.modelRef(new ModelRef("string"))
|
||||||
|
.parameterType("header")
|
||||||
|
.required(false)
|
||||||
|
.build();
|
||||||
|
pars.add(tokenPar.build());
|
||||||
|
|
||||||
|
return new Docket(DocumentationType.SWAGGER_2)
|
||||||
|
.groupName("Home模块相关API")
|
||||||
|
.apiInfo(adminApiInfo())
|
||||||
|
.select()
|
||||||
|
.apis(RequestHandlerSelectors.basePackage("com.atguigu.ssyx.activity.controller"))
|
||||||
|
.paths(PathSelectors.regex("/admin/.*"))
|
||||||
|
.build()
|
||||||
|
.globalOperationParameters(pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApiInfo adminApiInfo() {
|
||||||
|
return new ApiInfoBuilder()
|
||||||
|
.title("后台管理系统-API文档")
|
||||||
|
.description("本文档描述了尚上优选后台系统服务接口定义")
|
||||||
|
.version("1.0")
|
||||||
|
.contact(new Contact("atguigu", "http://atguigu.com", "atguigu"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.atguigu.ssyx.order.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
|
import springfox.documentation.builders.ParameterBuilder;
|
||||||
|
import springfox.documentation.builders.PathSelectors;
|
||||||
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
|
import springfox.documentation.schema.ModelRef;
|
||||||
|
import springfox.documentation.service.ApiInfo;
|
||||||
|
import springfox.documentation.service.Contact;
|
||||||
|
import springfox.documentation.service.Parameter;
|
||||||
|
import springfox.documentation.spi.DocumentationType;
|
||||||
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableSwagger2WebMvc
|
||||||
|
public class Knife4jConfig {
|
||||||
|
@Bean
|
||||||
|
public Docket adminApiConfig() {
|
||||||
|
List<Parameter> pars = new ArrayList<>();
|
||||||
|
ParameterBuilder tokenPar = new ParameterBuilder();
|
||||||
|
tokenPar.name("adminId")
|
||||||
|
.description("用户token")
|
||||||
|
.defaultValue("1")
|
||||||
|
.modelRef(new ModelRef("string"))
|
||||||
|
.parameterType("header")
|
||||||
|
.required(false)
|
||||||
|
.build();
|
||||||
|
pars.add(tokenPar.build());
|
||||||
|
|
||||||
|
return new Docket(DocumentationType.SWAGGER_2)
|
||||||
|
.groupName("订单相关API")
|
||||||
|
.apiInfo(adminApiInfo())
|
||||||
|
.select()
|
||||||
|
.apis(RequestHandlerSelectors.basePackage("com.atguigu.ssyx.activity.controller"))
|
||||||
|
.paths(PathSelectors.regex("/admin/.*"))
|
||||||
|
.build()
|
||||||
|
.globalOperationParameters(pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApiInfo adminApiInfo() {
|
||||||
|
return new ApiInfoBuilder()
|
||||||
|
.title("后台管理系统-API文档")
|
||||||
|
.description("本文档描述了尚上优选后台系统服务接口定义")
|
||||||
|
.version("1.0")
|
||||||
|
.contact(new Contact("atguigu", "http://atguigu.com", "atguigu"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.atguigu</groupId>
|
||||||
|
<artifactId>service</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>service-payment</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>service-payment</name>
|
||||||
|
<url>https://maven.apache.org</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!--导入微信支付sdk-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.wxpay</groupId>
|
||||||
|
<artifactId>wxpay-sdk</artifactId>
|
||||||
|
<version>0.0.3</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.atguigu.ssyx.payment;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.cloud.client.SpringCloudApplication;
|
||||||
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
@SpringCloudApplication
|
||||||
|
@EnableTransactionManagement
|
||||||
|
@EnableDiscoveryClient
|
||||||
|
public class ServicePaymentApplication {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ServicePaymentApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.atguigu.ssyx.payment.api;
|
||||||
|
|
||||||
|
import com.atguigu.ssyx.common.result.Result;
|
||||||
|
import com.atguigu.ssyx.enums.PaymentType;
|
||||||
|
import com.atguigu.ssyx.payment.service.PaymentService;
|
||||||
|
import com.atguigu.ssyx.payment.service.WeixinService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import io.swagger.annotations.ApiParam;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 微信支付 API
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Api(tags = "微信支付接口")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/payment/weixin")
|
||||||
|
@Slf4j
|
||||||
|
public class WeixinController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WeixinService weixinPayService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PaymentService paymentService;
|
||||||
|
|
||||||
|
@ApiOperation(value = "下单 小程序支付")
|
||||||
|
@GetMapping("/createJsapi/{orderNo}")
|
||||||
|
public Result createJsapi(
|
||||||
|
@ApiParam(name = "orderNo", value = "订单No", required = true)
|
||||||
|
@PathVariable("orderNo") String orderNo) {
|
||||||
|
return Result.ok(weixinPayService.createJsapi(orderNo));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "查询支付状态")
|
||||||
|
@GetMapping("/queryPayStatus/{orderNo}")
|
||||||
|
public Result queryPayStatus(
|
||||||
|
@ApiParam(name = "orderNo", value = "订单No", required = true)
|
||||||
|
@PathVariable("orderNo") String orderNo) {
|
||||||
|
// 调用查询接口
|
||||||
|
Map<String, String> resultMap = weixinPayService.queryPayStatus(orderNo, PaymentType.WEIXIN.name());
|
||||||
|
if (resultMap == null) {// 出错
|
||||||
|
return Result.error("支付出错");
|
||||||
|
}
|
||||||
|
if ("SUCCESS".equals(resultMap.get("trade_state"))) {// 如果成功
|
||||||
|
// 更改订单状态,处理支付结果
|
||||||
|
String out_trade_no = resultMap.get("out_trade_no");
|
||||||
|
paymentService.paySuccess(out_trade_no, PaymentType.WEIXIN, resultMap);
|
||||||
|
return Result.success("支付成功");
|
||||||
|
}
|
||||||
|
return Result.success("支付中");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.atguigu.ssyx.payment.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
|
import springfox.documentation.builders.ParameterBuilder;
|
||||||
|
import springfox.documentation.builders.PathSelectors;
|
||||||
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
|
import springfox.documentation.schema.ModelRef;
|
||||||
|
import springfox.documentation.service.ApiInfo;
|
||||||
|
import springfox.documentation.service.Contact;
|
||||||
|
import springfox.documentation.service.Parameter;
|
||||||
|
import springfox.documentation.spi.DocumentationType;
|
||||||
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableSwagger2WebMvc
|
||||||
|
public class Knife4jConfig {
|
||||||
|
@Bean
|
||||||
|
public Docket adminApiConfig() {
|
||||||
|
List<Parameter> pars = new ArrayList<>();
|
||||||
|
ParameterBuilder tokenPar = new ParameterBuilder();
|
||||||
|
tokenPar.name("adminId")
|
||||||
|
.description("用户token")
|
||||||
|
.defaultValue("1")
|
||||||
|
.modelRef(new ModelRef("string"))
|
||||||
|
.parameterType("header")
|
||||||
|
.required(false)
|
||||||
|
.build();
|
||||||
|
pars.add(tokenPar.build());
|
||||||
|
|
||||||
|
return new Docket(DocumentationType.SWAGGER_2)
|
||||||
|
.groupName("支付相关API")
|
||||||
|
.apiInfo(adminApiInfo())
|
||||||
|
.select()
|
||||||
|
.apis(RequestHandlerSelectors.basePackage("com.atguigu.ssyx.activity.controller"))
|
||||||
|
.paths(PathSelectors.regex("/admin/.*"))
|
||||||
|
.build()
|
||||||
|
.globalOperationParameters(pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApiInfo adminApiInfo() {
|
||||||
|
return new ApiInfoBuilder()
|
||||||
|
.title("后台管理系统-API文档")
|
||||||
|
.description("本文档描述了尚上优选后台系统服务接口定义")
|
||||||
|
.version("1.0")
|
||||||
|
.contact(new Contact("atguigu", "http://atguigu.com", "atguigu"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.atguigu.ssyx.payment.service;
|
||||||
|
|
||||||
|
import com.atguigu.ssyx.enums.PaymentType;
|
||||||
|
import com.atguigu.ssyx.model.order.PaymentInfo;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface PaymentService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存交易记录
|
||||||
|
*/
|
||||||
|
PaymentInfo savePaymentInfo(String orderNo, PaymentType paymentType);
|
||||||
|
|
||||||
|
PaymentInfo getPaymentInfo(String orderNo, PaymentType paymentType);
|
||||||
|
|
||||||
|
// 支付成功
|
||||||
|
void paySuccess(String orderNo, PaymentType paymentType, Map<String, String> paramMap);
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.atguigu.ssyx.payment.service;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface WeixinService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据订单号下单,生成支付链接
|
||||||
|
*
|
||||||
|
* @param orderNo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Map createJsapi(String orderNo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据订单号去微信第三方查询支付状态
|
||||||
|
*
|
||||||
|
* @param orderNo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Map queryPayStatus(String orderNo, String paymentType);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
package com.atguigu.ssyx.payment.service.impl;
|
||||||
|
|
||||||
|
import com.atguigu.ssyx.common.result.ResultCodeEnum;
|
||||||
|
import com.atguigu.ssyx.enums.PaymentStatus;
|
||||||
|
import com.atguigu.ssyx.enums.PaymentType;
|
||||||
|
import com.atguigu.ssyx.model.order.OrderInfo;
|
||||||
|
import com.atguigu.ssyx.model.order.PaymentInfo;
|
||||||
|
import com.atguigu.ssyx.payment.service.PaymentService;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class PaymentServiceImpl implements PaymentService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PaymentInfoMapper paymentInfoMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OrderFeignClient orderFeignClient;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RabbitService rabbitService;
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@Override
|
||||||
|
public PaymentInfo savePaymentInfo(String orderNo, PaymentType paymentType) {
|
||||||
|
OrderInfo order = orderFeignClient.getOrderInfoByOrderNo(orderNo);
|
||||||
|
if (null == order) {
|
||||||
|
throw new GmallException(ResultCodeEnum.DATA_ERROR);
|
||||||
|
}
|
||||||
|
// 保存交易记录
|
||||||
|
PaymentInfo paymentInfo = new PaymentInfo();
|
||||||
|
paymentInfo.setCreateTime(new Date());
|
||||||
|
paymentInfo.setOrderId(order.getId());
|
||||||
|
paymentInfo.setPaymentType(paymentType);
|
||||||
|
paymentInfo.setUserId(order.getUserId());
|
||||||
|
paymentInfo.setOrderNo(order.getOrderNo());
|
||||||
|
paymentInfo.setPaymentStatus(PaymentStatus.UNPAID);
|
||||||
|
String subject = "test";
|
||||||
|
paymentInfo.setSubject(subject);
|
||||||
|
// paymentInfo.setTotalAmount(order.getTotalAmount());
|
||||||
|
paymentInfo.setTotalAmount(new BigDecimal("0.01"));
|
||||||
|
|
||||||
|
paymentInfoMapper.insert(paymentInfo);
|
||||||
|
return paymentInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PaymentInfo getPaymentInfo(String orderNo, PaymentType paymentType) {
|
||||||
|
LambdaQueryWrapper<PaymentInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(PaymentInfo::getOrderNo, orderNo);
|
||||||
|
queryWrapper.eq(PaymentInfo::getPaymentType, paymentType);
|
||||||
|
return paymentInfoMapper.selectOne(queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@Override
|
||||||
|
public void paySuccess(String orderNo, PaymentType paymentType, Map<String, String> paramMap) {
|
||||||
|
LambdaQueryWrapper<PaymentInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(PaymentInfo::getOrderNo, orderNo);
|
||||||
|
queryWrapper.eq(PaymentInfo::getPaymentType, paymentType);
|
||||||
|
PaymentInfo paymentInfo = paymentInfoMapper.selectOne(queryWrapper);
|
||||||
|
if (paymentInfo.getPaymentStatus() != PaymentStatus.UNPAID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaymentInfo paymentInfoUpd = new PaymentInfo();
|
||||||
|
paymentInfoUpd.setPaymentStatus(PaymentStatus.PAID);
|
||||||
|
String tradeNo = paymentType == PaymentType.WEIXIN ? paramMap.get("ransaction_id") : paramMap.get("trade_no");
|
||||||
|
paymentInfoUpd.setTradeNo(tradeNo);
|
||||||
|
paymentInfoUpd.setCallbackTime(new Date());
|
||||||
|
paymentInfoUpd.setCallbackContent(paramMap.toString());
|
||||||
|
paymentInfoMapper.update(paymentInfoUpd, new LambdaQueryWrapper<PaymentInfo>().eq(PaymentInfo::getOrderNo, orderNo));
|
||||||
|
// 表示交易成功!
|
||||||
|
|
||||||
|
// 发送消息
|
||||||
|
rabbitService.sendMessage(MqConst.EXCHANGE_PAY_DIRECT, MqConst.ROUTING_PAY_SUCCESS, orderNo);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
package com.atguigu.ssyx.payment.service.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.atguigu.ssyx.enums.PaymentType;
|
||||||
|
import com.atguigu.ssyx.model.order.PaymentInfo;
|
||||||
|
import com.atguigu.ssyx.payment.service.PaymentService;
|
||||||
|
import com.atguigu.ssyx.payment.service.WeixinService;
|
||||||
|
import com.atguigu.ssyx.payment.util.ConstantPropertiesUtils;
|
||||||
|
import com.atguigu.ssyx.payment.util.HttpClient;
|
||||||
|
import com.atguigu.ssyx.vo.user.UserLoginVo;
|
||||||
|
import com.github.wxpay.sdk.WXPayUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class WeixinServiceImpl implements WeixinService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PaymentService paymentService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据订单号下单,生成支付链接
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> createJsapi(String orderNo) {
|
||||||
|
try {
|
||||||
|
// Map payMap = (Map) redisTemplate.opsForValue().get(orderNo);
|
||||||
|
// if(null != payMap) return payMap;
|
||||||
|
|
||||||
|
PaymentInfo paymentInfo = paymentService.getPaymentInfo(orderNo, PaymentType.WEIXIN);
|
||||||
|
if (null == paymentInfo) {
|
||||||
|
paymentInfo = paymentService.savePaymentInfo(orderNo, PaymentType.WEIXIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> paramMap = new HashMap();
|
||||||
|
// 1、设置参数
|
||||||
|
paramMap.put("appid", ConstantPropertiesUtils.APPID);
|
||||||
|
paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);
|
||||||
|
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
|
||||||
|
paramMap.put("body", paymentInfo.getSubject());
|
||||||
|
paramMap.put("out_trade_no", paymentInfo.getOrderNo());
|
||||||
|
int totalFee = paymentInfo.getTotalAmount().multiply(new BigDecimal(100)).intValue();
|
||||||
|
paramMap.put("total_fee", String.valueOf(totalFee));
|
||||||
|
paramMap.put("spbill_create_ip", "127.0.0.1");
|
||||||
|
paramMap.put("notify_url", ConstantPropertiesUtils.NOTIFYURL);
|
||||||
|
paramMap.put("trade_type", "JSAPI");
|
||||||
|
// paramMap.put("openid", "o1R-t5trto9c5sdYt6l1ncGmY5iY");
|
||||||
|
UserLoginVo userLoginVo = (UserLoginVo) redisTemplate.opsForValue().get("user:login:" + paymentInfo.getUserId());
|
||||||
|
if (null != userLoginVo && !StringUtils.isEmpty(userLoginVo.getOpenId())) {
|
||||||
|
paramMap.put("openid", userLoginVo.getOpenId());
|
||||||
|
} else {
|
||||||
|
paramMap.put("openid", "oD7av4igt-00GI8PqsIlg5FROYnI");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2、HTTPClient来根据URL访问第三方接口并且传递参数
|
||||||
|
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
|
||||||
|
|
||||||
|
// client设置参数
|
||||||
|
client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
|
||||||
|
client.setHttps(true);
|
||||||
|
client.post();
|
||||||
|
// 3、返回第三方的数据
|
||||||
|
String xml = client.getContent();
|
||||||
|
Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
|
||||||
|
log.info("微信下单返回结果:{}", JSON.toJSONString(resultMap));
|
||||||
|
|
||||||
|
// 4、再次封装参数
|
||||||
|
Map<String, String> parameterMap = new HashMap<>();
|
||||||
|
String prepayId = String.valueOf(resultMap.get("prepay_id"));
|
||||||
|
String packages = "prepay_id=" + prepayId;
|
||||||
|
parameterMap.put("appId", ConstantPropertiesUtils.APPID);
|
||||||
|
parameterMap.put("nonceStr", resultMap.get("nonce_str"));
|
||||||
|
parameterMap.put("package", packages);
|
||||||
|
parameterMap.put("signType", "MD5");
|
||||||
|
parameterMap.put("timeStamp", String.valueOf(new Date().getTime()));
|
||||||
|
String sign = WXPayUtil.generateSignature(parameterMap, ConstantPropertiesUtils.PARTNERKEY);
|
||||||
|
|
||||||
|
// 返回结果
|
||||||
|
Map<String, String> result = new HashMap();
|
||||||
|
result.put("timeStamp", parameterMap.get("timeStamp"));
|
||||||
|
result.put("nonceStr", parameterMap.get("nonceStr"));
|
||||||
|
result.put("signType", "MD5");
|
||||||
|
result.put("paySign", sign);
|
||||||
|
result.put("package", packages);
|
||||||
|
if (null != resultMap.get("result_code")) {
|
||||||
|
// 微信支付二维码2小时过期,可采取2小时未支付取消订单
|
||||||
|
redisTemplate.opsForValue().set(orderNo, result, 120, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map queryPayStatus(String orderNo, String paymentType) {
|
||||||
|
try {
|
||||||
|
// 1、封装参数
|
||||||
|
Map paramMap = new HashMap<>();
|
||||||
|
paramMap.put("appid", ConstantPropertiesUtils.APPID);
|
||||||
|
paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);
|
||||||
|
paramMap.put("out_trade_no", orderNo);
|
||||||
|
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
|
||||||
|
|
||||||
|
// 2、设置请求
|
||||||
|
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
|
||||||
|
client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
|
||||||
|
client.setHttps(true);
|
||||||
|
client.post();
|
||||||
|
// 3、返回第三方的数据
|
||||||
|
String xml = client.getContent();
|
||||||
|
Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
|
||||||
|
// 6、转成Map
|
||||||
|
// 7、返回
|
||||||
|
return resultMap;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
server:
|
||||||
|
port: 8210
|
||||||
|
|
||||||
|
bunny:
|
||||||
|
datasource:
|
||||||
|
host: 106.15.251.123
|
||||||
|
port: 3305
|
||||||
|
sqlData: shequ-order
|
||||||
|
username: root
|
||||||
|
password: "02120212"
|
||||||
|
|
||||||
|
redis:
|
||||||
|
host: 47.120.65.66
|
||||||
|
port: 6379
|
||||||
|
database: 3
|
||||||
|
password: "02120212"
|
||||||
|
|
||||||
|
rabbitmq:
|
||||||
|
# host: 192.168.1.4
|
||||||
|
host: 192.168.3.98
|
||||||
|
port: 5672
|
||||||
|
username: bunny
|
||||||
|
password: "02120212"
|
||||||
|
|
||||||
|
nacos:
|
||||||
|
server-addr: z-bunny.cn:8848
|
||||||
|
discovery:
|
||||||
|
namespace: ssyx
|
|
@ -0,0 +1,77 @@
|
||||||
|
server:
|
||||||
|
port: 8210
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: service-payment
|
||||||
|
profiles:
|
||||||
|
active: dev
|
||||||
|
|
||||||
|
datasource:
|
||||||
|
type: com.zaxxer.hikari.HikariDataSource
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
url: jdbc:mysql://${bunny.datasource.host}:${bunny.datasource.port}/${bunny.datasource.sqlData}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
|
||||||
|
username: ${bunny.datasource.username}
|
||||||
|
password: ${bunny.datasource.password}
|
||||||
|
|
||||||
|
redis:
|
||||||
|
host: ${bunny.redis.host}
|
||||||
|
port: ${bunny.redis.port}
|
||||||
|
database: ${bunny.redis.database}
|
||||||
|
password: ${bunny.redis.password}
|
||||||
|
lettuce:
|
||||||
|
pool:
|
||||||
|
max-active: 20 #最大连接数
|
||||||
|
max-wait: -1 #最大阻塞等待时间(负数表示没限制)
|
||||||
|
max-idle: 5 #最大空闲
|
||||||
|
min-idle: 0 #最小空闲
|
||||||
|
|
||||||
|
rabbitmq:
|
||||||
|
host: ${bunny.rabbitmq.host}
|
||||||
|
port: ${bunny.rabbitmq.port}
|
||||||
|
username: ${bunny.rabbitmq.username}
|
||||||
|
password: ${bunny.rabbitmq.password}
|
||||||
|
publisher-confirm-type: CORRELATED
|
||||||
|
publisher-returns: true
|
||||||
|
listener:
|
||||||
|
simple:
|
||||||
|
prefetch: 1
|
||||||
|
concurrency: 3
|
||||||
|
acknowledge-mode: manual
|
||||||
|
retry:
|
||||||
|
enabled: true # 开启消费者失败重试
|
||||||
|
initial-interval: 1000ms # 初始失败等待时长
|
||||||
|
multiplier: 1 # 下次失败等待时间被树,下次等待时长 multiplier * last-interval
|
||||||
|
max-attempts: 3 # 最大重试次数
|
||||||
|
stateless: true # true 无状态 false 有状态。如果业务中包含事务,这里改为false
|
||||||
|
|
||||||
|
cloud:
|
||||||
|
sentinel:
|
||||||
|
log:
|
||||||
|
dir: logs/${spring.application.name}/sentinel
|
||||||
|
nacos:
|
||||||
|
discovery:
|
||||||
|
namespace: ${bunny.nacos.discovery.namespace}
|
||||||
|
server-addr: ${bunny.nacos.server-addr}
|
||||||
|
|
||||||
|
jackson:
|
||||||
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
|
time-zone: GMT+8
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
com.atguigu.ssyx.order.mapper: debug
|
||||||
|
com.atguigu.ssyx.order.controller: info
|
||||||
|
com.atguigu.ssyx.order.service: info
|
||||||
|
pattern:
|
||||||
|
dateformat: HH:mm:ss:SSS
|
||||||
|
file:
|
||||||
|
path: "logs/${spring.application.name}"
|
||||||
|
|
||||||
|
# 微信
|
||||||
|
weixin:
|
||||||
|
#小程序微信公众平台appId
|
||||||
|
appid: wxcc651fcbab275e33
|
||||||
|
partner: 1481962542
|
||||||
|
partnerkey: MXb72b9RfshXZD4FRGV5KLqmv5bx9LT9
|
||||||
|
notifyurl: http://gmall-prod.atguigu.cn/api/payment/weixin/notify
|
||||||
|
cert: D:\yygh_work\yygh_parent\service\service-order\src\main\resources\apiclient_cert.p12
|
|
@ -0,0 +1,16 @@
|
||||||
|
-----------------▄██-█▄---------
|
||||||
|
-----------------███▄██▄--------
|
||||||
|
-----------------███████--------
|
||||||
|
-----------------▀███████-------
|
||||||
|
-------------------██████▄▄-----
|
||||||
|
-------------------█████████▄---
|
||||||
|
-------------------██████▄████--
|
||||||
|
-------▄███████████████████████-
|
||||||
|
-----▄███████████████████████▀--
|
||||||
|
---▄██████████████████████------
|
||||||
|
---███████████████████████------
|
||||||
|
---███████████████████████------
|
||||||
|
-▄▄██████████████████████▀------
|
||||||
|
-█████████████████▀█████--------
|
||||||
|
-▀██████████████▀▀-▀█████▄------
|
||||||
|
-------▀▀▀▀▀▀▀▀▀------▀▀▀▀------
|
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Loading…
Reference in New Issue