1. 页面原型 161-166
2. 快钱demo搭建 166
kq-demo
创建一个新的模块
直接完成即可
2.1 搭建环境 166
资源在E:\java学习\盈利宝\资料\资料\10-快钱支付\人民币网关\DEMO\JAVA\人民币网关支付\rmb\FI\WebRoot
2.2 工具类 166
新建一个java
资源在E:\java学习\盈利宝\资料\资料\10-快钱支付\人民币网关\DEMO\JAVA\人民币网关支付\rmb\FI\src\Util
Pkipair
package Util;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
//工具类 166
public class Pkipair {
//生成签名 166
public String signMsg( String signMsg) {
String base64 = "";
try {
KeyStore ks = KeyStore.getInstance("PKCS12");
//商户私钥文件
String file = Pkipair.class.getResource("10012140356.pfx").getPath().replaceAll("%20", " ");
System.out.println(file);
FileInputStream ksfis = new FileInputStream(file);
BufferedInputStream ksbufin = new BufferedInputStream(ksfis);
char[] keyPwd = "123456".toCharArray();
//char[] keyPwd = "YaoJiaNiLOVE999Year".toCharArray();
ks.load(ksbufin, keyPwd);
PrivateKey priK = (PrivateKey) ks.getKey("test-alias", keyPwd);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(priK);
signature.update(signMsg.getBytes("utf-8"));
sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
base64 = encoder.encode(signature.sign());
} catch(FileNotFoundException e){
System.out.println("123");
}catch (Exception ex) {
ex.printStackTrace();
}
System.out.println("test = "+base64);
return base64;
}
//验签得方法 166
public boolean enCodeByCer( String val, String msg) {
boolean flag = false;
try {
//快钱得公钥文件
String file = Pkipair.class.getResource("CFCA_sandbox.cer").toURI().getPath();//99bill[1].cert.rsa.20140803.cer
System.out.println(file); // 99bill.cert.rsa.20140803.cer
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;
}
}
2.3 拷贝私钥文件 166
资源在E:\java学习\盈利宝\资料\资料\10-快钱支付\人民币网关\DEMO\JAVA\人民币网关支付\rmb\FI\src\Util
2.4 依赖 166
kq-demo
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjpowernode</groupId>
<artifactId>kq-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>kq-demo Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!--资源插件-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.pfx</include>
</includes>
</resource>
</resources>
</build>
</project>
2.5 配置tomcat 167
直接启动tomcat
启动成功
浏览器访问http://localhost:8080/kq/index.jsp
点击提交
3. 测试支付跳转到页面167
3.1 新建一个模块
3.2 依赖 167
pom.xml
micr-pay
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--自己的父项目-->
<parent>
<groupId>com.bjpowernode</groupId>
<artifactId>micr-parent</artifactId>
<version>1.0.0</version>
<relativePath/>
</parent>
<artifactId>micr-pay</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--dubbo公共项目依赖-->
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>micr-api</artifactId>
<version>1.0.0</version>
</dependency>
<!--dubbo起步依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!--zookeeper起步依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>micr-common</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--模板引擎依赖 169-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!--资源插件 170-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.pfx</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
改个名字
3.3 配置文件 168
application.yml
micr-pay
server:
port: 9000
servlet:
context-path: /pay
spring:
thymeleaf:
cache: false
application: #169
name: micr-pay
dubbo: #169
registry:
address: zookeeper://localhost:2181
scan:
base-packages: com.bjpowernode.pay
consumer:
check: false
timeout: 60000
retries: 0
3.4 页面 168
micr-pay
kqForm.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>提交请求给快钱</h1>
<form name="kqPay" action="https://sandbox.99bill.com/gateway/recvMerchantInfoAction.htm" method="get">
<input type="hidden" name="inputCharset" value="<%=inputCharset%>" />
<input type="hidden" name="pageUrl" value="<%=pageUrl%>" />
<input type="hidden" name="bgUrl" value="<%=bgUrl%>" />
<input type="hidden" name="version" value="<%=version%>" />
<input type="hidden" name="language" value="<%=language%>" />
<input type="hidden" name="signType" value="<%=signType%>" />
<input type="hidden" name="signMsg" value="<%=signMsg%>" />
<input type="hidden" name="merchantAcctId" value="<%=merchantAcctId%>" />
<input type="hidden" name="payerName" value="<%=payerName%>" />
<input type="hidden" name="payerContactType" value="<%=payerContactType%>" />
<input type="hidden" name="payerContact" value="<%=payerContact%>" />
<input type="hidden" name="payerIdType" value="<%=payerIdType%>" />
<input type="hidden" name="payerId" value="<%=payerId%>" />
<input type="hidden" name="payerIP" value="<%=payerIP%>" />
<input type="hidden" name="orderId" value="<%=orderId%>" />
<input type="hidden" name="orderAmount" value="<%=orderAmount%>" />
<input type="hidden" name="orderTime" value="<%=orderTime%>" />
<input type="hidden" name="orderTimestamp" value="<%=orderTimestamp%>" />
<input type="hidden" name="productName" value="<%=productName%>" />
<input type="hidden" name="productNum" value="<%=productNum%>" />
<input type="hidden" name="productId" value="<%=productId%>" />
<input type="hidden" name="productDesc" value="<%=productDesc%>" />
<input type="hidden" name="ext1" value="<%=ext1%>" />
<input type="hidden" name="ext2" value="<%=ext2%>" />
<input type="hidden" name="payType" value="<%=payType%>" />
<input type="hidden" name="bankId" value="<%=bankId%>" />
<input type="hidden" name="redoFlag" value="<%=redoFlag%>" />
<input type="hidden" name="pid" value="<%=pid%>" />
<input type="submit" name="submit" value="提交到快钱">
</form>
</body>
</html>
error.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>请求错误</h1>
</body>
</html>
3.4 控制类controller 168
KuaiQianController
micr-pay
package com.bjpowernode.pay.controller;
import org.apache.catalina.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.annotation.Resource;
import java.math.BigDecimal;
//支付功能 168
@Controller
@RequestMapping("/kq")
public class KuaiQianController {
/*接收来自vue项目的支付充值请求 168*/
@GetMapping("/rece/recharge")
public String receFrontRechargeKQ(Integer uid,
BigDecimal rechargeMoney){
//默认是错误视图
String view="err";
if(uid != null && uid > 0 &&
rechargeMoney != null && rechargeMoney.doubleValue() > 0 ){
//提交支付请求给快钱的form页面(thymeleaf) 168
view = "kqForm";
}
return view;
}
}
小测一下 168
看看能不能跳转到页面
只启动micr-pay
浏览器输入http://localhost:9000/pay/kq/rece/recharge?uid=28&rechargeMoney=0.01
成功没问题
4. 为支付表单生成参数 169
4.1 业务实现类 169
4.1.1 工具类 170
micr-pay
Pkipair
package com.bjpowernode.util;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
//工具类 166
public class Pkipair {
//生成签名 166
public String signMsg( String signMsg) {
String base64 = "";
try {
KeyStore ks = KeyStore.getInstance("PKCS12");
//商户私钥文件,改进此方法使之可以读到中文路径
String filePath = Pkipair.class.getResource("10012140356.pfx").getPath().replaceAll("%20", " ");
// 将编码后的路径进行解码
String decodedPath = URLDecoder.decode(filePath, "UTF-8");
// 替换路径中的 "%20" 为实际的空格字符
String file = decodedPath.replaceAll("%20", " ");
// 输出解码后的路径
System.out.println("文件="+file);
FileInputStream ksfis = new FileInputStream(file);
BufferedInputStream ksbufin = new BufferedInputStream(ksfis);
char[] keyPwd = "123456".toCharArray();
ks.load(ksbufin, keyPwd);
PrivateKey priK = (PrivateKey) ks.getKey("test-alias", keyPwd);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(priK);
signature.update(signMsg.getBytes("utf-8"));
sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
base64 = encoder.encode(signature.sign());
} catch(FileNotFoundException e){
e.printStackTrace();
}catch (Exception ex) {
ex.printStackTrace();
}
return base64;
}
//验签得方法 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;
}
}
4.1.2 获取用户信息 169
micr-pay
KuaiQianService
package com.bjpowernode.pay.service;
import com.bjpowernode.api.model.User;
import com.bjpowernode.api.service.UserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
//支付业务实现类 169
@Service
public class KuaiQianService {
@DubboReference(interfaceClass = UserService.class,version = "1.0")
private UserService userService;
//获取用户信息 169
public User queryUser(Integer uid){
User user = userService.queryById(uid);
return user;
}
}
4.1.3 生成快钱支付接口的数据参数 170
配置文件application.yml 171
redis: #171
host: localhost
port: 6379
注入StringRedisTemplate模板类
redis常量类 171
//redis自增 171
public static final String KEY_RECHARGE_ORDERID = "RECHARGE:ORDERID:SEQ";
消费者实现类KuaiQianService 170-171
micr-pay
//创建快钱支付接口需要的请求参数 170
//生成快钱支付接口的数据参数 Map是发送给快钱的所有请求参数 170
public Map<String,String> generateFormData(Integer uid,String phone, BigDecimal rechargeMoney) {
Map<String,String> data = new HashMap<>();
//人民币网关账号,该账号为11位人民币网关商户编号+01,该参数必填。
String merchantAcctId = "1001214035601";//
//编码方式,1代表 UTF-8; 2 代表 GBK; 3代表 GB2312 默认为1,该参数必填。
String inputCharset = "1";
//接收支付结果的页面地址,该参数一般置为空即可。
String pageUrl = "";
//服务器接收支付结果的后台地址,该参数务必填写,不能为空。
String bgUrl = "http://localhost:9000/pay/kq/rece/notify";
//网关版本,固定值:v2.0,该参数必填。
String version = "v2.0";
//语言种类,1代表中文显示,2代表英文显示。默认为1,该参数必填。
String language = "1";
//签名类型,该值为4,代表PKI加密方式,该参数必填。
String signType = "4";
//支付人姓名,可以为空。
String payerName= "";
//支付人联系类型,1 代表电子邮件方式;2 代表手机联系方式。可以为空。
String payerContactType = "2";
//支付人联系方式,与payerContactType设置对应,payerContactType为1,则填写邮箱地址;payerContactType为2,则填写手机号码。可以为空。
String payerContact = phone;
//指定付款人,可以为空
String payerIdType = "3";
//付款人标识,可以为空
String payerId = String.valueOf(uid);
//付款人IP,可以为空
String payerIP = "";
//商户订单号,以下采用时间来定义订单号,商户可以根据自己订单号的定义规则来定义该值,不能为空。
String orderId = "KQ"+generateOrderId();
//订单金额,金额以“分”为单位,商户测试以1分测试即可,切勿以大金额测试。该参数必填。 171
//stripTrailingZeros 去掉小数点后面得00.01 * 100 == 1.00 ->1
//由于结果是 科学计数法 1 * 10^7 toPlainString 将科学计数法转为数字 100000*100 = 10000000 ,
String orderAmount = rechargeMoney.multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString();
//订单提交时间,格式:yyyyMMddHHmmss,如:20071117020101,不能为空。
String orderTime = new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(new java.util.Date());
//快钱时间戳,格式:yyyyMMddHHmmss,如:20071117020101, 可以为空
String orderTimestamp = orderTime;
//商品名称,可以为空。
String productName= "智选理财产品";
//商品数量,可以为空。
String productNum = "1";
//商品代码,可以为空。
String productId = "10000";
//商品描述,可以为空。
String productDesc = "购买产品";
//扩展字段1,商户可以传递自己需要的参数,支付完快钱会原值返回,可以为空。
String ext1 = "";
//扩展自段2,商户可以传递自己需要的参数,支付完快钱会原值返回,可以为空。
String ext2 = "";
//支付方式,一般为00,代表所有的支付方式。如果是银行直连商户,该值为10-1或10-2,必填。
String payType = "00";
//银行代码,如果payType为00,该值可以为空;如果payType为10-1或10-2,该值必须填写,具体请参考银行列表。
String bankId = "";
//同一订单禁止重复提交标志,实物购物车填1,虚拟产品用0。1代表只能提交一次,0代表在支付不成功情况下可以再提交。可为空。
String redoFlag = "0";
//快钱合作伙伴的帐户号,即商户编号,可为空。
String pid = "";
// signMsg 签名字符串 不可空,生成加密签名串
String signMsgVal = "";
signMsgVal = appendParam(signMsgVal, "inputCharset", inputCharset,data);
signMsgVal = appendParam(signMsgVal, "pageUrl", pageUrl,data);
signMsgVal = appendParam(signMsgVal, "bgUrl", bgUrl,data);
signMsgVal = appendParam(signMsgVal, "version", version,data);
signMsgVal = appendParam(signMsgVal, "language", language,data);
signMsgVal = appendParam(signMsgVal, "signType", signType,data);
signMsgVal = appendParam(signMsgVal, "merchantAcctId",merchantAcctId,data);
signMsgVal = appendParam(signMsgVal, "payerName", payerName,data);
signMsgVal = appendParam(signMsgVal, "payerContactType",payerContactType,data);
signMsgVal = appendParam(signMsgVal, "payerContact", payerContact,data);
signMsgVal = appendParam(signMsgVal, "payerIdType", payerIdType,data);
signMsgVal = appendParam(signMsgVal, "payerId", payerId,data);
signMsgVal = appendParam(signMsgVal, "payerIP", payerIP,data);
signMsgVal = appendParam(signMsgVal, "orderId", orderId,data);
signMsgVal = appendParam(signMsgVal, "orderAmount", orderAmount,data);
signMsgVal = appendParam(signMsgVal, "orderTime", orderTime,data);
signMsgVal = appendParam(signMsgVal, "orderTimestamp", orderTimestamp,data);
signMsgVal = appendParam(signMsgVal, "productName", productName,data);
signMsgVal = appendParam(signMsgVal, "productNum", productNum,data);
signMsgVal = appendParam(signMsgVal, "productId", productId,data);
signMsgVal = appendParam(signMsgVal, "productDesc", productDesc,data);
signMsgVal = appendParam(signMsgVal, "ext1", ext1,data);
signMsgVal = appendParam(signMsgVal, "ext2", ext2,data);
signMsgVal = appendParam(signMsgVal, "payType", payType,data);
signMsgVal = appendParam(signMsgVal, "bankId", bankId,data);
signMsgVal = appendParam(signMsgVal, "redoFlag", redoFlag,data);
signMsgVal = appendParam(signMsgVal, "pid", pid,data);
System.out.println(signMsgVal);
Pkipair pki = new Pkipair();
//生成签名串 171
String signMsg = pki.signMsg(signMsgVal);
//需要signMsg
data.put("signMsg",signMsg);
return data;
}
/**************辅助工具方法 170***********************************/
private String appendParam(String returns, String paramId, String paramValue,Map<String,String> data) {
if (returns != "") {
if (paramValue != "" && paramValue != null) {
returns += "&" + paramId + "=" + paramValue;
}
} else {
if (paramValue != "" && paramValue != null) {
returns = paramId + "=" + paramValue;
}
}
//如果data不等于空说明我传了这个参数 171
if( data != null ){
data.put(paramId,paramValue);
}
return returns;
}
//生成orderId 171
private String generateOrderId(){
//唯一值。1. 使用数据库的自增主键
// 2. 使用redis的自增
// orderId = 时间戳 + redis的自增
String key = RedisKey.KEY_RECHARGE_ORDERID;
//redis自增increment
Long incr = stringRedisTemplate.boundValueOps(key).increment();
//实例格式化,保证在毫秒间也不会重复
String orderId
= DateFormatUtils.format(new Date(),"yyyyMMddHHmmssSSS") + incr;
return orderId;
}
4.2 表单页面 172
加上thymeleaf表达式
micr-pay
kqForm.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form name="kqPay" action="https://sandbox.99bill.com/gateway/recvMerchantInfoAction.htm" method="get">
<input type="hidden" name="inputCharset" th:value="${inputCharset}" />
<input type="hidden" name="pageUrl" th:value="${pageUrl}" />
<input type="hidden" name="bgUrl" th:value="${bgUrl}" />
<input type="hidden" name="version" th:value="${version}" />
<input type="hidden" name="language" th:value="${language}" />
<input type="hidden" name="signType" th:value="${signType}" />
<input type="hidden" name="signMsg" th:value="${signMsg}" />
<input type="hidden" name="merchantAcctId" th:value="${merchantAcctId}" />
<input type="hidden" name="payerName" th:value="${payerName}" />
<input type="hidden" name="payerContactType" th:value="${payerContactType}" />
<input type="hidden" name="payerContact" th:value="${payerContact}" />
<input type="hidden" name="payerIdType" th:value="${payerIdType}" />
<input type="hidden" name="payerId" th:value="${payerId}" />
<input type="hidden" name="payerIP" th:value="${payerIP}" />
<input type="hidden" name="orderId" th:value="${orderId}" />
<input type="hidden" name="orderAmount" th:value="${orderAmount}" />
<input type="hidden" name="orderTime" th:value="${orderTime}" />
<input type="hidden" name="orderTimestamp" th:value="${orderTimestamp}" />
<input type="hidden" name="productName" th:value="${productName}" />
<input type="hidden" name="productNum" th:value="${productNum}" />
<input type="hidden" name="productId" th:value="${productId}" />
<input type="hidden" name="productDesc" th:value="${productDesc}" />
<input type="hidden" name="ext1" th:value="${ext1}" />
<input type="hidden" name="ext2" th:value="${ext2}" />
<input type="hidden" name="payType" th:value="${payType}" />
<input type="hidden" name="bankId" th:value="${bankId}" />
<input type="hidden" name="redoFlag" th:value="${redoFlag}" />
<input type="hidden" name="pid" th:value="${pid}" />
<input type="submit" name="submit" th:value="提交到快钱">
</form>
</body>
</html>
4.3 控制类controller 169
KuaiQianController
micr-pay
package com.bjpowernode.pay.controller;
import com.bjpowernode.api.model.User;
import com.bjpowernode.pay.service.KuaiQianService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Map;
//支付功能 168
@Controller
@RequestMapping("/kq")
public class KuaiQianController {
@Resource
private KuaiQianService kQService;
/*接收来自vue项目的支付充值请求 168*/
@GetMapping("/rece/recharge")
public String receFrontRechargeKQ(Integer uid,
BigDecimal rechargeMoney,
Model model){
//默认是错误视图
String view="err";
if(uid != null && uid > 0 &&
rechargeMoney != null && rechargeMoney.doubleValue() > 0 ){
//1. 检查uid是否是有效用户 169
User user = kQService.queryUser(uid);
if(user != null){
//创建快钱支付接口需要的请求参数
Map<String,String> data = kQService.generateFormData(uid,user.getPhone(),rechargeMoney);
//将data数据放入到request中 ,
// 然后我们的表单kqForm就可以在request中取数据了 171
model.addAllAttributes(data);
//提交支付请求给快钱的form页面(thymeleaf) 168
view = "kqForm";
}
}
return view;
}
//接收快钱给商家的支付结果 , 快钱以get方式,发送请求给商家 170
@GetMapping("/rece/notify")
@ResponseBody
public String payResultNotify(HttpServletRequest request){
return "ok";
}
}
4.4 测试 172
启动micr-dataservice
debug启动micr-pay
浏览器输入http://localhost:9000/pay/kq/rece/recharge?uid=28&rechargeMoney=0.01
点击按钮跳转到快钱得支付页面
看看控制台输出签名串和私钥文件路径(中文我们做了处理)
如下
//商户私钥文件,改进此方法使之可以读到中文路径
String filePath = Pkipair.class.getResource("10012140356.pfx").getPath().replaceAll("%20", " ");
// 将编码后的路径进行解码
String decodedPath = URLDecoder.decode(filePath, "UTF-8");
// 替换路径中的 "%20" 为实际的空格字符
String file = decodedPath.replaceAll("%20", " ");
// 输出解码后的路径
System.out.println("文件="+file);
FileInputStream ksfis = new FileInputStream(file);
BufferedInputStream ksbufin = new BufferedInputStream(ksfis);
看看页面,成功拿到数据参数
成功跳转
5. 创建充值记录和把订单号存放到redis 172
5.1 业务实现类 172
5.1.1 定义常量类 172
micr-common
//充值状态 172
public static final int RECHARGE_STATUS_PROCESSING = 0; //充值中
public static final int RECHARGE_STATUS_SUCCESS = 1; //充值成功
public static final int RECHARGE_STATUS_FAIL = 2; //充值失败
5.1.2 业务接口 172
RechargeService
micr-api
//添加充值记录 172
int addRechargeRecord(RechargeRecord record);
5.1.3 业务实现类 172
micr-dataservice
RechargeServiceImpl
//添加充值记录 172
@Override
public int addRechargeRecord(RechargeRecord record) {
return rechargeMapper.insertSelective(record);
}
创建充值记录实现类KuaiQianService 172
micr-pay
//创建充值记录 172
public boolean addRecharge(Integer uid,
BigDecimal rechargeMoney,
String orderId) {
RechargeRecord record = new RechargeRecord();
record.setChannel("KQ");
record.setRechargeDesc("快钱充值");
record.setRechargeMoney(rechargeMoney);
record.setRechargeNo(orderId);
record.setRechargeStatus(YLBConstant.RECHARGE_STATUS_PROCESSING);
record.setRechargeTime(new Date());
record.setUid(uid);
int rows = rechargeService.addRechargeRecord(record);
return rows > 0;
}
5.2 把订单号存放到redis 172
5.2.1 常量类 172
micr-common
//orderIds 172
public static final String KEY_ORDERID_SET = "RECHARGE:ORDERID:SET";
5.2.2 业务实现类 172
KuaiQianService
micr-pay
//把订单号存放到redis 172
public void addOrderIdToRedis(String orderId) {
String key = RedisKey.KEY_ORDERID_SET;
stringRedisTemplate.boundZSetOps(key).add(orderId, new Date().getTime());
}
5.3 控制类controller 172
KuaiQianController
micr-pay
//创建充值记录 172
kQService.addRecharge(uid,rechargeMoney,data.get("orderId"));
//把订单号存放到redis 172
kQService.addOrderIdToRedis(data.get("orderId"));
5.4 测试 173
启动micr-dataservice
启动micr-pay
浏览器输入http://localhost:9000/pay/kq/rece/recharge?uid=28&rechargeMoney=0.01
看看数据库充值表
看看redis中成功存入订单号