在线支付原理与实现

  • 支付方式
  • 支付流程和注意事项
  • 步骤分析
  • 代码实现

1)支付方式


2)支付流程和注意事项

注意事项

  1. 发送哪些数据?
    第三方规定
  2. 如何保证数据安全?
    数字签名:需要商城将第三方需要的数据及加密后的数据发送给第三方支付,第三方获取所有的数据后,将商城发送过来的数据重新按照分配的商城的密钥和算法重新生成一个数据,然后和商城传递过来的加密后的数据做对比,若一致,就没有问题。
    - 商城在第三方开的账户
    - 第三方给商城的秘钥
    - 第三方给商城的算法

3)步骤分析

  1. 在order_info.jsp页面上,填写收货人信息,然后点击 确认订单:${path}/order/pay
  2. 在OrderServlet中的pay操作:
    • 获取收货人信息,并且更新数据库中的orders表
    • 拼装url,给第三方的数据
    • 重定向到第三方
  3. 在用户完成支付之后,银行通知第三方支付成功,第三方需要通知用户和商城支付成功(要求商城必须有固定的IP,这里就先不做效果了,通知用户即可)
  4. 支付结果需要通知商城和客户,url:回调函数,http://localhost:8080/store/order/callbak
  5. 在callback中获取第三方发送过来的数据,判断数据是否被篡改过
    若没有被篡改,修改订单状态
    若被篡改,提示信息被篡改

4)代码实现

因为要使用第三方易宝支付,所以要查看易宝提供的接口使用文档:

① merchantInfo.properties配置文件

 ## 商户编号--此账号是已经开通的一个公益账号p1_MerId=10001126856## 第三方提供的秘钥keyValue=69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl## 回跳地址--自己定responseURL=http://localhost:8080/store/order/callback

② 修改页面

<form class="form-horizontal" style="margin-top:5px;margin-left:150px;"action="${path }/order/pay" method="post" id="orderForm"><!-- 传入oid --><input type="hidden" name="oid" value="${order.oid }"/>...<input type="text" class="form-control" id="username"name="address" placeholder="请输入收货地址">...<input type="text" class="form-control" id="inputPassword3"name="name" placeholder="请输收货人">...<input type="text" class="form-control" id="confirmpwd"name="telephone" placeholder="请输入联系方式">...<a href="javascript:document.getElementById('orderForm').submit();       <img src="${path }/images/finalbutton.gif" width="204" height="51" border="0" /></a>...
</form>

③ 导入第三方提供的PaymentUtil

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

④ OrderServlet实现支付的处理pay方法

这里大家可以不用自己完成pay方法,比较复杂,看一下流程即可:

 /*** 支付处理* @param request* @param response*/private void pay(HttpServletRequest request, HttpServletResponse response) throws Exception{//接受参数String address=request.getParameter("address");String name=request.getParameter("name");String telephone=request.getParameter("telephone");String oid=request.getParameter("oid");//通过id获取orderOrder order = orderService.getById(oid);order.setAddress(address);order.setName(name);order.setTelephone(telephone);//更新orderorderService.updateOrder(order);// 组织发送支付公司需要哪些数据String pd_FrpId = request.getParameter("pd_FrpId");String p0_Cmd = "Buy";String p1_MerId = ResourceBundle.getBundle("merchantInfo").getString("p1_MerId");String p2_Order = oid;//设置金额0.01--自己的钱String p3_Amt = "0.01";String p4_Cur = "CNY";String p5_Pid = "";String p6_Pcat = "";String p7_Pdesc = "";// 支付成功回调地址 ---- 第三方支付公司会访问、用户访问// 第三方支付可以访问网址String p8_Url = ResourceBundle.getBundle("merchantInfo").getString("responseURL");String p9_SAF = "";String pa_MP = "";String pr_NeedResponse = "1";// 加密hmac 需要密钥String keyValue = ResourceBundle.getBundle("merchantInfo").getString("keyValue");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);//发送给第三方StringBuffer sb = new StringBuffer("https://www.yeepay.com/app-merchant-proxy/node?");sb.append("p0_Cmd=").append(p0_Cmd).append("&");sb.append("p1_MerId=").append(p1_MerId).append("&");sb.append("p2_Order=").append(p2_Order).append("&");sb.append("p3_Amt=").append(p3_Amt).append("&");sb.append("p4_Cur=").append(p4_Cur).append("&");sb.append("p5_Pid=").append(p5_Pid).append("&");sb.append("p6_Pcat=").append(p6_Pcat).append("&");sb.append("p7_Pdesc=").append(p7_Pdesc).append("&");sb.append("p8_Url=").append(p8_Url).append("&");sb.append("p9_SAF=").append(p9_SAF).append("&");sb.append("pa_MP=").append(pa_MP).append("&");sb.append("pd_FrpId=").append(pd_FrpId).append("&");sb.append("pr_NeedResponse=").append(pr_NeedResponse).append("&");sb.append("hmac=").append(hmac);response.sendRedirect(sb.toString());}

⑤ 完成dao层update方法(service层自己写)

 @Overridepublic void update(Order order) throws SQLException {String sql="update orders set state=?,address=?,name=?,telephone=? where oid=?";qr.update(sql,order.getState(),order.getAddress(),order.getName(),order.getTelephone(),order.getOid());}

⑥ OrderServlet中完成支付回调的callback方法

 /*** 支付回调方法* @param request* @param response* @throws Exception */private void callback(HttpServletRequest request, HttpServletResponse response) throws Exception {String p1_MerId = request.getParameter("p1_MerId");String r0_Cmd = request.getParameter("r0_Cmd");String r1_Code = request.getParameter("r1_Code");String r2_TrxId = request.getParameter("r2_TrxId");String r3_Amt = request.getParameter("r3_Amt");String r4_Cur = request.getParameter("r4_Cur");String r5_Pid = request.getParameter("r5_Pid");String r6_Order = request.getParameter("r6_Order");String r7_Uid = request.getParameter("r7_Uid");String r8_MP = request.getParameter("r8_MP");String r9_BType = request.getParameter("r9_BType");String rb_BankId = request.getParameter("rb_BankId");String ro_BankOrderId = request.getParameter("ro_BankOrderId");String rp_PayDate = request.getParameter("rp_PayDate");String rq_CardNo = request.getParameter("rq_CardNo");String ru_Trxtime = request.getParameter("ru_Trxtime");// 身份校验 --- 判断是不是支付公司通知你String hmac = request.getParameter("hmac");String keyValue = ResourceBundle.getBundle("merchantInfo").getString("keyValue");// 自己对上面数据进行加密 --- 比较支付公司发过来hamcboolean isValid = PaymentUtil.verifyCallback(hmac, p1_MerId, r0_Cmd,r1_Code, r2_TrxId, r3_Amt, r4_Cur, r5_Pid, r6_Order, r7_Uid,r8_MP, r9_BType, keyValue);if (isValid) {// 响应数据有效if (r9_BType.equals("1")) {// 浏览器重定向System.out.println("111");request.setAttribute("msg", "您的订单号为:"+r6_Order+",金额为:"+r3_Amt+"已经支付成功,等待发货~~");} else if (r9_BType.equals("2")) {// 服务器点对点 --- 支付公司通知你System.out.println("付款成功!222");// 修改订单状态 为已付款// 回复支付公司response.getWriter().print("success");}//修改订单状态Order order =orderService.getById(r6_Order); order.setState(1);orderService.updateOrder(order);} else {// 数据无效System.out.println("数据被篡改!");}request.getRequestDispatcher("/jsp/msg.jsp").forward(request, response);}

⑦ 测试即可

21_在线支付原理与实现相关推荐

  1. Paypal 在线支付接口应用从零开始,第2节,[支付API原理及流程]

    今天看看Paypal支付流程和简单的认证原理,我画了一张图.应该能表达这两点意思了 我们的站点名字,为了好理解,暂且就定为西狐的网站吧. 点此查看清晰原图 恩,理论知识很重要哈,先把这图理解了,下一步 ...

  2. 支付原理及实现在线支付步骤

    //在线支付 //你的订单号2018010311111 //总金额 2034元 //提交支付 //第三方支付平台:块钱,网银在线.支付宝 //第三方支付平台和银行进行接口交互 //支付过程: 先pos ...

  3. 【SSH网上商城项目实战23】完成在线支付功能

    转自:https://blog.csdn.net/eson_15/article/details/51464415 上一节我们做好了支付页面的显示,从上一节支付页面显示的jsp代码中可以看出,当用户点 ...

  4. 【SSH网上商城项目实战20】在线支付平台的介绍

    之前已经完成了首页的显示,用户添加购物车,确认订单等功能,下面就是支付功能的开发了.用户确认了订单后会直接跳转到支付页面进行在线支付,在线支付需要第三方的接口,这一节主要介绍一些关于第三方支付的内容, ...

  5. java在线支付---13.java在线支付所有源码:

    13.java在线支付所有源码: 创梦综合技术qq交流群:CreDream:251572072 ------------------------------------- a.新建工程payment ...

  6. java在线支付---06,07,08_在线支付_编写将数据提交给易宝支付的JSP页面,集成和测试向易宝发送支付请求,实现浏览器自动向易宝发送支付请求

    06_在线支付_编写将数据提交给易宝支付的JSP页面 -------------------------------------------------------------- 1./payment ...

  7. 支付宝在线支付接口开发教程

    1.什么是第三方支付 所谓第三方支付,就是一些和各大银行签约.并具备一定实力和信誉保障的第三方独立机构提供的交易支持平台.在通过第三方支付平台的交易中,买方选购商品后,使用第三方平台提供的账户进行货款 ...

  8. 第三方支付原理与概述

    前两天下班和同事一起去车站坐公交车,路上聊了会儿第三方支付的问题,他是做我们产品的第三方支付的,所以对这块也比较清楚,通过他的简单讲解,我基本明白了第三方支付的原理,特在此记录.  目前有很很多第三方 ...

  9. html跳转qq浏览器,javascript,_银联在线支付接口,qq浏览器不能跳转,javascript - phpStudy...

    银联在线支付接口,qq浏览器不能跳转 银联在线支付接口,qq浏览器不能跳转,其他浏览器可以跳转 //html代码 提交 确认充值 //js代码 function topupmoney() { //充值 ...

  10. Paypal 在线支付接口

    http://www.paypal-china.org/wangzhai/188.html 关于paypal在线支付的信息可以直接访问http://www.paypal.com.paypal作为国际在 ...

最新文章

  1. 顶部标题栏(四)自定义ActionBar风格和样式
  2. leetcode442. 数组中重复的数据
  3. 【IPF2020】浪潮集团高级副总裁彭震:智算中心 筑基智慧世界
  4. 软件工程质量管理体系要求_软件质量管理| 软件工程
  5. 【程序猿脱单指南】送你一份大礼包去追女神
  6. python 中判断是不是通过break;跳出循环(一分钟读懂)
  7. kafka consumer group 定义
  8. Excel 2007数据透视表如何对数值进行筛选
  9. Windows API笔记(六)内存映射文件
  10. linux学习笔记(十二)
  11. 在网页中嵌入QQ聊天、阿里旺旺聊天、邮件发送等代码
  12. 虚拟机VMware安装XP系统错误解决办法
  13. Six Sigma Basics
  14. czl蒻蒟的一周总结(9.4~9.10)
  15. 抖音小店入驻条件及费用最新版,2022抖音开店,商家入门指南
  16. Avira Free Antivirus 小红伞免费杀毒软件广告去除工具
  17. 计算机二级c语言模拟上机,计算机二级C语言上机模拟题
  18. linux命令行安装ifconfig,CentOS 7安装 ifconfig 管理命令
  19. 亿级以上的数据量 ES如何优化
  20. 许昌 地图。满屏的饭馆。

热门文章

  1. 一. 图模型(graphical model, GM)的表示
  2. Neural Style Transfer
  3. 矩阵运算中的trick
  4. mysql loader_Mysql的批量导入类 MySqlBulkLoader
  5. 什么是OM3、OM4光纤跳线?
  6. android获取当前显示的view,Android中ViewPager获取当前显示的Fragment
  7. 译:Datetime类型的扩展
  8. Oracle 数据库常用操作总结二之数据库的导入和导出
  9. Java集合Collection之实现原理解读(Map)
  10. spring源码:@Import注解