引言:写这篇文章之前,先回顾一下年初的“2015年中国(深圳)IT领袖峰会”,其中说到,现在正是从IT走向DT时代的阶段,也道出了IT和DT的区别(DT和IT时代区别,IT以我为中心,DT以别人为中心),不光是中国,海外也一样,都相信整个DT时代会慢慢到来,海外有趣的称之为“D经济”。
支付的便捷明显对社会产生了很大的影响,已不可否认。
博主也是刚接触“翼支付”不久,下面就翼支付中Web支付做一些介绍。
首先看下,支付的流程:
流程说明:用户在商户交易网站选择产品或服务,在下订单支付完成后,商户网站会将该订单号及对应订单金额等相关信息提交到翼支付网关,然后跳转到翼支付网关页面进行支付。当支付完成后,翼支付网关将支付结果返回商户,并且根据商户指定的地址跳转到商户指定页面。商户系统后台接收到支付结果之后,对数据库进行相应更新,然后在显示给用户的页面中作出相应提示。
以上是官方提供的说明, 在此就不多言了,下面主要介绍如何去实现,这才是应该真正在意的。
1. 商户注册签约
2. 下载用户操作文档和开发文档
3. 下载商户秘钥
4. 分析接口
二、开发
-
前提假设
现“用户”已可以提交“订单”至“商户”的平台。
此订单中必须要包含的信息如下:订单号,订单请求交易流水号,订单总额,订单描述。其他的字段可依照具体需求实现。
一种是,点击“提交订单”时,就去支付;一种是提交订单时不支付,后续再支付。假设是第一种情况,第二种情况类似。
-
提交支付接口
开发一个页面,里面是一个表单的提交(按钮显示为支付),用于提交支付接口。
当用户点击“提交订单”,此时,商户应先将订单信息保存至系统(后台操作不可见),并且提示“准备跳转至支付”之类的信息,一般都有“等待几秒”的提示,等待结束之后,跳转至当前开发的页面,展现订单的相关信息,点击提交。
当前开发的页面呢,主要开发的功能就是一个表单的提交,具体的表单展现涉及保密信息就不展示了,下面介绍几个重要字段的处理。
先看一下翼支付Web支付接口的数据模型:
public class PayModel {private String merchantID;// 商户代码private String orderSeq;// 订单号private String orderReqTranSeq;// 订单请求流水号private String orderDate;// 订单日期private String orderAmount;// 总金额,单位为分private String productAmount;// 产品金额,单位为分private String attachAmount;// 附加金额,单位为分private String curType;// 币种private String encodeType;// 加密方式private String merchantUrl;// 前台地址private String backMerchantUrl;// 后台地址private String busiCode;// 业务类型代码private String productDesc;// 产品描述private String mac;// MAC校验域private String clientIp;// 客户端IP/*** 省略get和set方法,以上只包含翼支付接口必须提供的参数,其他参数根据需求添加即可**/}
1)orderReqTranSeq(订单流水号):博主的系统中,订单原型中没有定义订单的流水号,此时根据要求在订单号后面添加“4-6位的数字和字母组合”来生成响应的流水号,当然该流水号最好有一定的增长性,不要过于复杂,最简单使用“000001”即可,后面如果有同样的订单号,最下一次交易时,流水号即为“000002”,简单易懂;
2)orderDate(订单日期):日期要注意的就是格式问题,格式为“yyyyMMddhhmmss”,做好formatter即可;
3)orderAmount(总金额)、productAmount(产品金额)、attachAmount(附加金额):在这几个金额中,第一要注意的是,单位是“分”,一般给客户看的都是以元为单位,提交至翼支付接口时,需要转换为分;第二,这三者的关系,总金额=产品金额+附加金额,在博主的系统中,是没有附加金额的,而且金额的计算都是靠商户自己的系统结算的,最终的结果就是总金额了,所以附加金额就默认为0即可; 单位的转换方法:
/*** 转换订单总额,以分为单位* @param orderAmount* @return*/public static String convertOrderAmount(BigDecimal orderAmount){BigDecimal _m = new BigDecimal(“100”);return Integer.toString(orderAmount.multiply(_m).intValue());}
4)encodeType(加密方式):参照文档,默认且必须为1,使用加密方式;
5)merchantUrl(前台地址):该地址是,商户系统需要开发的支付结果页面跳转地址,通俗一点,该地址最终是给客户看的,客户需要看到的支付结果页面。
6)backMerchantUrl(后台地址):该地址,是商户接受翼支付接口反馈的结果,再做相应处理的请求地址,通俗一点,这个地址,就是让商户系统接受到反馈之后需要做相应的处理,比如订单状态的更新等。
7)mac(校验域):该参数是重点,一定要根据文档的要求去生成,参数的顺序,大小写都一定要规范,官网提供的demo中,有名为CryptTool的工具类,可以加密,其中将编码改成UTF-8,不然会遇到数字签名验证不正确的问题;
8)clientIp(客户端IP):该参数是为了防止钓鱼,保证安全性。 获取客户端服务期IP的方法:
/*** 获取服务器端ip地址* @param request* @return*/public static String getIpRemote(HttpServletRequest request){String ip = request.getHeader(“x-forwarded-for”);if(ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)){ip = request.getHeader(“Proxy-Client-IP”);}if(ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)){ip = request.getHeader(“WL-Proxy-Client-IP”);}if(ip == null || ip.length() == 0 || “unknown”.equalsIgnoreCase(ip)){ip = request.getRemoteAddr();}return ip.equals(“0:0:0:0:0:0:0:1″)?”127.0.0.1”:ip;}
页面的开发很简单,将商户系统中的订单信息和相关参数,写到这个数据模型中,将该模型对象传到页面,放入表单值中,其中保重所有参数是不可编辑的,当然也可以用样式,将表单美化,可以完全看不出来是表单,有些商户信息,具体的处理因人而异,涉及到保密的信息,尽量不要暴露出来。
- 翼支付中转
- 结果反馈
- 商户处理