tyle="margin:20px 0px 0px; line-height:26px; font-family:Arial">

在这些服务中,服务类型大致可以分为以下几类:

  1. WebService查询服务:

    通过服务器后台发起一个http请求,然后从服务器上返回一个Xml类型的返回结果。比如,user_query 服务,支付宝id 或者支付宝的账户email通过服务器后台查询一个支付宝会员信息。

  2. 带有页面跳转的交互服务:

    用户在实现一个web功能的过程中需要调用到支付宝的几个web页面作为,服务流程中的一部分。比如,user_authentication服务需要调用支付宝的一个用户认证页面。Custome_sign 需要使用支付的代扣协议签订页面。

    另外,在支付宝协作页面跳转回原页面的时候,需要对参数签名进行验证,或者对notifyId进行验证是否是合法的web回调请求。

    2.业务场景分析

现在支付宝提供的这些服务接口,调用端只能通过查询支付宝提供api文档,通过api文档进行接口开发。

偶在开发口碑卡项目中需要用到user_query,user_authentication,customer_sign等支付宝服务,以前,口碑的业务也有调用过支付宝的接口,于是我就想重用以前其他同学已经写过的调用支付宝服务的代码。结果发现,有很多参数已经写死了,比如key,partnerid,还有sign的算法。所以代码根本没有办法重用,只能ctrl+C加ctrl+V,而且我在开发过程中为了解决参数签名匹配不上的问题搞了很长时间。

所以,我认为应该开发一个类似淘宝TOP平台提供的API代码接口,这个api接口的开发难度比淘宝open api 应该简单,因为,在和支付宝交互的数据结构比较简单。

2.1.Api所要实现的目标

解决参数签名,调用支付宝服务过程中,参数签名的作用是保证用户请求的参数没有被黑客截取篡改参数值,在所有的请求中都会有参数签名。为了代码实现简单,先默认参数签名方式为MD5签名。参数签名应该像面向切面编程一样,在开发一个具体的结果过程中程序员不用关心参数签名,这也是做这个框架的重要意义所在。当初,我照着api文档的时候为了参数签名真是折腾了好长时间,为了避免其他同学重蹈我的覆辙。必须要将参数签名封装成一个模块能够重复调用。

2.2.支持多种字符集

这个API框架能够在多种字符集环境下使用,所以这个框架要能够支持UTF8,GBK等多种环境,只需要简单配置就能切换。

2.3.新功能容易扩充

现在实现的接口还只是支付宝提供的所有web服务中的小部分,但是已经涵盖到了所有前面提到的所有种类的服务(服务器后台请求,协同页面),如果想通过此框架实现其余的页面只需要实现少部分代码就能实现功能。

3. 实现

3.1.整体类图

3.2.核心类

3.2.1 BasicAlipayToolkit

该类是所有支付宝服务的基类,他提供了一些所有服务接口都要调用的方法。

方法有:

  • urlEncode()

    将传输的值进行编码,按照GBK或者UTF8或者其他编码格式进行编码。

  • sign()

    将传输的参数集合进行签名

  • getPartner()

    取得支付宝分配给用户的partnerid

3.2.2.AlipayApply

支付宝的所有web服务都是通过http协议请求发送的,通过这个类可以通过用户设置的一些基本的参数组装出发送给支付宝的http的url,如果当请求是在页面中需要使用标签<form>来发送的话,就可以通过buildSubmitForm方法生成一个html的form表单。

这些方法有:

  •  prepareParamMap()

    将除partner,_input_charset,service参数字段放到map的数据结构中。

  •  buildSubmitForm()

    创建出一个from表单,可以在html页面中使用,用于在想支付宝发起请求。

  •  getPayGateWay()

    取得支付宝请求地址,如https://www.alipay.com/cooperate/gateway.do

  •  buildHref()

    取得向支付宝请求的url。

3.2.3 BasicWebServiceApply

  • getMapResult()

    解析支付宝远端的返回的XML结果,封装成一个pojo对象。

  • getValueElementName()

    设置支付宝返回结果中代表结果值的xml节点名称。

  • createResult()

    创建一个远端结果对象。

  • resultCallback()

    返回一个结果之后设置返回结果对象的值。

3.2.4 Profile,DefaultProfile

支付宝服务请求的用户信息封装,能够取到PartnerId和getGateway,不同的用户需要通过调用。

[java]  view plain copy

 
  1. Profile profile = new DefaultProfile("adfasdfasdq24234sdf3434","http://aliapi.alipay.net/gateway.do"
  2. ,"2088101010199999");
  3. BasicAlipayToolkit.setProfile(profile);

3.3. 时序图分析

支付宝提供了两种服务,webService和页面协作,根据两种服务类型,选取两个服务分析一下服务的流程。

3.3.1 user_query服务

  1. 单元测试Test启动,调用BasicAlipayToolkit的静态方法setProfile()设置连接需要用到的key,gateway,和partnerid
  2. 调用者设置查询参数,然后调用getAlipayPojo方法,向支付宝发起查询请求。
  3. 支付宝返回查询结果对象AlipayQuery调用getMapResult()生成查询结果
  4. 封装查询结果的过程中先要生成包装查询结果的对象。
  5. 创建查询结果
  6. 根据支付宝返回的结果设置查询结果是否成功
  7. 如果查询有错误的话设置错误编码
  8. 没够成功拿到查询结果,设置查询结果对象的属性值

3.4. 功能说明

3.4.1.支付宝会员登陆验证

用户需要通过支付宝认证用户信息,代码如下:

[java]  view plain copy

 
  1. AlipayAuthenticateCooperate  cooperate =  return new AlipayAuthenticateCooperate(
  2. "http://localhost/callbackUrl.html",
  3. CharSet.GBK);

在页面上打印超链接

[xhtml]  view plain copy

 
  1. <a href="<s:property escape="false" value="alipayAuthenticateCooperate.buildHref()" />">支付宝认证登录</a>

在页面上打印一个form表单

[xhtml]  view plain copy

 
  1. <s:property  escape="false" value="alipayAuthenticateCooperate.buildSubmitForm(‘提交’)" />

当用户在支付宝用户认证之后,跳转到原网站页面,需要取得支付宝会员信息:

[java]  view plain copy

 
  1. HttpServletRequest request = ServletActionContext.getRequest();
  2. AlipayAuthenticateCallback authenticateCallback = new AlipayAuthenticateCallback(
  3. CharSet.UTF8);
  4. AlipayResult alipayResult = authenticateCallback
  5. .getAlipayResult(request.getParameterMap());
  6. if (!alipayResult.isSuccess()) {
  7. throw new BizException("alipayResult is false,error code:"
  8. + alipayResult.getErrorCode() + "request url:["
  9. + request.getQueryString() + "]");}
  10. String alipayid = alipayResult.getUserid();
  11. AlipayAccount account = new AlipayAccount(alipayid, bizContext);
  12. account.setAccountId(alipayid + "0156");
  13. account.setEmail(alipayResult.getEmail());
  14. account.setMobile(alipayResult.getMobile());

注意:在使用该服务api代码必要代码中设置的CharSet需要和当前tomcat URLencode要一致,否则,跳转会原页面会有sign不一致的问题。

3.4.2. 即时到帐

在页面中要发起一个即时到帐的请求,代码如下:

[java]  view plain copy

 
  1. AlipayPayment patment =  return new AlipayPayment("mozhenghua19811109@126.com",
  2. "http://localhost/return_url.html",
  3. "http://localhost/notify_url.html",
  4. "http://localhost/showurl.html",
  5. "123456", // out_trade_no
  6. 12f, //单价
  7. 3,//数量
  8. CharSet.GBK,
  9. Configuration.GetConfig("sellerEmail")// 卖家email账户
  10. );
  11. // 设置跳转的url
  12. action.setRedirectUrl(String.valueOf(payment.buildHref()));

用户在支付宝完成即时到帐功能之后跳转到原页面

[java]  view plain copy

 
  1. import com.koubei.kac.alipaytaobaocooperate.CallbackValidate;
  2. llbackValidate validate = new CallbackValidate();
  3. HttpServletRequest request = ServletActionContext.getRequest();
  4. // 判断url sign 是否正确
  5. if (!validate.isValidCallbackApply(request.getParameterMap())) {
  6. getLog().error(
  7. "is invalid callback request from alipay notfiyid:"
  8. + this.getNotify_id()
  9. + " out_trade_no[delivery_detail PK]:"
  10. + this.out_trade_no);
  11. // 跳转到错误页面
  12. return getErrorResult();
  13. }
  14. if (!validate.isValidNotify(this.notify_id)) {
  15. getLog().error(
  16. "not valid notifyid, notify_id:" + this.notify_id
  17. + " out_trade_no:" + out_trade_no
  18. + " trade_status:" + trade_status);
  19. // 非法请求跳转到错误页面
  20. return getErrorResult();
  21. }

3.4.3.CAE代扣协议

[java]  view plain copy

 
  1. CAEAlipayCooperate cooperate =
  2. return new CAEAlipayCooperate(
  3. "http://localhost/callback.html",
  4. "http://localhost/notify.html",
  5. "mozhenghua19811109@126.com", "CAE业务提交", CharSet.UTF8,bizCode
  6. );
  7. cooperate. buildHref();//生成cae代扣协议的url
  8. // 结果:
  9. /**
  10. http://aliapi.alipay.net/gateway.do?sign_type=MD5&sign=d78ce0c98deabe389c0b05dabc1ae1c9&_input_charset=utf-8&customer_email=mozhenghua19811109%40<br />
  11. 126.com&notify_url=http%3A%2F%2Fhangzhou.koubei.com%2Fka%2Fnotify.html&service=customer_sign&partner=2088101010199999&type_code=123456&return_url<br />
  12. =http%3A%2F%2Fhangzhou.koubei.com%2Fka%2Fcallback.html
  13. */
  14. cooperate.buildSubmitForm();//生成cae代扣协议提交的form表单
  15. //结果:
  16. /**
  17. <form  method="post" action="http://aliapi.alipay.net/gateway.do?_input_charset=utf-8">  <input type="hidden" name="_input_charset" value="utf-8" /><br />
  18. <input type="hidden" name="customer_email" value="mozhenghua19811109@126.com" /><br />
  19. <input type="hidden" name="notify_url" value="http://localhost/notify.html"/><br />
  20. <input type="hidden" name="service" value="customer_sign" /><br />
  21. <input type="hidden" name="partner" value="2088101010159999" /><br />
  22. <input type="hidden" name="type_code" value="123456" /><br />
  23. <input type="hidden" name="return_url" value="http://localhost/callback.html" /><br />
  24. <input type="hidden" name="sign" value="d78ce0c98deabe389c0b05dabc1ae1c9" />  <input type="hidden" name="sign_type" value="MD5" /> <input class<br />
  25. ="submitBtn" type="submit"  value="CAE业务提交"/> </form>
  26. */

用户完成支付宝代扣协议跳转到口碑页面

[java]  view plain copy

 
  1. HttpServletRequest request = ServletActionContext.getRequest();
  2. CallbackValidate validate = new CallbackValidate();
  3. boolean isValidApply = validate.isValidCallbackApply(request
  4. .getParameterMap(), new CallbackValidate.KeyIgnorJudgement() {
  5. @Override
  6. public boolean ignor(String key) {
  7. return "sign".equalsIgnoreCase(key)
  8. || "sign_type".equalsIgnoreCase(key)
  9. || "action".equalsIgnoreCase(key);
  10. }
  11. });
  12. // 非法请求
  13. if (!isValidApply) {
  14. return ERROR;
  15. }
  16. // 测试该请求是否合法
  17. boolean isSuccess = "T".equalsIgnoreCase(request
  18. .getParameter("is_success"));
  19. if (!isSuccess) {
  20. return "caesingerror";
  21. }

如果你需要源代码,请点击下载 http://vdisk.weibo.com/s/8C6k,如果有任何疑问请发邮件,baisui@taobao.com

支付宝api指南的更多相关文章

  1. Zookeeper C API 指南四(C API 概览)(转)

    上一节<Zookeeper C API 指南三(回调函数)>重点讲了 Zookeeper C API 中各种回调函数的原型,本节将切入正题,正式讲解 Zookeeper C API.相信大 ...

  2. Zookeeper C API 指南三(回调函数)(转)

    2013-02-21 12:54 by Haippy, 9237 阅读, 0 评论, 收藏, 编辑 接上一篇<Zookeeper C API 指南二(监视(Wathes), 基本常量和结构体介绍 ...

  3. Zookeeper C API 指南一(转)

    Zookeeper 监视(Watches) 简介 Zookeeper C API 的声明和描述在 include/zookeeper.h 中可以找到,另外大部分的 Zookeeper C API 常量 ...

  4. Android开发-API指南-<provider>

    <provider> 英文原文:http://developer.android.com/guide/topics/manifest/provider-element.html 采集(更新 ...

  5. Android开发-API指南-Intent和Intent过滤器

    Intents and Intent Filters 英文原文:http://developer.android.com/guide/components/intents-filters.html 采 ...

  6. 支付宝api教程,支付宝根据交易号自动充值

    最近公司要用php做一个网站支付宝自动充值的功能,具体就是客户把钱直接转到公司的支付宝账号里,然后在我们网站上填写上交易号,我们网站程序自动获取交易信息,自动给网站的账户充值. 我的具体想法就是利用支 ...

  7. Android API 指南

    原文链接:http://android.eoe.cn/topic/android_sdk Android API 指南 - Android API Guides 应用的组成部分 - Applicati ...

  8. RabbitMQ-Java客户端API指南-下

    RabbitMQ-Java客户端API指南-下 使用主机列表 可以将Address数组传递给newConnection().的地址是简单地在一个方便的类com.rabbitmq.client包与主机 ...

  9. RabbitMQ-Java客户端API指南-上

    RabbitMQ-Java客户端API指南-上 客户端API严格按照AMQP 0-9-1协议规范进行建模,并提供了易于使用的附加抽象. RabbitMQ Java客户端使用com.rabbitmq.c ...

随机推荐

  1. Java WEB —— Java提升

    Java 5.0新特性: 枚举: enum Grade{ --> 相当于类 A("80~100"),B("70~80"),C("60~70&qu ...

  2. js运动 多数据运动 含JSON

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  3. gpgcheck

    warning: rpmts_HdrFromFdno: Header V3 RSA/SHA256 Signature, key ID fd431d51: NOKEY Public key for co ...

  4. OpenGL复习要点

    [OpenGL要点复习] 1.和像素有关的信息(例如像素的颜色)组织成位平面 (bitplane)的形式,位平面又可以组织成帧缓冲区(framebuffer)的形式.位平面是一块内存区域,保存了屏幕上 ...

  5. ThinkPad X220i 刷白名单BIOS,改装第三方无线网卡

    ThinkPad X220i自带的网卡是REALTEK RTL8188CE,这张卡在Mac下目前是无解的.国外网站有该卡liunx.unix内核的驱动,但还是没有高人编译出来. 不等了,这卡没戏.正好 ...

  6. 原生的AJAX写法,可以直接复制过来套用

    方法一: function createXMLHTTPRequest() { //1.创建XMLHttpRequest对象 //这是XMLHttpReuquest对象无部使用中最复杂的一步 //需要针 ...

  7. UVa 11536 Smallest Sub-Array (水题, 滑动窗口)

    题意:给定 n 个由0~m-1的整数组成的序列,输入 k ,问你找出连续的最短序列,使得这个序列含有1-k的所有整数. 析:这个题,很简单么,只要从头开始扫一遍就OK,时间复杂度为O(n). 代码如下 ...

  8. GC:垃圾回收器简介

    Java堆内存被划分为新生代和年老代两部分,新生代主要使用复制和标记-清除垃圾回收算法,年老代主要使用标记-整理垃圾回收算法,因此java虚拟中针对新生代和年老代分别提供了多种不同的垃圾收集器,JDK ...

  9. hdoj 5328 Problems killer

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5328 #include<stdio.h> #include<algorithm> ...

  10. Windows操作系统单文件夹下到底能存放多少文件及单文件的最大容量

    本文是转自:http://hi.baidu.com/aqgjoypubihoqxr/item/c896921f8c2eaba5feded5f2         最近需要了解Windows中单个文件夹下 ...