1. 前端实现
1.1 创建路由 174
{ //174
path: '/page/user/userpay',
name: 'UserPayView',
component: () => import('../views/UserPayView.vue')
}
1.2 按钮跳转 174
UserCenterView.vue
1.3 添加页面 174
1.3.1 UserPayView.vue
<template>
<div>
<Header></Header>
<!--充值-->
<div class="user-pay-box clearfix">
<div class="user-pay-left fl">
<p class="user-pay-title1">我的账户</p>
<div class="user-pay-list">
<a href="javascript:;" class="user-pay-list-on">充值</a>
<a href="javascript:;" target="_blank">我的信息</a>
<a href="javascript:;" target="_blank">投资记录</a>
<a href="javascript:;" target="_blank">收益记录</a>
</div>
</div>
<div class="user-pay-right fl">
<p class="user-pay-title2">第三方支付平台</p>
<div class="user-pay-form">
<img src="@/assets/image/kq.png" alt="">
<form action="http://localhost:9000/pay/kq/rece/recharge" target="_blank" id="money_submit">
<p class="user-pay-form-ts">请输入金额</p>
<input type="text" placeholder="元" name="rechargeMoney" value="0.01" class="number-money" >
<input type="hidden" name="uid" v-bind:value="userId">
<input type="submit" value="支付" class="submit-btn">
</form>
</div>
<div class="user-pay-sm">
<h3>温馨提示</h3>
<p>1.为了您的使用安全,充值操作建议不要使用公共电脑。</p>
<p>2.银行卡充值限额,由各银行限制。</p>
<p>3.品台禁止用卡套现、虚拟交易、洗钱等行为,一经发现并确认,将终止该账户的使用。</p>
<p>4.如果充值中出现问题,请联系客服400-890-0000。</p>
</div>
</div>
</div>
<Footer></Footer>
</div>
</template>
<script>
import Header from "@/components/common/Header";
import Footer from "@/components/common/Footer";
export default {
name: "UserPayView",
data(){
return {
userId:0
}
},
mounted() {
let userinfo = window.localStorage.getItem("userinfo");
if( userinfo ){
this.userId = JSON.parse(userinfo).uid;
}
},
components:{
// eslint-disable-next-line vue/no-unused-components
Header,
// eslint-disable-next-line vue/no-unused-components
Footer
},
methods:{
}
}
</script>
<style scoped>
</style>
1.3.2 优化form表单页面 175
后端kqForm.html 175
micr-pay
<script>
document.forms[0].submit(); //175
</script>
1.4 测试 175
点击支付
页面跳转成功
2. 后端支付结果发送给商家 175
2.1 处理后续充值 176
2.1.1 业务接口RechargeService
micr-api
//处理充值 后续 176
int handleKQNotify(String orderId, String payAmount, String payResult);
2.1.2 业务接口实现类RechargeServiceImpl 176
根据订单号查询充值表 记录176
在mapper中定义方法
RechargeRecordMapper
micr-dataservice
//根据订单号查询充值表 记录 176
RechargeRecord selectByRechargeNo(@Param("rechargeNo") String orderId);
编写sql 176
RechargeRecordMapper.xml
micr-dataservice
<!--根据订单号查询充值表 记录 176-->
<select id="selectByRechargeNo" resultMap="BaseResultMap">
select <include refid="Base_Column_List" />
from b_recharge_record
where recharge_no = #{rechargeNo} for update
</select>
更新资金账户 178
在mapper中定义方法
FinanceAccountMapper
micr-dataservice
//充值更新金额 178
int updateAvailableMoneyByRecharge(@Param("uid") Integer uid,
@Param("rechargeMoney") BigDecimal rechargeMoney);
编写sql语句
FinanceAccountMapper.xml
micr-dataservice
<!--充值更新金额 178-->
<update id="updateAvailableMoneyByRecharge">
update u_finance_account set available_money = available_money + #{rechargeMoney}
where uid = #{uid}
</update>
更新充值记录的状态 178
在mapper中定义方法
RechargeRecordMapper
micr-dataservice
//更新充值记录的状态 178
int updateStatus(@Param("id") Integer id, @Param("newStatus") int rechargeStatusSuccess);
编写sql
RechargeRecordMapper.xml
micr-dataservice
<!--更新充值记录的状态 178-->
<update id="updateStatus">
update b_recharge_record set recharge_status = #{newStatus} where id = #{id}
</update>
实现类RechargeServiceImpl 177-178
micr-dataservice
//处理充值 后续 176
@Transactional(rollbackFor = Exception.class)
@Override
public synchronized int handleKQNotify(String orderId, String payAmount, String payResult) {
int result = 0;//订单不存在
int rows = 0;
//1.查询订单 176
RechargeRecord record = rechargeMapper.selectByRechargeNo(orderId);
if(record != null ){ //177
if( record.getRechargeStatus() == YLBConstant.RECHARGE_STATUS_PROCESSING){
//2.判断金额是否一致 177
String fen = record.getRechargeMoney().multiply(new BigDecimal("100"))
.stripTrailingZeros().toPlainString();
if( fen.equals(payAmount)){
//金额一致 177
if("10".equals(payResult)){//判断快钱返回给我们得充值成功状态码
//成功 178
//充值更新金额 178
rows = accountMapper.updateAvailableMoneyByRecharge(record.getUid(),record.getRechargeMoney());
if(rows < 1 ){
throw new RuntimeException("充值更新资金账号失败");
}
//更新充值记录的状态 178
rows = rechargeMapper.updateStatus(record.getId(),YLBConstant.RECHARGE_STATUS_SUCCESS);
if( rows < 1) {
throw new RuntimeException("充值更新充值记录状态失败");
}
result = 1;//成功
} else {
//充值失败
//更新充值记录的状态
rows = rechargeMapper.updateStatus(record.getId(), YLBConstant.RECHARGE_STATUS_FAIL);
if( rows < 1) {
throw new RuntimeException("充值更新充值记录状态失败");
}
result = 2;//充值结果是失败的
}
} else {
result = 4;//金额不一样
}
} else {
result = 3;//订单已经处理过了
}
}
return result;
}
2.2 消费者 接收快钱给商家的支付结果 176
拷贝公钥到此 179
资源在E:\java学习\盈利宝\资料\资料\10-快钱支付\人民币网关\DEMO\JAVA\人民币网关支付\rmb\FI\WebRoot\WEB-INF\classes\Util
添加资源插件 179
验签Pkipair 179
//验签得方法 166
public boolean enCodeByCer( String val, String msg) {
boolean flag = false;
try {
//快钱得公钥文件
//修改此方法使之可以读到中文路径
String filePath = Pkipair.class.getResource("99bill[1].cert.rsa.20140803.cer").toURI().getPath();
// 解码路径中的中文字符
String file = URLDecoder.decode(filePath, StandardCharsets.UTF_8.toString());
System.out.println("文件路径="+file);
FileInputStream inStream = new FileInputStream(file);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
PublicKey pk = cert.getPublicKey();
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(pk);
signature.update(val.getBytes());
sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
System.out.println(new String(decoder.decodeBuffer(msg)));
flag = signature.verify(decoder.decodeBuffer(msg));
System.out.println(flag);
} catch (Exception e) {
e.printStackTrace();
System.out.println("no");
}
return flag;
}
KuaiQianService
micr-pay
//接收快钱给商家的支付结果 176
//处理异步通知
public void kqNotify(HttpServletRequest request) {
String merchantAcctId = request.getParameter("merchantAcctId");
String version = request.getParameter("version");
String language = request.getParameter("language");
String signType = request.getParameter("signType");
String payType = request.getParameter("payType");
String bankId = request.getParameter("bankId");
String orderId = request.getParameter("orderId");
String orderTime = request.getParameter("orderTime");
String orderAmount = request.getParameter("orderAmount");
String bindCard = request.getParameter("bindCard");
if(request.getParameter("bindCard")!=null){
bindCard = request.getParameter("bindCard");}
String bindMobile="";
if(request.getParameter("bindMobile")!=null){
bindMobile = request.getParameter("bindMobile");}
String dealId = request.getParameter("dealId");
String bankDealId = request.getParameter("bankDealId");
String dealTime = request.getParameter("dealTime");
String payAmount = request.getParameter("payAmount");
String fee = request.getParameter("fee");
String ext1 = request.getParameter("ext1");
String ext2 = request.getParameter("ext2");
String payResult = request.getParameter("payResult");
String aggregatePay = request.getParameter("aggregatePay");
String errCode = request.getParameter("errCode");
String signMsg = request.getParameter("signMsg");
//拼接签名计算的串 176
String merchantSignMsgVal = "";
merchantSignMsgVal = appendParam(merchantSignMsgVal,"merchantAcctId", merchantAcctId,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "version",version,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "language",language,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "signType",signType,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "payType",payType,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "bankId",bankId,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "orderId",orderId,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "orderTime",orderTime,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "orderAmount",orderAmount,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "bindCard",bindCard,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "bindMobile",bindMobile,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "dealId",dealId,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "bankDealId",bankDealId,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "dealTime",dealTime,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "payAmount",payAmount,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "fee", fee,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "ext1", ext1,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "ext2", ext2,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "payResult",payResult,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "aggregatePay",aggregatePay,null);
merchantSignMsgVal = appendParam(merchantSignMsgVal, "errCode",errCode,null);
Pkipair pki = new Pkipair();
boolean flag = pki.enCodeByCer(merchantSignMsgVal, signMsg);
System.out.println("flag==="+flag);
//为了方便测试我们模拟验签成功 178
flag = true;
if( flag ){
/**
* 可以处理业务逻辑 176
* 1.判断商户号是商家自己的吗
* 2.判断订单在商家是否存在,是否处理过
* 3.判断金额是否一致
* 4.如果成功,更新用户的资金
* 5.修改充值表的记录状态
* 6.删除redis中的处理过的订单号
*/
if("1001214035601".equals(merchantAcctId)){
int rechargeResult = rechargeService.handleKQNotify(orderId,payAmount,payResult);
System.out.println("订单"+orderId+",充值处理结果:"+rechargeResult);
} else {
System.out.println("订单"+orderId+",充值处理结果:商家号不正确");
}
} else {
System.out.println("订单"+orderId+"验签失败,不能处理");
}
//删除redis中的订单记录
stringRedisTemplate.boundZSetOps(RedisKey.KEY_ORDERID_SET).remove(orderId);
}
KuaiQianController 170、179
micr-pay
//接收快钱给商家的支付结果 , 快钱以get方式,发送请求给商家 170
@GetMapping("/rece/notify")
@ResponseBody
public String payResultNotify(HttpServletRequest request){
kQService.kqNotify(request);
return "<result>1</result><redirecturl>http://localhost:8000/</redirecturl>";
}
2.3 测试 179
debug启动micr-dataservice
debug启动micr-pay
浏览器输入
http://localhost:9000/pay/kq/rece/notify?merchantAcctId=1001214035601&version=v2.0&language=1&signType=4&payType=10&bankId=CCB&orderId=KQ2023080320121582617&orderAmount=1&orderTime=20190520094107&ext1=&ext2=&payAmount=1&dealId=3411469393&bankDealId=WG82301201905200944297620305&dealTime=20190520095014&payResult=10&errCode=&fee=1&signMsg=FbBOrXH6bBBd9Y6aytUeQMpi5j8b7FVO%2FGSgMQ56MJguZKvLCZULIv6fGAHun5VgGlAZ%2Bg8tTI%2FniyZLVP8oK7rRKCo7nXc1lztC5%2Bn5BIh67jT1Gn3PzXYQLxyy3gh0MsJ5fEs1BRc%2FZ%2FD9XW9r7Lmvlpusoeuy6pRgbEZI%2F0WnIebzPw9wGDTQwTsYpcPIqfPd15DB3VsLB86DVtJhlfaCoG0LVfFelAMTP1d3OR5Hm40p9W8XN7yvlpUm%2FZsHjeyb4JjpCJ9%2FAFXMou3TYrltnjbaQa%2BzlkD4SWNXQD4go%2BgqWj%2BFXeJrwqf8k5uk3C3SXSx31jj6bqgXRIxRQg%3D%3D
redis此记录,我们测试此订单号
看看数据库 充值记录表
成功充值状态变为1代表充值成功
这是原来的资金表
成功增加1分钱
看看redis
成功删掉此订单,剩下的都是未处理订单