最近公司有电脑网站跟手机网站的支付宝支付需求,正好博主最近相对有空,于是花了一天时间去实现这个功能。先是在支付宝的开放平台的文档中心看了半天,,发现并不能找到立马就能上手开发的内容。于是搜了几篇博客,综合之下终于实现了功能。在此将java沙箱调试的历程整理出来,希望能对大家有所帮助,好了废话不扯,来看看怎么一步步实现的。 第一步 访问开放平台文档中西,看看支付宝的支付流程,大概了解一下就行了。地址如下https://docs.open.alipay.com/270/105898/ 第二步 下载java的demo(非常重要),里面包含了需要的jar包以及定义好了支付宝支付的基本参数,下载下来之后我们把自己的参数copy进去,调用起来就很方便。下载路径如下
第三步 申请沙箱环境。沙箱环境相当于是一个支付宝的测试中心,申请之后,会给你指定的appid,测试买家的账号(付款账号),测试卖家账号(收款账号)。有了这些,我们就能愉快的享受调试买买买的乐趣了。 申请及资料采集步骤如下 1.进入支付宝沙箱测试中心 2.需要生成RSA2(SHA256)的应用公钥,并且配置好RSA2(SHA256)的应用公钥,这里注意,不需要配置RSA(SHA1)密钥。(生成RSA2的应用公钥详情请参考:https://docs.open.alipay.com/291/105971) 然后将生成的公钥填写到下图中的应用公钥,再将支付宝的公钥copy下来备用。
3.沙箱应用中,还需要配置应用网关,这里就需要做内网穿透了。需要让你本地的服务能在公网上被访问到。博主使用的是natapp工具,使用起来很方便,生成了自己的域名之后,然后直接访问,看看tomcat服务能不能跑起来,能访问到之后,将域名天下到应用网关下。至此,沙箱配置就完成啦
第四步,将下载下来的demo解压,导入到自己的开发工具中,博主用的myeclipse,目录及结构如下
其中为了方便处理支付宝的结构化参数,额外导入了fastjson的包 ,具体的资源大家可以在百度maven 在仓库中搜索下载啦 第五部,添加自己的代码快,如下 package com.inspiron.alipay;
import java.util.HashMap; import java.util.Map;
import com.alibaba.fastjson.JSON; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.internal.util.StringUtils; import com.alipay.api.request.AlipayTradeCancelRequest; import com.alipay.api.request.AlipayTradePagePayRequest; import com.alipay.api.request.AlipayTradePayRequest; import com.alipay.api.request.AlipayTradePrecreateRequest; import com.alipay.api.request.AlipayTradeQueryRequest; import com.alipay.api.request.AlipayTradeRefundRequest; import com.alipay.api.request.AlipayTradeWapPayRequest; import com.alipay.api.response.AlipayTradeCancelResponse; import com.alipay.api.response.AlipayTradePayResponse; import com.alipay.api.response.AlipayTradePrecreateResponse; import com.alipay.api.response.AlipayTradeQueryResponse; import com.alipay.api.response.AlipayTradeRefundResponse; import com.alipay.config.AlipayConfig;
public class AlipayClientFactory { /*private static final AlipayClient client = new DefaultAlipayClient( AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY); */ private static final AlipayClient client = new DefaultAlipayClient( AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE); public static AlipayClient getAlipayClientInstance() { return client; } /** * appAuthToken * 如ISV代替商家调用当面付接口,需将商户授权后获取的app_auth_token带上;如商家申请当面付自己调用,则传null bizContent * JSON格式 商户的请求参数 */ // 手机网页支付 网站支付 public String ydAndPc_Pay(Map<String, String> maps) throws AlipayApiException { AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest(); String NotifyUrl = maps.get("NotifyUrl"); String ReturnUrl = maps.get("ReturnUrl"); // 后台回调 if (!StringUtils.isEmpty(NotifyUrl)) { alipayRequest.setNotifyUrl(NotifyUrl); // bizContent 中不需要 公共参数 maps.remove("NotifyUrl"); } // 页面回调 if (!StringUtils.isEmpty(ReturnUrl)) { alipayRequest.setReturnUrl(ReturnUrl); // bizContent 中不需要 公共参数 maps.remove("ReturnUrl"); } String bizCon = JSON.toJSONString(maps); alipayRequest.setBizContent(bizCon); String form = ""; try { form = AlipayClientFactory.getAlipayClientInstance() .pageExecute(alipayRequest).getBody(); } catch (AlipayApiException e) { form = "err"; e.printStackTrace(); } // 调用SDK生成表单 return form; } public String Pc_Pay(Map<String, String> maps) throws AlipayApiException { AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); String NotifyUrl = maps.get("NotifyUrl"); String ReturnUrl = maps.get("ReturnUrl"); // 后台回调 if (!StringUtils.isEmpty(NotifyUrl)) { alipayRequest.setNotifyUrl(NotifyUrl); // bizContent 中不需要 公共参数 maps.remove("NotifyUrl"); } // 页面回调 if (!StringUtils.isEmpty(ReturnUrl)) { alipayRequest.setReturnUrl(ReturnUrl); // bizContent 中不需要 公共参数 maps.remove("ReturnUrl"); } String bizCon = JSON.toJSONString(maps); System.out.println("bizCon :"+bizCon); alipayRequest.setBizContent(bizCon); String form = ""; try { form = AlipayClientFactory.getAlipayClientInstance() .pageExecute(alipayRequest).getBody(); } catch (AlipayApiException e) { form = "err"; e.printStackTrace(); } // 调用SDK生成表单 return form; } // 查询订单状态 public AlipayTradeQueryResponse query(String appAuthToken, String bizContent) throws AlipayApiException { AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); request.putOtherTextParam("app_auth_token", appAuthToken); request.setBizContent(bizContent); return AlipayClientFactory.getAlipayClientInstance().execute(request); } // 条码支付 public AlipayTradePayResponse pay(String appAuthToken, String bizContent) throws AlipayApiException { AlipayTradePayRequest request = new AlipayTradePayRequest(); request.putOtherTextParam("app_auth_token", appAuthToken); request.setBizContent(bizContent); return AlipayClientFactory.getAlipayClientInstance().execute(request); } // 扫码支付 public AlipayTradePrecreateResponse precreate(String appAuthToken, String bizContent) throws AlipayApiException { AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest(); request.putOtherTextParam("app_auth_token", appAuthToken); request.setBizContent(bizContent); return AlipayClientFactory.getAlipayClientInstance().execute(request); } // 订单撤销 public AlipayTradeCancelResponse cancel(String appAuthToken, String bizContent) throws AlipayApiException { AlipayTradeCancelRequest request = new AlipayTradeCancelRequest(); request.putOtherTextParam("app_auth_token", appAuthToken); request.setBizContent(bizContent); return AlipayClientFactory.getAlipayClientInstance().execute(request); } // 申请退款 public AlipayTradeRefundResponse refund(String appAuthToken, String bizContent) throws AlipayApiException { AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); request.putOtherTextParam("app_auth_token", appAuthToken); request.setBizContent(bizContent); return AlipayClientFactory.getAlipayClientInstance().execute(request); } @SuppressWarnings("unused") public static void main(String[] args) { AlipayClientFactory c = new AlipayClientFactory(); try { Map<String, String> map = new HashMap<String, String>(); map.put("out_trade_no", "20160914113218"); String bizContent = JSON.toJSONString(map); System.err.println(bizContent); AlipayTradeQueryResponse rp = c.query(null, bizContent); } catch (AlipayApiException e) { e.printStackTrace(); } }
}
package com.inspiron.alipay;
import java.io.IOException; import java.util.HashMap; import java.util.Map;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import com.alipay.api.AlipayApiException;
public class CsPay extends HttpServlet { private static final long serialVersionUID = 1L;
/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); }
/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 参数目前都是 写死的 根据业务需求 写活 System.out.println("已经成功进入到后台接口"); Map<String, String> maps = new HashMap<String, String>(); maps.put("out_trade_no", UtilDate.getOrderNum()); maps.put("total_amount","1.00"); maps.put("subject", "Iphone6 16G"); maps.put("body", "Iphone6 16G"); //maps.put("product_code", "QUICK_WAP_PAY"); maps.put("product_code", "FAST_INSTANT_TRADE_PAY");//网页版参数不同 // 下面两个 参数的 KEY 不要乱写 要和工具类里面对应 maps.put("ReturnUrl", "http://f8s7ks./alipay.trade.wap.pay-java-utf-8/return_url.jsp"); maps.put("NotifyUrl", "http://f8s7ks./alipay.trade.wap.pay-java-utf-8/notify_url.jsp"); try { AlipayClientFactory ali = new AlipayClientFactory(); String form = ali.Pc_Pay(maps); if (!form.equals("err")) { response.setContentType("text/html;charset=utf-8"); response.getWriter().write(form);// 直接将完整的表单html输出到页面 response.getWriter().flush(); } } catch (AlipayApiException e) { e.printStackTrace(); } }
}
package com.inspiron.alipay;
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map;
public class CsUtil { /** * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串 * * @param params 需要排序并参与字符拼接的参数组 * @return 拼接后字符串 */ public static String createLinkString(Map<String, String> params) {
List<String> keys = new ArrayList<String>(params.keySet()); Collections.sort(keys);
String prestr = "";
for (int i = 0; i < keys.size(); i++) { String key = keys.get(i); String value = params.get(key);
if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符 prestr = prestr + key + "=" + value; } else { prestr = prestr + key + "=" + value + "&"; } }
return prestr; }
}
package com.inspiron.alipay;
import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Random;
/* * * 类名:UtilDate 功能:自定义订单类 详细:工具类,可以用作获取系统日期、订单编号等 版本:3.3 日期:2012-08-17 说明: * 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 */ public class UtilDate {
/** 年月日时分秒(无下划线) yyyyMMddHHmmss */ public static final String dtLong = "yyyyMMddHHmmss";
/** 完整时间 yyyy-MM-dd HH:mm:ss */ public static final String simple = "yyyy-MM-dd HH:mm:ss";
/** 年月日(无下划线) yyyyMMdd */ public static final String dtShort = "yyyyMMdd";
/** * 返回系统当前时间(精确到毫秒),作为一个唯一的订单编号 * * @return 以yyyyMMddHHmmss为格式的当前系统时间 */ public static String getOrderNum() { Date date = new Date(); DateFormat df = new SimpleDateFormat(dtLong); return df.format(date); }
/** * 获取系统当前日期(精确到毫秒),格式:yyyy-MM-dd HH:mm:ss * * @return */ public static String getDateFormatter() { Date date = new Date(); DateFormat df = new SimpleDateFormat(simple); return df.format(date); }
/** * 获取系统当期年月日(精确到天),格式:yyyyMMdd * * @return */ public static String getDate() { Date date = new Date(); DateFormat df = new SimpleDateFormat(dtShort); return df.format(date); }
/** * 产生随机的三位数 * * @return */ public static String getThree() { Random rad = new Random(); return rad.nextInt(1000) + ""; }
}
代码贴进去之后,填写AlipayConfig文件中的参数,如下
然后需要配置servelt的入口,我们在web.xml 文件中作如下配置 <servlet> <servlet-name>cspay</servlet-name> <servlet-class>com.inspiron.alipay.CsPay</servlet-class> </servlet> <servlet-mapping> <servlet-name>cspay</servlet-name> <url-pattern>/cspay</url-pattern>
</servlet-mapping>
将项目加载到服务器中,访问路径 http://自己的网址/alipay.trade.wap.pay-java-utf-8/cspay 出现以下页面
恭喜你,大公高成啦。
如果是手机网站,调用app的方式,需要在代码中做如下修改
然后访问出现如下页面
表示成功 。然后可以登录沙箱给我们的买家的账号,就可以体验支付的流程啦 如果有问题,欢迎大家沟通指导~~
|