支付功能如何实现个性化定制?

2026-04-29 20:172阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计4835个文字,预计阅读时间需要20分钟。

支付功能如何实现个性化定制?

1. 页面原型161-166

2.快钱demo搭建166+kq-demo,创建一个新模块,直接完成即可

2.1 搭建环境166 资源在E:\java学习\旺利宝\资料\资料\10-快钱支付\人民币网关\DEMO\JAVA\人民币网关支付\RMBC\FI\WebRoot

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="maven.apache.org/POM/4.0.0" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="maven.apache.org/POM/4.0.0 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>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配置tomcat167

直接启动tomcat

启动成功

浏览器访问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="maven.apache.org/POM/4.0.0" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="maven.apache.org/POM/4.0.0 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="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控制类controller168

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

浏览器输入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.yml171

redis: #171 host: localhost port: 6379

注入StringRedisTemplate模板类

redis常量类171

//redis自增 171 public static final String KEY_RECHARGE_ORDERID = "RECHARGE:ORDERID:SEQ";

消费者实现类KuaiQianService170-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 = "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="www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form name="kqPay" action="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控制类controller169

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.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.创建充值记录和把订单号存放到redis172

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); }

创建充值记录实现类KuaiQianService172

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把订单号存放到redis172

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控制类controller172

micr-pay

//创建充值记录 172 kQService.addRecharge(uid,rechargeMoney,data.get("orderId")); //把订单号存放到redis 172 kQService.addOrderIdToRedis(data.get("orderId"));

5.4测试173

启动micr-dataservice

启动micr-pay

浏览器输入localhost:9000/pay/kq/rece/recharge?uid=28&rechargeMoney=0.01

看看数据库充值表

看看redis中成功存入订单号

本文共计4835个文字,预计阅读时间需要20分钟。

支付功能如何实现个性化定制?

1. 页面原型161-166

2.快钱demo搭建166+kq-demo,创建一个新模块,直接完成即可

2.1 搭建环境166 资源在E:\java学习\旺利宝\资料\资料\10-快钱支付\人民币网关\DEMO\JAVA\人民币网关支付\RMBC\FI\WebRoot

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="maven.apache.org/POM/4.0.0" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="maven.apache.org/POM/4.0.0 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>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配置tomcat167

直接启动tomcat

启动成功

浏览器访问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="maven.apache.org/POM/4.0.0" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="maven.apache.org/POM/4.0.0 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="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控制类controller168

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

浏览器输入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.yml171

redis: #171 host: localhost port: 6379

注入StringRedisTemplate模板类

redis常量类171

//redis自增 171 public static final String KEY_RECHARGE_ORDERID = "RECHARGE:ORDERID:SEQ";

消费者实现类KuaiQianService170-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 = "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="www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form name="kqPay" action="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控制类controller169

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.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.创建充值记录和把订单号存放到redis172

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); }

创建充值记录实现类KuaiQianService172

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把订单号存放到redis172

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控制类controller172

micr-pay

//创建充值记录 172 kQService.addRecharge(uid,rechargeMoney,data.get("orderId")); //把订单号存放到redis 172 kQService.addOrderIdToRedis(data.get("orderId"));

5.4测试173

启动micr-dataservice

启动micr-pay

浏览器输入localhost:9000/pay/kq/rece/recharge?uid=28&rechargeMoney=0.01

看看数据库充值表

看看redis中成功存入订单号