diff --git a/.gitignore b/.gitignore index 47fca9c..fa4fe09 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ /novel-crawl/novel-crawl.iml /novel-crawl/target /novel-admin/target +/*.iml +/novel-admin/*.iml diff --git a/novel-admin/novel-admin.iml b/novel-admin/novel-admin.iml deleted file mode 100644 index 9efc71a..0000000 --- a/novel-admin/novel-admin.iml +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/novel-common/src/main/java/com/java2nb/novel/entity/OrderPay.java b/novel-common/src/main/java/com/java2nb/novel/entity/OrderPay.java new file mode 100644 index 0000000..4500b1f --- /dev/null +++ b/novel-common/src/main/java/com/java2nb/novel/entity/OrderPay.java @@ -0,0 +1,123 @@ +package com.java2nb.novel.entity; + +import java.util.Date; +import javax.annotation.Generated; + +public class OrderPay { + @Generated("org.mybatis.generator.api.MyBatisGenerator") + private Long id; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + private Long outTradeNo; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + private String tradeNo; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + private Byte payChannel; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + private Integer totalAmount; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + private Long userId; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + private Byte payStatus; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + private Date createTime; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + private Date updateTime; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public Long getId() { + return id; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public void setId(Long id) { + this.id = id; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public Long getOutTradeNo() { + return outTradeNo; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public void setOutTradeNo(Long outTradeNo) { + this.outTradeNo = outTradeNo; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public String getTradeNo() { + return tradeNo; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public void setTradeNo(String tradeNo) { + this.tradeNo = tradeNo == null ? null : tradeNo.trim(); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public Byte getPayChannel() { + return payChannel; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public void setPayChannel(Byte payChannel) { + this.payChannel = payChannel; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public Integer getTotalAmount() { + return totalAmount; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public void setTotalAmount(Integer totalAmount) { + this.totalAmount = totalAmount; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public Long getUserId() { + return userId; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public void setUserId(Long userId) { + this.userId = userId; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public Byte getPayStatus() { + return payStatus; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public void setPayStatus(Byte payStatus) { + this.payStatus = payStatus; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public Date getCreateTime() { + return createTime; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public Date getUpdateTime() { + return updateTime; + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } +} \ No newline at end of file diff --git a/novel-common/src/main/java/com/java2nb/novel/mapper/OrderPayDynamicSqlSupport.java b/novel-common/src/main/java/com/java2nb/novel/mapper/OrderPayDynamicSqlSupport.java new file mode 100644 index 0000000..4d39beb --- /dev/null +++ b/novel-common/src/main/java/com/java2nb/novel/mapper/OrderPayDynamicSqlSupport.java @@ -0,0 +1,64 @@ +package com.java2nb.novel.mapper; + +import java.sql.JDBCType; +import java.util.Date; +import javax.annotation.Generated; +import org.mybatis.dynamic.sql.SqlColumn; +import org.mybatis.dynamic.sql.SqlTable; + +public final class OrderPayDynamicSqlSupport { + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public static final OrderPay orderPay = new OrderPay(); + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public static final SqlColumn id = orderPay.id; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public static final SqlColumn outTradeNo = orderPay.outTradeNo; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public static final SqlColumn tradeNo = orderPay.tradeNo; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public static final SqlColumn payChannel = orderPay.payChannel; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public static final SqlColumn totalAmount = orderPay.totalAmount; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public static final SqlColumn userId = orderPay.userId; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public static final SqlColumn payStatus = orderPay.payStatus; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public static final SqlColumn createTime = orderPay.createTime; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public static final SqlColumn updateTime = orderPay.updateTime; + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + public static final class OrderPay extends SqlTable { + public final SqlColumn id = column("id", JDBCType.BIGINT); + + public final SqlColumn outTradeNo = column("out_trade_no", JDBCType.BIGINT); + + public final SqlColumn tradeNo = column("trade_no", JDBCType.VARCHAR); + + public final SqlColumn payChannel = column("pay_channel", JDBCType.TINYINT); + + public final SqlColumn totalAmount = column("total_amount", JDBCType.INTEGER); + + public final SqlColumn userId = column("user_id", JDBCType.BIGINT); + + public final SqlColumn payStatus = column("pay_status", JDBCType.TINYINT); + + public final SqlColumn createTime = column("create_time", JDBCType.TIMESTAMP); + + public final SqlColumn updateTime = column("update_time", JDBCType.TIMESTAMP); + + public OrderPay() { + super("order_pay"); + } + } +} \ No newline at end of file diff --git a/novel-common/src/main/java/com/java2nb/novel/mapper/OrderPayMapper.java b/novel-common/src/main/java/com/java2nb/novel/mapper/OrderPayMapper.java new file mode 100644 index 0000000..f8406d8 --- /dev/null +++ b/novel-common/src/main/java/com/java2nb/novel/mapper/OrderPayMapper.java @@ -0,0 +1,224 @@ +package com.java2nb.novel.mapper; + +import static com.java2nb.novel.mapper.OrderPayDynamicSqlSupport.*; +import static org.mybatis.dynamic.sql.SqlBuilder.*; + +import com.java2nb.novel.entity.OrderPay; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import javax.annotation.Generated; +import org.apache.ibatis.annotations.DeleteProvider; +import org.apache.ibatis.annotations.InsertProvider; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.ResultMap; +import org.apache.ibatis.annotations.Results; +import org.apache.ibatis.annotations.SelectProvider; +import org.apache.ibatis.annotations.UpdateProvider; +import org.apache.ibatis.type.JdbcType; +import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.delete.DeleteDSLCompleter; +import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; +import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider; +import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider; +import org.mybatis.dynamic.sql.select.CountDSLCompleter; +import org.mybatis.dynamic.sql.select.SelectDSLCompleter; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.update.UpdateDSL; +import org.mybatis.dynamic.sql.update.UpdateDSLCompleter; +import org.mybatis.dynamic.sql.update.UpdateModel; +import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider; +import org.mybatis.dynamic.sql.util.SqlProviderAdapter; +import org.mybatis.dynamic.sql.util.mybatis3.MyBatis3Utils; + +@Mapper +public interface OrderPayMapper { + @Generated("org.mybatis.generator.api.MyBatisGenerator") + BasicColumn[] selectList = BasicColumn.columnList(id, outTradeNo, tradeNo, payChannel, totalAmount, userId, payStatus, createTime, updateTime); + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + @SelectProvider(type=SqlProviderAdapter.class, method="select") + long count(SelectStatementProvider selectStatement); + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + @DeleteProvider(type=SqlProviderAdapter.class, method="delete") + int delete(DeleteStatementProvider deleteStatement); + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + @InsertProvider(type=SqlProviderAdapter.class, method="insert") + int insert(InsertStatementProvider insertStatement); + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + @InsertProvider(type=SqlProviderAdapter.class, method="insertMultiple") + int insertMultiple(MultiRowInsertStatementProvider multipleInsertStatement); + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + @SelectProvider(type=SqlProviderAdapter.class, method="select") + @ResultMap("OrderPayResult") + Optional selectOne(SelectStatementProvider selectStatement); + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + @SelectProvider(type=SqlProviderAdapter.class, method="select") + @Results(id="OrderPayResult", value = { + @Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true), + @Result(column="out_trade_no", property="outTradeNo", jdbcType=JdbcType.BIGINT), + @Result(column="trade_no", property="tradeNo", jdbcType=JdbcType.VARCHAR), + @Result(column="pay_channel", property="payChannel", jdbcType=JdbcType.TINYINT), + @Result(column="total_amount", property="totalAmount", jdbcType=JdbcType.INTEGER), + @Result(column="user_id", property="userId", jdbcType=JdbcType.BIGINT), + @Result(column="pay_status", property="payStatus", jdbcType=JdbcType.TINYINT), + @Result(column="create_time", property="createTime", jdbcType=JdbcType.TIMESTAMP), + @Result(column="update_time", property="updateTime", jdbcType=JdbcType.TIMESTAMP) + }) + List selectMany(SelectStatementProvider selectStatement); + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + @UpdateProvider(type=SqlProviderAdapter.class, method="update") + int update(UpdateStatementProvider updateStatement); + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default long count(CountDSLCompleter completer) { + return MyBatis3Utils.countFrom(this::count, orderPay, completer); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default int delete(DeleteDSLCompleter completer) { + return MyBatis3Utils.deleteFrom(this::delete, orderPay, completer); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default int deleteByPrimaryKey(Long id_) { + return delete(c -> + c.where(id, isEqualTo(id_)) + ); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default int insert(OrderPay record) { + return MyBatis3Utils.insert(this::insert, record, orderPay, c -> + c.map(id).toProperty("id") + .map(outTradeNo).toProperty("outTradeNo") + .map(tradeNo).toProperty("tradeNo") + .map(payChannel).toProperty("payChannel") + .map(totalAmount).toProperty("totalAmount") + .map(userId).toProperty("userId") + .map(payStatus).toProperty("payStatus") + .map(createTime).toProperty("createTime") + .map(updateTime).toProperty("updateTime") + ); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default int insertMultiple(Collection records) { + return MyBatis3Utils.insertMultiple(this::insertMultiple, records, orderPay, c -> + c.map(id).toProperty("id") + .map(outTradeNo).toProperty("outTradeNo") + .map(tradeNo).toProperty("tradeNo") + .map(payChannel).toProperty("payChannel") + .map(totalAmount).toProperty("totalAmount") + .map(userId).toProperty("userId") + .map(payStatus).toProperty("payStatus") + .map(createTime).toProperty("createTime") + .map(updateTime).toProperty("updateTime") + ); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default int insertSelective(OrderPay record) { + return MyBatis3Utils.insert(this::insert, record, orderPay, c -> + c.map(id).toPropertyWhenPresent("id", record::getId) + .map(outTradeNo).toPropertyWhenPresent("outTradeNo", record::getOutTradeNo) + .map(tradeNo).toPropertyWhenPresent("tradeNo", record::getTradeNo) + .map(payChannel).toPropertyWhenPresent("payChannel", record::getPayChannel) + .map(totalAmount).toPropertyWhenPresent("totalAmount", record::getTotalAmount) + .map(userId).toPropertyWhenPresent("userId", record::getUserId) + .map(payStatus).toPropertyWhenPresent("payStatus", record::getPayStatus) + .map(createTime).toPropertyWhenPresent("createTime", record::getCreateTime) + .map(updateTime).toPropertyWhenPresent("updateTime", record::getUpdateTime) + ); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default Optional selectOne(SelectDSLCompleter completer) { + return MyBatis3Utils.selectOne(this::selectOne, selectList, orderPay, completer); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default List select(SelectDSLCompleter completer) { + return MyBatis3Utils.selectList(this::selectMany, selectList, orderPay, completer); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default List selectDistinct(SelectDSLCompleter completer) { + return MyBatis3Utils.selectDistinct(this::selectMany, selectList, orderPay, completer); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default Optional selectByPrimaryKey(Long id_) { + return selectOne(c -> + c.where(id, isEqualTo(id_)) + ); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default int update(UpdateDSLCompleter completer) { + return MyBatis3Utils.update(this::update, orderPay, completer); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + static UpdateDSL updateAllColumns(OrderPay record, UpdateDSL dsl) { + return dsl.set(id).equalTo(record::getId) + .set(outTradeNo).equalTo(record::getOutTradeNo) + .set(tradeNo).equalTo(record::getTradeNo) + .set(payChannel).equalTo(record::getPayChannel) + .set(totalAmount).equalTo(record::getTotalAmount) + .set(userId).equalTo(record::getUserId) + .set(payStatus).equalTo(record::getPayStatus) + .set(createTime).equalTo(record::getCreateTime) + .set(updateTime).equalTo(record::getUpdateTime); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + static UpdateDSL updateSelectiveColumns(OrderPay record, UpdateDSL dsl) { + return dsl.set(id).equalToWhenPresent(record::getId) + .set(outTradeNo).equalToWhenPresent(record::getOutTradeNo) + .set(tradeNo).equalToWhenPresent(record::getTradeNo) + .set(payChannel).equalToWhenPresent(record::getPayChannel) + .set(totalAmount).equalToWhenPresent(record::getTotalAmount) + .set(userId).equalToWhenPresent(record::getUserId) + .set(payStatus).equalToWhenPresent(record::getPayStatus) + .set(createTime).equalToWhenPresent(record::getCreateTime) + .set(updateTime).equalToWhenPresent(record::getUpdateTime); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default int updateByPrimaryKey(OrderPay record) { + return update(c -> + c.set(outTradeNo).equalTo(record::getOutTradeNo) + .set(tradeNo).equalTo(record::getTradeNo) + .set(payChannel).equalTo(record::getPayChannel) + .set(totalAmount).equalTo(record::getTotalAmount) + .set(userId).equalTo(record::getUserId) + .set(payStatus).equalTo(record::getPayStatus) + .set(createTime).equalTo(record::getCreateTime) + .set(updateTime).equalTo(record::getUpdateTime) + .where(id, isEqualTo(record::getId)) + ); + } + + @Generated("org.mybatis.generator.api.MyBatisGenerator") + default int updateByPrimaryKeySelective(OrderPay record) { + return update(c -> + c.set(outTradeNo).equalToWhenPresent(record::getOutTradeNo) + .set(tradeNo).equalToWhenPresent(record::getTradeNo) + .set(payChannel).equalToWhenPresent(record::getPayChannel) + .set(totalAmount).equalToWhenPresent(record::getTotalAmount) + .set(userId).equalToWhenPresent(record::getUserId) + .set(payStatus).equalToWhenPresent(record::getPayStatus) + .set(createTime).equalToWhenPresent(record::getCreateTime) + .set(updateTime).equalToWhenPresent(record::getUpdateTime) + .where(id, isEqualTo(record::getId)) + ); + } +} \ No newline at end of file diff --git a/novel-common/src/main/resources/application-common-dev.yml b/novel-common/src/main/resources/application-common-dev.yml index bd8a8cc..a2636a1 100644 --- a/novel-common/src/main/resources/application-common-dev.yml +++ b/novel-common/src/main/resources/application-common-dev.yml @@ -2,9 +2,9 @@ spring: profiles: include: [common] datasource: - url: jdbc:mysql://127.0.0.1:3306/novel_biz?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai + url: jdbc:mysql://127.0.0.1:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai username: root - password: + password: test123456 driver-class-name: com.mysql.cj.jdbc.Driver diff --git a/novel-common/src/main/resources/mybatis/generatorConfig.xml b/novel-common/src/main/resources/mybatis/generatorConfig.xml index a7bbbce..b4015c0 100644 --- a/novel-common/src/main/resources/mybatis/generatorConfig.xml +++ b/novel-common/src/main/resources/mybatis/generatorConfig.xml @@ -8,8 +8,8 @@ - +
diff --git a/novel-front/pom.xml b/novel-front/pom.xml index 767e631..273d04e 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -26,6 +26,13 @@ jjwt${jjwt.version} + + + + com.alipay.sdk + alipay-sdk-java + 4.9.153.ALL + diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/PayController.java b/novel-front/src/main/java/com/java2nb/novel/controller/PayController.java new file mode 100644 index 0000000..4fd2210 --- /dev/null +++ b/novel-front/src/main/java/com/java2nb/novel/controller/PayController.java @@ -0,0 +1,153 @@ +package com.java2nb.novel.controller; + +import com.alipay.api.AlipayClient; +import com.alipay.api.DefaultAlipayClient; +import com.alipay.api.internal.util.AlipaySignature; +import com.alipay.api.request.AlipayTradePagePayRequest; +import com.java2nb.novel.core.bean.UserDetails; +import com.java2nb.novel.core.config.AlipayConfig; +import com.java2nb.novel.service.OrderService; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * @author 11797 + */ +@Controller +@RequestMapping("pay") +@RequiredArgsConstructor +@Slf4j +public class PayController extends BaseController { + + + private final AlipayConfig alipayConfig; + + private final OrderService orderService; + + + /** + * 支付宝支付 + */ + @SneakyThrows + @PostMapping("aliPay") + public void aliPay(Integer payAmount,HttpServletRequest request,HttpServletResponse httpResponse) { + + UserDetails userDetails = getUserDetails(request); + if (userDetails == null) { + //未登录,跳转到登陆页面 + httpResponse.sendRedirect("/user/login.html?originUrl=/pay/aliPay?payAmount="+payAmount); + return; + }else { + //创建充值订单 + Long outTradeNo = orderService.createPayOrder((byte)1,payAmount,userDetails.getId()); + + //获得初始化的AlipayClient + AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getGatewayUrl(), alipayConfig.getAppId(), alipayConfig.getMerchantPrivateKey(), "json", alipayConfig.getCharset(), alipayConfig.getPublicKey(), alipayConfig.getSignType()); + //创建API对应的request + AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); + alipayRequest.setReturnUrl(alipayConfig.getReturnUrl()); + //在公共参数中设置回跳和通知地址 + alipayRequest.setNotifyUrl(alipayConfig.getNotifyUrl()); + //填充业务参数 + alipayRequest.setBizContent("{" + + " \"out_trade_no\":\"" + outTradeNo + "\"," + + " \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," + + " \"total_amount\":" + payAmount + "," + + " \"subject\":\"小说精品屋-plus\"" + + " }"); + //调用SDK生成表单 + String form = alipayClient.pageExecute(alipayRequest).getBody(); + + httpResponse.setContentType("text/html;charset=utf-8"); + //直接将完整的表单html输出到页面 + httpResponse.getWriter().write(form); + httpResponse.getWriter().flush(); + httpResponse.getWriter().close(); + } + + + + + } + + /** + * 支付宝支付通知 + * */ + @SneakyThrows + @RequestMapping("aliPay/notify") + public void aliPayNotify(HttpServletRequest request,HttpServletResponse httpResponse){ + + + PrintWriter out = httpResponse.getWriter(); + + //获取支付宝POST过来反馈信息 + Map params = new HashMap(); + Map requestParams = request.getParameterMap(); + for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { + String name = (String) iter.next(); + String[] values = (String[]) requestParams.get(name); + String valueStr = ""; + for (int i = 0; i < values.length; i++) { + valueStr = (i == values.length - 1) ? valueStr + values[i] + : valueStr + values[i] + ","; + } + params.put(name, valueStr); + } + + //调用SDK验证签名 + boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType()); + + //——请在这里编写您的程序(以下代码仅作参考)—— + + /* 实际验证过程建议商户务必添加以下校验: + 1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号, + 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额), + 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email) + 4、验证app_id是否为该商户本身。 + */ + if(signVerified) { + //验证成功 + //商户订单号 + String outTradeNo = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8"); + + //支付宝交易号 + String tradeNo = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8"); + + //交易状态 + String tradeStatus = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8"); + + //更新订单状态 + orderService.updatePayOrder(Long.parseLong(outTradeNo), tradeNo, tradeStatus); + + + out.println("success"); + + }else {//验证失败 + out.println("fail"); + + //调试用,写文本函数记录程序运行情况是否正常 + //String sWord = AlipaySignature.getSignCheckContentV1(params); + //AlipayConfig.logResult(sWord); + } + + + + } + + + + + + +} diff --git a/novel-front/src/main/java/com/java2nb/novel/core/config/AlipayConfig.java b/novel-front/src/main/java/com/java2nb/novel/core/config/AlipayConfig.java new file mode 100644 index 0000000..0d31fa8 --- /dev/null +++ b/novel-front/src/main/java/com/java2nb/novel/core/config/AlipayConfig.java @@ -0,0 +1,23 @@ +package com.java2nb.novel.core.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author 11797 + */ +@Data +@Component +@ConfigurationProperties(prefix="alipay") +public class AlipayConfig { + + private String appId; + private String merchantPrivateKey; + private String publicKey; + private String notifyUrl; + private String returnUrl; + private String signType; + private String charset; + private String gatewayUrl; +} diff --git a/novel-front/src/main/java/com/java2nb/novel/service/OrderService.java b/novel-front/src/main/java/com/java2nb/novel/service/OrderService.java new file mode 100644 index 0000000..83d5109 --- /dev/null +++ b/novel-front/src/main/java/com/java2nb/novel/service/OrderService.java @@ -0,0 +1,29 @@ +package com.java2nb.novel.service; + + + +/** + * @author 11797 + */ +public interface OrderService { + + + /** + * 创建充值订单 + * + * @param payChannel 支付渠道 + * @param payAmount 支付金额 + * @param userId 用户ID + * @return 商户订单号 + * */ + Long createPayOrder(Byte payChannel, Integer payAmount, Long userId); + + + /** + * 更新订单状态 + * @param outTradeNo 商户订单号 + * @param tradeNo 支付宝/微信 订单号 + * @param tradeStatus 支付状态 + * */ + void updatePayOrder(Long outTradeNo, String tradeNo, String tradeStatus); +} diff --git a/novel-front/src/main/java/com/java2nb/novel/service/UserService.java b/novel-front/src/main/java/com/java2nb/novel/service/UserService.java index 0b3df2d..930c9ad 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/UserService.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/UserService.java @@ -117,4 +117,9 @@ public interface UserService { void updatePassword(Long userId, String oldPassword, String newPassword); + /** + * 增加用户余额 + * @param userId 用户ID + * @param amount 增加的余额 */ + void addAmount(Long userId, int amount); } diff --git a/novel-front/src/main/java/com/java2nb/novel/service/impl/OrderServiceImpl.java b/novel-front/src/main/java/com/java2nb/novel/service/impl/OrderServiceImpl.java new file mode 100644 index 0000000..1ff25ee --- /dev/null +++ b/novel-front/src/main/java/com/java2nb/novel/service/impl/OrderServiceImpl.java @@ -0,0 +1,85 @@ +package com.java2nb.novel.service.impl; + +import com.java2nb.novel.entity.OrderPay; +import com.java2nb.novel.mapper.OrderPayDynamicSqlSupport; +import com.java2nb.novel.mapper.OrderPayMapper; +import com.java2nb.novel.service.OrderService; +import com.java2nb.novel.service.UserService; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Random; + +import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo; +import static org.mybatis.dynamic.sql.select.SelectDSL.select; + +/** + * @author 11797 + */ +@Service +@RequiredArgsConstructor +public class OrderServiceImpl implements OrderService { + + private final OrderPayMapper orderPayMapper; + + private final UserService userService; + + + @SneakyThrows + @Override + public Long createPayOrder(Byte payChannel, Integer payAmount, Long userId) { + Date currentDate = new Date(); + Long outTradeNo = Long.parseLong(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(currentDate)+new Random().nextInt(10)); + OrderPay orderPay = new OrderPay(); + orderPay.setOutTradeNo(outTradeNo); + orderPay.setPayChannel(payChannel); + orderPay.setTotalAmount(payAmount); + orderPay.setUserId(userId); + orderPay.setCreateTime(currentDate); + orderPay.setUpdateTime(currentDate); + orderPayMapper.insertSelective(orderPay); + return outTradeNo; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void updatePayOrder(Long outTradeNo, String tradeNo, String tradeStatus) { + SelectStatementProvider selectStatement = select(OrderPayDynamicSqlSupport.id,OrderPayDynamicSqlSupport.payStatus,OrderPayDynamicSqlSupport.totalAmount,OrderPayDynamicSqlSupport.userId) + .from(OrderPayDynamicSqlSupport.orderPay) + .where(OrderPayDynamicSqlSupport.outTradeNo, isEqualTo(outTradeNo)) + .build() + .render(RenderingStrategies.MYBATIS3); + + OrderPay orderPay = orderPayMapper.selectMany(selectStatement).get(0); + + if(orderPay.getPayStatus()!=1) { + //此订单还未处理过 + + if (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED")) { + //支付成功 + //1.更新订单状态为成功 + orderPay.setPayStatus((byte) 1); + orderPay.setUpdateTime(new Date()); + orderPayMapper.updateByPrimaryKeySelective(orderPay); + + //2.增加用户余额 + userService.addAmount(orderPay.getUserId(),orderPay.getTotalAmount()*100); + + + + + + + } + } + + + + } +} diff --git a/novel-front/src/main/java/com/java2nb/novel/service/impl/UserServiceImpl.java b/novel-front/src/main/java/com/java2nb/novel/service/impl/UserServiceImpl.java index ed715fe..26cac3f 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/impl/UserServiceImpl.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/impl/UserServiceImpl.java @@ -211,7 +211,7 @@ public class UserServiceImpl implements UserService { @Override public User userInfo(Long userId) { - SelectStatementProvider selectStatement = select(username, nickName, userPhoto,userSex) + SelectStatementProvider selectStatement = select(username, nickName, userPhoto,userSex,accountBalance) .from(user) .where(id, isEqualTo(userId)) .build() @@ -256,6 +256,15 @@ public class UserServiceImpl implements UserService { } + @Transactional(rollbackFor = Exception.class) + @Override + public void addAmount(Long userId, int amount) { + User user = this.userInfo(userId); + user.setId(userId); + user.setAccountBalance(user.getAccountBalance()+amount); + userMapper.updateByPrimaryKeySelective(user); + + } } diff --git a/novel-front/src/main/resources/application-alipay.yml b/novel-front/src/main/resources/application-alipay.yml new file mode 100644 index 0000000..e19affc --- /dev/null +++ b/novel-front/src/main/resources/application-alipay.yml @@ -0,0 +1,17 @@ +alipay: + #请填写您的AppId,例如:2019091767145019 + app-id: 2016101600696458 + #请填写您的应用私钥,例如:MIIEvQIBADANB + merchant-private-key: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCJrd9qg88m1p9c7IopcGlLksP9ts0eaf1wesgz4K3O6CzmgaCfR2f+scRI4xrMhKBHfzKDdKlW16LtrebD/YS/aDhRL9MM1GJ0Pr7zFdw6fIka9eIz1FojmmXNyaQVEbaGt/7DvoI+rJjjNtTQAYpMztHnof2W0Nfpra5U4dShJrzsvumS8NapEt9YgQ36jY9Z40RJ97Z06avmMGrAVlQSSTvUInTYz8EQmM3YN0ed3CmnlQFRhuW7kkbgBtZKjq+24iaU2mzp4qvWi5T89l3wuMahhxhFTgTNd24qxFuYShIdD0G3KCtunpwegomj1iQnF47qGv97UwOuA36b6l75AgMBAAECggEAJraZZ94AVa9ryDlK8DQHp5RxP9oy+yZaeVJNESlQNina1kYE4ES33UonI0eYtYFlgDUoAwa+xwiDa8nGZb3XoeqwS0PjWGwv8vfhwYCYGGoEM2yIWoKPhgtYLPFSDgqZBHCgVnIvNWha5Sj51jNYrBhLtZI7ODkpPS/1ITEPFPDds9LmH3Ujci20ttzr1SffKL/1caZ2Xph/Jkm2Xhh227cclORakDsggUmaxt723zibwFwpS6wwRlPJYf7hr3v3SnIgcc0osqKAcnJzrBlmaJVTBgnOAdulp+m/DjKVoIEieMr75OIYTWMRi0trlxAyvv4aDHxxJB6cDGNHFQLIMQKBgQD5j4fJDub2n9EjgxqYS9B6qa2pH5S9yypU+mM6fIXO/AjHpNwEzFQgU8lN3FE1CVfFb4yZx8sOJsQvZPGLvIhMPYT/2xMOIRL2IguJICt23Xnw+c1tNkvHvsHAiLvo/yzwSFixHcOaEwXDKUDsydPyalDFWBrwCGmGGxPEFG/Q/wKBgQCNO0+Muo+HzeUButDyA5gt9oPCX7uZ9g64rnFhuQXZ/eLDQeCW/lhjRiT2R+QafvbRyOYYomKZ6/1iQALY4tqQD7XMClRdu0OUvYR2WaNb9j4sWXl8qhMxgWjXssqorZRzNe+txicX8yOA5/ZVhhq647e2zt4kOS5H6Np0HvxYBwKBgQDvNfA+/cTPk4NhWdLNNqagXTJz0Sy+/BYYnGUu85tDOvyjeVfYVY8x6X4k3tEMWGdEfdc0tHjjmK8misipW8793V417WUHfxZwzVNnXmmrJ0IyhQ+u5oOe9C8+ARK1lJsbuw0gwNn0PtWgK1PrZM5/J/9CGmC/wiB8BkpdAgXoOwKBgE5fa3Wc0al7CGo9UVX7yKc49UUX+vMlKGYz55djJWwjB4NzOz6PRl1Qv5IrstlBO5aO9aEV+8GOw72R6AKTYNYw4aGo2chp8sbHpIpIk+6kZzwVKuWTO7NtLNEF1pBkQszsUWUNYQRZWIpgLsKm+I5db8VyZrOTR6t//DoUN9RhAoGAQLNaaULlw5L2Qsq9hbsdZVkbZN6YY4oiqMufmDKavbpUvchagFBe7/bneX4orza+DiC4vBFDIUOsZawB9eStx8hvL4AcuUF+eoZT3FCmvHB8dAYs4vok28f1nqUpYLmu4yN+wc/sLhihaJd7keErc987/E8mxW18AEin4Q4pKK8= + #支付宝公钥字符串 + public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoR1gAyrjj/XugdKT3zUJBJksYnCXxD3RDiBex+JGfo6oO0oPbyoIQb2cAIIJjCCxT97QATlbYpRGMa+RuXxlxTeBh5ZFkELOsGc/UX0d9Tm51UvN+OV5pyysytlRdZfVgOETORzv9CvfnK7ND1SSHUPDan7TkMoVFipmQnf8205V3tcsDBat5kHEPFCmWXkPxrtLPVge1dAtKSRW9KFMslXkKrspvF1fSLGt12CE38ZwzP39INKgaI+RbIk3o7aRW5CrLqPkYdrgE1KcFBOj/gJXqbZvL/30q1KVn29UQUYm9SR/n6ZaLlAG38p4O3dL9Lu2lGhTBQlUr2qtpo+g8QIDAQAB + #填写您的支付类接口异步通知接收服务地址,例如:https://www:test:com/callback: + notify-url: http://50148a0b.ngrok.io/pay/aliPay/notify + #支付成功跳转页面 + return-url: http://127.0.0.1:8080/user/userinfo.html + #签名方式 + sign-type: RSA2 + #编码 + charset: utf-8 + #支付宝网关 + gateway-url: https://openapi.alipaydev.com/gateway.do diff --git a/novel-front/src/main/resources/application.yml b/novel-front/src/main/resources/application.yml index f8181f2..9ab7ea8 100644 --- a/novel-front/src/main/resources/application.yml +++ b/novel-front/src/main/resources/application.yml @@ -4,6 +4,7 @@ server: spring: profiles: active: dev + include: alipay jwt: secret: novel!#20191230 @@ -23,3 +24,6 @@ xss: excludes: /system/notice/* # 匹配链接 (多个用逗号分隔) urlPatterns: /book/addBookComment,/user/addFeedBack + + + diff --git a/novel-front/src/main/resources/static/images/pay_wx.png b/novel-front/src/main/resources/static/images/pay_wx.png new file mode 100644 index 0000000..ed823d1 Binary files /dev/null and b/novel-front/src/main/resources/static/images/pay_wx.png differ diff --git a/novel-front/src/main/resources/static/images/pay_zfb.png b/novel-front/src/main/resources/static/images/pay_zfb.png new file mode 100644 index 0000000..1fef995 Binary files /dev/null and b/novel-front/src/main/resources/static/images/pay_zfb.png differ diff --git a/novel-front/src/main/resources/static/javascript/common.js b/novel-front/src/main/resources/static/javascript/common.js index dfcaab0..750008d 100644 --- a/novel-front/src/main/resources/static/javascript/common.js +++ b/novel-front/src/main/resources/static/javascript/common.js @@ -1,6 +1,6 @@ var needLoginPath = ['/user/favorites.html','/user/comment.html','/user/feedback.html', '/user/feedback_list.html','/user/read_history.html','/user/set_name.html', - '/user/set_password.html','/user/set_sex.html','/user/setup.html','/user/userinfo.html']; + '/user/set_password.html','/user/set_sex.html','/user/setup.html','/user/userinfo.html',"/pay/index.html"]; var isLogin = false; var url = window.location.search; //key(需要检索的键) diff --git a/novel-front/src/main/resources/static/javascript/pay.js b/novel-front/src/main/resources/static/javascript/pay.js new file mode 100644 index 0000000..faaf28d --- /dev/null +++ b/novel-front/src/main/resources/static/javascript/pay.js @@ -0,0 +1,93 @@ +var UserPay = { + czData: [[30, "3000屋币"], [50, "5000屋币"], [100, "10000屋币"], [200, "20000屋币"], [500, "50000屋币"], [365, "全站包年阅读"] ], + czPayPalData: [[20, "10000屋币"], [50, "25000屋币"], [100, "50000屋币"], [80, "全站包年阅读"]], + sendPay: function () { + $("#payform").submit(); + }, + GetPayState: function (payId) { + $.post("/api/book.aspx", { act: "getpaystatus", pid: payId }, function (data, textStatus) { + if (data == "1") { + location.href = '/pay/wx_return.aspx?out_trade_no=sc'+payId; + } + else { + setTimeout("UserPay.GetPayState("+payId+")",3000); + } + }, "html"); + } +} + +$(function () { + $("#ulPayType li").click(function () { + + if($(this).attr("valp")==2){ + layer.alert("微信支付暂未开通,敬请期待"); + } + + return ; + + + + $($(this).parent()).children().each(function () { + $(this).removeClass("on"); + }); + $(this).addClass("on"); + + var type = $(this).attr("valp"); + if (type == "3") { + $("#ulPayPal").show(); + $("#ulPayPalXJ").show(); + $("#ulZFWX").hide(); + $("#ulZFWXXJ").hide(); + } + else { + $("#ulPayPal").hide(); + $("#ulPayPalXJ").hide(); + $("#ulZFWX").show(); + $("#ulZFWXXJ").show(); + } + + var postUrl = ""; + switch (type) + { + case "1": + postUrl = "sendalipay.aspx"; + break; + case "2": + postUrl = "sendwxpaynowqr.aspx"; + break; + case "3": + postUrl = "sendpaypal.aspx"; + break; + } + $("#payform").attr("action", postUrl); + }) + + $("#ulZFWX li").click(function () { + $("#ulZFWX li").removeClass("on"); + $(this).addClass("on"); + if ($(this).attr("vals") > 0) { + $("#pValue").val($(this).attr("vals")); + $("#showTotal").html('¥' + $(this).attr("vals") + '元'); + for (var i = 0; i < UserPay.czData.length; i++) { + if (UserPay.czData[i][0] == $(this).attr("vals")) { + $("#showRemark").html(UserPay.czData[i][1]); + break; + } + } + } + }); + $("#ulPayPal li").click(function () { + $("#ulPayPal li").removeClass("on"); + $(this).addClass("on"); + if ($(this).attr("vals") > 0) { + $("#pValue").val($(this).attr("vals")); + $("#showPayPalTotal").html($(this).attr("vals") + '美元'); + for (var i = 0; i < UserPay.czData.length; i++) { + if (UserPay.czPayPalData[i][0] == $(this).attr("vals")) { + $("#showPayPalRemark").html(UserPay.czPayPalData[i][1]); + break; + } + } + } + }); +}); \ No newline at end of file diff --git a/novel-front/src/main/resources/templates/common/top.html b/novel-front/src/main/resources/templates/common/top.html index 163dd47..0b78dc1 100644 --- a/novel-front/src/main/resources/templates/common/top.html +++ b/novel-front/src/main/resources/templates/common/top.html @@ -42,7 +42,7 @@
  • 首页
  • 全部作品
  • 排行榜
  • -
  • 充值
  • +
  • 充值
  • 作家专区
  • diff --git a/novel-front/src/main/resources/templates/pay/index.html b/novel-front/src/main/resources/templates/pay/index.html new file mode 100644 index 0000000..91f3ec6 --- /dev/null +++ b/novel-front/src/main/resources/templates/pay/index.html @@ -0,0 +1,139 @@ + + + + + + + + + + + +
    +
    + +
    +
    + +
    + +
    +
    +
    + 充值账号:余额:0屋币 +
    + +
    +
    +
    选择充值方式
    +
      +
    • 支付宝支付
    • +
    • 微信支付
    • + +
    +
    选择充值金额
    +
      +
    • 10元1000屋币
    • +
    • 30元3000屋币
    • +
    • 50元5000屋币
    • +
    • 100元10000屋币
    • +
    • 200元20000屋币
    • +
    • 500元50000屋币
    • +
    + +
      +
    • 当前汇率:1元=100屋币
    • +
    • 总计金额:¥50元 获得 5000屋币
    • +
    • 立即支付
    • +
    + +
    +
    + 温馨提示 +
      +
    • 1. 充值阅读权限仅限本书城使用
    • +
    • 2. 充值支持信用卡、借记卡、支付宝余额、微信零钱等支付
    • +
    • 3. 包年时间是365天,重复购买时间会累加
    • +
    • 4. 若充值遇到问题,点此留言
    • +
    +
    +
    + +
    +
    + + + + +
    +
    +
    + + + + + + + \ No newline at end of file diff --git a/novel-front/src/main/resources/templates/user/userinfo.html b/novel-front/src/main/resources/templates/user/userinfo.html index 8fdb3b3..706c40d 100644 --- a/novel-front/src/main/resources/templates/user/userinfo.html +++ b/novel-front/src/main/resources/templates/user/userinfo.html @@ -30,7 +30,7 @@

    @@ -96,6 +96,8 @@ $("#my_name").html(data.data.username); } + $("#accountBalance").html(data.data.accountBalance); + } else if (data.code == 1001) { //未登录 location.href = '/user/login.html?originUrl=' + decodeURIComponent(location.href); diff --git a/novel.iml b/novel.iml deleted file mode 100644 index 3ac9e4e..0000000 --- a/novel.iml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sql/20200511.sql b/sql/20200511.sql new file mode 100644 index 0000000..8eb12a3 --- /dev/null +++ b/sql/20200511.sql @@ -0,0 +1,33 @@ +/* +Navicat MySQL Data Transfer + +Source Server : localhost +Source Server Version : 50725 +Source Host : localhost:3306 +Source Database : novel_plus + +Target Server Type : MYSQL +Target Server Version : 50725 +File Encoding : 65001 + +Date: 2020-05-11 17:56:23 +*/ + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for order_pay +-- ---------------------------- +DROP TABLE IF EXISTS `order_pay`; +CREATE TABLE `order_pay` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', + `out_trade_no` bigint(20) NOT NULL COMMENT '商户订单号', + `trade_no` varchar(64) DEFAULT NULL COMMENT '支付宝/微信交易号', + `pay_channel` tinyint(1) NOT NULL DEFAULT '1' COMMENT '支付渠道,1:支付宝,2:微信', + `total_amount` int(11) NOT NULL COMMENT '交易金额(单位元)', + `user_id` bigint(20) NOT NULL COMMENT '支付用户ID', + `pay_status` tinyint(1) DEFAULT '2' COMMENT '支付状态:0:支付失败,1:支付成功,2:待支付', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COMMENT='充值订单';