├── src
└── main
│ ├── resources
│ ├── application.yml
│ ├── keystore.p12
│ ├── wxinfo.properties
│ ├── zfbinfo.properties
│ ├── spring-context-dubbo.xml
│ ├── application-dev.properties
│ ├── logback-spring.xml
│ └── acp_sdk.properties
│ ├── webapp
│ ├── index.jsp
│ └── WEB-INF
│ │ └── web.xml
│ └── java
│ └── com
│ └── howie
│ ├── domain
│ ├── service
│ │ └── UserService.java
│ ├── annotation
│ │ └── Cluster.java
│ ├── mapper
│ │ ├── UserMapper.java
│ │ └── User.java
│ ├── datasource
│ │ ├── ReadWriteSplitRoutingDataSource.java
│ │ ├── DataSourceConfiguration.java
│ │ └── MybatisConfiguration.java
│ ├── controller
│ │ ├── UserController.java
│ │ └── TestController.java
│ └── interceptor
│ │ └── ClusterIntecerptor.java
│ ├── pay
│ ├── Service
│ │ ├── IUnionPayService.java
│ │ ├── IWeixinPayService.java
│ │ └── IAliPayService.java
│ ├── Constants
│ │ ├── PayWay.java
│ │ ├── PayType.java
│ │ └── Constants.java
│ ├── WXUtils
│ │ ├── MD5Util.java
│ │ ├── qrCodeUtil.java
│ │ ├── OpenIdClass.java
│ │ ├── HttpUtil.java
│ │ ├── XMLUtil.java
│ │ ├── ClientCustomSSL.java
│ │ ├── MobileUtil.java
│ │ ├── PayCommonUtil.java
│ │ └── ConfigUtil.java
│ ├── Main
│ │ ├── Application.java
│ │ └── Swagger2.java
│ ├── AliUtils
│ │ ├── AliPayConfig.java
│ │ ├── CommonUtil.java
│ │ ├── DateUtil.java
│ │ └── AddressUtils.java
│ ├── Controller
│ │ ├── PayController.java
│ │ ├── UnionPayController.java
│ │ ├── AliPayController.java
│ │ ├── WeixinMobilePayController.java
│ │ └── WeixinPayController.java
│ ├── DTO
│ │ └── InfoDTO.java
│ ├── UnionpayUtils
│ │ ├── BaseHttpSSLSocketFactory.java
│ │ ├── UnionConfig.java
│ │ ├── SDKUtil.java
│ │ ├── HttpClient.java
│ │ ├── SDKConstants.java
│ │ └── SDKConfig.java
│ └── ServiceImpl
│ │ ├── UnionPayServiceImpl.java
│ │ ├── AliPayServiceImpl.java
│ │ └── WeixinPayServiceImpl.java
│ ├── domian
│ └── serviceImpl
│ │ └── UserServiceImpl.java
│ ├── Swagger2Config.java
│ └── Application.java
├── README.md
└── pom.xml
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | profiles:
3 | active: dev
--------------------------------------------------------------------------------
/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World!
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/keystore.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Howie1995/UnionPay/HEAD/src/main/resources/keystore.p12
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Archetype Created Web Application
7 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UnionPay
2 |
3 | 这是别人的一个开源项目(戳[这里](https://gitee.com/52itstyle/spring-boot-pay)),当初本意是通过模仿这个项目去学习spring-boot的一些东西,后来在学习过程中加了一些自己的东西;
4 |
5 |
6 | 然后,如果在实际项目中有订单的业务也是可以拿去用的,添加对应的业务逻辑即可,工程里还自定义注解实现了分库的操作.......
7 |
8 |
9 | 然后,下面这个是一个博客的链接([戳](https://blog.csdn.net/Dream__Snow/article/details/82414181)),里面是我在学习过程中的一些总结,还有一些其他的优秀博客的集锦
10 |
11 |
12 | 希望能对有需要的朋友有点帮助,就酱.....
13 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/domain/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.howie.domain.service;
2 |
3 | import org.springframework.stereotype.Service;
4 |
5 | import com.howie.domain.annotation.Cluster;
6 | import com.howie.domain.mapper.User;
7 |
8 | public interface UserService {
9 |
10 | User findByName(String name);
11 |
12 | int insert(String id,String name,String pass);
13 |
14 | }
--------------------------------------------------------------------------------
/src/main/java/com/howie/domain/annotation/Cluster.java:
--------------------------------------------------------------------------------
1 | package com.howie.domain.annotation;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Target({ElementType.METHOD,ElementType.TYPE})
9 | @Retention(RetentionPolicy.RUNTIME)
10 | public @interface Cluster {
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/pay/Service/IUnionPayService.java:
--------------------------------------------------------------------------------
1 | package com.howie.pay.service;
2 |
3 | import java.util.Map;
4 |
5 | import com.howie.pay.dto.InfoDTO;
6 |
7 |
8 | public interface IUnionPayService {
9 | /**
10 | * 银联支付
11 | * @author hongyang.jiang
12 | */
13 | String unionPay(InfoDTO infoDTO);
14 |
15 | /**
16 | * @author hongyang.jiang
17 | */
18 | String validate(Map valideData, String encoding);
19 | /**
20 | * 对账单下载
21 | * @author hongyang.jiang
22 | */
23 | void fileTransfer();
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/resources/wxinfo.properties:
--------------------------------------------------------------------------------
1 | #\u670d\u52a1\u53f7\u7684\u5e94\u7528ID
2 | APP_ID = XXXXXXXXXXXXXXXX
3 | #\u670d\u52a1\u53f7\u7684\u5e94\u7528\u5bc6\u94a5
4 | APP_SECRET = XXXXXXXXXXXXXXXX
5 | #\u670d\u52a1\u53f7\u7684\u914d\u7f6etoken
6 | TOKEN = XXXXXXXXXXXXXXXX
7 | #\u5546\u6237\u53f7
8 | MCH_ID = XXXXXXXXXXXXXXXX
9 | #API\u5bc6\u94a5
10 | API_KEY = XXXXXXXXXXXXXXXX
11 | #\u7b7e\u540d\u52a0\u5bc6\u65b9\u5f0f
12 | SIGN_TYPE = MD5
13 | #/\u5fae\u4fe1\u652f\u4ed8\u8bc1\u4e66\u540d\u79f0,\u5230\u5fae\u4fe1\u7f51\u7ad9\u4e0b\u8f7d
14 | CERT_PATH = apiclient_cert.p12
--------------------------------------------------------------------------------
/src/main/java/com/howie/domain/mapper/UserMapper.java:
--------------------------------------------------------------------------------
1 | package com.howie.domain.mapper;
2 |
3 | import org.apache.ibatis.annotations.Insert;
4 | import org.apache.ibatis.annotations.Mapper;
5 | import org.apache.ibatis.annotations.Param;
6 | import org.apache.ibatis.annotations.Select;
7 |
8 | import com.howie.domain.annotation.Cluster;
9 |
10 | @Mapper
11 | public interface UserMapper {
12 |
13 | @Select("SELECT * FROM USER WHERE username = #{name}")
14 | User findByName(@Param("name") String name);
15 |
16 | @Insert("INSERT INTO `user`(`user`.id,`user`.username,`user`.`password`) VALUES(#{id},#{name},#{pass})")
17 | int insert(@Param("id")String id,@Param("name") String name,@Param("pass")String pass);
18 |
19 | }
--------------------------------------------------------------------------------
/src/main/java/com/howie/domain/mapper/User.java:
--------------------------------------------------------------------------------
1 | package com.howie.domain.mapper;
2 |
3 | public class User {
4 |
5 | private String id;
6 | private String username;
7 | private String password;
8 |
9 | public String getId() {
10 | return id;
11 | }
12 | public void setId(String id) {
13 | this.id = id;
14 | }
15 | public String getUsername() {
16 | return username;
17 | }
18 | public void setUsername(String username) {
19 | this.username = username;
20 | }
21 | public String getPassword() {
22 | return password;
23 | }
24 | public void setPassword(String password) {
25 | this.password = password;
26 | }
27 | @Override
28 | public String toString() {
29 | return "user [id=" + id + ", username=" + username + ", password="
30 | + password + "]";
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/domian/serviceImpl/UserServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.howie.domian.serviceImpl;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Service;
5 |
6 | import com.howie.domain.annotation.Cluster;
7 | import com.howie.domain.mapper.User;
8 | import com.howie.domain.mapper.UserMapper;
9 | import com.howie.domain.service.UserService;
10 |
11 | @Service(value="userService")
12 | public class UserServiceImpl implements UserService {
13 |
14 | @Autowired
15 | private UserMapper userMapper;
16 |
17 | @Override
18 | @Cluster
19 | public User findByName(String name) {
20 | return userMapper.findByName(name);
21 | }
22 |
23 | @Override
24 | public int insert(String id, String name, String pass) {
25 | return userMapper.insert(id, name, pass);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/pay/Constants/PayWay.java:
--------------------------------------------------------------------------------
1 | package com.howie.pay.constants;
2 | /**
3 | * 支付途径
4 | * @author hongyang.jiang
5 | */
6 | public enum PayWay {
7 | PC("PC,平板",(short)1),MOBILE("手机",(short)2);
8 |
9 | private Short code;
10 | private String name;
11 |
12 | private PayWay(String name, Short code) {
13 | this.name = name;
14 | this.code = code;
15 | }
16 |
17 | public static String getName(Short code,String name) {
18 | for (PayWay c : PayWay.values()) {
19 | if (c.getCode() == code) {
20 | return c.name;
21 | }
22 | }
23 | return null;
24 | }
25 |
26 | public String getName() {
27 | return name;
28 | }
29 |
30 | public void setName(String name) {
31 | this.name = name;
32 | }
33 |
34 | public short getCode() {
35 | return code;
36 | }
37 |
38 | public void setCode(short code) {
39 | this.code = code;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/pay/Constants/PayType.java:
--------------------------------------------------------------------------------
1 | package com.howie.pay.constants;
2 | /**
3 | * 支付类型
4 | * @author hongyang.jiang
5 | */
6 | public enum PayType {
7 | /**支付类型*/
8 | ALI("支付宝",(short)1),WECHAT("微信",(short)2),UNION("银联",(short)3);
9 |
10 | private Short code;
11 | private String name;
12 |
13 | private PayType(String name, Short code) {
14 | this.name = name;
15 | this.code = code;
16 | }
17 |
18 | public static String getName(Short code,String name) {
19 | for (PayType c : PayType.values()) {
20 | if (c.getCode() == code) {
21 | return c.name;
22 | }
23 | }
24 | return null;
25 | }
26 |
27 | public String getName() {
28 | return name;
29 | }
30 |
31 | public void setName(String name) {
32 | this.name = name;
33 | }
34 |
35 | public short getCode() {
36 | return code;
37 | }
38 |
39 | public void setCode(short code) {
40 | this.code = code;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/domain/datasource/ReadWriteSplitRoutingDataSource.java:
--------------------------------------------------------------------------------
1 | package com.howie.domain.datasource;
2 |
3 | import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
4 |
5 |
6 | public class ReadWriteSplitRoutingDataSource extends AbstractRoutingDataSource {
7 |
8 | private static final ThreadLocal contextHolder = new ThreadLocal();
9 |
10 | /*@Override
11 | public void afterPropertiesSet() {
12 | setDefaultTargetDataSource();
13 | }*/
14 |
15 | @Override
16 | protected Object determineCurrentLookupKey() {
17 | return getDBType();
18 | }
19 |
20 | public enum DBType {
21 | MASTER, CLUSTER
22 | }
23 |
24 | public static void setDbType(DBType dbType) {
25 | if (dbType == null)
26 | throw new NullPointerException();
27 | contextHolder.set(dbType);
28 | }
29 |
30 | public static DBType getDBType() {
31 | return contextHolder.get() == null ? DBType.MASTER : contextHolder.get();
32 | }
33 |
34 | public static void clearDbType() {
35 | contextHolder.remove();
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/pay/Service/IWeixinPayService.java:
--------------------------------------------------------------------------------
1 | package com.howie.pay.service;
2 |
3 | import com.howie.pay.dto.InfoDTO;
4 |
5 | public interface IWeixinPayService {
6 | /**
7 | * 微信支付下单(模式二) 扫码支付 还有模式一 适合固定商品ID 有兴趣的同学可以自行研究
8 | * @author hongyang.jiang
9 | */
10 | String weixinPay2(InfoDTO infoDTO);
11 |
12 | /**
13 | * 微信支付下单(模式一)
14 | * @author hongyang.jiang
15 | */
16 | void weixinPay1(InfoDTO infoDTO);
17 |
18 | /**
19 | * 微信支付退款
20 | * @author hongyang.jiang
21 | */
22 | String weixinRefund(InfoDTO infoDTO);
23 |
24 | /**
25 | * 关闭订单
26 | * @author hongyang.jiang
27 | */
28 | String weixinCloseorder(InfoDTO infoDTO);
29 |
30 | /**
31 | * 下载微信账单
32 | * @author hongyang.jiang
33 | */
34 | void saveBill();
35 |
36 | /**
37 | * 微信公众号支付返回一个url地址
38 | * @author hongyang.jiang
39 | */
40 | String weixinPayMobile(InfoDTO infoDTO);
41 |
42 | /**
43 | * H5支付 唤醒 微信APP 进行支付 申请入口:登录商户平台-->产品中心-->我的产品-->支付产品-->H5支付
44 | * @author hongyang.jiang
45 | */
46 | String weixinPayH5(InfoDTO infoDTO);
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/resources/zfbinfo.properties:
--------------------------------------------------------------------------------
1 | # \u652f\u4ed8\u5b9d\u7f51\u5173\u540d\u3001partnerId\u548cappId
2 | open_api_domain = https://openapi.alipay.com/gateway.do
3 | mcloud_api_domain = http://mcloudmonitor.com/gateway.do
4 | #\u6b64\u5904\u8bf7\u586b\u5199\u4f60\u7684PID
5 | pid =XXXXXXXXXXXXXXXX
6 | #\u6b64\u5904\u8bf7\u586b\u5199\u4f60\u5f53\u9762\u4ed8\u7684APPID
7 | appid =XXXXXXXXXXXXXXXX
8 |
9 | # RSA\u79c1\u94a5\u3001\u516c\u94a5\u548c\u652f\u4ed8\u5b9d\u516c\u94a5
10 | private_key = XXXXXXXXXXXXXXXX
11 | public_key = XXXXXXXXXXXXXXXX
12 | alipay_public_key = XXXXXXXXXXXXXXXX
13 |
14 | # \u5f53\u9762\u4ed8\u6700\u5927\u67e5\u8be2\u6b21\u6570\u548c\u67e5\u8be2\u95f4\u9694\uff08\u6beb\u79d2\uff09
15 | max_query_retry = 5
16 | query_duration = 5000
17 |
18 | # \u5f53\u9762\u4ed8\u6700\u5927\u64a4\u9500\u6b21\u6570\u548c\u64a4\u9500\u95f4\u9694\uff08\u6beb\u79d2\uff09
19 | max_cancel_retry = 3
20 | cancel_duration = 2000
21 |
22 | # \u4ea4\u6613\u4fdd\u969c\u7ebf\u7a0b\u7b2c\u4e00\u6b21\u8c03\u5ea6\u5ef6\u8fdf\u548c\u8c03\u5ea6\u95f4\u9694\uff08\u79d2\uff09
23 | heartbeat_delay = 5
24 | heartbeat_duration = 900
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/pay/Constants/Constants.java:
--------------------------------------------------------------------------------
1 | package com.howie.pay.constants;
2 |
3 | import org.springframework.util.ClassUtils;
4 |
5 | public class Constants {
6 |
7 | public static final String SF_FILE_SEPARATOR = System.getProperty("file.separator");//文件分隔符
8 | public static final String SF_LINE_SEPARATOR = System.getProperty("line.separator");//行分隔符
9 | public static final String SF_PATH_SEPARATOR = System.getProperty("path.separator");//路径分隔符
10 |
11 | public static final String QRCODE_PATH = ClassUtils.getDefaultClassLoader().getResource("static").getPath()+SF_FILE_SEPARATOR+"qrcode";
12 |
13 | //微信账单 相关字段 用于load文本到数据库
14 | public static final String WEIXIN_BILL = "tradetime, ghid, mchid, submch, deviceid, wxorder, bzorder, openid, tradetype, tradestatus, bank, currency, totalmoney, redpacketmoney, wxrefund, bzrefund, refundmoney, redpacketrefund, refundtype, refundstatus, productname, bzdatapacket, fee, rate";
15 |
16 | public static final String PATH_BASE_INFO_XML = SF_FILE_SEPARATOR+"WEB-INF"+SF_FILE_SEPARATOR+"xmlConfig"+SF_FILE_SEPARATOR;
17 |
18 | public static final String CURRENT_USER = "UserInfo";
19 |
20 | public static final String SUCCESS = "success";
21 |
22 | public static final String FAIL = "fail";
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/domain/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.howie.domain.controller;
2 |
3 | import io.swagger.annotations.Api;
4 | import io.swagger.annotations.ApiOperation;
5 |
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Controller;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RequestMethod;
10 | import org.springframework.web.bind.annotation.RestController;
11 |
12 | import com.howie.domain.annotation.Cluster;
13 | import com.howie.domain.mapper.User;
14 | import com.howie.domain.service.UserService;
15 |
16 | @Controller
17 | @RestController
18 | @RequestMapping("/user")
19 | @Api(tags="用戶管理接口")
20 | public class UserController {
21 |
22 | @Autowired
23 | private UserService userService;
24 |
25 | @RequestMapping(value="/addUser.json",method=RequestMethod.GET)
26 | @ApiOperation(value="添加用戶",notes="添加用戶")
27 | int addUser(String id,String name,String pass){
28 | return userService.insert(id, name, pass);
29 | }
30 |
31 | @RequestMapping(value="/queryUser.json",method=RequestMethod.GET)
32 | @ApiOperation(value="查詢用戶",notes="查詢用戶")
33 | User queryUser(String name){
34 | return userService.findByName(name);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/domain/controller/TestController.java:
--------------------------------------------------------------------------------
1 | package com.howie.domain.controller;
2 |
3 | import io.swagger.annotations.Api;
4 | import io.swagger.annotations.ApiOperation;
5 |
6 | import java.time.LocalDateTime;
7 |
8 | import org.springframework.beans.factory.annotation.Value;
9 | import org.springframework.stereotype.Controller;
10 | import org.springframework.web.bind.annotation.RequestMapping;
11 | import org.springframework.web.bind.annotation.RequestMethod;
12 | import org.springframework.web.bind.annotation.RestController;
13 |
14 | @Controller
15 | @RestController
16 | @RequestMapping("/test")
17 | @Api(tags="測試接口")
18 | public class TestController {
19 |
20 | @Value("${test_variable}")
21 | private int test_variable;
22 |
23 | @RequestMapping(value="/test.json",method=RequestMethod.GET)
24 | @ApiOperation(value="测试接口",notes="返回问候信息")
25 | String index(){
26 | return "Hello,This is SpringBoot!";
27 | }
28 |
29 |
30 | @RequestMapping(value="/now.json",method=RequestMethod.GET)
31 | @ApiOperation(value="测试时间接口",notes="返回当前时间")
32 | String now(){
33 | return "現在是北京時間:"+LocalDateTime.now().toString();
34 | }
35 |
36 | @RequestMapping(value="/getVar.json",method=RequestMethod.GET)
37 | @ApiOperation(value="获取yml配置变量",notes="获取配置文件变量")
38 | int getVar(){
39 | return test_variable;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/pay/WXUtils/MD5Util.java:
--------------------------------------------------------------------------------
1 | package com.howie.pay.wxUtils;
2 |
3 | import java.security.MessageDigest;
4 | /**
5 | * MD5加密
6 | * @author hongyang.jiang
7 | */
8 | public class MD5Util {
9 |
10 | private static String byteArrayToHexString(byte b[]) {
11 | StringBuffer resultSb = new StringBuffer();
12 | for (int i = 0; i < b.length; i++)
13 | resultSb.append(byteToHexString(b[i]));
14 |
15 | return resultSb.toString();
16 | }
17 |
18 | private static String byteToHexString(byte b) {
19 | int n = b;
20 | if (n < 0)
21 | n += 256;
22 | int d1 = n / 16;
23 | int d2 = n % 16;
24 | return hexDigits[d1] + hexDigits[d2];
25 | }
26 |
27 | public static String MD5Encode(String origin, String charsetname) {
28 | String resultString = null;
29 | try {
30 | resultString = new String(origin);
31 | MessageDigest md = MessageDigest.getInstance("MD5");
32 | if (charsetname == null || "".equals(charsetname))
33 | resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
34 | else
35 | resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
36 | } catch (Exception exception) {
37 | }
38 | return resultString;
39 | }
40 |
41 | private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/howie/pay/WXUtils/qrCodeUtil.java:
--------------------------------------------------------------------------------
1 | package com.howie.pay.wxUtils;
2 | import java.util.SortedMap;
3 | import java.util.TreeMap;
4 |
5 | import com.alipay.demo.trade.utils.ZxingUtils;
6 | /**
7 | * 二维码生成器(扫码支付模式一)
8 | * @author hongyang.jiang
9 | */
10 | public class qrCodeUtil {
11 | //商户支付回调URL设置指引:进入公众平台-->微信支付-->开发配置-->扫码支付-->修改 加入回调URL
12 | public static void main(String[] args) {
13 | //注意参数初始化 这只是个Demo
14 | SortedMap