最近公司有电脑网站跟手机网站的支付宝支付需求,正好博主最近相对有空,于是花了一天时间去实现这个功能。先是在支付宝的开放平台的文档中心看了半天,,发现并不能找到立马就能上手开发的内容。于是搜了几篇博客,综合之下终于实现了功能。在此将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.natappfree.cc/alipay.trade.wap.pay-java-utf-8/return_url.jsp");
maps.put("NotifyUrl", "http://f8s7ks.natappfree.cc/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的方式,需要在代码中做如下修改
然后访问出现如下页面
表示成功 。然后可以登录沙箱给我们的买家的账号,就可以体验支付的流程啦
如果有问题,欢迎大家沟通指导~~