核心业务6:投资人投资实现

核心业务6:投资人投资实现

1.投资业务流程图

-----------------完善标的详情页展示-----------------

2.投资业务流程

3.展示标的页前端

4.展示标的页后端

5.标的详情页前端

6.标的详情页后端

-----------------完善标的详情页展示-----------------
-----------------投资人发起投资------------

7.投资人投资流程图

8.数据库表的详解

9.投资人投资流程详解

10.前端流程

11.汇付宝接口流程

12.尚融宝接口流程

-----------------投资人发起投资------------

核心业务6:投资人投资实现

1.投资业务流程图

在这里插入图片描述

①用户注册,登录,绑定,充值后

②可以选择投标

在这里插入图片描述

2.投资业务流程

①用户点击我要投资进入标的页面

在这里插入图片描述

②标的页面,点击标的可以进行投资

在这里插入图片描述

③点击具体标的可以展示标的的具体信息

在这里插入图片描述

④该标的详情页展示用户的余额,根据用户填写的投资金额动态算出获得利润

在这里插入图片描述

3.展示标的页前端

①调用接口

在这里插入图片描述

②具体页面代码

srb-site\pages\lend\index.vue

<template>
  <!--列表-->
  <div class="page-filter wrap">
    <div class="breadcrumbs">
      <a href="index.html">首页</a>&gt;<span class="cur">散标投资列表</span>
    </div>
    <div class="invest-filter" data-target="sideMenu">
      <div class="filter-inner clearfix">
        <div class="filter-item">
          <div class="hd">
            <h3>筛选投资项目</h3>
            <label>
              <input id="filterMulti" name="multiple_choice" type="checkbox" />
              多选</label
            >
          </div>
          <div class="bd">
            <dl>
              <dt>项目类型</dt>
              <dd>
                <ul>
                  <li class="n1">
                    <a
                      href="javascript:url('post_type','');"
                      id="post_type_"
                      class="active"
                      >不限</a
                    >
                  </li>
                  <li class="n2">
                    <a
                      href="javascript:url('post_type','car');"
                      id="post_type_car"
                      >车易贷</a
                    >
                  </li>
                  <li class="n3">
                    <a
                      href="javascript:url('post_type','house');"
                      id="post_type_house"
                      >房易贷</a
                    >
                  </li>
                  <li class="n4">
                    <a
                      href="javascript:url('post_type','bridge');"
                      id="post_type_bridge"
                      >赎楼贷</a
                    >
                  </li>
                  <li class="n5">
                    <a
                      href="javascript:url('post_type','worth');"
                      id="post_type_worth"
                      >债权贷</a
                    >
                  </li>
                </ul>
              </dd>
            </dl>
            <dl>
              <dt>年利率</dt>
              <dd>
                <ul>
                  <li class="n1">
                    <a
                      href="javascript:url('borrow_interestrate','');"
                      id="borrow_interestrate_"
                      class="active"
                      >不限</a
                    >
                  </li>
                  <li class="n2">
                    <a
                      id="borrow_interestrate_1"
                      href="javascript:url('borrow_interestrate','1');"
                      >12%以下</a
                    >
                  </li>
                  <li class="n3">
                    <a
                      id="borrow_interestrate_2"
                      href="javascript:url('borrow_interestrate','2');"
                      >12%-14%</a
                    >
                  </li>
                  <li class="n4">
                    <a
                      id="borrow_interestrate_3"
                      href="javascript:url('borrow_interestrate','3');"
                      >14%-16%</a
                    >
                  </li>
                  <li class="n5">
                    <a
                      id="borrow_interestrate_4"
                      href="javascript:url('borrow_interestrate','4');"
                      >16%及以上</a
                    >
                  </li>
                </ul>
              </dd>
            </dl>
            <dl>
              <dt>期限</dt>
              <dd>
                <ul>
                  <li class="n1">
                    <a
                      href="javascript:url('spread_month','');"
                      id="spread_month_"
                      class="active"
                      >不限</a
                    >
                  </li>
                  <li class="n2">
                    <a
                      id="spread_month_1"
                      href="javascript:url('spread_month','1');"
                      >1月以下</a
                    >
                  </li>
                  <li class="n3">
                    <a
                      id="spread_month_2"
                      href="javascript:url('spread_month','2');"
                      >1-3</a
                    >
                  </li>
                  <li class="n4">
                    <a
                      id="spread_month_3"
                      href="javascript:url('spread_month','3');"
                      >3-6</a
                    >
                  </li>
                  <li class="n5">
                    <a
                      id="spread_month_4"
                      href="javascript:url('spread_month','4');"
                      >6-12</a
                    >
                  </li>
                  <li class="n6">
                    <a
                      id="spread_month_5"
                      href="javascript:url('spread_month','5');"
                      >12月及以上</a
                    >
                  </li>
                </ul>
              </dd>
            </dl>
            <dl class="repayment">
              <dt>还款方式</dt>
              <dd>
                <ul>
                  <li class="n1">
                    <a
                      href="javascript:url('repay_style','');"
                      id="repay_style_"
                      class="active"
                      >不限</a
                    >
                  </li>
                  <li class="n2">
                    <a
                      id="repay_style_end"
                      href="javascript:url('repay_style','end');"
                      >到期还本付息</a
                    >
                  </li>
                  <li class="n2">
                    <a
                      id="repay_style_endmonth"
                      href="javascript:url('repay_style','endmonth');"
                      >按月付息,到期还本</a
                    >
                  </li>
                  <li class="n2">
                    <a
                      id="repay_style_month"
                      href="javascript:url('repay_style','month');"
                      >等额本息</a
                    >
                  </li>
                </ul>
              </dd>
            </dl>
          </div>
        </div>
        <div class="common-problem">
          <h3>常见问题</h3>
          <ul>
            <li><a href="#">什么是债权贷?</a></li>
            <li><a href="#">关于"债权贷"产品的说明</a></li>
            <li><a href="#">金融理财收费标准</a></li>
            <li><a href="#">债权贷和房易贷、车易贷有什么区别?</a></li>
          </ul>
        </div>
      </div>
    </div>
    <div class="invest-list mrt30 clearfix">
      <div class="hd">
        <h3>投资列表</h3>
        <div class="count">
          <ul>
            <li class="line">
              散标投资交易金额&nbsp;&nbsp;<span class="f20 bold"
                >73.54亿元</span
              >
            </li>
            <li>
              累计赚取收益&nbsp;&nbsp;<span class="f20 bold">2.52亿元</span>
            </li>
          </ul>
        </div>
      </div>
      <div class="bd">
        <div class="invest-table clearfix">
          <div class="title clearfix">
            <ul>
              <li class="col-330">借款标题</li>
              <li class="col-180">
                <a href="javascript:url('order','account_up');" class=""
                  >借款金额</a
                >
              </li>
              <li class="col-110">
                <a href="javascript:url('order','apr_up');" class="">年利率</a>
              </li>
              <li class="col-150">
                <a href="javascript:url('order','period_up');" class=""
                  >借款期限</a
                >
              </li>
              <li class="col-150">还款方式</li>
              <li class="col-120">
                <a href="javascript:url('order','scale_up');" class=""
                  >借款进度</a
                >
              </li>
              <li class="col-120-t">操作</li>
            </ul>
          </div>
          <!------------投资列表-------------->
          <div class="item" v-for="lend in lendList" :key="lend.id">
            <ul>
              <li class="col-330 col-t">
                <NuxtLink :to="'/lend/' + lend.id" target="_blank">
                  <i class="icon icon-zhai"></i>
                </NuxtLink>
                <NuxtLink
                  class="f18"
                  :to="'/lend/' + lend.id"
                  :title="lend.title"
                  target="_blank"
                >
                  {{ lend.title }}
                </NuxtLink>
              </li>
              <li class="col-180">
                <span class="f20 c-333"> {{ lend.amount }}</span>
              </li>
              <li class="col-110 relative">
                <span class="f20 c-orange">
                  {{ lend.lendYearRate * 100 }}%
                </span>
              </li>
              <li class="col-150">
                <span class="f20 c-333">{{ lend.period }}个月</span>
              </li>
              <li class="col-150">{{ lend.param.returnMethod }}</li>
              <li class="col-120">
                <div class="circle">
                  <div class="left progress-bar">
                    <!-- <div
                      :class="
                        'progress-bgPic progress-bfb' +
                          Math.floor((lend.investAmount / lend.amount) * 10)
                      "
                    > -->
                    <div
                      :class="
                        'progress-bgPic progress-bfb' +
                          Math.floor((lend.investAmount / lend.amount) * 10)
                      "
                    >
                      <div class="show-bar">
                        {{ (lend.investAmount / lend.amount) * 100 }}%
                      </div>
                    </div>
                  </div>
                </div>
              </li>
              <li class="col-120-2">
                <NuxtLink
                  class="ui-btn btn-gray"
                  :to="'/lend/' + lend.id"
                  target="_blank"
                >
                  {{ lend.param.status }}
                </NuxtLink>
              </li>
            </ul>
          </div>
          <!------------投资列表-------------->
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import '~/assets/css/index.css'
import '~/assets/css/detail.css'
export default {
  async asyncData({ $axios }) {
    let response = await $axios.$get('/api/core/lend/list')
    return {
      lendList: response.data.lendList,
    }
  },
}
</script>

4.展示标的页后端

①接口

在这里插入图片描述

②代码复用

  • 之前获得的标的页详细信息可以拿来用
package com.atguigu.srb.core.controller.api;

import com.atguigu.common.result.R;
import com.atguigu.srb.core.pojo.entity.Lend;
import com.atguigu.srb.core.service.LendService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


import javax.annotation.Resource;
import java.util.List;

@Api(tags = "标的")
@RestController
@RequestMapping("/api/core/lend")
@Slf4j
public class LendController {

    @Resource
    private LendService lendService;

    @ApiOperation("获取标的列表")
    @GetMapping("/list")
    public R list() {
        List<Lend> lendList = lendService.selectList();
        return R.ok().data("lendList", lendList);
    }
}

5.标的详情页前端

①前端展示对象

  • 标的信息
    在这里插入图片描述
  • 标的中借款人的信息
    在这里插入图片描述

②前端接口

  • 获取标的信息和借款人信息
    在这里插入图片描述
  • 查询账户余额

在这里插入图片描述

  • 计算收益
    在这里插入图片描述

③前端代码

srb-site\pages\lend_id.vue

<template>
  <!--信息详细-->
  <div class="item-detail wrap">
    <div class="breadcrumbs">
      <a href="/">首页</a>&gt; <a href="/lend">散标投资列表</a>&gt;
      <span class="cur">项目详情</span>
    </div>
    <div class="item-detail-head clearfix" data-target="sideMenu">
      <div class="hd">
        <i class="icon icon-xin"></i>
        <h2 style="width:70%">{{ lend.title }}</h2>
      </div>

      <!-- 标的信息开始 -->
      <div class="bd clearfix">
        <div class="data" style="width: auto;">
          <ul>
            <li>
              <span class="f16">借款金额</span><br />
              <span class="f30 c-333">{{ lend.amount }}</span></li>
            <li class="relative">
              <span class="f16">年利率</span><br />
              <span class="f30 c-orange">{{ lend.lendYearRate * 100 }}% </span>
            </li>
            <li>
              <span class="f16">借款期限</span><br />
              <span class="f30 c-333">{{ lend.period }}</span>
              个月
            </li>
            <li><span class="c-888">借款编号:</span>{{ lend.lendNo }}</li>
            <li>
              <span class="c-888">借款时间:</span>
              {{ lend.lendStartDate }}{{ lend.lendEndDate }}
            </li>
            <li>
              <span class="c-888">还款方式:</span>{{ lend.param.returnMethod }}
            </li>
            <li class="colspan" style="line-height: 60px;">
              <span class="c-888 fl">投标进度:</span>
              <div class="progress-bar fl" style="margin-top:26px;">
                <span
                  :style="
                    'width:' + (lend.investAmount / lend.amount) * 100 + '%'
                  "
                ></span>
              </div>
              <span class="c-orange">
                {{ (lend.investAmount / lend.amount) * 100 }}%
              </span>
              <span>
                已有{{ lend.investNum }}人投资{{ lend.investAmount }}</span>
            </li>
          </ul>
        </div>
      </div>
      <!-- 标的信息开始 -->

      <!-- 投资表单开始 -->
      <div v-if="userType === 1 && lend.status === 1" class="bd clearfix">
        <div class="data" style="width: auto;">
          <el-form :inline="true" class="demo-form-inline">
            <el-form-item label="投资金额">
              <el-input
                v-model="invest.investAmount"
                :disabled="lend.status != 1"
                @blur="getInterestCount()"
              >
                <template slot="append"></template>
              </el-input>
            </el-form-item>
            <el-form-item label="您将获得收益">
              <span class="c-orange">{{ interestCount }}</span></el-form-item>
            <el-form-item>
              <el-checkbox v-model="agree">同意</el-checkbox>
              <span class="orange">
                <a href="#">《出借协议》</a>
              </span>
              <el-button
                type="warning"
                @click="commitInvest"
                :disabled="!agree"
              >
                立即投资
              </el-button>
            </el-form-item>
          </el-form>
          <p>
            您的账户余额 <span class="c-orange">{{ account }}</span> 元,
            <a href="/user/recharge" class="c-888">马上充值</a>
          </p>
        </div>
      </div>
      <!-- 投资表单结束 -->
    </div>

    <!-- 投资记录 -->
    <div class="item-detail-body clearfix mrt30 ui-tab">
      <div class="ui-tab-nav hd">
        <ul>
          <li class="nav_li active">
            <a href="javascript:;">投资记录</a>
          </li>
        </ul>
      </div>
      <div class="bd">
        <div class="ui-tab-item active" style="display: block;">
          <div class="repayment-list">
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
              <tbody>
                <tr>
                  <th>投标人</th>
                  <th>投标金额</th>
                  <th>投标时间</th>
                </tr>
              </tbody>
              <tbody id="repayment_content">
                <tr v-for="lendItem in lendItemList" :key="lendItem.id">
                  <td>{{ lendItem.investName }}</td>
                  <td>
                    <span class="c-orange">{{ lendItem.investAmount }}</span
                    >account
                  </td>
                  <td>{{ lendItem.investTime }}</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>

    <!-- 还款计划 -->
    <div class="item-detail-body clearfix mrt30 ui-tab">
      <div class="ui-tab-nav hd">
        <ul>
          <li class="nav_li active">
            <a href="javascript:;">还款计划</a>
          </li>
        </ul>
      </div>
      <div class="bd">
        <div class="ui-tab-item active" style="display: block;">
          <div class="repayment-list">
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
              <thead>
                <tr>
                  <th>还款期数</th>
                  <th>还款日期</th>
                  <th>应还本金()</th>
                  <th>应还利息()</th>
                  <th>状态</th>
                  <th>是否逾期</th>
                  <th>操作</th>
                </tr>
              </thead>
              <tbody id="repayment_content">
                <tr v-for="lendReturn in lendReturnList" :key="lendReturn.id">
                  <td>{{ lendReturn.currentPeriod }}</td>
                  <td>{{ lendReturn.returnDate }}</td>
                  <td class="c-orange">{{ lendReturn.principal }}</td>
                  <td class="c-orange">{{ lendReturn.interest }}</td>
                  <td>{{ lendReturn.status === 0 ? '未还款' : '已还款' }}</td>
                  <td>
                    <span v-if="lendReturn.overdue">
                      是(逾期金额:{{ lendReturn.overdueTotal }}元)
                    </span>
                    <span v-else></span>
                  </td>
                  <td>
                    <a href="javascript:" @click="commitReturn(lendReturn.id)">
                      {{ lendReturn.status === 0 ? '还款' : '' }}
                    </a>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>

    <!-- 回款计划 -->
    <div v-if="userType === 1" class="item-detail-body clearfix mrt30 ui-tab">
      <div class="ui-tab-nav hd">
        <ul>
          <li class="nav_li active">
            <a href="javascript:;">回款计划</a>
          </li>
        </ul>
      </div>
      <div class="bd">
        <div class="ui-tab-item active" style="display: block;">
          <div class="repayment-list">
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
              <thead>
                <tr>
                  <th>期数</th>
                  <th>本金()</th>
                  <th>利息()</th>
                  <th>本息()</th>
                  <th>计划回款日期</th>
                  <th>实际回款日期</th>
                  <th>状态</th>
                  <th>是否逾期</th>
                </tr>
              </thead>
              <tbody id="repayment_content">
                <tr
                  v-for="lendItemReturn in lendItemReturnList"
                  :key="lendItemReturn.id"
                >
                  <td>{{ lendItemReturn.currentPeriod }}</td>
                  <td class="c-orange">{{ lendItemReturn.principal }}</td>
                  <td class="c-orange">{{ lendItemReturn.interest }}</td>
                  <td class="c-orange">{{ lendItemReturn.total }}</td>
                  <td>{{ lendItemReturn.returnDate }}</td>
                  <td>{{ lendItemReturn.realReturnTime }}</td>
                  <td>
                    {{ lendItemReturn.status === 0 ? '未还款' : '已还款' }}
                  </td>
                  <td>
                    <span v-if="lendItemReturn.overdue">
                      是(逾期金额:{{ lendReturn.overdueTotal }}元)
                    </span>
                    <span v-else></span>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>

    <!-- 借款和借款人信息 -->
    <div class="item-detail-body clearfix mrt30 ui-tab">
      <div class="ui-tab-nav hd">
        <ul>
          <li class="nav_li active">
            <a href="javascript:;">借款信息</a>
          </li>
        </ul>
      </div>
      <div class="bd">
        <div class="ui-tab-item active" style="display: block;">
          <div class="borrow-info" style="width:auto;">
            <dl class="item">
              <dt>
                <h3>项目介绍</h3>
              </dt>
              <dd>
                <div class="text">
                  <p class="MsoNormal" style="margin-left:0cm;text-indent:0cm;">
                    {{ lend.lendInfo }}
                  </p>
                </div>
              </dd>
            </dl>

            <dl class="item">
              <dt>
                <h3>借款人信息</h3>
              </dt>
              <dd>
                <div class="text">
                  <p class="MsoNormal" style="margin-left:0cm;text-indent:0cm;">
                    姓名:{{ borrower.name }} <br />
                    手机号码:{{ borrower.mobile }} <br />
                    身份认证:已认证 <br />
                    注册时间:{{ borrower.createTime }} <br />
                  </p>
                </div>
              </dd>
            </dl>

            <dl class="item">
              <dt>
                <h3>审核信息</h3>
              </dt>
              <dd>
                <div class="verify clearfix" style="width: auto;">
                  <ul>
                    <li>
                      <i class="icon icon-4"></i><br />
                      身份证
                    </li>
                    <li>
                      <i class="icon icon-5"></i><br />
                      户口本
                    </li>
                    <li>
                      <i class="icon icon-6"></i><br />
                      结婚证
                    </li>
                    <li>
                      <i class="icon icon-7"></i><br />
                      工作证明
                    </li>
                    <li>
                      <i class="icon icon-8"></i><br />
                      工资卡流水
                    </li>
                    <li>
                      <i class="icon icon-9"></i><br />
                      收入证明
                    </li>
                    <li>
                      <i class="icon icon-10"></i><br />
                      征信报告
                    </li>
                    <li>
                      <i class="icon icon-11"></i><br />
                      亲属调查
                    </li>
                    <li>
                      <i class="icon icon-19"></i><br />
                      行驶证
                    </li>
                    <li>
                      <i class="icon icon-20"></i><br />
                      车辆登记证
                    </li>
                    <li>
                      <i class="icon icon-21"></i><br />
                      车辆登记发票
                    </li>
                    <li>
                      <i class="icon icon-22"></i><br />
                      车辆交强险
                    </li>
                    <li>
                      <i class="icon icon-23"></i><br />
                      车辆商业保险
                    </li>
                    <li>
                      <i class="icon icon-24"></i><br />
                      车辆评估认证
                    </li>
                  </ul>
                </div>
              </dd>
            </dl>
            <dl class="item">
              <dt>
                <h3>风控步骤</h3>
              </dt>
              <dd>
                <div class="text">
                  <p class="MsoNormal" style="margin-left:0cm;text-indent:0cm;">
                    调查:风控部对借款人各项信息进行了全面的电话征信,一切资料真实可靠。<span
                    ></span>
                  </p>
                  <p class="MsoNormal" style="margin-left:0cm;text-indent:0cm;">
                    抵押物:全款长安福特福克斯汽车,车牌号:川<span>AYY***</span>,新车购买于<span>2013</span>年,裸车价<span>14</span>万,评估价<span>5</span>万。
                  </p>
                  <p class="MsoNormal" style="margin-left:0cm;text-indent:0cm;">
                    权证:汽车已入库、已办理相关手续等。
                  </p>
                  <p class="MsoNormal" style="margin-left:0cm;text-indent:0cm;">
                    担保:质押物担保。
                  </p>
                  <p class="MsoNormal" style="margin-left:0cm;text-indent:0cm;">
                    结论:此客户为老客户,上笔贷款<span>4</span>万元,标的号为<span>20200745682</span>,已结清,现因资金周转,再次申请贷款。借款人居住稳定,收入来源可靠,经风控综合评估,同意放款<span>4</span>万。
                  </p>
                  <p class="MsoNormal" style="margin-left:0cm;text-indent:0cm;">
                    保障:借款逾期<span>48</span>小时内,易贷风险准备金先行垫付。
                  </p>
                </div>
                <div class="step clearfix">
                  <ul>
                    <li><i class="icon icon-1"></i>资料审核</li>
                    <li><i class="icon icon-2"></i>实地调查</li>
                    <li><i class="icon icon-3"></i>资产评估</li>
                    <li class="no"><i class="icon icon-4"></i>发布借款</li>
                  </ul>
                </div>
              </dd>
            </dl>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import '~/assets/css/index.css'
import '~/assets/css/detail.css'
import cookie from 'js-cookie'

export default {
  async asyncData({ $axios, params }) {
    let lendId = params.id
    let response = await $axios.$get('/api/core/lend/show/' + lendId)
    return {
      lend: response.data.lendDetail.lend, //标的详情
      borrower: response.data.lendDetail.borrower, //借款人信息
    }
  },

  data() {
    return {
      account: 0, //账户余额
      agree: false, //是否同意协议
      invest: {
        lendId: 0, //标的id
        investAmount: 100, //投资金额
      },
      interestCount: 0, //将获得收益
      userType: 0, //用户类型
    }
  },

  //此时方法在客户端的浏览器中执行,可以获取到cookie
  mounted() {
    //查询账户余额
    this.fetchAccount()

    //判断登录人的用户类型
    this.fetchUserType()
  },

  methods: {
    //查询账户余额
    fetchAccount() {
      let userInfo = cookie.get('userInfo')
      if (userInfo) {
        this.$axios
          .$get('/api/core/userAccount/auth/getAccount')
          .then((response) => {
            this.account = response.data.account
            console.log(this.account)
          })
      }
    },

    //获取登录人的用户类型
    fetchUserType() {
      let userInfo = cookie.get('userInfo')
      if (userInfo) {
        userInfo = JSON.parse(userInfo)
        this.userType = userInfo.userType
      }
    },

    //计算收益
    getInterestCount() {
      this.$axios
        .$get(
          `/api/core/lend/getInterestCount/${this.invest.investAmount}/${this.lend.lendYearRate}/${this.lend.period}/${this.lend.returnMethod}`
        )
        .then((response) => {
          this.interestCount = response.data.interestCount
        })
    },

    //投资
    commitInvest() {},
  },
}
</script>

⑤前端代码逻辑

  • 进入详情页后,利用前端服务器渲染的技术先将标的和借款人信息渲染
  • 查询账户余额显示出来
  • 然后根据用户类型来确定是否展示立即投资条(判断类型)

6.标的详情页后端

①接口

在这里插入图片描述
在这里插入图片描述

②引入工具类

  • 计算四种借款方式的受益

③查询账户余额

  • controller
    com.atguigu.srb.core.controller.api.UserAccountController
    @ApiOperation("查询账户余额")
    @GetMapping("/auth/getAccount")
    public R getAccount(HttpServletRequest request){
        String token = request.getHeader("token");
        Long userId = JwtUtils.getUserId(token);
        BigDecimal account = userAccountService.getAccount(userId);
        return R.ok().data("account", account);
    }
  • service
    com/atguigu/srb/core/service/UserAccountService.java
BigDecimal getAccount(Long userId);
 /**
     * @param userId:
     * @return BigDecimal
     * @author Likejin
     * @description 查询账户余额
     * @date 2023/4/17 15:43
     */

    @Override
    public BigDecimal getAccount(Long userId) {
        QueryWrapper<UserAccount> userAccountQueryWrapper = new QueryWrapper<>();
        userAccountQueryWrapper.eq("user_id",userId);

        UserAccount userAccount = baseMapper.selectOne(userAccountQueryWrapper);
        BigDecimal amount = userAccount.getAmount();
        return amount;
    }

④获取标的信息

  • controller:利用map封装数据,前面写过
    com/atguigu/srb/core/controller/api/LendController.java
@ApiOperation("获取标的信息")
    @GetMapping("/show/{id}")
    public R show(
            @ApiParam(value = "标的id", required = true)
            @PathVariable Long id) {
        Map<String, Object> lendDetail = lendService.getLendDetail(id);
        return R.ok().data("lendDetail", lendDetail);
    }

⑤计算投资受益

  • controller
    com/atguigu/srb/core/controller/api/LendController.java

    @ApiOperation("计算投资收益")
    @GetMapping("/getInterestCount/{invest}/{yearRate}/{totalmonth}/{returnMethod}")
    public R getInterestCount(
            @ApiParam(value = "投资金额", required = true)
            @PathVariable("invest") BigDecimal invest,

            @ApiParam(value = "年化收益", required = true)
            @PathVariable("yearRate")BigDecimal yearRate,

            @ApiParam(value = "期数", required = true)
            @PathVariable("totalmonth")Integer totalmonth,

            @ApiParam(value = "还款方式", required = true)
            @PathVariable("returnMethod")Integer returnMethod) {

        BigDecimal  interestCount = lendService.getInterestCount(invest, yearRate, totalmonth, returnMethod);
        return R.ok().data("interestCount", interestCount);
    }
  • service
    com/atguigu/srb/core/service/LendService.java
BigDecimal getInterestCount(BigDecimal invest, BigDecimal yearRate, Integer totalmonth, Integer returnMethod);
 /**
     * @param invest:
     * @param yearRate:
     * @param totalmonth:
     * @param returnMethod:
     * @return BigDecimal
     * @author Likejin
     * @description 计算利息
     * @date 2023/4/17 16:31
     */
    @Override
    public BigDecimal getInterestCount(BigDecimal invest, BigDecimal yearRate, Integer totalmonth, Integer returnMethod) {

        BigDecimal interestCount;
        //计算总利息
        if (returnMethod.intValue() == ReturnMethodEnum.ONE.getMethod()) {
            interestCount = Amount1Helper.getInterestCount(invest, yearRate, totalmonth);
        } else if (returnMethod.intValue() == ReturnMethodEnum.TWO.getMethod()) {
            interestCount = Amount2Helper.getInterestCount(invest, yearRate, totalmonth);
        } else if(returnMethod.intValue() == ReturnMethodEnum.THREE.getMethod()) {
            interestCount = Amount3Helper.getInterestCount(invest, yearRate, totalmonth);
        } else {
            interestCount = Amount4Helper.getInterestCount(invest, yearRate, totalmonth);
        }
        return interestCount;
    }

⑥代码逻辑

  • 查询账户余额
    直接利用token解析出user_id查询余额即可
  • 获取标的详细信息
    利用传入的参数标的id,组装一个标的数据lend和borrow的详细信息。
    borrow的详细信息通过调用前面的写过封装的方法
  • 计算投资受益
    根据传入的投资金额,还款方式,期数,年化收益得到利息返回。
    判断还款方式来计算不同的方式的利息返回(调用工具类)

7.投资人投资流程

①投资人点击立即投资

在这里插入图片描述

②根据尚融宝返回的表单自动提交数据到汇付宝,汇付宝返回表单回显页

在这里插入图片描述

③提交的汇付宝更新数据

④汇付宝同步返回页面

在这里插入图片描述

⑤汇付宝异步调用尚融宝接口更新尚融宝

8.数据库表的详解

①尚融宝数据库

  • 标的lend表
    在这里插入图片描述
  • 相关标的借款信息 lend_item表
    在这里插入图片描述
  • 流水表trans_flow
    在这里插入图片描述

②尚融宝三表关联

  • trans_flow根据user_id与唯一账户绑定(三表都有user_id)
  • lend_item和lend表通过lend的id进行绑定

③汇付宝表

  • user_account
    在这里插入图片描述
  • user_invest
    在这里插入图片描述

④汇付宝两表关联

  • user_account和user_invest表通过user_code关联

⑤汇付宝和尚融宝表关联

  • 尚融宝中的lend_item的lend_item_no与汇付宝中的user_invest的agent_bill_no关联,
  • 汇付宝中的user_invest的agent_bill_no与尚融宝中的trans_flow的trans_no关联。
  • 故三表关联

9.投资人投资流程详解

①投资人点击投资

  • 尚融宝接收到投资金额数据
    返回汇付宝需要提交的表单数据(自动提交)
    更新自己的lend_item表,插入一条item(生成lend_item_no)。
  • 尚融宝根据汇付宝需要数据封装表单数据
  • 汇付宝返回给用户表单界面

②投资人在汇付宝界面中点击确定

  • 汇付宝根据表单的vote_bind_code(更新user_account)和agent_bill_no以及vote_amt(更新user_invest)来更新自己的表单。
  • 汇付宝同步返回页面
  • 汇付宝异步向尚融宝发起更新数据请求

③汇付宝异步调用尚融宝

  • 汇付宝封装数据给尚融宝
  • 尚融宝利用vote_bind_code和vote_amt来更新user_account表(余额)
  • 尚融宝更改lend_item的状态为已支付(状态)
  • 尚融宝根据vote_amt来修改更新lend(已投资人数,已投资金额)
  • 尚融宝根据agent_billno来创建一条交易流水trans_flow

10.前端流程

①按钮绑定事件

在这里插入图片描述

②代码

srb-site\pages\lend_id.vue

 //投资
    commitInvest() {
      //校验用户是否登录
      let userInfo = cookie.get('userInfo')
      // console.log(typeof userInfo)
      // console.log(!userInfo) //true
      if (!userInfo) {
        window.location.href = '/login'
        return
      }
      //借款人看不到页面(双重校验)
      //校验当前用户是否是投资人
      let userInfoObj = JSON.parse(userInfo)
      if (userInfoObj.userType == 2) {
        //借款人
        this.$message.error('借款人无法投资')
        return
      }

      //判断标的是否超卖:标的已投金额 + 本次投资金额 > 标的总金额
      if (
        this.lend.investAmount + Number(this.invest.investAmount) >
        this.lend.amount
      ) {
        this.$message.error('标的可投资金额不足')
        return
      }

      //是否是100的整数倍
      // console.log(this.invest.investAmount)
      // console.log(Number(this.invest.investAmount))
      // console.log(typeof Number(this.invest.investAmount))
      // return
      if (
        Number(this.invest.investAmount) === 0 ||
        this.invest.investAmount % this.lend.lowestAmount != 0
      ) {
        this.$message.error(`投资金额必须是${this.lend.lowestAmount}的整数倍`)
        return
      }

      //余额的判断
      if (this.invest.investAmount > this.account) {
        this.$message.error('余额不足,请充值')
        return
      }

      //数据提交
      this.$alert(
        '<div style="size: 18px;color: red;">您即将前往汇付宝确认标的</div>',
        '前往汇付宝资金托管平台',
        {
          dangerouslyUseHTMLString: true,
          confirmButtonText: '立即前往',
          callback: (action) => {
            console.log('action', action)
            if (action === 'confirm') {
              this.invest.lendId = this.lend.id
              this.$axios
                .$post('/api/core/lendItem/auth/commitInvest', this.invest)
                .then((response) => {
                  // console.log(response.data.formStr)
                  // debugger
                  document.write(response.data.formStr)
                })
            }
          },
        }
      )
    },
  },

11.汇付宝接口流程

①汇付宝接受表单数据

在这里插入图片描述

②汇付宝异步调用尚融宝请求数据

)

12.尚融宝接口流程

①尚融宝数据对象

  • 封装前端数据(不是直接对应,还需修改)
    在这里插入图片描述

②尚融宝接口

在这里插入图片描述

③尚融宝具体代码

  • controller
package com.atguigu.srb.core.controller.api;

import com.alibaba.fastjson.JSON;
import com.atguigu.common.result.R;
import com.atguigu.srb.base.util.JwtUtils;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.pojo.vo.InvestVO;
import com.atguigu.srb.core.service.LendItemService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Api(tags = "标的的投资")
@RestController
@RequestMapping("/api/core/lendItem")
@Slf4j
public class LendItemController {

    @Resource
    LendItemService lendItemService;

    @ApiOperation("会员投资提交数据")
    @PostMapping("/auth/commitInvest")
    //注意:此处的vo并不能完全封装前端对象,只能封装id和投资金额,其他的优token获得
    public R commitInvest(@RequestBody InvestVO investVO, HttpServletRequest request) {

        String token = request.getHeader("token");
        Long userId = JwtUtils.getUserId(token);
        String userName = JwtUtils.getUserName(token);
        investVO.setInvestUserId(userId);
        investVO.setInvestName(userName);

        //构建充值自动提交表单
        String formStr = lendItemService.commitInvest(investVO);
        return R.ok().data("formStr", formStr);
    }

    @ApiOperation("会员投资异步回调")
    @PostMapping("/notify")
    public String notify(HttpServletRequest request) {

        Map<String, Object> paramMap = RequestHelper.switchMap(request.getParameterMap());
        log.info("用户投资异步回调:" + JSON.toJSONString(paramMap));

        //校验签名 P2pInvestNotifyVo
        if(RequestHelper.isSignEquals(paramMap)) {
            if("0001".equals(paramMap.get("resultCode"))) {
                lendItemService.notify(paramMap);
            } else {
                log.info("用户投资异步回调失败:" + JSON.toJSONString(paramMap));
                return "fail";
            }
        } else {
            log.info("用户投资异步回调签名错误:" + JSON.toJSONString(paramMap));
            return "fail";
        }
        return "success";
    }
}

  • service
package com.atguigu.srb.core.service;

import com.atguigu.srb.core.pojo.entity.LendItem;
import com.atguigu.srb.core.pojo.vo.InvestVO;
import com.baomidou.mybatisplus.extension.service.IService;

import java.util.Map;

/**
 * <p>
 * 标的出借记录表 服务类
 * </p>
 *
 * @author Likejin
 * @since 2023-04-09
 */
public interface LendItemService extends IService<LendItem> {

    String commitInvest(InvestVO investVO);

    void notify(Map<String, Object> paramMap);

}

package com.atguigu.srb.core.service.impl;

import com.atguigu.common.exception.Assert;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.srb.core.enums.LendStatusEnum;
import com.atguigu.srb.core.enums.TransTypeEnum;
import com.atguigu.srb.core.hfb.FormHelper;
import com.atguigu.srb.core.hfb.HfbConst;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.mapper.LendItemMapper;
import com.atguigu.srb.core.mapper.LendMapper;
import com.atguigu.srb.core.mapper.UserAccountMapper;
import com.atguigu.srb.core.pojo.bo.TransFlowBO;
import com.atguigu.srb.core.pojo.entity.Lend;
import com.atguigu.srb.core.pojo.entity.LendItem;
import com.atguigu.srb.core.pojo.vo.InvestVO;
import com.atguigu.srb.core.service.*;
import com.atguigu.srb.core.util.LendNoUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 标的出借记录表 服务实现类
 * </p>
 *
 * @author Likejin
 * @since 2023-04-09
 */

@Service
public class LendItemServiceImpl extends ServiceImpl<LendItemMapper, LendItem> implements LendItemService {

    @Resource
    private UserBindService userBindService;

    @Resource
    private LendMapper lendMapper;


    @Resource
    private UserAccountService userAccountService;

    @Resource
    private LendService lendService;

    @Resource
    private TransFlowService transFlowService;

    @Resource
    private UserAccountMapper userAccountMapper;
    /**
     * @param investVO:
     * @return String
     * @author Likejin
     * @description 封装投资表单(尚融宝需要的)
     * @date 2023/4/18 9:35
     */

    @Override
    public String commitInvest(InvestVO investVO) {

        //健壮性校验
        Long lendId = investVO.getLendId();
        Lend lend = lendMapper.selectById(lendId);

        //判断标的的状态为募资中
        Assert.isTrue(lend.getStatus()== LendStatusEnum.INVEST_RUN.getStatus().intValue(), ResponseEnum.LEND_INVEST_ERROR);

        //超卖:已投金额+当前投资金额 <= 标的金额 正常
        BigDecimal sumAmount = lend.getInvestAmount().add(new BigDecimal(investVO.getInvestAmount()));
        Assert.isTrue(sumAmount.doubleValue()<lend.getAmount().doubleValue(),ResponseEnum.LEND_FULL_SCALE_ERROR);

        //判断用户余额:当前余额 >=当前投资金额
        Long investUserId = investVO.getInvestUserId();
        BigDecimal account = userAccountService.getAccount(investUserId);
        Assert.isTrue(account.doubleValue()>=Double.parseDouble(investVO.getInvestAmount())
                ,ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);

        //获取paramMap中需要的参数



        //获取投资人的绑定协议号
        String bindCode = userBindService.getBindCodeByUserId(investUserId);
        //获取借款人的绑定协议号
        String benefitBindCode = userBindService.getBindCodeByUserId(lend.getUserId());


        //产生投资记录,产生投资的订单编号lend_item(生成标的下的投资信息)
        LendItem lendItem = new LendItem();
        lendItem.setInvestUserId(investUserId);//投资人id
        lendItem.setInvestName(investVO.getInvestName());//投资人名字
        String lendItemNo = LendNoUtils.getLendItemNo();
        lendItem.setLendItemNo(lendItemNo); //投资条目编号(一个Lend对应一个或多个LendItem)
        lendItem.setLendId(investVO.getLendId());//对应的标的id
        lendItem.setInvestAmount(new BigDecimal(investVO.getInvestAmount())); //此笔投资金额
        lendItem.setLendYearRate(lend.getLendYearRate());//年化
        lendItem.setInvestTime(LocalDateTime.now()); //投资时间
        lendItem.setLendStartDate(lend.getLendStartDate()); //开始时间
        lendItem.setLendEndDate(lend.getLendEndDate()); //结束时间

        //计算平台预期受益(放款)
        BigDecimal ExpectAmount = lendService.getInterestCount(
                lendItem.getInvestAmount(),
                lendItem.getLendYearRate(),
                lend.getPeriod(),
                lend.getReturnMethod());
        lendItem.setExpectAmount(ExpectAmount);//投资人预期受益

        //实际受益(未放款)
        lendItem.setRealAmount(new BigDecimal(0));//投资人实际受益
        //造成预期受益和实际受益不同:如果不满标则实际收益不同

        //投资记录状态
        lendItem.setStatus(0);//刚刚创建投资记录,账户信息尚未修改

        baseMapper.insert(lendItem);//存入数据库

        //组装投资相关的参数,提交到汇付宝资金托管平台==========================================
        //在托管平台同步用户的投资信息,修改用户的账户资金信息==========================================

        //封装提交至汇付宝的参数
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);
        paramMap.put("voteBindCode", bindCode);
        paramMap.put("benefitBindCode",benefitBindCode);
        paramMap.put("agentProjectCode", lend.getLendNo());//项目标号
        paramMap.put("agentProjectName", lend.getTitle());

        //在资金托管平台上的投资订单的唯一编号,要和lendItemNo保持一致。
        paramMap.put("agentBillNo", lendItemNo);//订单编号
        paramMap.put("voteAmt", investVO.getInvestAmount());
        paramMap.put("votePrizeAmt", "0");
        paramMap.put("voteFeeAmt", "0");
        paramMap.put("projectAmt", lend.getAmount()); //标的总金额
        paramMap.put("note", "");
        paramMap.put("notifyUrl", HfbConst.INVEST_NOTIFY_URL); //检查常量是否正确
        paramMap.put("returnUrl", HfbConst.INVEST_RETURN_URL);
        paramMap.put("timestamp", RequestHelper.getTimestamp());
        String sign = RequestHelper.getSign(paramMap);
        paramMap.put("sign", sign);

        //构建充值自动提交表单
        String formStr = FormHelper.buildForm(HfbConst.INVEST_URL, paramMap);
        return formStr;
    }

    /**
     * @param paramMap:
     * @return void
     * @author Likejin
     * @description 投资人投资后汇付宝回调的接口
     * @date 2023/4/18 10:14
     */

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void notify(Map<String, Object> paramMap) {

        //判断幂等性(判断交易流水的增加)
        //获取投资编号
        String agentBillNo = (String)paramMap.get("agentBillNo");
        boolean result = transFlowService.isSaveTransFlow(agentBillNo);
        if(result){
            log.warn("幂等性返回");
            return;
        }


        //修改账户金额:余额减去投资金额,冻结增加投资金额user_account
        String voteBindCode = (String)paramMap.get("voteBindCode");
        String voteAmt = (String)paramMap.get("voteAmt");
        //余额中减少金额,冻结中增加金额
        userAccountMapper.updateAccount(
                voteBindCode,
                new BigDecimal( "-"+voteAmt),
                new BigDecimal(voteAmt)
        );

        //修改投资记录的状态lend_item
        LendItem lendItem = this.getByLendItemNo(agentBillNo);
        lendItem.setStatus(1);//状态为已支付
        baseMapper.updateById(lendItem);

        //修改标的记录,标的信息字段投资人数,已投金额修改lend
        Long lendId = lendItem.getLendId();
        Lend lend = lendMapper.selectById(lendId);
        lend.setInvestNum(lend.getInvestNum()+1);
        lend.setInvestAmount(lend.getInvestAmount().add(lendItem.getInvestAmount()));
        lendMapper.updateById(lend);

        //新增交易流水
        //新增交易流水
        TransFlowBO transFlowBO = new TransFlowBO(
                agentBillNo,
                voteBindCode,
                new BigDecimal(voteAmt),
                TransTypeEnum.INVEST_LOCK,
                "投资项目编号:" + lend.getLendNo() + ",项目名称:" + lend.getTitle());
        transFlowService.saveTransFlow(transFlowBO);

    }


    /**
     * @param lendItemNo:
     * @return LendItem
     * @author Likejin
     * @description 根据lend_item_no查询具体的lend_item
     * @date 2023/4/18 11:06
     */

    private LendItem getByLendItemNo(String lendItemNo){
        QueryWrapper<LendItem> lendItemQueryWrapper = new QueryWrapper<>();
        lendItemQueryWrapper.eq("lend_item_no", lendItemNo);
        return baseMapper.selectOne(lendItemQueryWrapper);
    }
}

  • 其他调用的service
    com/atguigu/srb/core/service/UserBindService.java
    String getBindCodeByUserId(Long userId);
    /**
     * @param userId: 
     * @return String
     * @author Likejin
     * @description  根据user_id获取到user_bind
     * @date 2023/4/18 11:35
     */

    @Override
    public String getBindCodeByUserId(Long userId) {

        QueryWrapper<UserBind> userBindQueryWrapper = new QueryWrapper<>();
        QueryWrapper<UserBind> user_id = userBindQueryWrapper.eq("user_id", userId);
        UserBind userBind = baseMapper.selectOne(userBindQueryWrapper);
        return userBind.getBindCode();
    }

④代码逻辑

  • 返回组装表单
    目的:利用请求数据(标的id和投资金额)返回汇付宝所需表单,保存一条lend_item
    业务流程:
    利用token获取到用户user_id,经过一系列的健壮性校验,封装lend_item数据库表需要的数据,封装汇付宝表单需要的数据。
  • 回调
    目的:利用请求数据一系列表返回sucess
    业务流程:
    校验sign签名,判断幂等性,修改账户金额user_account,修改投资记录状态lend_item,修改标的信息lend,新增交易流水trans_flow

未更新

未更新

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值