javaweb商城实现在线支付
1、在线支付概述
什么是在线支付呢?没错,就是在网上花钱!大家一定有过这样的经历。但是你可能不太了解在线支付的“内情”,下面我们来了解一下!
如果你现在开始经营一个电子商务网站,用户买了东西一定要支付,你的网站一定要可以连接各大银行了,然后在各大银行支付完成后,再返回到你的网站上显示“支付成功”!
这就是今天我们要做的事情,连接银行的网银系统完成支付。说专业一点,我们称之为“开发在线支付的网关”
2、两种在线支付的方式
在线支付一共有两种方式:
*电商直接与银行对接
*电商通过第三方支付平台与银行对接
电商直接与银行对接,这也要银行同意才行,但可惜的是,银行很“牛”,不是谁想与它对接都可以的。如果你的电商每日的资金流量够大,那么银行会和你对接,因为客户支付给电商的钱都存到了银行的帐户中!但是如果资金流量小,银行不会理你的!
当小网站资金量不足时,不能与银行对接,那么它们会选择与第三方支付公司合作。大家也都明白这是些什么公司,例如:支付宝、易宝、财富通、快钱等公司是国内比较有名的。它们这些公司可以与银行对接(因为资金够多),然后小电商与它们对接!但是第三方是要求收费的!第三方一般会收取电商1%的费用,不过不会收客户的钱。
通过上图大家可以了解到,在银行的页面上会显示出商城名称、RMB订单号、订单时间。。。,这些东西银行是怎么知道的,当然是电商传递给银行的。当电商与银行对接后,电商要给银行的页面传递银行页面需要的参数,所以银行的页面才能显示这些数据!
但是,我们的商城不能只可以对接一家银行吧!怎么也要对接BOC、CCB、ABC、ICBC四家吧!不同的银行需要的对接参数是不相同的,这说明我们在开发时要为不同的银行写不同的对接代码。这也是直接与银行对接的缺点!当然与银行直接对接也有好处,就是安全,没有手续费!
为不同的银行开发不同的代码(缺点);
安全(优点);
没有手续费(优点);
小电商银行不让对接(缺点)。
上图中已经说明,客户在电商的网站上点击确认支付后,会定向到第三方的网站,然后再由第三方与银行对接。这说明电商要传递给第三方参数!再由第三方把参数传递给银行。这种方式的好处是:只需要针对第三方开发即可,而不用再为每家银行提供参数。为每家银行提供参数的工作是第三方的任务了。但是,第三方不老可靠的,如果第三方倒闭了,人跑了,那你的钱就没了。因为客户支付的钱没有到你的银行帐户中,而是支付到了第三方的银行帐户中,而你是在第三方有一个帐户。而且第三方还要收手续费,一般是1%,这可不是小数字啊(真黑)。
3、通过第三方在线支付规则
电商想在第三方注册商户,需要向第三方提供ICP认证。ICP经营许可证是根据国家《互联网管理办法规定》,经营性网站必须办理的网站经营许可证,没有就属于非法经营。
我们不可能因为练习就去办理ICP!所以我们无法在第三方注册商户。不过我们已经有现成的在易宝注册的商户,所以这一步就可以忽略了。
当你在易宝注册成功后,易宝会给你如下几样东西:
在易宝的开户账号(即商户编码):10001126856
易宝接入规范:一个chm文件
对称加密算法类:PaymentUtil.java
密钥:69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl
在易宝接入规范中,我们可以查找到易宝的支付网关,其实就是一个URL,用来与易宝对接的一个网址:https://www.yeepay.com/app-merchant-proxy/node
在易宝接入规范中,还可以查找到易宝要求的参数,在电商与易宝对接时需要给支付网关传递这些参数:
正式请求地址:https://www.yeepay.com/app-merchant-proxy/node
这些参数需要追加到URL后面。
但是要注意,这些参数的值需要加密。加密的密钥和加密算法易宝都会提供!
其中p8_Url表示当支付成功后,返回到电商的哪个页面。这说明我们需要写一个显示结果的页面。第三方在支付成功后,会重定向到我们指定的返回页面,而且还会带给我们一些参数,我们的页面需要获取这些参数,显示在页面中。下面是第三方返回的参数:
4、开发第三方在线支付系统
步骤:
index.jsp页面:一个表单,提交到BuyServlet,表单项有:订单编号、付款金额、选择银行
BuyServlet:获取表单数据,准备连接第三方网关。因为在index.jsp页面中只给出3个参数,而第三方需要的参数有N多,页面没有给出的参数由BuyServlet补充。而且参数还需要加密,这也需要在BuyServlet中完成
BackServlet:当用户支付成功后,第三方会重定向到我们指定的返回页面,我们使用BackServlet作为返回页面,它用来接收第三方传递的参数,显示在页面中
因为已经有了在易宝的注册商号,所以我们就不用自己去注册商号了。所以这里使用易宝做为第三方支付平台来测试。因为我本人没有电商(必须通过ICP认证的电商),所以也不能在第三方注册商号。
我们现在使用的易宝商号是由传智播客提供的,巴巴运动网在易宝注册的商号。所以在测试时支付的钱都给了巴巴运动网在易宝注册的商号了。
<form action="" method="post">订单号:<input type="text" name="p2_Order"/><br/>金 额:<input type="text" name="p3_Amt"/><br/>选择银行:<br/><input type="radio" name="pd_FrpId" value="ICBC-NET-B2C"/>工商银行<img src="bank_img/icbc.bmp" align="middle"/><input type="radio" name="pd_FrpId" value="BOC-NET-B2C"/>中国银行<img src="bank_img/bc.bmp" align="middle"/><br/><br/><input type="radio" name="pd_FrpId" value="ABC-NET-B2C"/>农业银行<img src="bank_img/abc.bmp" align="middle"/><input type="radio" name="pd_FrpId" value="CCB-NET-B2C"/>建设银行<img src="bank_img/ccb.bmp" align="middle"/><br/><br/><input type="radio" name="pd_FrpId" value="BOCO-NET-B2C"/>交通银行<img src="bank_img/bcc.bmp" align="middle"/><br/><input type="submit" value="确认支付"/>
</form>
每个银行对应的值:
第二步:BuyServlet.java
public class BuyServlet extends HttpServlet {public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");String p0_Cmd = "Buy";// 业务类型,固定值为buy,即“买”String p1_MerId = "10001126856";// 在易宝注册的商号String p2_Order = request.getParameter("p2_Order");// 订单编号String p3_Amt = request.getParameter("p3_Amt");// 支付的金额String p4_Cur = "CNY";// 交易种币,固定值为CNY,表示人民币String p5_Pid = "";// 商品名称String p6_Pcat = "";// 商品各类String p7_Pdesc = "";// 商品描述String p8_Url = "http://localhost:8080/buy/BackServlet";// 电商的返回页面,当支付成功后,易宝会重定向到这个页面String p9_SAF = "";// 送货地址String pa_MP = "";// 商品扩展信息String pd_FrpId = request.getParameter("pd_FrpId");// 支付通道,即选择银行String pr_NeedResponse = "1";// 应答机制,固定值为1// 密钥,由易宝提供,只有商户和易宝知道这个密钥。String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl";// 通过上面的参数、密钥、加密算法,生成hmac值// 参数的顺序是必须的,如果没有值也不能给出null,而应该给出空字符串。String hmac = PaymentUtil.buildHmac(p0_Cmd, p1_MerId, p2_Order, p3_Amt,p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc, p8_Url, p9_SAF, pa_MP,pd_FrpId, pr_NeedResponse, keyValue);// 把所有参数连接到网关地址后面String url = "https://www.yeepay.com/app-merchant-proxy/node";url += "?p0_Cmd=" + p0_Cmd + "&p1_MerId=" + p1_MerId +"&p2_Order=" + p2_Order + "&p3_Amt=" + p3_Amt + "&p4_Cur=" + p4_Cur + "&p5_Pid=" + p5_Pid + "&p6_Pcat=" + p6_Pcat + "&p7_Pdesc=" + p7_Pdesc + "&p8_Url=" + p8_Url + "&p9_SAF=" + p9_SAF + "&pa_MP=" + pa_MP + "&pd_FrpId=" + pd_FrpId + "&pr_NeedResponse=" + pr_NeedResponse + "&hmac=" + hmac;System.out.println(url);// 重定向到网关response.sendRedirect(url);}
}
第三步:BackServlet
public class BackServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=utf-8");/** 易宝会提供一系列的结果参数,我们获取其中需要的即可* 获取支付结果:r1_Code,1表示支付成功。* 获取支付金额:r3_Amt* 获取电商的订单号:r6_Order* 获取结果返回类型:r9_BType,1表示重定向返回,2表示点对点返回,* 但点对点我们收不到,因为我们的ip都是局域网ip。*/String r1_Code = request.getParameter("r1_Code");String r3_Amt = request.getParameter("r3_Amt");String r6_Order = request.getParameter("r6_Order");String r9_BType = request.getParameter("r9_BType");if(r1_Code.equals("1")) {if(r9_BType.equals("1")) {response.getWriter().print("<h1>支付成功!</h1>");//其实支付不成功时根本易宝根本就不会返回到本Servletresponse.getWriter().print("支付金额为:" + r3_Amt + "<br/>");response.getWriter().print("订单号为:" + r6_Order + "<br/>");}}}
}
易宝支付提供的获取hmac的工具类
public class PaymentUtil {private static String encodingCharset = "UTF-8";/*** 生成hmac方法* * @param p0_Cmd 业务类型* @param p1_MerId 商户编号* @param p2_Order 商户订单号* @param p3_Amt 支付金额* @param p4_Cur 交易币种* @param p5_Pid 商品名称* @param p6_Pcat 商品种类* @param p7_Pdesc 商品描述* @param p8_Url 商户接收支付成功数据的地址* @param p9_SAF 送货地址* @param pa_MP 商户扩展信息* @param pd_FrpId 银行编码* @param pr_NeedResponse 应答机制* @param keyValue 商户密钥* @return*/public static String buildHmac(String p0_Cmd,String p1_MerId,String p2_Order, String p3_Amt, String p4_Cur,String p5_Pid, String p6_Pcat,String p7_Pdesc,String p8_Url, String p9_SAF,String pa_MP,String pd_FrpId,String pr_NeedResponse,String keyValue) {StringBuilder sValue = new StringBuilder();// 业务类型sValue.append(p0_Cmd);// 商户编号sValue.append(p1_MerId);// 商户订单号sValue.append(p2_Order);// 支付金额sValue.append(p3_Amt);// 交易币种sValue.append(p4_Cur);// 商品名称sValue.append(p5_Pid);// 商品种类sValue.append(p6_Pcat);// 商品描述sValue.append(p7_Pdesc);// 商户接收支付成功数据的地址sValue.append(p8_Url);// 送货地址sValue.append(p9_SAF);// 商户扩展信息sValue.append(pa_MP);// 银行编码sValue.append(pd_FrpId);// 应答机制sValue.append(pr_NeedResponse);return PaymentUtil.hmacSign(sValue.toString(), keyValue);}/*** 返回校验hmac方法* * @param hmac 支付网关发来的加密验证码* @param p1_MerId 商户编号* @param r0_Cmd 业务类型* @param r1_Code 支付结果* @param r2_TrxId 易宝支付交易流水号* @param r3_Amt 支付金额* @param r4_Cur 交易币种* @param r5_Pid 商品名称* @param r6_Order 商户订单号* @param r7_Uid 易宝支付会员ID* @param r8_MP 商户扩展信息* @param r9_BType 交易结果返回类型* @param keyValue 密钥* @return*/public static boolean verifyCallback(String hmac, String p1_MerId,String r0_Cmd, String r1_Code, String r2_TrxId, String r3_Amt,String r4_Cur, String r5_Pid, String r6_Order, String r7_Uid,String r8_MP, String r9_BType, String keyValue) {StringBuilder sValue = new StringBuilder();// 商户编号sValue.append(p1_MerId);// 业务类型sValue.append(r0_Cmd);// 支付结果sValue.append(r1_Code);// 易宝支付交易流水号sValue.append(r2_TrxId);// 支付金额sValue.append(r3_Amt);// 交易币种sValue.append(r4_Cur);// 商品名称sValue.append(r5_Pid);// 商户订单号sValue.append(r6_Order);// 易宝支付会员IDsValue.append(r7_Uid);// 商户扩展信息sValue.append(r8_MP);// 交易结果返回类型sValue.append(r9_BType);String sNewString = PaymentUtil.hmacSign(sValue.toString(), keyValue);return sNewString.equals(hmac);}/*** @param aValue* @param aKey* @return*/public static String hmacSign(String aValue, String aKey) {byte k_ipad[] = new byte[64];byte k_opad[] = new byte[64];byte keyb[];byte value[];try {keyb = aKey.getBytes(encodingCharset);value = aValue.getBytes(encodingCharset);} catch (UnsupportedEncodingException e) {keyb = aKey.getBytes();value = aValue.getBytes();}Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);Arrays.fill(k_opad, keyb.length, 64, (byte) 92);for (int i = 0; i < keyb.length; i++) {k_ipad[i] = (byte) (keyb[i] ^ 0x36);k_opad[i] = (byte) (keyb[i] ^ 0x5c);}MessageDigest md = null;try {md = MessageDigest.getInstance("MD5");} catch (NoSuchAlgorithmException e) {return null;}md.update(k_ipad);md.update(value);byte dg[] = md.digest();md.reset();md.update(k_opad);md.update(dg, 0, 16);dg = md.digest();return toHex(dg);}public static String toHex(byte input[]) {if (input == null)return null;StringBuffer output = new StringBuffer(input.length * 2);for (int i = 0; i < input.length; i++) {int current = input[i] & 0xff;if (current < 16)output.append("0");output.append(Integer.toString(current, 16));}return output.toString();}/*** * @param args* @param key* @return*/public static String getHmac(String[] args, String key) {if (args == null || args.length == 0) {return (null);}StringBuffer str = new StringBuffer();for (int i = 0; i < args.length; i++) {str.append(args[i]);}return (hmacSign(str.toString(), key));}/*** @param aValue* @return*/public static String digest(String aValue) {aValue = aValue.trim();byte value[];try {value = aValue.getBytes(encodingCharset);} catch (UnsupportedEncodingException e) {value = aValue.getBytes();}MessageDigest md = null;try {md = MessageDigest.getInstance("SHA");} catch (NoSuchAlgorithmException e) {e.printStackTrace();return null;}return toHex(md.digest(value));}// public static void main(String[] args) {
// System.out.println(hmacSign("AnnulCard1000043252120080620160450.0http://localhost/SZXpro/callback.asp杩?4564868265473632445648682654736324511","8UPp0KE8sq73zVP370vko7C39403rtK1YwX40Td6irH216036H27Eb12792t"));
// }
}
易宝回调
点对点:易宝直接访问电商,这里没有客户端什么事了
这种方式是必须要使用的,我们这种方式是收不到的!因为我们没有固定IP
易宝有一个重发机制,如果它访问你,你不给它回信息,它会一直重发!
电商需要返回一个以SUCCESS开头的字符串即可!
引导客户端浏览器重定向到电商。是让客户端访问电商!
可以不使用的!
hmac:13参数值+keyValue(密钥) + 算法(md5)
13参数值:自己设置的!
keyValue:易宝在我们注册后发给我们的,这个东东只有我们和易宝知道!
底层为md5的算法:PaymentUtil.buildHmac(14个),它返回hmac
提醒:转载于脚本之家,发布时间是2016年,上面的账户什么肯定是不能再用了。
javaweb商城实现在线支付相关推荐
- php订单系统 帝国cms,帝国CMS商城系统在线支付后,订单邮件提醒
帝国CMS是个强大的内容办理系统.其商城的功能也很强大 当用户下单.支付后我们如何知道有用户下单了呢?因为我们不克不及不时刻刻都在网站后台.不竭的刷新页面去看有无订单.最常用的做法是用邮件提醒我们.有 ...
- 【SSH网上商城项目实战23】完成在线支付功能
转自:https://blog.csdn.net/eson_15/article/details/51464415 上一节我们做好了支付页面的显示,从上一节支付页面显示的jsp代码中可以看出,当用户点 ...
- 【SSH网上商城项目实战20】在线支付平台的介绍
之前已经完成了首页的显示,用户添加购物车,确认订单等功能,下面就是支付功能的开发了.用户确认了订单后会直接跳转到支付页面进行在线支付,在线支付需要第三方的接口,这一节主要介绍一些关于第三方支付的内容, ...
- 校园二手书商城源代码基于微信小程序云开发,可在线支付提现,含详细配置教程
校园二手书商城源代码基于微信小程序云开发,可在线支付提现,含详细配置教程 完整代码下载地址:校园二手书商城源代码基于微信小程序云开发 欢迎使用,下面是配置教程 长话短说,下面直接说配置流程 一.小程序 ...
- JavaWeb开发调用支付宝接口实现在线支付(整个支付过程从头到尾)
项目中需要用到在线支付,实现了调用支付宝接口的在线支付,记录下来以便以后使用. 一.进入蚂蚁金服开放平台登录 网址:https://openhome.alipay.com/developmentDoc ...
- 网上商城——在线支付
概念 在线支付是指卖方与买方通过因特网上的电子商务网站进行交易时,银行为其提供网上资金结算服务的一种业务.它为企业和个人提供了一个安全.快捷.方便的电子商务应用环境和网上资金结算工具.在线支付不仅帮助 ...
- 小白也能看懂的教程:微信小程序在线支付功能开通详细流程(图文介绍)
微信小程序不仅是一个展示平台,更多会用到小程序的电商功能,当然了,支付目前而言需要接入微信支付,那么具体而言,微信小程序要怎么开通支付功能呢?最近需要在微信小程序中用到在线支付功能,于是看了一下官方的 ...
- 一文带你全面了解电商在线支付
本文由作者 书丰 发布于社区 在电商系统中,方便的在线支付功能大大推进了电商的发展,可以说没有在线支付的发展就没有今天发展完善的电商系统,本文就来讨论一下在线支付相关的内容. 01 网银支付 1. 什 ...
- 支付宝在线支付接口开发教程
1.什么是第三方支付 所谓第三方支付,就是一些和各大银行签约.并具备一定实力和信誉保障的第三方独立机构提供的交易支持平台.在通过第三方支付平台的交易中,买方选购商品后,使用第三方平台提供的账户进行货款 ...
最新文章
- 微信搜索谁把你删除了
- kafka单节点部署无法访问问题解决
- linux下安装 配置 redis数据库
- SQL Server表分区【转】
- python去掉重复内容并按原来次序输出元素_在Python中,从列表中删除重复项以使所有元素在保留顺序时都是唯一的最快的算法是什么?...
- Java Math类toDegrees()方法与示例
- Linux文件属性1——文件类型
- api 原生hbase_数据查询的玄铁剑:云HBase原生二级索引发布
- android seekbar 源码,Android SeekBar调节音量
- Atitit.web 视频播放器classid clsid 大总结quicktime,vlc 1. Classid的用处。用来指定播放器	1 2. object 标签用于包含对象,比如图像、音
- 面试必考之Java三大特性
- 重装助手教你如何在Windows中正确调整屏幕分辨率设置
- 论文 结构图 用 visio
- 前端html网站的发布过程
- vscode搭建c++开发环境
- 万元怎样保留小数点_如何让数字以万元为单位显示并保留2位小数,且有千位分隔符...
- python的运行方式有哪两种 有何区别_python程序的两种运行方式是什么
- Windows7安装mysql-压缩包方式
- long型转String(*)
- 学习笔记 | 高效能团队打造