maven依赖
支付宝支付SDK依赖
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.0.0</version>
</dependency>
前端代码示例
前端采用的是mui.js
mui.init();
var urltemp = "";//请支付宝充值接口
var wxChannel = null; // 微信支付
var aliChannel = null; // 支付宝支付
$(function() {
mui.plusReady(function() {
//获取支付通道
plus.payment.getChannels(function(channels) {
for (var i in channels) {
if (channels[i].id == "wxpay") {
wxChannel = channels[i];
} else {
aliChannel = channels[i];
}
}
}, function(e) {
alert("获取支付通道失败:" + e.message);
});
//点击充值按钮
document.getElementById("rechargeBtn").addEventListener('tap', function() {
mui.ajax({
url: urltemp,
data: dataInfo,//请求参数,按下面支付宝充值接口参数要求传入即可
async: false, // 异步 || 同步
dataType: 'json',
type: 'post',
timeout: 5000,
success: function(data) {
//表示调用支付宝支付接口成功
if (data.status == 0) {
var data = data.data;//数据为支付宝充值接口返回的response.getBody()
plus.payment.request(aliChannel , data, function(result) {
plus.nativeUI.alert("充值成功!", function() {
var list = plus.webview.currentWebview().opener();
//触发父页面的自定义事件(refresh),从而进行刷新
mui.fire(list, 'refresh');
mui.back();
});
}, function(error) {
console.log("[" + error.code + "]:" + error.message);
plus.nativeUI.alert("充值失败:已取消支付");
});
} else if (data.status == 1000) {
plus.nativeUI.toast(data.msg);
}
},
error: function(xhr, type, errorThrown) {
}
});
});
});
})
请求接口
支付宝充值接口
@ApiOperation(httpMethod = "POST", value = "支付宝充值", produces = MediaType.APPLICATION_JSON_VALUE, notes = "充值")
@ApiImplicitParams({
@ApiImplicitParam(name = "token", value = "广告主token", required = true, paramType = "query"),
@ApiImplicitParam(name = "advertUserId", value = "广告主id", required = true, paramType = "query"),
@ApiImplicitParam(name = "payAmount", value = "付款金额", required = true, paramType = "query"),
@ApiImplicitParam(name = "giveAmount", value = "赠送金额", required = true, paramType = "query"),
})
@ApiResponses({@ApiResponse(code = 0, message = "OK"), @ApiResponse(code = 1, message = "ERROR"),})
@RequestMapping(value = "/zfbPayRecharge")
public HoneyResult zfbPayRecharge(String token, String advertUserId, double payAmount, double giveAmount) {
String tokenKey = "token" + advertUserId;
if (token == null || !token.equals(jedisClient.get(tokenKey))) {
return HoneyResult.build(StatusCode.CODE_NOTLOGIN, "请先登录");
}
if (advertUserId == null || "".equals(advertUserId)) {
return HoneyResult.build(StatusCode.CODE_NOLL_ERROR, "请求参数存在空值");
}
if (payAmount / 1000 < 0.1) {
return HoneyResult.build(StatusCode.CODE_ERROR, "充值金额不得低于0.1元");
}
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET_UTF8, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
String orderId = UUIDUtils.getCurrentDateStr();
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody(String.format("ZFB_%s_%.2f_%.2f", advertUserId, payAmount / 1000, giveAmount / 1000));//交易描述
model.setSubject("订单编号 " + orderId);//商品的标题/交易标题/订单标题/订单关键字等。
model.setOutTradeNo(orderId);//商户网站唯一订单号
model.setTimeoutExpress("30m");//该笔订单允许的最晚付款时间,逾期将关闭交易。
model.setTotalAmount(String.format("%.2f", payAmount / 1000.00));//支付宝支付单位为元
model.setProductCode("QUICK_MSECURITY_PAY");//销售产品码,商家和支付宝签约的产品码
request.setBizModel(model);
request.setNotifyUrl(AlipayConfig.notify_url);//支付宝回调地址
try {
// 这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
logger.info("AlipayTradeAppPayResponse return :" + response.getBody());// -
if (response.isSuccess()) {
return HoneyResult.build(StatusCode.CODE_SUCCESS, "获取支付宝支付参数成功", response.getBody());
} else {
return HoneyResult.build(StatusCode.CODE_ERROR, "调用失败");
}
} catch (AlipayApiException e) {
return HoneyResult.build(StatusCode.CODE_ERROR, "调用失败");
}
}
支付宝回调地址接口
@ApiOperation(httpMethod = "GET", value = "支付宝充值回调", produces = MediaType.APPLICATION_JSON_VALUE, notes = "充值回调")
@RequestMapping(value = "/zfbNotify")
public String zfbNotify(HttpServletRequest request) throws Exception {
//获取支付宝POST过来反馈信息
Map<String, String> params = new HashMap<String, String>();
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 < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
params.put(name, valueStr);
}
//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
//商户订单号
String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
//支付宝交易号
String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
//交易状态
String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
String trade_body = new String(request.getParameter("body").getBytes("ISO-8859-1"), "UTF-8");
boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET_UTF8, AlipayConfig.SIGNTYPE);
String returnParam = "fail";
if (verify_result) {//验证成功
if (trade_status.equals("TRADE_FINISHED")) {
returnParam = "success";
} else if (trade_status.equals("TRADE_SUCCESS")) {
//付款用户编号
String advertUserId = trade_body.split("_")[1];
//支付金额
double payAmount = Double.valueOf(trade_body.split("_")[2]);
//赠送金额
double giveAmount = Double.valueOf(trade_body.split("_")[3]);
//充值记录插入
honeyRecharGerecordService.saveRechargerecord(advertUserId, payAmount, giveAmount, "0", trade_no);
returnParam = "success";
}
} else {//验证失败
logger.error("支付宝签名验证失败");
returnParam = "fail";
}
return returnParam;
}
}
工具类
1.错误状态码工具类
package com.zhhong.honey.common;
public class StatusCode {
public static int CODE_SUCCESS = 0; //成功返回
public static int CODE_ERROR = 1000; //通用返回
}
2.通用返回值工具类
package com.zhhong.honey.common;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
/**
* 自定义响应结构
*/
public class HoneyResult {
// 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper();
// 响应业务状态
private Integer status;
// 响应消息
private String msg;
// 响应中的数据
private Object data;
private long count;
public long getCount() {
return count;
}
public HoneyResult(Integer status, String msg, Object data, long count) {
this.status = status;
this.msg = msg;
this.data = data;
this.count = count;
}
public void setCount(long count) {
this.count = count;
}
public static HoneyResult build(Integer status, String msg, Object data) {
return new HoneyResult(status, msg, data);
}
public static HoneyResult build(Integer status, String msg, Object data,long count) {
return new HoneyResult(status, msg, data,count);
}
public static HoneyResult ok(Object data) {
return new HoneyResult(data);
}
public static HoneyResult ok() {
return new HoneyResult(null);
}
public HoneyResult() {
}
public static HoneyResult build(Integer status, String msg) {
return new HoneyResult(status, msg, null);
}
public HoneyResult(Integer status, String msg, Object data) {
this.status = status;
this.msg = msg;
this.data = data;
}
public HoneyResult(Object data) {
this.status = 200;
this.msg = "OK";
this.data = data;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
/**
* 将json结果集转化为QPsssResult对象
*
* @param jsonData json数据
* @param clazz HandyExpressResult中的object类型
* @return
*/
public static HoneyResult formatToPojo(String jsonData, Class<?> clazz) {
try {
if (clazz == null) {
return MAPPER.readValue(jsonData, HoneyResult.class);
}
JsonNode jsonNode = MAPPER.readTree(jsonData);
JsonNode data = jsonNode.get("data");
Object obj = null;
if (clazz != null) {
if (data.isObject()) {
obj = MAPPER.readValue(data.traverse(), clazz);
} else if (data.isTextual()) {
obj = MAPPER.readValue(data.asText(), clazz);
}
}
return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
} catch (Exception e) {
return null;
}
}
/**
* 没有object对象的转化
*
* @param json
* @return
*/
public static HoneyResult format(String json) {
try {
return MAPPER.readValue(json, HoneyResult.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Object是集合转化
*
* @param jsonData json数据
* @param clazz 集合中的类型
* @return
*/
public static HoneyResult formatToList(String jsonData, Class<?> clazz) {
try {
JsonNode jsonNode = MAPPER.readTree(jsonData);
JsonNode data = jsonNode.get("data");
Object obj = null;
if (data.isArray() && data.size() > 0) {
obj = MAPPER.readValue(data.traverse(),
MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
}
return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
} catch (Exception e) {
return null;
}
}
}
3.支付宝公用参数配置工具类
package com.zhhong.honey.utils.config.zfb;
public class AlipayConfig {
// 商户appid
public static String APPID = "";
//私钥 pkcs8格式的
public static String RSA_PRIVATE_KEY =";
// 支付宝回调地址
public static String notify_url = "";
//页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
public static String return_url = "";
// 请求网关地址
public static String URL = "https://openapi.alipay.com/gateway.do";
// 编码
public static String CHARSET_UTF8 = "UTF-8";
public static String CHARSET_GBK = "GBK";
// 返回格式
public static String FORMAT = "json";
// 支付宝公钥
public static String ALIPAY_PUBLIC_KEY ="";
// 日志记录目录
public static String log_path = "/log";
// RSA2
public static String SIGNTYPE = "RSA2";
}