标签:
项目中实现在线支付的功能有两种方式:
第一种方式:使用银行提供的接口直接和银行对接。这种方式不用交第三方费用,但是如果要接入多个银行,则需要在本网站中一一使用不同银行提供的接口,这个过程比较麻烦,其次商业银行一般只对大型企业及集团公司的网站提供接口,对个人及小企业的网站不提供,所以个人网站或者小企业网站接入商业银行比较困难;
第二种方式:通过第三方支付平台使网站和银行间接对接:第三方支付平台整合所有类型银行的接口,直接和银行对接;我们自己的网站只需要调用第三方支付平台的接口就可以实现和银行的间接对接。这种对接方式放低了对接门槛,减轻了对接的难度,但该对接方式需要向第三方支付平台缴纳相应的费用。这种对接方式是目前使用最多的一种,比如支付宝、PayPal和易宝支付等都是非常有名的第三方支付平台。这种对接方式的支付流程如下图:
说明:淡灰箭头表示支付的过程;红箭头表示支付结束后数据返回。
下面给大家介绍易宝支付的实现过程,代码下载地址在最下面:
代码一:DigestUtil文件
package com.yeepay.util; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; /** * 加密工具类 * * @author GaoHuanjie */ public class DigestUtil { private static String ENCODING_CHARSET = "UTF-8"; /** * @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(ENCODING_CHARSET); value = aValue.getBytes(ENCODING_CHARSET); } 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); } private 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(ENCODING_CHARSET); } 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)); } }
代码二:YeePayUtil文件
package com.yeepay.util; /** * 易宝支付工具类 * * @author GaoHuanjie */ public class YeePayUtil { /** * 获取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 getHmac(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) { String payInfo = new StringBuilder().//payInfo保存支付信息 append(p0_Cmd).// 业务类型 append(p1_MerId).// 商户编号 append(p2_Order).// 商户订单号 append(p3_Amt).// 支付金额 append(p4_Cur).// 交易币种 append(p5_Pid).// 商品名称 append(p6_Pcat).// 商品种类 append(p7_Pdesc).// 商品描述 append(p8_Url).// 商户接收支付成功数据的地址 append(p9_SAF).// 送货地址 append(pa_MP).// 商户扩展信息 append(pd_FrpId).// 银行编码 append(pr_NeedResponse).// 应答机制 toString(); return DigestUtil.hmacSign(payInfo, keyValue); } /** * 校验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 密钥 * @param hmac 支付网关发来的加密验证码 * @return */ public static boolean checkHmac(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, String hmac) { String resultValue = new StringBuilder(). append(p1_MerId).// 商户编号 append(r0_Cmd).// 业务类型 append(r1_Code).// 支付结果 append(r2_TrxId).// 易宝支付交易流水号 append(r3_Amt).// 支付金额 append(r4_Cur).// 交易币种 append(r5_Pid).// 商品名称 append(r6_Order).// 商户订单号 append(r7_Uid).// 易宝支付会员ID append(r8_MP).// 商户扩展信息 append(r9_BType).// 交易结果返回类型 toString(); String newHmac = DigestUtil.hmacSign(resultValue, keyValue); return newHmac.equals(hmac); } }
代码三:PayBeginServlet文件
package com.yeepay.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.yeepay.util.YeePayUtil; /** * 处理开始付款请求 */ public class PayBeginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String orderNumber=request.getParameter("orderNumber");//订单号 String payAmount=request.getParameter("payAmount");//付款金额 String bankCode=request.getParameter("bankCode"); //选择的支付银行 // 付款需要的参数: String p0_Cmd = "Buy"; // 业务类型 请求命令,在线支付固定为Buy String p1_MerId = "10001126856";// 商户编号 String p2_Order = orderNumber;// 订单编号 String p3_Amt = payAmount; // 付款金额 String p4_Cur = "CNY"; // 交易币种 String p5_Pid = ""; // 商品id String p6_Pcat = ""; // 商品种类 String p7_Pdesc = ""; // 商品描述 String p8_Url = "http://192.168.1.10:8080/yeepayDemo/PayEndServlet"; // 商户接收支付结束后数据的地址 String p9_SAF = ""; // 送货地址 即需要填写送货信息 0:不需要 1:需要 String pa_MP = ""; // 商户扩展信息 String pd_FrpId = bankCode;// 支付通道编码,即银行编码 String pr_NeedResponse = "1"; // 应答机制 1: 需要应答机制; 0: 不需要应答机制 String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl"; // 商户密钥 String hmac = YeePayUtil.getHmac(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); // hmac // 向易宝发送请求: String payUrl = new StringBuffer(). append("https://www.yeepay.com/app-merchant-proxy/node?"). append("p0_Cmd=").append(p0_Cmd).append("&"). append("p1_MerId=").append(p1_MerId).append("&"). append("p2_Order=").append(p2_Order).append("&"). append("p3_Amt=").append(p3_Amt).append("&"). append("p4_Cur=").append(p4_Cur).append("&"). append("p5_Pid=").append(p5_Pid).append("&"). append("p6_Pcat=").append(p6_Pcat).append("&"). append("p7_Pdesc=").append(p7_Pdesc).append("&"). append("p8_Url=").append(p8_Url).append("&"). append("p9_SAF=").append(p9_SAF).append("&"). append("pa_MP=").append(pa_MP).append("&"). append("pd_FrpId=").append(pd_FrpId).append("&"). append("pr_NeedResponse=").append(pr_NeedResponse).append("&"). append("hmac=").append(hmac).toString(); // 重定向方式向易宝发送请求: response.sendRedirect(payUrl); } }
注意:在本机运行时要将上面IP地址改成本机IP地址。
代码四:PayEndServlet文件
package com.yeepay.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.yeepay.util.YeePayUtil; /** * 处理支付结束请求 */ public class PayEndServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String p1_MerId = "10001126856"; // 商家编号 String r0_Cmd = request.getParameter("r0_Cmd"); //业务类型 String r1_Code = request.getParameter("r1_Code"); //扣款结果,该字段值为1时表示扣款成功. String r2_TrxId = request.getParameter("r2_TrxId"); //YeePay易宝交易订单号 String r3_Amt = request.getParameter("r3_Amt");//扣款金额,交易结束后,YeePay易宝交易系统将实际扣款金额返回给商户 String r4_Cur = request.getParameter("r4_Cur");//交易币种,人民币为CNY String r5_Pid = request.getParameter("r5_Pid");//商品ID String r6_Order = request.getParameter("r6_Order");//商户订单号 String r7_Uid = request.getParameter("r7_Uid");//YeePay易宝会员ID String r8_MP = request.getParameter("r8_MP");//商户扩展信息,可以任意填写1K 的字符串,交易返回时将原样返回 String r9_BType = request.getParameter("r9_BType");//交易结果通知类型,1: 交易成功回调(浏览器重定向)2: 交易成功主动通知(服务器点对点通讯) String rb_BankId = request.getParameter("rb_BankId");//支付银行 String rp_PayDate = request.getParameter("rp_PayDate");//在银行支付时的时间 String hmac = request.getParameter("hmac");//MD5交易签名 String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl"; // 商家密钥 boolean result = YeePayUtil.checkHmac(p1_MerId, r0_Cmd, r1_Code, r2_TrxId, r3_Amt, r4_Cur, r5_Pid, r6_Order, r7_Uid, r8_MP, r9_BType, keyValue, hmac); System.out.println("p1_MerId:"+p1_MerId+",r0_Cmd:"+r0_Cmd+",r1_Code:"+r1_Code+",r2_TrxId:" +r2_TrxId+",r3_Amt:"+r3_Amt+",r4_Cur:"+r4_Cur+",r5_Pid:"+r5_Pid+",r6_Order:" +r6_Order+",r7_Uid:"+r7_Uid+",r8_MP:"+r8_MP+",r9_BType:"+r9_BType+",rb_BankId:"+rb_BankId+",rp_PayDate:"+rp_PayDate); if(result){ if("1".equals(r1_Code)){//付款成功 request.setAttribute("r0_Cmd", r0_Cmd); request.setAttribute("r1_Code", r1_Code); request.setAttribute("r2_TrxId", r2_TrxId); request.setAttribute("r3_Amt", r3_Amt); request.setAttribute("r4_Cur", r4_Cur); request.setAttribute("r5_Pid", r5_Pid); request.setAttribute("r6_Order", r6_Order); request.setAttribute("r7_Uid", r7_Uid); request.setAttribute("r8_MP", r8_MP); request.setAttribute("r9_BType", r9_BType); request.setAttribute("rb_BankId", rb_BankId); request.setAttribute("rp_PayDate", rp_PayDate); request.getRequestDispatcher("paySuccess.jsp").forward(request, response); return; }else{ request.setAttribute("errorMsg", "Sorry,支付失败!!!"); } }else{ request.setAttribute("errorMsg", "Sorry,因数据来源非法,支付停止!!!"); } request.getRequestDispatcher("payFail.jsp").forward(request, response); return; } }
代码五:payBegin.jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@page import="java.text.SimpleDateFormat,java.util.Date"%> <% String basePath = request.getContextPath(); %> <!DOCTYPE html> <html lang="zh-CN"> <head> <title>付款页面</title> <script type="text/javascript" src="<%=basePath%>/js/jquery-1.7.1.min.js"></script> <script type="text/javascript"> $(function(){ $(".submit_order").click(function(){ $("#pay_form").submit(); }); }); </script> <style type="text/css"> *{ margin: 0px; padding: 0px; } body{ margin-top: 10% } .container { width: 90%; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto } img { vertical-align: middle } h4 { margin-top: 10px; margin-bottom: 10px; font-size: 18px } .row { margin-right: -15px; margin-left: -15px } .line { margin-top: 15px; border-top: 1px solid #9A9A9A; height: 10px; } .row:after,.row:before{ display: table; content: " " } .row:after{ clear: both } .submit_order { height: 50px; width: 150px; background-color: #FF5000; float: right; text-align: center; line-height: 50px; color: #FFFFFF; font-size: 16px; cursor: pointer; } .submit_order:HOVER { background-color:#FF0000; } </style> </head> <body> <% Date now = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); String orderNumber = sdf.format(now); String payAmount="0.01"; %> <div class="container"> <div class="row"> <table width="100%"> <tr> <td>订单编号为:<%=orderNumber %></td> <td style="text-align: right;"> <span>订单总价为:</span> <span style="color: red;"> <strong>¥<%=payAmount %>元 </strong> </span> </td> </tr> </table> </div> <div class="row line"></div> <div class="row"> <h4><strong>选择银行</strong></h4> </div> <form action="<%=basePath%>/PayBeginServlet" id="pay_form" method="post" > <input type="hidden" value="<%=orderNumber %>" name="orderNumber"> <input type="hidden" value="<%=payAmount %>" name="payAmount"> <table width="100%"> <tr align="center"> <td> <input type="radio" name="bankCode" value="ICBC-NET-B2C" checked="checked"/> <img src="<%=basePath%>/imgs/icbc.bmp" align="middle" title="工商银行"/> </td> <td> <input type="radio" name="bankCode" value="BOC-NET-B2C"/> <img src="<%=basePath%>/imgs/bc.bmp" align="middle" title="中国银行"/> </td> <td> <input type="radio" name="bankCode" value="ABC-NET-B2C"/> <img src="<%=basePath%>/imgs/abc.bmp" align="middle" title="农业银行"/> </td> <td> <input type="radio" name="bankCode" value="POST-NET-B2C"/> <img src="<%=basePath%>/imgs/post.bmp" align="middle" title="中国邮政"/> </td> </tr> </table> <table width="100%" style="margin-top: 15px"> <tr align="center"> <td> <input type="radio" name="bankCode" value="PINGANBANK-NET"/> <img src="<%=basePath%>/imgs/pingan.bmp" align="middle" title="平安银行"/> </td> <td> <input type="radio" name="bankCode" value="CCB-NET-B2C"/> <img src="<%=basePath%>/imgs/ccb.bmp" align="middle" title="建设银行"/> </td> <td> <input type="radio" name="bankCode" value="CEB-NET-B2C"/> <img src="<%=basePath%>/imgs/guangda.bmp" align="middle" title="光大银行"/> </td> <td> <input type="radio" name="bankCode" value="CMBCHINA-NET-B2C"/> <img src="<%=basePath%>/imgs/cmb.bmp" align="middle" title="招商银行"/> </td> </tr> </table> <table width="100%" style="margin-top: 15px"> <tr align="center"> <td> <input type="radio" name="bankCode" value="CCB-NET-B2C"/> <img src="<%=basePath%>/imgs/ccb.bmp" align="middle" title="建设银行"/> </td> <td> <input type="radio" name="bankCode" value="BCCB-NET-B2C"/> <img src="<%=basePath%>/imgs/bj.bmp" align="middle" title="北京银行"/> </td> <td> <input type="radio" name="bankCode" value="CBHB-NET-B2C"/> <img src="<%=basePath%>/imgs/bh.bmp" align="middle" title="渤海银行"/> </td> <td> <input type="radio" name="bankCode" value="CIB-NET-B2C"/> <img src="<%=basePath%>/imgs/cib.bmp" align="middle" title="兴业银行"/> </td> </tr> </table> <table width="100%" style="margin-top: 15px"> <tr align="center"> <td> <input type="radio" name="bankCode" value="NBCB-NET-B2C"/> <img src="<%=basePath%>/imgs/ningbo.bmp" align="middle" title="宁波银行"/> </td> <td> <input type="radio" name="bankCode" value="BOCO-NET-B2C"/> <img src="<%=basePath%>/imgs/bcc.bmp" align="middle" title="交通银行"/> </td> <td> <input type="radio" name="bankCode" value="SHB-NET-B2C"/> <img src="<%=basePath%>/imgs/sh.bmp" align="middle" title="上海银行"/> </td> <td> <input type="radio" name="bankCode" value="CZ-NET-B2C"/> <img src="<%=basePath%>/imgs/zheshang.bmp" align="middle" title="浙商银行"/> </td> </tr> </table> </form> <div class="row line"></div> </div> <div class="container"> <div class="row"> <div class="submit_order">确认付款</div> </div> </div> </body> </html>
代码六:paySuccess.jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String basePath = request.getContextPath(); %> <!DOCTYPE html> <html lang="zh-CN"> <head> <title>付款成功页面</title> <style type="text/css"> *{ margin: 0px; padding: 0px; } body { margin-top: 10%; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.42857143; color: #333; } img { vertical-align: middle } .container { width: 45%; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto } .pay_info{ width: 100%; height: 400px; border: 1px solid #555555; } .pay_info_top{ height: 33%; width: 100%; } .pay_info_top_lef{ width: 50%; height: 100%; float: left; text-align: center; line-height: 133px; } .pay_info_top_right{ width: 50%; height: 100%; float: right; text-align:left; line-height: 133px; font-size: 25px; font-weight: bold; } .pay_info_bottom{ margin-left:auto; margin-right:auto; } </style> </head> <body> <div class="container"> <div class="pay_info"> <div class="pay_info_top"> <div class="pay_info_top_lef"> <img width="120px" height="120px" src="<%=basePath%>/imgs/success.jpg" /> </div> <div class="pay_info_top_right"> 恭喜!支付成功 </div> </div> <div class="pay_info_bottom"> <table style="margin:auto"> <tr> <td>业务类型:</td><td><%=request.getParameter("r0_Cmd")%></td> </tr> <tr> <td>扣款状态:</td><td><%=request.getParameter("r1_Code")%></td> </tr> <tr> <td>易宝订单系统订单号:</td><td><%=request.getParameter("r2_TrxId")%></td> </tr> <tr> <td>扣款金额:</td><td><%=request.getParameter("r3_Amt")%></td> </tr> <tr> <td>交易币种:</td><td><%=request.getParameter("r4_Cur")%></td> </tr> <tr> <td>商品ID:</td><td><%=request.getParameter("r5_Pid")%></td> </tr> <tr> <td>商户订单号:</td><td><%=request.getParameter("r6_Order")%></td> </tr> <tr> <td>易宝会员ID:</td><td><%=request.getParameter("r7_Uid")%></td> </tr> <tr> <td>商户扩展信息:</td><td><%=request.getParameter("r8_MP")%></td> </tr> <tr> <td>交易结果通知类型:</td><td><%=request.getParameter("r9_BType")%></td> </tr> <tr> <td>支付银行:</td><td><%=request.getParameter("rb_BankId")%></td> </tr> <tr> <td>支付时间:</td><td><%=request.getParameter("rp_PayDate")%></td> </tr> </table> </div> </div> </div> </body> </html>
代码七:payFail.jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String basePath = request.getContextPath(); %> <!DOCTYPE html> <html lang="zh-CN"> <head> <title>付款失败页面</title> <style type="text/css"> *{ margin: 0px; padding: 0px; } body { margin-top: 10%; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.42857143; color: #333; } img { vertical-align: middle } .container { width: 45%; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } .pay_info{ width: 100%; height: 135px; border: 1px solid #555555; } .pay_info_lef{ width: 50%; height: 100%; float: left; text-align: center; line-height: 133px; } .pay_info_right{ width: 50%; height: 100%; float: right; text-align:left; line-height: 133px; font-size: 15px; font-weight: bold; } </style> </head> <body> <div class="container"> <div class="pay_info"> <div class="pay_info_lef"> <img width="120px" height="120px" src="<%=basePath%>/imgs/fail.jpg" /> </div> <div class="pay_info_right"> <%=request.getAttribute("errorMsg") %> </div> </div> </div> </body> </html>【0分下载代码】
标签:
原文地址:http://blog.csdn.net/gaohuanjie/article/details/51923890