博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用SpringCloud Alibaba搭建属于自己的微服务(三十三)~业务开发~支付接口开发
阅读量:4203 次
发布时间:2019-05-26

本文共 11700 字,大约阅读时间需要 39 分钟。

一.概述

本文本打算接入微信支付和支付宝支付作为讲解,但是没有弄到微信和支付宝的商户账户.所以支付将只会讲解扣除账户余额的方式.

二.新建server-pay微服务

1.创建server-pay的maven工程.

在这里插入图片描述

2.引入maven工程依赖.

com.ccm
assembly-mysql
1.0.0
org.springframework.cloud
spring-cloud-starter-openfeign

3.编写工程的启动类.

package com.ccm.server.pay;import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.openfeign.EnableFeignClients;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Import;import springfox.documentation.swagger2.annotations.EnableSwagger2;/** * @Description server-pay服务启动类 * @Author ccm * @CreateTime 2020/8/19 14:18 */@EnableFeignClients@EnableDiscoveryClient //注册中心客户端@ComponentScan(basePackages = "com.ccm")@EnableSwagger2@MapperScan(basePackages = "com.ccm.server.pay.dao.mysql.mapper")@SpringBootApplication //声明为一个启动类@Import(value = {
PaginationInterceptor.class})public class ServerPayApplication {
public static void main(String[] args) {
SpringApplication.run(ServerPayApplication.class,args); }}

4.编写bootstrap.yml配置文件.

server:  port: 5000  #服务端口spring:  application:    name: server-pay #服务名称  cloud:    nacos:      discovery:        server-addr: 47.96.131.185:8849      config:        server-addr: 47.96.131.185:8849  #nacos config配置中心ip和端口        file-extension: yaml  #文件扩展名格式,针对于默认的{spring.application.name}-${profile}.${file-extension:properties}配置        enabled: true #开启或关闭配置中心  datasource:    username: root    password: Test2016@    url: jdbc:mysql://47.96.131.185:3306/pay?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true    type: com.alibaba.druid.pool.DruidDataSourcemybatis-plus:  typeAliasesPackage: com.ccm.server.pay.dao.mysql.domain  #数据库实体类包  mapper-locations: classpath:mappering/*.xml #xml文件扫描#自定义配置server-order:  serverNumber: 1  #机器服务号

5.swagger配置.

package com.ccm.server.pay.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.Parameter;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import java.util.ArrayList;import java.util.List;/** * @Description swagger配置 * @Author ccm * @CreateTime 2020/7/8 17:38 */@Configurationpublic class SwaggerConfig {
@Bean public Docket createRestApi() {
List
pars = new ArrayList
(); ParameterBuilder ticketPar = new ParameterBuilder(); ticketPar.name("ccm-token").description("必要参数(白名单接口无需传递)") .modelRef(new ModelRef("string")).parameterType("header") .required(false).build(); //header中的ticket参数非必填,传空也可以 pars.add(ticketPar.build()); return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.ccm.server.pay.controller")) //swagger接口扫描包 .paths(PathSelectors.any()).build().globalOperationParameters(pars); } private ApiInfo apiInfo() {
return new ApiInfoBuilder().version("1.0.0") .title("欢迎") .description("光临") .termsOfServiceUrl("www.baidu.com") .build(); }}

6.自定义配置的映射实体.

package com.ccm.server.pay.constants;import com.alibaba.fastjson.JSONObject;import lombok.Data;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;/** * @Description 自定义配置映射实体 * @Author ccm * @CreateTime 2020/08/18 15:01 */@Slf4j@Data@Component@ConfigurationProperties(prefix = "server-pay")public class ServerPayProperties {
private String serverNumber; @PostConstruct public void init() {
log.info("ServerPayProperties初始化完成......{}", JSONObject.toJSONString(this)); }}

7.gateway网关增加server-pay服务的路由.

spring:  cloud:    #gateway组件相关配置    gateway:      routes: #路由配置        - id: server-pay #路由名称,不配默认为UUID          uri: lb://server-pay #满足断言的路由到此服务          predicates: #为一个数组,每个规则为并且的关系            - Path=/api-pay/** #断言表达式,如果args不写key的,会自动生成一个id,如下会生成一个xxx0的key,值为/foo/*          filters: #请求路由转发前执行的filter,为数组            - StripPrefix=1  #缩写,和name=StripPrefix,args,参数=1是一个意思,该过滤器为路由转发过滤去            - name: AuthFilter

三.支付接口开发

1.控制层.

(1).PayController
package com.ccm.server.pay.controller;import com.ccm.common.exception.result.ResultSet;import com.ccm.server.pay.controller.service.PayService;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import io.swagger.annotations.ApiParam;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.*;import java.util.List;/** *  @Description 支付控制层 *  @Author ccm *  @CreateTime 2020/08/19 14:38 */@Api(tags = "支付")@RestController@RequestMapping(value = "pay")@Validatedpublic class PayController {
@Autowired private PayService payService; @ApiOperation(value = "支付") @PostMapping(value = "pay") public ResultSet
pay(@ApiParam(hidden = true) @RequestHeader(name = "ccm-userId") Long userId, @ApiParam(value = "支付金额")@RequestParam BigDecimal payMoney) {
String flowingWaterId = payService.pay(userId,payMoney); return ResultSet.success(flowingWaterId); }}

2.业务层.

(1).PayService
package com.ccm.server.pay.controller.service;/** *  @Description 支付业务层 *  @Author ccm *  @CreateTime 2020/08/19 15:13 */public interface PayService {
/** * @Description 支付 * @Author ccm * @CreateTime 2020/8/19 16:06 * @Params [userId, payMoney] * @Return java.lang.String */ String pay(Long userId, BigDecimal payMoney);}
(2).PayServiceImpl
package com.ccm.server.pay.controller.service.impl;import com.ccm.common.exception.result.ResultSet;import com.ccm.server.pay.config.FlowingWaterIdGenerator;import com.ccm.server.pay.controller.service.PayService;import com.ccm.server.pay.dao.mysql.domain.PayFlowingWater;import com.ccm.server.pay.dao.mysql.mapper.PayFlowingWaterMapper;import com.ccm.server.pay.feign.ServerUserFeign;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;/** *  @Description 支付业务层实现 *  @Author ccm *  @CreateTime 2020/08/19 15:14 */@Servicepublic class PayServiceImpl implements PayService {
@Autowired private FlowingWaterIdGenerator flowingWaterIdGenerator; @Autowired private ServerUserFeign serverUserFeign; @Autowired private PayFlowingWaterMapper flowingWaterMapper; @Override public String pay(Long userId, BigDecimal payMoney) {
//生成支付流水号 String flowingWaterId = flowingWaterIdGenerator.nextFlowingWaterId(); //调用server-user的账户扣除余额接口 ResultSet.getFeignData(serverUserFeign.deduction(userId,payMoney)); //pay_flowing_water表插入数据 PayFlowingWater payFlowingWater = new PayFlowingWater(); payFlowingWater.setUserId(userId); payFlowingWater.setFlowingWaterId(flowingWaterId); payFlowingWater.setPayMoney(payMoney); flowingWaterMapper.insert(payFlowingWater); return flowingWaterId; }}
(3).FlowingWaterIdGenerator
package com.ccm.server.pay.config;import com.ccm.server.pay.constants.ServerPayProperties;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.text.SimpleDateFormat;import java.util.Date;import java.util.UUID;/** * @Description 支付流水号id生成器 * @Author ccm * @CreateTime 2020/02/16 15:17 */@Componentpublic class FlowingWaterIdGenerator {
private Long lastTimeStamp = 0L; //上次生成订单id的时间戳 @Autowired private ServerPayProperties serverPayProperties; /** * @Description 生成支付流水号 * @Author ccm * @CreateTime 2020/2/16 15:17 * @Params [] * @Return java.lang.String */ public String nextFlowingWaterId() {
Long timeStamp; synchronized (this.getClass()) {
while(true) {
Long nowTimeStamp = System.currentTimeMillis(); if(!nowTimeStamp.equals(lastTimeStamp)) {
timeStamp = nowTimeStamp; lastTimeStamp = nowTimeStamp; break; } } } String timeStampStr = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date(timeStamp)); StringBuffer idStringBuffer = new StringBuffer(); idStringBuffer.append(timeStampStr) .append(UUID.randomUUID().toString().replace("-","")) .append(serverPayProperties.getServerNumber()); return idStringBuffer.substring(0,32); }}

3.调用外部服务的feign层.

(1).ServerUserFeign
package com.ccm.server.pay.feign;import com.ccm.common.exception.result.ResultSet;import io.swagger.annotations.ApiParam;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.PutMapping;import org.springframework.web.bind.annotation.RequestHeader;import org.springframework.web.bind.annotation.RequestParam;/** *  @Description 调用server-user服务的feign层 *  @Author ccm *  @CreateTime 2020/08/19 16:21 */@FeignClient(name = "server-user")public interface ServerUserFeign {
@PutMapping(value = "account/deduction") ResultSet deduction(@ApiParam(hidden = true) @RequestHeader(name = "ccm-userId") Long userId, @ApiParam(value = "金额") @RequestParam BigDecimal amountOfMoney);}

4.持久层.

(1).PayFlowingWaterMapper
package com.ccm.server.pay.dao.mysql.mapper;import com.ccm.server.pay.dao.mysql.domain.PayFlowingWater;/** *  @Description pay_flowing_water表操作持久层 *  @Author ccm *  @CreateTime 2020/08/19 15:20 */public interface PayFlowingWaterMapper {
int insert(PayFlowingWater payFlowingWater);}
(2).PayFlowingWaterMapper.xml
insert into pay_flowing_water ( flowing_water_id, pay_money, user_id, create_time ) values ( #{flowingWaterId}, #{payMoney}, #{userId}, now() )
(3).PayFlowingWater
package com.ccm.server.pay.dao.mysql.domain;import lombok.Data;import java.util.Date;/** *  @Description pay_flowing_water表映射实体类 *  @Author ccm *  @CreateTime 2020/08/19 15:17 */@Datapublic class PayFlowingWater {
private String flowingWaterId; private BigDecimal payMoney; private Long userId; private Date createTime;}
(4).pay.PayFlowingWater表结构

在这里插入图片描述

四.测试

1.启动gateway网关、server-user服务和server-pay服务.

在这里插入图片描述

2.打开gateway网关的swagger界面.

在这里插入图片描述

3.为user.user_info表中的账户余额充值到100元.

在这里插入图片描述

4.调用支付接口,支付1元.

在这里插入图片描述

在这里插入图片描述

5.查看数据库.

账户余额成功扣款1元

在这里插入图片描述
生成了支付流水
在这里插入图片描述至此,完事!

您的点赞、收藏、转发和关注是我持续创作的动力!

源码地址:

转载地址:http://zutli.baihongyu.com/

你可能感兴趣的文章