1.前台请求后台获得相应的地址参数,跳转URL 前台跳转支付页面
(1)前台
window.document.location = "${ctxPath}/api/alipay.html?_batch=true&_type=alipayPay&_c="+_this.id;
(2)后台
/**
* 生成跳转支付宝页面
*/
public String _$indexBatchAlipayPay() {
Map map = alipayPay();
String from = map.get("form");
if ("200".equals(map.get("status"))) {
renderHtml(from);//返回渲染HTML页面
} else {
try {
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
basePath = basePath + "/member/order?type=route&key=123#/order/unpaid?_c=" + map.get("_c") + "&text=" + URLEncoder.encode(from, "UTF-8");
response.sendRedirect(basePath);
attr("text", from);
} catch (Exception e) {
e.printStackTrace();
logger.error("[{}] [{}] [{}]", "生成跳转支付宝页面失败 请求消息-->" + map.toString(), "<异常-->", e);
}
}
return null;
}
/**
* 生成跳转支付宝页面
*
* @author: hjj
* @date: 2018年1月30日 上午11:52:28
* @param: @return:
* void @throws
*/
public Map alipayPay() {
Map map = new HashMap<>();
map.put("status", "404");
map.put("_c", _c);
if (!StringUtils.isBlank(_c)) {
Members members = getMembers();
OrderForm orderForm = orderFormService.queryCodeObject(_c);
if (orderForm == null || isDel(orderForm) || !Constants.ORDER_FORM_STATUS_BUY_UNPAID.equals(orderForm.getStatus())) {//
map.put("form", "未找到未支付订单");
return map;
}
if (orderForm.getMembersId() == null || !members.getId().equals(orderForm.getMembersId().getId())) {
map.put("form", "未找到用户未支付订单");
return map;
}
RouteInfor routeId = routeInforService.getById(orderForm.getRouteId().getId());
RLock lock = null;
// 锁库存
try {
lock = CacheFactory.build(CacheFactory.REDIS).getRLock(Constants.ROUTE_QUOTA_RLOCK + orderForm.getRouteId().getId());
if (Constants.IS_TRUE.equals(routeId.getIsScareBuying())) {// 抢购活动
Boolean boo = routeInforService.judgeScareBuying(routeId.getBuyingStartDate(), routeId.getBuyingEndDate(), new Date());
if (!boo) {// 不在抢购时间内
map.put("form", "抢购时间已过!");
return map;
}
}
int quota = routeId.getQuota() == null ? 0 : routeId.getQuota();
int pendingQuota = routeId.getPendingQuota() == null ? 0 : routeId.getPendingQuota();
Integer amount = orderForm.getAmount() == null ? 0 : orderForm.getAmount();
if ((quota - pendingQuota) <= 0 || (quota - pendingQuota - amount) < 0) {
map.put("form", "库存不足,请刷新后重新操作!");
return map;
}
// 金额
String totalAmount = orderForm.getAmountPaid().toString();
// 订单编号 唯一
String outTradeNo = orderForm.getCoding();
// 支付页面有效时间 默认1分钟
int TimeoutExpress = 1;
if (Constants.IS_TRUE.equals(orderForm.getIsScareBuying())) {// 抢购
String value = sysParameterService.querySysParameterDate(Constants.SYS_PARAMETER_CODE_SCARE_BUYING_PAGE_TIME);
if (value != null && StringUtils.isNumeric(value)) {
TimeoutExpress = Integer.parseInt(value);
}
} else {// 订单
String value = sysParameterService.querySysParameterDate(Constants.SYS_PARAMETER_CODE_ORDER_PAGE_TIME);
if (value != null && StringUtils.isNumeric(value)) {
TimeoutExpress = Integer.parseInt(value);
}
}
Cache cache = CacheFactory.build(CacheFactory.EHCACHE_PAGE_EXPIRED);// 缓存对象
Element element = cache.get(Constants.CODE_KEY_ORDER_PAGE_EXPIRED + _c);
App app = WebHelper.getApp(request);
if (element == null) {// 无缓存才锁库存
// 尝试加锁,最多等待5秒,上锁以后10秒自动解锁
boolean res = lock.tryLock(5, 10, TimeUnit.SECONDS);
if (!res) {// 加锁失败
map.put("form", "系统繁忙,请重新操作!");
return map;
}
cache.set(Constants.CODE_KEY_ORDER_PAGE_EXPIRED + _c, _c, TimeoutExpress * 60);
MemOperateLog memOperateLog = new MemOperateLog();
memOperateLog.setModule("订单模块");
memOperateLog.setMembersId(members);
memOperateLog.setContent("生成支付宝页面,并锁定库存");
memOperateLog.setIp(IpUtil.getIpAddr(request));// ip
memOperateLog.setResult(Constants.IS_TRUE);
routeInforService.updateRouteInforQuota(null, routeId.getId(), amount, Constants.ROUTE_PENDING_QUOTA_JIA, members, new Date(), memOperateLog, app);
lock.unlock();
}
HttpServletRequest request = ServletActionContext.getRequest();
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
String returnUrl = basePath + "api/alipay/new.json";
String notifyUrl = basePath + "api/alipay.txt";// .txt后缀会直接输出resp的message属性
if (App.isPc(app)) {
// PC
AlipayTradePayModel model = new AlipayTradePayModel();
// model.setBody("Javen IJPay PC支付测试");//订单描述
model.setTimeoutExpress(TimeoutExpress + "m");// 支付页面有效时间
model.setOutTradeNo(outTradeNo);
// 销售产品码,与支付宝签约的产品码名称。 注:目前仅支持FAST_INSTANT_TRADE_PAY
model.setProductCode("FAST_INSTANT_TRADE_PAY");
model.setTotalAmount(totalAmount);
model.setSubject(orderForm.getRouteName());// 订单标题
String form = tradePage(response, model, notifyUrl, returnUrl);
map.put("status", "200");
map.put("form", form);
}else{
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setTimeoutExpress(TimeoutExpress + "m");// 支付页面有效时间
// model.setBody("Javen IJPay PC支付测试");//订单描述
model.setOutTradeNo(outTradeNo);
// 销售产品码,与支付宝签约的产品码名称。 注:目前仅支持FAST_INSTANT_TRADE_PAY
model.setProductCode("QUICK_MSECURITY_PAY");
model.setTotalAmount(totalAmount);
model.setSubject(orderForm.getRouteName());// 订单标题
String alipay = tradePageMP(response, model, notifyUrl, returnUrl);
map.put("status", "200");
map.put("form", alipay);
}
} catch (Exception e) {
e.printStackTrace();
map.put("form", "系统异常,请重新操作");
logger.error("[{}] [{}]", "生成支付宝页面异常", e);
if (lock != null && lock.isLocked()) {// 锁未解开时解开
lock.unlock();
}
}
} else {
map.put("form", "未找到订单");
}
return map;
}
2.支付完成后有一个直接回调 returnUrl 验签回调(页面及时反馈 ) notifyUrl 异步支付结果回调(支付结果以这个未准)
// 支付宝网关(固定)
private static final String URL = "https://openapi.alipay.com/gateway.do";
//private static final String URL = "https://openapi.alipaydev.com/gateway.do";
// APPID 即创建应用后生成
private static final String APP_ID = "...";
// private static final String APP_ID = "...";
// 开发者私钥,由开发者自己生成
private static final String APP_PRIVATE_KEY = "...";
// 参数返回格式,只支持json
private static final String FORMAT = "json";
// 编码集,支持GBK/UTF-8
private static final String CHARSET = "UTF-8";
// 支付宝公钥,由支付宝生成
private static final String ALIPAY_PUBLIC_KEY = "...;
// private static final String ALIPAY_PUBLIC_KEY = "...";
// 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2
private static final String SIGN_TYPE = "RSA2";
private static final AlipayClient ALIPAY_CLIENT = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE);
/**
* 异步通知处理 //notify_url eg. POST /api/alipay.txt
*
* @author: hjj
* @date: 2018年1月26日 上午10:32:25
* @param: @return:
*/
@Override
public String create() {
// 获取支付宝POST过来反馈信息 -->
Map params = new HashMap();
PaymentSubmitLog paymentSubmitLog = new PaymentSubmitLog();// 支付提交日志
paymentSubmitLog.setChannel(Constants.PAYMENT_CHANNEL_ALIPAY);
paymentSubmitLog.setStatus(Constants.OPERATE_RESULT_FALSE);
String reTxt = "fail";
RLock lock = null;
boolean res = true;
Cache cache = CacheFactory.build(CacheFactory.REDIS);
Members members = new Members();
OrderForm orderForm = new OrderForm();
try {
params = toMap(request);
members.setUserName("支付宝");
boolean verify_result = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, CHARSET, SIGN_TYPE);
String out_trade_no = params.get("out_trade_no");// 订单编号
String trade_no = params.get("trade_no");// 支付宝交易号
String total_amount = params.get("total_amount") == null ? "0" : params.get("total_amount");// 支付宝交易金额
paymentSubmitLog.setCoding(out_trade_no);
paymentSubmitLog.setSerialNumber(trade_no);
paymentSubmitLog.setAmount(new BigDecimal(total_amount));
if (verify_result) {// 验签成功
// 在这里加上商户的业务逻辑程序代码 异步通知可能出现订单重复通知 需要做去重处理
String trade_status = params.get("trade_status");
if (trade_status != null && trade_status.equals("TRADE_SUCCESS")) {// 支付成功
List list = orderFormService.queryOrderForm(out_trade_no, null);
if (list != null && list.size() > 0) {// 找到订单
orderForm = list.get(0);
orderForm.setAmountRealPaid(new BigDecimal(total_amount));// 支付宝交易金额
// 锁库存
lock = cache.getRLock(Constants.ROUTE_QUOTA_RLOCK + orderForm.getRouteId().getId());
res = lock.tryLock(5, 10, TimeUnit.SECONDS);
if (res) {// 获得锁
paymentSubmitLog = orderFormService.handleAlipayOrder(orderForm, members, params, paymentSubmitLog);
reTxt = "success";// 成功必须返回这个
lock.unlock();
}
} else {
paymentSubmitLog.setRemark("支付成功-->支付宝反馈信息-->" + params.toString() + "未找到订单订单编号-->" + out_trade_no);
logger.info("[{}] [{}]", "非法", params.toString());
}
} else {
paymentSubmitLog.setRemark("支付失败-->支付宝反馈信息-->" + params.toString());
logger.info("[{}] [{}]", "失败", params.toString());
}
} else {
paymentSubmitLog.setRemark("验签失败-->支付宝反馈信息-->" + params.toString());
logger.info("[{}] [{}]", "非法", params.toString());
}
} catch (Exception e) {
e.printStackTrace();
paymentSubmitLog.setRemark("运行异常-->支付宝反馈信息-->" + params.toString() + "异常信息-->" + e.getMessage());
logger.error("[{}] [{}] [{}]", "异常", params.toString(), e);
if (lock != null && lock.isLocked()) {// 锁未解开时解开
lock.unlock();
}
}
if (Constants.OPERATE_RESULT_PROBLEM.equals(paymentSubmitLog.getStatus())) {
logger.info("[{}] [{}]", "问题订单", params.toString());
} else if (Constants.OPERATE_RESULT_TRUE.equals(paymentSubmitLog.getStatus())) {
logger.info("[{}] [{}]", "支付成功", params.toString());
} else if (Constants.OPERATE_RESULT_FALSE.equals(paymentSubmitLog.getStatus())) {
logger.info("[{}] [{}]", "支付失败", params.toString());
} else if (Constants.OPERATE_RESULT_PENDING.equals(paymentSubmitLog.getStatus())) {
logger.info("[{}] [{}]", "支付待处理", params.toString());
}
paymentSubmitLogService.save(paymentSubmitLog);
if (!res) {
paymentSubmitLog.setStatus(Constants.OPERATE_RESULT_PENDING);
Map params2 = new HashMap();
params2.put("orderType", "alipay");
params2.put("orderForm", orderForm);
params2.put("params", params);
params2.put("members", members);
params2.put("paymentSubmitLogId", paymentSubmitLog.getId());
cache.ladd(Constants.PAYMENT_ORDER_LIST, params2);
}
logger.info("[{}]", "记录操作日志成功!!!");
initResult(RespCode.OK, reTxt);
return reTxt;
}
/**
* 同步商户页面验签,这里只是返回验签的状态 //return_url get /api/alipay/new.json
*
* @author: hjj
* @date: 2018年1月26日上午10:32:25
* @param: @return:
* void @throws
*/
@Override
public String editNew() {
initResult(RespCode.OK);
Map map = toMap(request);
try {
boolean verify_result = AlipaySignature.rsaCheckV1(map, ALIPAY_PUBLIC_KEY, CHARSET, SIGN_TYPE);
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
if (verify_result) {// 验证成功
String out_trade_no = map.get("out_trade_no");
List list = orderFormService.queryOrderForm(out_trade_no, null);
if (list != null && list.size() > 0) {
logger.info("[{}] [{}]", "同步商户页面验签 验证成功 请求消息-->", map.toString());
basePath = basePath + "/member/order?type=route&key=123#/order/finish?_c=" + list.get(0).getCoding();
} else {
logger.info("[{}] [{}]", "订单不存在 订单号-->" + out_trade_no, "<请求消息-->" + map.toString());
}
} else {
logger.info("[{}] [{}]", "同步商户页面验签 验证失败 请求消息-->", map.toString());
}
response.sendRedirect(basePath);
} catch (Exception e) {
// 返回页面失败
e.printStackTrace();
logger.error("[{}] [{}] [{}]", "同步商户页面验签 验证失败 请求消息-->" + map.toString(), "<异常-->", e);
}
return "";
}