位置: IT常识 - 正文

尚融宝25-投资列表展示以及实现充值功能(尚融资本)

发布时间:2024-01-16
尚融宝25-投资列表展示以及实现充值功能

目录

一、展示投资列表

(一)需求

(二)后端

(三)前端

二、充值功能

(一)需求

1、需求描述

2、流程

(二)充值

1、后端

2、前端

(三)回调接口

1、定义回调接口

2、增加交易流水

(四)接口调用幂等性

1、接口幂等性原则

2、解决方案


一、展示投资列表(一)需求

推荐整理分享尚融宝25-投资列表展示以及实现充值功能(尚融资本),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:尚融宝盈(宁波)投资中心(有限合伙),尚融资本是不是骗局,尚融商城是真的吗,尚融资本是不是骗局,尚融公司,尚融资本怎么样,尚融资本是不是骗局,尚融宝项目,内容如对您有帮助,希望把文章链接给更多的朋友!

标的形成后,客户可在客户端看到标的列表,投资者可以通过点击标的了解详情并投资心仪标的

(二)后端

LendController中创建list方法

@Api(tags = "标的")@RestController@RequestMapping("/api/core/lend")@Slf4jpublic class LendController { @Resource private LendService lendService; @ApiOperation("获取标的列表") @GetMapping("/list") public R list() { List<Lend> lendList = lendService.selectList(); return R.ok().data("lendList", lendList); }}(三)前端

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.params.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.params.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 }) { console.log('服务器端获取远程数据。。。。。。。。。。。。。。。。') let response = await $axios.$get('/api/core/lend/list') return { lendList: response.data.lendList, } },}</script>二、充值功能(一)需求1、需求描述

标的产生后,平台展示标的,投资人就可以在平台投资标的,获取收益;投资人投资标的必须满足以下条件:

充值过程与绑定过程一致,也是在平台发送充值请求,跳转到资金托管平台(汇付宝),在资金托管平台(汇付宝)完成充值,然后同步或异步返回或通知平台

操作表:user_account(用户账户表) ====> trans_flow(交易流水表)

用户输入充值后,点击确认,此时我们需要有一个方法返回一个表单且需自动提交(携带汇付宝需要的参数且不能让客户看到表单,因此需要自动提交),然后汇付宝会调用我们的回调方法,在回调方法中,我们需要更新用户账户表并在交易流水表中产生一个记录

汇付宝携带参数说明

 

2、流程

step1:用户在个人中心点击 “充值” 

step2:尚融宝展示账户充值页面

step3:用户填写充值金额,点击“充值”按钮

step4:跳转到汇付宝页面(资金托管接口调用)

 

 step5:汇付宝验证用户交易密码

step6:汇付宝修改账号资金余额(更新user_account记录中的amount的值,这一步汇付宝做)

step7:异步回调

(1)账户金额更改

(2)添加交易流水

step8:用户点击“返回平台”,返回尚融宝

(二)充值1、后端

controller

UserAccountController 

@Api(tags = "会员账户")@RestController@RequestMapping("/api/core/userAccount")@Slf4jpublic class UserAccountController { @Resource private UserAccountService userAccountService; @ApiOperation("充值") @PostMapping("/auth/commitCharge/{chargeAmt}") public R commitCharge( @ApiParam(value = "充值金额", required = true) @PathVariable BigDecimal chargeAmt, HttpServletRequest request) { String token = request.getHeader("token"); Long userId = JwtUtils.getUserId(token); String formStr = userAccountService.commitCharge(chargeAmt, userId); return R.ok().data("formStr", formStr); }}

service

尚融宝25-投资列表展示以及实现充值功能(尚融资本)

接口:UserAccountService

String commitCharge(BigDecimal chargeAmt, Long userId);

实现:UserAccountServiceImpl

@Resourceprivate UserInfoMapper userInfoMapper;@Overridepublic String commitCharge(BigDecimal chargeAmt, Long userId) { UserInfo userInfo = userInfoMapper.selectById(userId); String bindCode = userInfo.getBindCode(); //判断账户绑定状态 Assert.notEmpty(bindCode, ResponseEnum.USER_NO_BIND_ERROR); Map<String, Object> paramMap = new HashMap<>(); paramMap.put("agentId", HfbConst.AGENT_ID); paramMap.put("agentBillNo", LendNoUtils.getNo()); paramMap.put("bindCode", bindCode); paramMap.put("chargeAmt", chargeAmt); paramMap.put("feeAmt", new BigDecimal("0")); paramMap.put("notifyUrl", HfbConst.RECHARGE_NOTIFY_URL);//检查常量是否正确 paramMap.put("returnUrl", HfbConst.RECHARGE_RETURN_URL); paramMap.put("timestamp", RequestHelper.getTimestamp()); String sign = RequestHelper.getSign(paramMap); paramMap.put("sign", sign); //构建充值自动提交表单 String formStr = FormHelper.buildForm(HfbConst.RECHARGE_URL, paramMap); return formStr;}2、前端

pages/user/recharge.vue

methods: { commitCharge() { this.$alert( '<div style="size: 18px;color: red;">您即将前往汇付宝充值</div>', '前往汇付宝资金托管平台', { dangerouslyUseHTMLString: true, confirmButtonText: '立即前往', callback: (action) => { if (action === 'confirm') { this.$axios .$post( '/api/core/userAccount/auth/commitCharge/' + this.chargeAmt ) .then((response) => { document.write(response.data.formStr) }) } }, } ) },},(三)回调接口1、定义回调接口

controller

UserAccountController中创建回调方法 

@ApiOperation(value = "用户充值异步回调")@PostMapping("/notify")public String notify(HttpServletRequest request) { Map<String, Object> paramMap = RequestHelper.switchMap(request.getParameterMap()); log.info("用户充值异步回调:" + JSON.toJSONString(paramMap)); //校验签名 if(RequestHelper.isSignEquals(paramMap)) { //充值成功交易 if("0001".equals(paramMap.get("resultCode"))) { return userAccountService.notify(paramMap); } else { log.info("用户充值异步回调充值失败:" + JSON.toJSONString(paramMap)); return "success"; } } else { log.info("用户充值异步回调签名错误:" + JSON.toJSONString(paramMap)); return "fail"; }}

service

接口:UserAccountService

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

实现:UserAccountServiceImpl

@Transactional(rollbackFor = Exception.class)@Overridepublic String notify(Map<String, Object> paramMap) { log.info("充值成功:" + JSONObject.toJSONString(paramMap)); String bindCode = (String)paramMap.get("bindCode"); //充值人绑定协议号 String chargeAmt = (String)paramMap.get("chargeAmt"); //充值金额 //优化 baseMapper.updateAccount(bindCode, new BigDecimal(chargeAmt), new BigDecimal(0)); //增加交易流水 //TODO return "success";}

mapper

接口:UserAccountMapper

void updateAccount( @Param("bindCode")String bindCode, @Param("amount")BigDecimal amount, @Param("freezeAmount")BigDecimal freezeAmount);

 XML:UserAccountMapper.xml

<update id="updateAccount"> update user_account set amount = amount + #{amount}, freeze_amount = freeze_amount + #{freezeAmount} where user_id = (select id from user_info where bind_code = #{bindCode})</update> 2、增加交易流水

增加枚举TransTypeEnum

@AllArgsConstructor@Getterpublic enum TransTypeEnum { RECHARGE(1,"充值"), INVEST_LOCK(2,"投标锁定"), INVEST_UNLOCK(3,"放款解锁"), CANCEL_LEND(4,"撤标"), BORROW_BACK(5,"放款到账"), RETURN_DOWN(6,"还款扣减"), INVEST_BACK(7,"出借回款"), WITHDRAW(8,"提现"), ; private Integer transType ; private String transTypeName; public static String getTransTypeName(int transType) { for (TransTypeEnum obj : TransTypeEnum.values()) { if (transType == obj.getTransType().intValue()) { return obj.getTransTypeName(); } } return ""; }}

创建BO对象

@Data@AllArgsConstructor@NoArgsConstructorpublic class TransFlowBO { private String agentBillNo; private String bindCode; private BigDecimal amount; private TransTypeEnum transTypeEnum; private String memo;}

 service

接口:TransFlowService

void saveTransFlow(TransFlowBO transFlowBO);

实现:TransFlowServiceImpl

@Resourceprivate UserInfoMapper userInfoMapper;@Overridepublic void saveTransFlow(TransFlowBO transFlowBO) { //获取用户基本信息 user_info QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>(); userInfoQueryWrapper.eq("bind_code", transFlowBO.getBindCode()); UserInfo userInfo = userInfoMapper.selectOne(userInfoQueryWrapper); //存储交易流水数据 TransFlow transFlow = new TransFlow(); transFlow.setUserId(userInfo.getId()); transFlow.setUserName(userInfo.getName()); transFlow.setTransNo(transFlowBO.getAgentBillNo()); transFlow.setTransType(transFlowBO.getTransTypeEnum().getTransType()); transFlow.setTransTypeName(transFlowBO.getTransTypeEnum().getTransTypeName()); transFlow.setTransAmount(transFlowBO.getAmount()); transFlow.setMemo(transFlowBO.getMemo()); baseMapper.insert(transFlow);}

 完整的回调函数notify

@Resourceprivate TransFlowService transFlowService;@Transactional(rollbackFor = Exception.class)@Overridepublic String notify(Map<String, Object> paramMap) { log.info("充值成功:" + JSONObject.toJSONString(paramMap)); String bindCode = (String)paramMap.get("bindCode"); //充值人绑定协议号 String chargeAmt = (String)paramMap.get("chargeAmt"); //充值金额 //优化 baseMapper.updateAccount(bindCode, new BigDecimal(chargeAmt), new BigDecimal(0)); //增加交易流水 String agentBillNo = (String)paramMap.get("agentBillNo"); //商户充值订单号 TransFlowBO transFlowBO = new TransFlowBO( agentBillNo, bindCode, new BigDecimal(chargeAmt), TransTypeEnum.RECHARGE, "充值"); transFlowService.saveTransFlow(transFlowBO); return "success";}(四)接口调用幂等性1、接口幂等性原则

接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次调用而产生了副作用。

举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条...这就没有保证接口的幂等性

回调重试

汇付宝向尚融宝发起回调,如果没有收到正确的响应 "success",则尚融宝会发起重试

汇付宝中的相关代码如下:

@Slf4jpublic class NotifyThread implements Runnable { private int count = 1; private String notifyUrl; private Map<String, Object> paramMap; public NotifyThread(){} public NotifyThread(String notifyUrl, Map<String, Object> paramMap) { this.notifyUrl = notifyUrl; this.paramMap = paramMap; } @Override public void run() { task(); } private void task() { String result = SignUtil.sendRequest(paramMap,notifyUrl); log.info(notifyUrl + ":" + result + " count:" + count); if(!"success".equals(result)) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //ScheduledTask.queue.offer(new NotifyVo(notifyUrl, paramMap)); count++; if(count <= 5) { task(); log.info("失败重试:" + JSON.toJSONString(this)); } } }}

存在的问题:当回调重试时,金额和流水会重复增加

 

2、解决方案

① 设置唯一索引

设置了唯一索引后,即使回调重复执行,遇到唯一索引,就会抛出异常,从而使事务回滚。

但很显然,我们不能光靠报错回滚数据库事务来防止接口幂等性 

② 判断流水是否存在

判断流水如果存在,则从业务方法中直接退出

接口:TransFlowService

boolean isSaveTransFlow(String agentBillNo);

实现:TransFlowServiceImpl

@Overridepublic boolean isSaveTransFlow(String agentBillNo) { QueryWrapper<TransFlow> queryWrapper = new QueryWrapper(); queryWrapper.eq("trans_no", agentBillNo); int count = baseMapper.selectCount(queryWrapper); if(count > 0) { return true; } return false;}

调用 :UserAccountServiceImpl

@Transactional(rollbackFor = Exception.class)@Overridepublic void notify(Map<String, Object> paramMap) { log.info("充值成功:" + JSONObject.toJSONString(paramMap)); //判断交易流水是否存在 String agentBillNo = (String)paramMap.get("agentBillNo"); //商户充值订单号 boolean isSave = transFlowService.isSaveTransFlow(agentBillNo); if(isSave){ log.warn("幂等性返回"); return; } ...... //增加交易流水 //agentBillNo = (String)paramMap.get("agentBillNo"); //商户充值订单号}
本文链接地址:https://www.jiuchutong.com/zhishi/297823.html 转载请保留说明!

上一篇:CSS实现背景图片模糊——毛玻璃效果 | 浅谈CSS属性 filter、backdrop-filter(css实现背景图片变透明)

下一篇:10分钟学会python对接【OpenAI API篇】(10分钟学会万用表)

  • 向境外企业支付利息代扣代缴
  • 免税进账转出怎么填表
  • 企业重组的特殊性税务处理比例
  • 减资需要交个税吗
  • 收到个税手续费返还增值税税率
  • 资金账簿减半征收印花税财税2018 50号
  • 未达起征点可以开专票吗
  • 定额发票可以用旧的营业执照发票章吗
  • 税务筹划的12种方法知乎
  • 小规模纳税人未开票收入填在哪里
  • 申报入库税款怎么分税种发给税管员
  • 企业增加注册资金怎么办理
  • 现金折扣是否可抵税
  • 物流运输途中损坏怎么办
  • 暂估入账估低了怎么办
  • 未按期预缴企业个税
  • 增值税发票三个点
  • 企业所得税税负怎么算
  • 买酒专票怎么可以抵税
  • 进项票一定要专票吗
  • 法定盈余公积是留存收益吗
  • 非居民企业间接转让中国应税财产
  • 应交税费贷方余额负数表示什么
  • 拓展销售市场发生的业务招待费计入
  • lsass.exe是什么进程
  • php include path
  • 代理业务怎么记账
  • 拉姆绍在哪里
  • 渐进模式的特点
  • vue项目引入ts
  • thinkphp框架怎么用
  • 牛客前端刷题怎么样
  • php怎么设置图片的大小
  • 织梦建站详细步骤
  • mongodb数据库中间创建自己名字首字母的数据库
  • dedecmsv6插件不能用
  • 筹建期所得税年度申报如何填列
  • 停工期间工资支付标准
  • 投资收益的主要形式有
  • java实现打印
  • 政府会计制度应收账款坏账准备
  • 个人独资企业购入设备可以一次性计提吗
  • 变动成本法是指什么
  • 维修设备增值税税率
  • 工会应付下级经费
  • 优惠券会计分录怎么做
  • 企业所得税弥补亏损可以弥补几年
  • 资金信息综合服务
  • 支付劳务公司的劳务费如何扣缴个人所得税?
  • 把办公场所转租合法吗
  • 建筑业发票的相关要求
  • 利润总额与应纳税所得额的差异国内动态
  • excel日记账系统的设置
  • win10预览版21301bug
  • ubuntu not authorized to perform operation
  • linux中apt-get和yum
  • windows取消定时任务
  • ubuntu x
  • macbookpro如何开启查找我的mac
  • macbookpro接听苹果手机电话
  • mstore.exe - mstore是什么进程 有什么用
  • onekey.exe是什么
  • linux计划任务每天九点
  • linux 多块硬盘虚拟成一块
  • cocos引擎教程
  • linux ls-l命令详解
  • 在shell命令行方式下,一行只能
  • Python生成随机数
  • Android 为LinearLayout增加分割线 divider
  • android图片透明度怎么设置
  • jquery ui autocomplete
  • unity jsonobject
  • python中__init__
  • 每天一篇文章锻炼口才的文章
  • javascript原型链详解
  • js中prototype的作用
  • 苏州市总工会主要领导
  • 城市配套费需要缴纳契税
  • 云南省国家税务局电子税务局官网
  • 广州地税网上服务大厅地址
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号