新增restful模式

This commit is contained in:
六如
2025-02-02 15:51:47 +08:00
parent 1f04edeaff
commit ddc709ede4
97 changed files with 1487 additions and 867 deletions

View File

@@ -0,0 +1,25 @@
target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
/local-config/

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.15</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.gitee.sop</groupId>
<artifactId>payment-service</artifactId>
<version>5.0.0-SNAPSHOT</version>
<name>payment-service</name>
<properties>
<java.version>1.8</java.version>
<!-- dubbo版本 -->
<dubbo.version>3.2.16</dubbo.version>
</properties>
<dependencies>
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>payment-api</artifactId>
<version>5.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>product-api</artifactId>
<version>5.0.0-SNAPSHOT</version>
</dependency>
<!-- sop接入依赖 -->
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-spring-boot-starter</artifactId>
<version>5.0.0-SNAPSHOT</version>
</dependency>
<!-- nacos注册中心 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
</dependency>
<!-- zookeeper注册中心 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-zookeeper-curator5-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<scope>provided</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<!-- 打包时跳过测试 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- 文档推送 -->
<plugin>
<groupId>com.ly.smart-doc</groupId>
<artifactId>smart-doc-maven-plugin</artifactId>
<version>3.0.9</version>
<configuration>
<!--指定生成文档的使用的配置文件-->
<configFile>./src/main/resources/smart-doc.json</configFile>
<!--指定项目名称-->
<projectName>${project.artifactId}</projectName>
</configuration>
<dependencies>
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-service-support</artifactId>
<version>5.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
<repository>
<id>maven_central</id>
<name>Maven Central</name>
<url>https://repo.maven.apache.org/maven2/</url>
</repository>
</repositories>
</project>

View File

@@ -0,0 +1 @@
mvn -Dfile.encoding=UTF-8 -Dcheckstyle.skip=true smart-doc:torna-rpc

View File

@@ -0,0 +1,16 @@
package com.gitee.sop.payment;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class ExamplePaymentApplication {
public static void main(String[] args) {
SpringApplication.run(ExamplePaymentApplication.class, args);
}
}

View File

@@ -0,0 +1,37 @@
package com.gitee.sop.payment.open;
import com.gitee.sop.payment.open.req.PayOrderSearchRequest;
import com.gitee.sop.payment.open.req.PayTradeWapPayRequest;
import com.gitee.sop.payment.open.resp.PayOrderSearchResponse;
import com.gitee.sop.payment.open.resp.PayTradeWapPayResponse;
import com.gitee.sop.support.annotation.Open;
/**
* 支付接口
*
* @author 六如
*/
public interface OpenPayment {
/**
* 手机网站支付接口
*
* @apiNote 该接口是页面跳转接口,用于生成用户访问跳转链接。
* 请在服务端执行SDK中pageExecute方法读取响应中的body()结果。
* 该结果用于跳转到页面,返回到用户浏览器渲染或重定向跳转到页面。
* 具体使用方法请参考 <a href="https://torna.cn" target="_blank">接入指南</a>
*/
@Open("pay.trade.wap.pay")
PayTradeWapPayResponse tradeWapPay(PayTradeWapPayRequest request);
/**
* 订单查询接口
*
* @param request
* @return
*/
@Open("pay.order.search")
PayOrderSearchResponse orderSearch(PayOrderSearchRequest request);
}

View File

@@ -0,0 +1,55 @@
package com.gitee.sop.payment.open.impl;
import com.gitee.sop.payment.open.OpenPayment;
import com.gitee.sop.payment.open.req.PayOrderSearchRequest;
import com.gitee.sop.payment.open.req.PayTradeWapPayRequest;
import com.gitee.sop.payment.open.resp.PayOrderSearchResponse;
import com.gitee.sop.payment.open.resp.PayTradeWapPayResponse;
import java.util.UUID;
import com.gitee.sop.story.api.ProductService;
import com.gitee.sop.story.api.resp.ProductResult;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Value;
/**
* 开放接口实现
*
* @author 六如
*/
@DubboService(validation = "true")
public class OpenPaymentImpl implements OpenPayment {
@DubboReference
private ProductService storyService;
@Value("${dubbo.labels:}")
private String env;
@Override
public PayTradeWapPayResponse tradeWapPay(PayTradeWapPayRequest request) {
PayTradeWapPayResponse payTradeWapPayResponse = new PayTradeWapPayResponse();
payTradeWapPayResponse.setPageRedirectionData(UUID.randomUUID().toString());
return payTradeWapPayResponse;
}
@Override
public PayOrderSearchResponse orderSearch(PayOrderSearchRequest request) {
PayOrderSearchResponse payOrderSearchResponse = new PayOrderSearchResponse();
payOrderSearchResponse.setOrderNo(request.getOrderNo());
payOrderSearchResponse.setPayNo("xxxx");
payOrderSearchResponse.setPayUserId(111L);
payOrderSearchResponse.setPayUserName("Jim");
try {
ProductResult storyResult = storyService.getById(1L);
payOrderSearchResponse.setRemark(storyResult + ",env:" + env);
} catch (Exception e) {
e.printStackTrace();
}
return payOrderSearchResponse;
}
}

View File

@@ -0,0 +1,20 @@
package com.gitee.sop.payment.open.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
/**
* @author 六如
*/
@Data
public class PayOrderSearchRequest {
/**
* 订单编号
* @mock xxxx
*/
@Length(max = 64) // 最大长度
private String orderNo;
}

View File

@@ -0,0 +1,193 @@
package com.gitee.sop.payment.open.req;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
/**
* pay.trade.wap.pay(手机网站支付接口)
*
* @author 六如
* https://opendocs.alipay.com/open/29ae8cb6_alipay.trade.wap.pay?pathHash=1ef587fd&ref=api&scene=21
*/
@Data
public class PayTradeWapPayRequest {
/**
* 商户网站唯一订单号
*
* @mock 70501111111S001111119
*/
@Length(max = 64)
@NotBlank(message = "商户网站唯一订单号必填")
private String outTradeNo;
/**
* 订单总金额.单位为元,精确到小数点后两位,取值范围:[0.01,100000000]
*
* @mock 9.00
*/
@NotNull(message = "订单总金额不能为空")
private BigDecimal totalAmount;
/**
* 订单标题。注意:不可使用特殊字符,如 /=& 等。
*
* @mock 大乐透
*/
@Length(max = 256)
@NotBlank(message = "订单标题不能为空")
private String subject;
/**
* 销售产品码商家和支付平台签约的产品码。手机网站支付为QUICK_WAP_WAY
*
* @mock QUICK_WAP_WAY
*/
@NotBlank(message = "销售产品码不能为空")
@Length(max = 64)
private String productCode;
/**
* 针对用户授权接口,获取用户相关数据时,用于标识用户授权关系
*
* @mock appopenBb64d181d0146481ab6a762c00714cC27
*/
@Length(max = 40)
private String authToken;
/**
* 用户付款中途退出返回商户网站的地址
*
* @mock http://www.taobao.com/product/113714.html
*/
@Length(max = 400)
private String quit_url;
/**
* 订单包含的商品列表信息json格式其它说明详见商品明细说明
*/
private List<GoodsDetail> goodsDetail;
/**
* 绝对超时时间格式为yyyy-MM-dd HH:mm:ss。超时时间范围1m~15d。
*
* @mock 2016-12-31 10:05:00
*/
@Length(max = 32)
private String timeExpire;
/**
* 商户传入业务信息具体值要和支付平台约定应用于安全营销等参数直传场景格式为json格式
*
* @mock {"mc_create_trade_ip":"127.0.0.1"}
*/
@Length(max = 512)
private String businessParams;
/**
* 公用回传参数如果请求时传递了该参数则返回给商户时会回传该参数。支付平台只会在同步返回包括跳转回商户网站和异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付平台。
*
* @mock merchantBizType%3d3C%26merchantBizNo%3d2016010101111
*/
@Length(max = 512)
private String passbackParams;
/**
* 商户原始订单号最大长度限制32位
*
* @mock {"mc_create_trade_ip":"127.0.0.1"}
*/
@Length(max = 32)
private String merchantOrderNo;
// ---
@Data
public static class GoodsDetail {
/**
* 商品的编号
*
* @mock apple-01
*/
@NotBlank
@Length(max = 64)
private String goodsId;
/**
* 商品名称
*
* @mock ipad
*/
@NotBlank
@Length(max = 256)
private String goodsName;
/**
* 商品数量
*
* @mock 1
*/
@NotNull
private Integer quantity;
/**
* 商品单价,单位为元
*
* @mock 2000
*/
@NotNull
private BigDecimal price;
/**
* 支付平台定义的统一商品编号
*
* @mock 20010001
*/
@Length(max = 32)
private String alipayGoodsId;
/**
* 商品类目
*
* @mock 34543238
*/
@Length(max = 24)
private String goodsCategory;
/**
* 商品类目树从商品类目根节点到叶子节点的类目id组成类目id值使用|分割
*
* @mock 124868003|126232002|126252004
*/
@Length(max = 128)
private String categoriesTree;
/**
* 商品描述信息
*
* @mock 特价手机
*/
@Length(max = 1000)
private String body;
/**
* 商品的展示地址
*
* @mock http://www.alipay.com/xxx.jpg
*/
@Length(max = 400)
private String showUrl;
}
}

View File

@@ -0,0 +1,35 @@
package com.gitee.sop.payment.open.resp;
import lombok.Data;
/**
* @author 六如
*/
@Data
public class PayOrderSearchResponse {
/**
* 订单编号
*/
private String orderNo;
/**
* 支付编号
*/
private String payNo;
/**
* 支付人id
*/
private Long payUserId;
/**
* 支付人姓名
*/
private String payUserName;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,21 @@
package com.gitee.sop.payment.open.resp;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author 六如
*/
@Data
public class PayTradeWapPayResponse {
/**
* 用于跳转支付平台页面的信息POST和GET方法生成内容不同使用POST方法执行结果为html form表单在浏览器渲染即可<br>使用GET方法会得到支付平台URL需要打开或重定向到该URL。建议使用POST方式。
*
* @mock 请参考响应示例
*/
@NotNull
private String pageRedirectionData;
}

View File

@@ -0,0 +1 @@
dubbo.registry.address=zookeeper://localhost:2181

View File

@@ -0,0 +1,2 @@
dubbo.registry.address=nacos://localhost:8848

View File

@@ -0,0 +1,10 @@
spring.profiles.active=dev
server.port=7072
spring.application.name=payment-service
dubbo.protocol.name=dubbo
dubbo.protocol.port=-1
dubbo.application.qos-enable=false
dubbo.consumer.check=false
dubbo.registry.address=zookeeper://localhost:2181

View File

@@ -0,0 +1,27 @@
{
// 开启推送
"enable": true,
// 扫描package多个用;隔开
"basePackage": "com.gitee.sop.payment.open",
// 推送URLIP端口对应Torna服务器
"url": "http://localhost:7700/api",
// 模块token
"token": "34ff76952462413982d21219cf099d46",
// 推送人
"author": "Jim",
// 打开调试:true/false
"debug": true,
// 是否替换文档true替换false不替换追加。默认true
"isReplace": true,
// 第三方jar中的class配置
"jarClass": {
"com.xx.Page": {
"records": { "value": "查询数据列表", "example": "" },
"total": { "value": "总数", "example": "100" },
"size": { "value": "页数", "example": "10" },
"current": { "value": "当前页", "example": "1" },
"countId": { "hidden": true },
"orders": { "hidden": true }
}
}
}

View File

@@ -0,0 +1,10 @@
# 错误配置
# 系统配置
isp.error_isv.common-error=The system is busy.
isp.error_isv.invalid-parameter=Invalid parameter, {0}
# ==== 参数配置 ====
goods.remark.notNull=The goods_remark can not be null
goods.comment.length=The goods_comment length must >= {0} and <= {1}

View File

@@ -0,0 +1,14 @@
# 错误配置
# 系统繁忙
isp.error_isv.common-error=\u7cfb\u7edf\u7e41\u5fd9
# 参数无效
isp.error_isv.invalid-parameter=\u53c2\u6570\u65e0\u6548, {0}
# ==== 参数配置 ====
# 商品备注不能为空
goods.remark.notNull=\u5546\u54c1\u5907\u6ce8\u4e0d\u80fd\u4e3a\u7a7a
# 商品评论长度必须在{0}和{1}之间
goods.comment.length=\u5546\u54c1\u8bc4\u8bba\u957f\u5ea6\u5fc5\u987b\u5728{0}\u548c{1}\u4e4b\u95f4

View File

@@ -0,0 +1,2 @@
isp.goods_error_100=the goods_name can NOT be null
isp.goods_error_101=the goods_name must bigger than {0}

View File

@@ -0,0 +1,5 @@
# 商品名字不能为空
isp.goods_error_100=\u5546\u54C1\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
# 商品名称太短,不能小于{0}个字
isp.goods_error_101=\u5546\u54C1\u540D\u79F0\u592A\u77ED\uFF0C\u4E0D\u80FD\u5C0F\u4E8E{0}\u4E2A\u5B57

View File

@@ -0,0 +1,13 @@
{
"framework": "sop",
"outPath": "target/doc",
"projectName": "项目",
"packageFilters": "com.gitee.sop.payment.open.*",
"openUrl": "http://localhost:7700/api", // torna服务器地址
"appToken": "34ff76952462413982d21219cf099d46", // torna应用token
"debugEnvName":"本地环境",
"debugEnvUrl":"http://127.0.0.1:8081",
"tornaDebug": true,
"replace": true,
"showValidation": false
}

View File

@@ -0,0 +1,14 @@
package com.gitee.sop.payment;
import cn.torna.swaggerplugin.SwaggerPlugin;
/**
* 推送swagger文档
* @author thc
*/
public class DocPushTest {
public static void main(String[] args) {
SwaggerPlugin.pushDoc();
}
}