1、创建应用并获取APPID2、配置应用环境开发者调用接口前需要先生成RSA密钥,RSA密钥包含应用私钥(APP_PRIVATE_KEY)、应用公钥(APP_PUBLIC_KEY)。生成密钥后在开放平台管理中心进行密钥配置,配置完成后可以获取支付宝公钥(ALIPAY_PUBLIC_KEY)。详细步骤请参考《配置应用环境》。
为了方便开发者生成一对RSA密钥支付宝提供一键生成工具,具体如何生成与配置密钥详见签名专区。
WINDOWS
MAC_OSX
下载该工具后,解压打开文件夹,运行“RSA签名验签工具.bat”(WINDOWS)或“RSA签名验签工具.command”(MAC_OSX)。
以下演示截图
以下是Mac电脑生成RSA密钥工具截图
工具生成一对RSA密钥之后将公钥配置到应用环境。
生成的私钥需妥善保管,避免遗失,不要泄露。应用私钥需填写到代码中供签名时使用。应用公钥需提供给支付宝账号管理者上传到支付宝开放平台。
3、配置沙箱环境注意:沙箱环境的密钥最好与正式上线的应用进行区分避免一些不必要的麻烦。WAP支付支持沙箱环境而app支付不支持沙箱环境
【官方介绍质料-箱环境使用说明】
上传对应的公钥,沙箱账号待会在测试的时候回使用到
4、服务端实现(集成并配置SDK)【官方资源下载地址】
服务端SDK下载与简介Maven项目中使用本地JAR包1、首先我在项目根目录中创建一个lib文件夹,将jar包拷贝到lib文件夹下
2、然后我们在maven的pom.xml中配置
<pre class="prettyprint prettyprinted" data-original-code=" com.alibaba alipay-sdk-java 20161129201425 system ${project.basedir}/lib/alipay-sdk-java20161129201425.jar" data-snippet-id="ext.a05cddfc6c8b5130264de97bd98a9bc0" data-snippet-saved="false" data-codota-status="done" name="code" style="box-sizing: border-box; outline: 0px; padding: 8px 16px 4px 56px; margin-bottom: 24px; position: relative; overflow-y: hidden; overflow-x: auto; font-family: Consolas, Inconsolata, Courier, monospace; color: rgb(0, 0, 0); word-break: break-all; border: none; background-color: rgb(246, 248, 250);"><dependency> <groupId>com.alibaba</groupId> <artifactId>alipay-sdk-java</artifactId> <version>20161129201425</version> <scope>system</scope> <systemPath>${project.basedir}/lib/alipay-sdk-java20161129201425.jar</systemPath></dependency>3、这里的groupId和artifactId以及version都是可以随便填写的 ,scope必须填写为system,而systemPath我们现在我们jar包的地址就可以了
4、最后我们必须在maven打包的过程中加入我们这个jar包。因为项目运行的时候需要这个Jar,并且我们得拷贝在WEB-INF/lib目录下
<pre class="prettyprint prettyprinted" data-original-code="org.apache.maven.plugins maven-war-plugin ${project.basedir}/lib WEB-INF/lib false **/*.jar 2.1.1 " data-snippet-id="ext.a374f7947ee9283bb872f3f7e89c5040" data-snippet-saved="false" data-codota-status="done" name="code" style="box-sizing: border-box; outline: 0px; padding: 8px 16px 4px 56px; margin-bottom: 24px; position: relative; overflow-y: hidden; overflow-x: auto; font-family: Consolas, Inconsolata, Courier, monospace; color: rgb(0, 0, 0); word-break: break-all; border: none; background-color: rgb(246, 248, 250);"><groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <webResources> <resource> <directory>${project.basedir}/lib</directory> <targetPath>WEB-INF/lib</targetPath> <filtering>false</filtering> <includes> <include>**/*.jar</include> </includes> </resource> </webResources> </configuration> <version>2.1.1</version> 集成在使用SDK调用具体API前,需要先配置通用接入参数
1、APP_ID 使用沙箱模式中的APP_ID.
2、APP_PRIVATE_KEY ALIPAY_PUBLIC_KEY 使用文章2、配置应用环境中生成的测试密钥.
3、CHARSET 默认使用UTF-8
然后,使用上述接入参数初始化AlipayClient:
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",APP_ID,APP_PRIVATE_KEY,"json",CHARSET,ALIPAY_PUBLIC_KEY);接下来,就可以用alipayClient来调用具体的API了。alipayClient只需要初始化一次,后续调用不同的API都可以使用同一个alipayClient对象。
手机网站支付不支持第三方授权,不能代商家发起请求。
调用接口系统调用类:直接从服务端发起HTTP请求,支付宝会同步返回请求结果。例如本产品中的交易查询等配套API。
调用流程图使用SDK快速接入手机网站支付alipay.trade.wap.pay:
对于页面跳转类API,SDK不会也无法像系统调用类API一样自动请求支付宝并获得结果,而是在接受request请求对象后,为开发者生成前台页面请求需要的完整form表单的html(包含自动提交脚本),商户直接将这个表单的String输出到http response中即可。
public void doPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { AlipayClient alipayClient = ... //获得初始化的AlipayClient AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//创建API对应的request alipayRequest.setReturnUrl("http://domain.com/CallBack/return_url.jsp"); alipayRequest.setNotifyUrl("http://domain.com/CallBack/notify_url.jsp");//在公共参数中设置回跳和通知地址 alipayRequest.setBizContent("{" + " \"out_trade_no\":\"20150320010101002\"," + " \"total_amount\":88.88," + " \"subject\":\"Iphone6 16G\"," + " \"seller_id\":\"2088123456789012\"," + " \"product_code\":\"QUICK_WAP_PAY\"" + " }");//填充业务参数 String form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单 httpResponse.setContentType("text/html;charset=" + AlipayServiceEnvConstants.CHARSET); httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面 httpResponse.getWriter().flush();}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
异步通知验签
<pre class="prettyprint prettyprinted" data-original-code="Map paramsMap = ... //将异步通知中收到的所有参数都存放到map中boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, ALIPAY_PUBLIC_KEY, CHARSET) //调用SDK验证签名if(signVerfied){ // TODO 验签成功后,按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,校验成功后在response中返回success并继续商户自身业务处理,校验失败返回failure}else{ // TODO 验签失败则记录异常日志,并在response中返回failure.}" data-snippet-id="ext.9858706436d55a08c02518033920dc8a" data-snippet-saved="false" data-codota-status="done" name="code" style="box-sizing: border-box; outline: 0px; padding: 8px 16px 4px 56px; margin-bottom: 24px; position: relative; overflow-y: hidden; overflow-x: auto; font-family: Consolas, Inconsolata, Courier, monospace; color: rgb(0, 0, 0); word-break: break-all; border: none; background-color: rgb(246, 248, 250);">Map<String, String> paramsMap = ... //将异步通知中收到的所有参数都存放到map中boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, ALIPAY_PUBLIC_KEY, CHARSET) //调用SDK验证签名if(signVerfied){ // TODO 验签成功后,按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,校验成功后在response中返回success并继续商户自身业务处理,校验失败返回failure}else{ // TODO 验签失败则记录异常日志,并在response中返回failure.}服务端具体封装将参数独立配置在一个属性文件中方便管理,当然也可以从数据库
加载接入参数并初始化AlipayClient
AlipayClient" title="" style="box-sizing: border-box; outline: 0px; margin-top: 24px; margin-bottom: 24px; max-width: 100%; word-break: break-all; cursor: zoom-in;">
使用SDK快速接入代码封装
public void wapPay(){ String body="我是测试数据"; String subject="Iphone6 16G"; String total_amount="0.01"; String passback_params="1"; BizContent content = new BizContent(); content.setBody(body); content.setOut_trade_no(OrderInfoUtil2_0.getOutTradeNo());; content.setPassback_params(passback_params); content.setSubject(subject); content.setTotal_amount(total_amount); content.setProduct_code("QUICK_WAP_PAY"); try { AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//创建API对应的request alipayRequest.setReturnUrl("http://javen.tunnel.qydev.com/alipay/return_url"); alipayRequest.setNotifyUrl("http://javen.tunnel.qydev.com/alipay/notify_url");//在公共参数中设置回跳和通知地址 //参数参考 https://doc.open.alipay.com/doc2/detail.htm?treeId=203&articleId=105463&docType=1#s0 System.out.println(JsonKit.toJson(content)); alipayRequest.setBizContent(JsonKit.toJson(content));//填充业务参数 String form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单 HttpServletResponse httpResponse = getResponse(); httpResponse.setContentType("text/html;charset=" + charset); httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面 httpResponse.getWriter().flush(); } catch (Exception e) { e.printStackTrace(); } renderNull(); }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
<pre class="prettyprint prettyprinted" data-original-code="public void return_url() { try { // 获取支付宝GET过来反馈信息 Map map = AliPayApi.toMap(getRequest()); for (Map.Entry entry : map.entrySet()) { System.out.println(entry.getKey() + " = " + entry.getValue()); } boolean verify_result = AlipaySignature.rsaCheckV1(map, AliPayApi.ALIPAY_PUBLIC_KEY, AliPayApi.CHARSET, AliPayApi.SIGN_TYPE); if (verify_result) {// 验证成功 // TODO 请在这里加上商户的业务逻辑程序代码 System.out.println("return_url 验证成功"); renderText("success"); return; } else { System.out.println("return_url 验证失败"); // TODO renderText("failure"); return; } } catch (AlipayApiException e) { e.printStackTrace(); renderText("failure"); } }" data-snippet-id="ext.61610dd45e14ff63e15fab0f969e7606" data-snippet-saved="false" data-codota-status="done" name="code" style="box-sizing: border-box; outline: 0px; padding: 8px 16px 4px 56px; margin-bottom: 24px; position: relative; overflow-y: hidden; overflow-x: auto; font-family: Consolas, Inconsolata, Courier, monospace; color: rgb(0, 0, 0); word-break: break-all; border: none; background-color: rgb(246, 248, 250);">public void return_url() { try { // 获取支付宝GET过来反馈信息 Map<String, String> map = AliPayApi.toMap(getRequest()); for (Map.Entry<String, String> entry : map.entrySet()) { System.out.println(entry.getKey() + " = " + entry.getValue()); } boolean verify_result = AlipaySignature.rsaCheckV1(map, AliPayApi.ALIPAY_PUBLIC_KEY, AliPayApi.CHARSET, AliPayApi.SIGN_TYPE); if (verify_result) {// 验证成功 // TODO 请在这里加上商户的业务逻辑程序代码 System.out.println("return_url 验证成功"); renderText("success"); return; } else { System.out.println("return_url 验证失败"); // TODO renderText("failure"); return; } } catch (AlipayApiException e) { e.printStackTrace(); renderText("failure"); } }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
<pre class="prettyprint prettyprinted" data-original-code="public void notify_url() { try { // 获取支付宝POST过来反馈信息 Map params = AliPayApi.toMap(getRequest()); for (Map.Entry entry : params.entrySet()) { System.out.println(entry.getKey() + " = " + entry.getValue()); } boolean verify_result = AlipaySignature.rsaCheckV1(params, AliPayApi.ALIPAY_PUBLIC_KEY, AliPayApi.CHARSET, AliPayApi.SIGN_TYPE); if (verify_result) {// 验证成功 // TODO 请在这里加上商户的业务逻辑程序代码 System.out.println("notify_url 验证成功succcess"); renderText("success"); return; } else { System.out.println("notify_url 验证失败"); // TODO renderText("failure"); return; } } catch (AlipayApiException e) { e.printStackTrace(); renderText("failure"); } }" data-snippet-id="ext.4ec088b4f16bf1797d26c0d13814d1b2" data-snippet-saved="false" data-codota-status="done" name="code" style="box-sizing: border-box; outline: 0px; padding: 8px 16px 4px 56px; margin-bottom: 24px; position: relative; overflow-y: hidden; overflow-x: auto; font-family: Consolas, Inconsolata, Courier, monospace; color: rgb(0, 0, 0); word-break: break-all; border: none; background-color: rgb(246, 248, 250);">public void notify_url() { try { // 获取支付宝POST过来反馈信息 Map<String, String> params = AliPayApi.toMap(getRequest()); for (Map.Entry<String, String> entry : params.entrySet()) { System.out.println(entry.getKey() + " = " + entry.getValue()); } boolean verify_result = AlipaySignature.rsaCheckV1(params, AliPayApi.ALIPAY_PUBLIC_KEY, AliPayApi.CHARSET, AliPayApi.SIGN_TYPE); if (verify_result) {// 验证成功 // TODO 请在这里加上商户的业务逻辑程序代码 System.out.println("notify_url 验证成功succcess"); renderText("success"); return; } else { System.out.println("notify_url 验证失败"); // TODO renderText("failure"); return; } } catch (AlipayApiException e) { e.printStackTrace(); renderText("failure"); } }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
<pre class="prettyprint prettyprinted" data-original-code="/** * 将异步通知的参数转化为Map * @param request * @return */ public static Map toMap(HttpServletRequest request) { Map params = new HashMap(); Map requestParams = request.getParameterMap(); for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { String name = (String) iter.next(); String[] values = (String[]) requestParams.get(name); String valueStr = ""; for (int i = 0; i /** * 将异步通知的参数转化为Map * @param request * @return */ public static Map<String, String> toMap(HttpServletRequest request) { Map<String, String> params = new HashMap<String, String>(); Map<String, String[]> requestParams = request.getParameterMap(); for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) { String name = (String) iter.next(); String[] values = (String[]) requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values : valueStr + values + ","; } // 乱码解决,这段代码在出现乱码时使用。 // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); params.put(name, valueStr); } return params; }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
此项目源码【下载地址】
测试下载部署如果没有做任何修改默认的分别为:
测试地址:http://域名或者IP/alipay/wapPay
回跳地址:http://域名或者IP/alipay/return_url
通知地址:http://域名或者IP/alipay/notify_url
测试截图