Commit aa8011de authored by jmdhappy's avatar jmdhappy
Browse files

升级支付宝为最新接口

parent 6bb11b08
...@@ -3,15 +3,12 @@ package org.xxpay.service.controller; ...@@ -3,15 +3,12 @@ package org.xxpay.service.controller;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.xxpay.common.util.MyBase64; import org.xxpay.common.util.MyBase64;
import org.xxpay.common.util.MyLog; import org.xxpay.common.util.MyLog;
import org.xxpay.dal.dao.model.MchInfo; import org.xxpay.dal.dao.model.MchInfo;
import org.xxpay.service.channel.alipay.sign.Base64;
import org.xxpay.service.service.MchInfoService; import org.xxpay.service.service.MchInfoService;
/** /**
......
package org.xxpay.service.controller; package org.xxpay.service.controller;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.xxpay.common.constant.PayConstant; import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.util.MyLog; import org.xxpay.common.util.MyLog;
import org.xxpay.dal.dao.model.PayChannel; import org.xxpay.dal.dao.model.PayChannel;
import org.xxpay.dal.dao.model.PayOrder; import org.xxpay.dal.dao.model.PayOrder;
import org.xxpay.service.channel.alipay.config.AlipayConfig; import org.xxpay.service.channel.alipay.AlipayConfig;
import org.xxpay.service.channel.alipay.util.AlipayNotify;
import org.xxpay.service.channel.tencent.common.Util;
import org.xxpay.service.channel.tencent.protocol.notify_protocol.NotifyUnifiedOrderResData;
import org.xxpay.service.service.PayChannelService; import org.xxpay.service.service.PayChannelService;
import org.xxpay.service.service.PayOrderService; import org.xxpay.service.service.PayOrderService;
...@@ -21,6 +18,7 @@ import javax.servlet.ServletException; ...@@ -21,6 +18,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
...@@ -56,16 +54,28 @@ public class Notify4AliPayController extends Notify4BasePay { ...@@ -56,16 +54,28 @@ public class Notify4AliPayController extends Notify4BasePay {
* @throws IOException * @throws IOException
*/ */
@RequestMapping(value = "/pay/aliPayNotifyRes.htm") @RequestMapping(value = "/pay/aliPayNotifyRes.htm")
@ResponseBody public void aliPayNotifyRes(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
public String aliPayNotifyRes(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String result = doAliPayRes(request, response);
return doAliPayRes(request, response); if(result != null) {
_log.info("alipay notify response: {}", result);
response.setContentType("text/html");
PrintWriter pw;
try {
pw = response.getWriter();
pw.print(result);
} catch (IOException e) {
_log.error("Pay response write exception.", e);
}
}
} }
public String doAliPayRes(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { public String doAliPayRes(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String logPrefix = "【支付宝支付回调通知】"; String logPrefix = "【支付宝支付回调通知】";
_log.info("====== 开始接收支付宝支付回调通知 ======"); _log.info("====== 开始接收支付宝支付回调通知 ======");
//获取支付宝POST过来反馈信息 //获取支付宝POST过来反馈信息
Map<String,String> params = new HashMap<>(); Map<String,String> params = new HashMap<String,String>();
Map requestParams = request.getParameterMap(); Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next(); String name = (String) iter.next();
...@@ -82,23 +92,17 @@ public class Notify4AliPayController extends Notify4BasePay { ...@@ -82,23 +92,17 @@ public class Notify4AliPayController extends Notify4BasePay {
_log.info("{}通知请求数据:reqStr={}", logPrefix, params); _log.info("{}通知请求数据:reqStr={}", logPrefix, params);
if(params.isEmpty()) { if(params.isEmpty()) {
_log.error("{}请求参数为空", logPrefix); _log.error("{}请求参数为空", logPrefix);
return makeRetData(PayConstant.RETURN_VALUE_FAIL, "请求参数为空"); return PayConstant.RETURN_ALIPAY_VALUE_FAIL;
} }
Map<String, Object> payContext = new HashMap(); Map<String, Object> payContext = new HashMap();
PayOrder payOrder; PayOrder payOrder;
payContext.put("parameters", params); payContext.put("parameters", params);
if(!verifyAliPayParams(payContext)) { if(!verifyAliPayParams(payContext)) {
return makeRetData(PayConstant.RETURN_VALUE_FAIL, (String) payContext.get("retMsg")); return PayConstant.RETURN_ALIPAY_VALUE_FAIL;
} }
_log.info("{}验证请求数据及签名通过", logPrefix); _log.info("{}验证请求数据及签名通过", logPrefix);
String out_trade_no = params.get("out_trade_no"); // 商户订单号
String trade_no = params.get("trade_no"); // 支付宝订单号
String trade_status = params.get("trade_status"); // 交易状态 String trade_status = params.get("trade_status"); // 交易状态
String buyer_email = params.get("buyer_email"); // 买家支付宝账号
// 支付状态成功或者完成 // 支付状态成功或者完成
if (trade_status.equals(PayConstant.AlipayConstant.TRADE_STATUS_SUCCESS) || if (trade_status.equals(PayConstant.AlipayConstant.TRADE_STATUS_SUCCESS) ||
trade_status.equals(PayConstant.AlipayConstant.TRADE_STATUS_FINISHED)) { trade_status.equals(PayConstant.AlipayConstant.TRADE_STATUS_FINISHED)) {
...@@ -133,38 +137,18 @@ public class Notify4AliPayController extends Notify4BasePay { ...@@ -133,38 +137,18 @@ public class Notify4AliPayController extends Notify4BasePay {
public boolean verifyAliPayParams(Map<String, Object> payContext) { public boolean verifyAliPayParams(Map<String, Object> payContext) {
Map<String,String> params = (Map<String,String>)payContext.get("parameters"); Map<String,String> params = (Map<String,String>)payContext.get("parameters");
String out_trade_no = params.get("out_trade_no"); // 商户订单号 String out_trade_no = params.get("out_trade_no"); // 商户订单号
String seller_email = params.get("seller_email"); // 卖家支付宝账号 String total_amount = params.get("total_amount"); // 支付金额
String total_fee = params.get("total_fee"); // 支付金额
String buyer_email = params.get("buyer_email"); // 买家支付宝账号
String sign = params.get("sign"); // 签名
if (StringUtils.isEmpty(out_trade_no)) { if (StringUtils.isEmpty(out_trade_no)) {
_log.error("AliPay Notify parameter out_trade_no is empty. out_trade_no={}", out_trade_no); _log.error("AliPay Notify parameter out_trade_no is empty. out_trade_no={}", out_trade_no);
payContext.put("retMsg", "out_trade_no is empty"); payContext.put("retMsg", "out_trade_no is empty");
return false; return false;
} }
if (StringUtils.isEmpty(seller_email)) { if (StringUtils.isEmpty(total_amount)) {
_log.error("AliPay Notify parameter seller_email is empty. seller_email={}", seller_email); _log.error("AliPay Notify parameter total_amount is empty. total_fee={}", total_amount);
payContext.put("retMsg", "seller_email is empty"); payContext.put("retMsg", "total_amount is empty");
return false;
}
if (StringUtils.isEmpty(total_fee)) {
_log.error("AliPay Notify parameter total_fee is empty. total_fee={}", total_fee);
payContext.put("retMsg", "total_fee is empty");
return false;
}
if (StringUtils.isEmpty(buyer_email)) {
_log.error("AliPay Notify parameter buyer_email is empty. buyer_email={}", buyer_email);
payContext.put("retMsg", "buyer_email is empty");
return false; return false;
} }
if (StringUtils.isEmpty(sign)) {
_log.error("AliPay Notify parameter sign is empty. sign={}", sign);
payContext.put("retMsg", "sign is empty");
return false;
}
String errorMessage; String errorMessage;
// 查询payOrder记录 // 查询payOrder记录
String payOrderId = out_trade_no; String payOrderId = out_trade_no;
PayOrder payOrder = payOrderService.selectPayOrder(payOrderId); PayOrder payOrder = payOrderService.selectPayOrder(payOrderId);
...@@ -173,7 +157,6 @@ public class Notify4AliPayController extends Notify4BasePay { ...@@ -173,7 +157,6 @@ public class Notify4AliPayController extends Notify4BasePay {
payContext.put("retMsg", "Can't found payOrder"); payContext.put("retMsg", "Can't found payOrder");
return false; return false;
} }
// 查询payChannel记录 // 查询payChannel记录
String mchId = payOrder.getMchId(); String mchId = payOrder.getMchId();
String channelId = payOrder.getChannelId(); String channelId = payOrder.getChannelId();
...@@ -183,20 +166,26 @@ public class Notify4AliPayController extends Notify4BasePay { ...@@ -183,20 +166,26 @@ public class Notify4AliPayController extends Notify4BasePay {
payContext.put("retMsg", "Can't found payChannel"); payContext.put("retMsg", "Can't found payChannel");
return false; return false;
} }
boolean verify_result = false;
try {
verify_result = AlipaySignature.rsaCheckV1(params, alipayConfig.init(payChannel.getParam()).getAlipay_public_key(), AlipayConfig.CHARSET, "RSA2");
} catch (AlipayApiException e) {
_log.error(e, "AlipaySignature.rsaCheckV1 error");
}
// 验证签名 // 验证签名
if (!AlipayNotify.verify(alipayConfig.init(payChannel.getParam()), params)) { if (!verify_result) {
errorMessage = "Verify VV pay sign failed."; errorMessage = "rsaCheckV1 failed.";
_log.error("AliPay Notify parameter {}", errorMessage); _log.error("AliPay Notify parameter {}", errorMessage);
payContext.put("retMsg", errorMessage); payContext.put("retMsg", errorMessage);
return false; return false;
} }
// 核对金额 // 核对金额
long aliPayAmt = new BigDecimal(total_fee).movePointRight(2).longValue(); long aliPayAmt = new BigDecimal(total_amount).movePointRight(2).longValue();
long dbPayAmt = payOrder.getAmount().longValue(); long dbPayAmt = payOrder.getAmount().longValue();
if (dbPayAmt != aliPayAmt) { if (dbPayAmt != aliPayAmt) {
_log.error("db payOrder record payPrice not equals total_fee. total_fee={},payOrderId={}", total_fee, payOrderId); _log.error("db payOrder record payPrice not equals total_amount. total_amount={},payOrderId={}", total_amount, payOrderId);
payContext.put("retMsg", ""); payContext.put("retMsg", "");
return false; return false;
} }
...@@ -204,15 +193,4 @@ public class Notify4AliPayController extends Notify4BasePay { ...@@ -204,15 +193,4 @@ public class Notify4AliPayController extends Notify4BasePay {
return true; return true;
} }
String makeRetData(String retCode, String retMsg) {
NotifyUnifiedOrderResData data = new NotifyUnifiedOrderResData();
data.setReturn_code(retCode);
data.setReturn_msg(retMsg);
return Util.objectToXML(data);
}
String makeRetData(String retCode) {
return makeRetData(retCode, "");
}
} }
...@@ -119,7 +119,7 @@ public class Notify4BasePay { ...@@ -119,7 +119,7 @@ public class Notify4BasePay {
pw = response.getWriter(); pw = response.getWriter();
pw.print(message); pw.print(message);
} catch (IOException e) { } catch (IOException e) {
_log.error("JDPay response write exception.", e); _log.error("Pay response write exception.", e);
} }
_log.info(">>>>>> PAY回调通知业务系统完成 <<<<<<"); _log.info(">>>>>> PAY回调通知业务系统完成 <<<<<<");
} }
......
...@@ -2,34 +2,35 @@ package org.xxpay.service.controller; ...@@ -2,34 +2,35 @@ package org.xxpay.service.controller;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.xxpay.common.constant.PayConstant; import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.constant.PayEnum; import org.xxpay.common.constant.PayEnum;
import org.xxpay.common.util.*; import org.xxpay.common.util.AmountUtil;
import org.xxpay.common.util.MyBase64;
import org.xxpay.common.util.MyLog;
import org.xxpay.common.util.XXPayUtil;
import org.xxpay.dal.dao.model.MchInfo; import org.xxpay.dal.dao.model.MchInfo;
import org.xxpay.dal.dao.model.PayChannel; import org.xxpay.dal.dao.model.PayChannel;
import org.xxpay.dal.dao.model.PayOrder; import org.xxpay.dal.dao.model.PayOrder;
import org.xxpay.service.channel.alipay.config.AlipayConfig; import org.xxpay.service.channel.alipay.AlipayConfig;
import org.xxpay.service.channel.alipay.sign.RSA;
import org.xxpay.service.channel.alipay.util.AlipayCore;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.Signature;
import org.xxpay.service.channel.tencent.common.Util;
import org.xxpay.service.channel.tencent.protocol.order_protocol.UnifiedOrderReqData;
import org.xxpay.service.channel.tencent.protocol.order_protocol.UnifiedOrderResData;
import org.xxpay.service.channel.tencent.service.UnifiedOrderService;
import org.xxpay.service.service.MchInfoService; import org.xxpay.service.service.MchInfoService;
import org.xxpay.service.service.PayChannelService; import org.xxpay.service.service.PayChannelService;
import org.xxpay.service.service.PayOrderService; import org.xxpay.service.service.PayOrderService;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
...@@ -44,18 +45,12 @@ public class PayChannel4AlipayController { ...@@ -44,18 +45,12 @@ public class PayChannel4AlipayController {
private final MyLog _log = MyLog.getLog(PayChannel4AlipayController.class); private final MyLog _log = MyLog.getLog(PayChannel4AlipayController.class);
@Autowired
private DiscoveryClient client;
@Autowired @Autowired
private PayOrderService payOrderService; private PayOrderService payOrderService;
@Autowired @Autowired
private PayChannelService payChannelService; private PayChannelService payChannelService;
@Autowired
UnifiedOrderService unifiedOrderService;
@Autowired @Autowired
private AlipayConfig alipayConfig; private AlipayConfig alipayConfig;
...@@ -63,8 +58,8 @@ public class PayChannel4AlipayController { ...@@ -63,8 +58,8 @@ public class PayChannel4AlipayController {
private MchInfoService mchInfoService; private MchInfoService mchInfoService;
/** /**
* 支付宝WAP支付 * 支付宝手机网站支付
* 文档:https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.ZGobeF&treeId=60&articleId=104790&docType=1 * 文档:https://docs.open.alipay.com/203/107090/
* @param jsonParam * @param jsonParam
* @return * @return
*/ */
...@@ -81,62 +76,41 @@ public class PayChannel4AlipayController { ...@@ -81,62 +76,41 @@ public class PayChannel4AlipayController {
if("".equals(resKey)) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0001)); if("".equals(resKey)) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0001));
PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId); PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId);
alipayConfig.init(payChannel.getParam()); alipayConfig.init(payChannel.getParam());
Map<String, String> payMap = new HashMap<>(); AlipayClient client = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getApp_id(), alipayConfig.getRsa_private_key(), AlipayConfig.FORMAT, AlipayConfig.CHARSET, alipayConfig.getAlipay_public_key(), AlipayConfig.SIGNTYPE);
payMap.put("service", "alipay.wap.create.direct.pay.by.user"); // 接口名称 AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();
payMap.put("partner", alipayConfig.getPartner()); // 签约的支付宝账号对应的支付宝唯一用户号 // 封装请求支付信息
payMap.put("_input_charset", "utf-8"); // 商户网站使用的编码格式,仅支持UTF-8 AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
payMap.put("notify_url", alipayConfig.getNotify_url()); // 支付宝服务器主动通知商户网站里指定的页面http路径 model.setOutTradeNo(payOrderId);
//if (!StringUtils.isEmpty(params.get("respUrl"))) { model.setSubject(payOrder.getSubject());
// payMap.put("return_url", params.get("respUrl")); // 支付宝处理完请求后,当前页面自动跳转到商户网站里指定页面的http路径(该字段可以不参与签名,但值不能为空!) model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getAmount().toString()));
//} model.setBody(payOrder.getBody());
payMap.put("out_trade_no", payOrderId); // 支付宝合作商户网站唯一订单号 model.setProductCode("QUICK_WAP_PAY");
payMap.put("subject", payOrder.getSubject()); // 商品的标题/交易标题/订单标题/订单关键字等
payMap.put("total_fee", AmountUtil.convertCent2Dollar(payOrder.getAmount().toString())); // 该笔订单的资金总额,单位为RMB-Yuan。取值范围为[0.01,100000000.00],精确到小数点后两位
payMap.put("seller_id", alipayConfig.getPartner()); // 卖家支付宝账号对应的支付宝唯一用户号
payMap.put("payment_type", "1"); // 支付类型。仅支持:1(商品购买)
// 获取objParams参数 // 获取objParams参数
String objParams = payOrder.getExtra(); String objParams = payOrder.getExtra();
String show_url = "http://www.xxpay.org"; if (StringUtils.isNotEmpty(objParams)) {
if (!org.springframework.util.StringUtils.isEmpty(objParams)) {
try { try {
JSONObject objParamsJson = JSONObject.parseObject(objParams); JSONObject objParamsJson = JSON.parseObject(objParams);
show_url = ObjectUtils.toString(objParamsJson.getString("ali_show_url"), "http://www.xxpay.org"); if(StringUtils.isNotBlank(objParamsJson.getString("quit_url"))) {
model.setQuitUrl(objParamsJson.getString("quit_url"));
}
} catch (Exception e) { } catch (Exception e) {
_log.error("{}objParams参数格式错误!", logPrefix); _log.error("{}objParams参数格式错误!", logPrefix);
} }
} }
payMap.put("show_url", show_url); // 用户付款中途退出返回商户网站的地址 alipay_request.setBizModel(model);
payMap.put("body", payOrder.getBody()); // 对一笔交易的具体描述信息 // 设置异步通知地址
payMap.put("it_b_pay", "60m"); // 设置未付款交易的超时时间,一旦超时,该笔交易就会自动被关闭 alipay_request.setNotifyUrl(alipayConfig.getNotify_url());
payMap.put("app_pay", "Y"); // app_pay=Y:尝试唤起支付宝客户端进行支付,若用户未安装支付宝,则继续使用wap收银台进行支付 // 设置同步地址
alipay_request.setReturnUrl(alipayConfig.getReturn_url());
String signContent = AlipayCore.createLinkString(payMap); String payUrl = null;
String paySign = RSA.sign(signContent, alipayConfig.getPrivate_key(), AlipayConfig.input_charset);
try { try {
/** payUrl = client.pageExecute(alipay_request).getBody();
* 仅需对sign 做URL编码 } catch (AlipayApiException e) {
*/
paySign = URLEncoder.encode(paySign, "UTF-8");
} catch (UnsupportedEncodingException e) {
_log.error(e, "URLEncoder AliPay Sign Exception");
}
_log.info("{}生成请求支付宝签名,sign={}", logPrefix, paySign);
payMap.put("sign_type", "RSA"); // 签名类型
payMap.put("sign", paySign); // 签名
// 对有中文的参数转码
try {
payMap.put("subject", URLEncoder.encode(payOrder.getSubject(), "UTF-8"));
payMap.put("body", URLEncoder.encode(payOrder.getBody(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace(); e.printStackTrace();
} }
String payUrl = alipayConfig.getGateway().concat("?").concat(AlipayCore.createLinkString(payMap));
_log.info("{}生成跳转路径:payUrl={}", logPrefix, payUrl); _log.info("{}生成跳转路径:payUrl={}", logPrefix, payUrl);
payOrderService.updateStatus4Ing(payOrderId, null); payOrderService.updateStatus4Ing(payOrderId, null);
_log.info("{}生成请求支付宝数据,req={}", logPrefix, alipay_request.getBizModel());
_log.info("{}生成请求支付宝数据,req={}", logPrefix, payMap);
_log.info("###### 商户统一下单处理完成 ######"); _log.info("###### 商户统一下单处理完成 ######");
Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null); Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
map.put("payOrderId", payOrderId); map.put("payOrderId", payOrderId);
...@@ -145,8 +119,8 @@ public class PayChannel4AlipayController { ...@@ -145,8 +119,8 @@ public class PayChannel4AlipayController {
} }
/** /**
* 支付宝PC支付(即时到帐接口) * 支付宝电脑网站支付
* 文档:https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.M7NEo1&treeId=62&articleId=104743&docType=1 * 文档:https://docs.open.alipay.com/270/105899/
* @param jsonParam * @param jsonParam
* @return * @return
*/ */
...@@ -163,60 +137,44 @@ public class PayChannel4AlipayController { ...@@ -163,60 +137,44 @@ public class PayChannel4AlipayController {
if("".equals(resKey)) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0001)); if("".equals(resKey)) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0001));
PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId); PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId);
alipayConfig.init(payChannel.getParam()); alipayConfig.init(payChannel.getParam());
Map<String, String> payMap = new HashMap<>(); AlipayClient client = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getApp_id(), alipayConfig.getRsa_private_key(), AlipayConfig.FORMAT, AlipayConfig.CHARSET, alipayConfig.getAlipay_public_key(), AlipayConfig.SIGNTYPE);
payMap.put("service", "create_direct_pay_by_user"); // 接口名称 AlipayTradePagePayRequest alipay_request = new AlipayTradePagePayRequest();
payMap.put("partner", alipayConfig.getPartner()); // 签约的支付宝账号对应的支付宝唯一用户号 // 封装请求支付信息
payMap.put("_input_charset", "utf-8"); // 编码字符集 AlipayTradePagePayModel model=new AlipayTradePagePayModel();
payMap.put("notify_url", alipayConfig.getNotify_url()); // 支付宝服务器主动通知商户网站里指定的页面http路径 model.setOutTradeNo(payOrderId);
//if (!StringUtils.isEmpty(params.get("respUrl"))) { model.setSubject(payOrder.getSubject());
// payMap.put("return_url", params.get("respUrl")); // 支付宝处理完请求后,当前页面自动跳转到商户网站里指定页面的http路径(该字段可以不参与签名,但值不能为空!) model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getAmount().toString()));
//} model.setBody(payOrder.getBody());
payMap.put("out_trade_no", payOrderId); // 商户网站唯一订单号 model.setProductCode("FAST_INSTANT_TRADE_PAY");
payMap.put("subject", payOrder.getSubject()); // 订单标题 // 获取objParams参数
payMap.put("payment_type", "1"); // 支付类型,只支持取值为1(商品购买)
payMap.put("total_fee", AmountUtil.convertCent2Dollar(payOrder.getAmount().toString())); // 订单总金额
payMap.put("seller_id", alipayConfig.getPartner()); // 卖家支付宝用户号
payMap.put("body", payOrder.getBody()); // 对交易或商品的描述
// 附加参数
payMap.put("qr_pay_mode", "4");
String objParams = payOrder.getExtra(); String objParams = payOrder.getExtra();
if (!org.springframework.util.StringUtils.isEmpty(objParams)) { String qr_pay_mode = "2";
String qrcode_width = "200";
if (StringUtils.isNotEmpty(objParams)) {
try { try {
JSONObject objParamsJson = JSONObject.parseObject(objParams); JSONObject objParamsJson = JSON.parseObject(objParams);
payMap.put("qr_pay_mode", ObjectUtils.toString(objParamsJson.getString("qr_pay_mode"), "4")); // 扫码支付的方式,支持前置模式和跳转模式。(4:直接显示二维码) qr_pay_mode = ObjectUtils.toString(objParamsJson.getString("qr_pay_mode"), "2");
payMap.put("qrcode_width", ObjectUtils.toString(objParamsJson.getString("qrcode_width"), "200")); // 扫码支付的方式,支持前置模式和跳转模式。(定义二维码大小) qrcode_width = ObjectUtils.toString(objParamsJson.getString("qrcode_width"), "200");
} catch (Exception e) { } catch (Exception e) {
_log.error("{}objParams参数格式错误!", logPrefix); _log.error("{}objParams参数格式错误!", logPrefix);
} }
} }
model.setQrPayMode(qr_pay_mode);
String signContent = AlipayCore.createLinkString(payMap); model.setQrcodeWidth(Long.parseLong(qrcode_width));
String paySign = RSA.sign(signContent, alipayConfig.getPrivate_key(), AlipayConfig.input_charset); alipay_request.setBizModel(model);
// 设置异步通知地址
alipay_request.setNotifyUrl(alipayConfig.getNotify_url());
// 设置同步地址
alipay_request.setReturnUrl(alipayConfig.getReturn_url());
String payUrl = null;
try { try {
/** payUrl = client.pageExecute(alipay_request).getBody();
* 仅需对sign 做URL编码 } catch (AlipayApiException e) {
*/
paySign = URLEncoder.encode(paySign, "UTF-8");
} catch (UnsupportedEncodingException e) {
_log.error(e, "URLEncoder AliPay Sign Exception");
}
_log.info("{}生成请求支付宝签名,sign={}", logPrefix, paySign);
payMap.put("sign_type", "RSA"); // 签名类型
payMap.put("sign", paySign); // 签名
// 对有中文的参数转码
try {
payMap.put("subject", URLEncoder.encode(payOrder.getSubject(), "UTF-8"));
payMap.put("body", URLEncoder.encode(payOrder.getBody(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace(); e.printStackTrace();
} }
String payUrl = alipayConfig.getGateway().concat("?").concat(AlipayCore.createLinkString(payMap));
_log.info("{}生成跳转路径:payUrl={}", logPrefix, payUrl); _log.info("{}生成跳转路径:payUrl={}", logPrefix, payUrl);
payOrderService.updateStatus4Ing(payOrderId, null); payOrderService.updateStatus4Ing(payOrderId, null);
_log.info("{}生成请求支付宝数据,req={}", logPrefix, payMap); _log.info("{}生成请求支付宝数据,req={}", logPrefix, alipay_request.getBizModel());
_log.info("###### 商户统一下单处理完成 ######"); _log.info("###### 商户统一下单处理完成 ######");
Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null); Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
map.put("payOrderId", payOrderId); map.put("payOrderId", payOrderId);
...@@ -225,13 +183,14 @@ public class PayChannel4AlipayController { ...@@ -225,13 +183,14 @@ public class PayChannel4AlipayController {
} }
/** /**
* 支付宝支付,生产签名及请求支付宝的参数(注:不会向支付宝发请求) * 支付宝APP支付,生产签名及请求支付宝的参数(注:不会向支付宝发请求)
* 文档: https://docs.open.alipay.com/204/105465/
* @param jsonParam * @param jsonParam
* @return * @return
*/ */
@RequestMapping(value = "/pay/channel/ali_mobile") @RequestMapping(value = "/pay/channel/ali_mobile")
public String doAliPayMobileReq(@RequestParam String jsonParam) { public String doAliPayMobileReq(@RequestParam String jsonParam) {
String logPrefix = "【支付宝支付下单】"; String logPrefix = "【支付宝APP支付下单】";
JSONObject paramObj = JSON.parseObject(new String(MyBase64.decode(jsonParam))); JSONObject paramObj = JSON.parseObject(new String(MyBase64.decode(jsonParam)));
PayOrder payOrder = paramObj.getObject("payOrder", PayOrder.class); PayOrder payOrder = paramObj.getObject("payOrder", PayOrder.class);
String payOrderId = payOrder.getPayOrderId(); String payOrderId = payOrder.getPayOrderId();
...@@ -242,43 +201,32 @@ public class PayChannel4AlipayController { ...@@ -242,43 +201,32 @@ public class PayChannel4AlipayController {
if("".equals(resKey)) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0001)); if("".equals(resKey)) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0001));
PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId); PayChannel payChannel = payChannelService.selectPayChannel(channelId, mchId);
alipayConfig.init(payChannel.getParam()); alipayConfig.init(payChannel.getParam());
Map<String, String> payMap = new HashMap<>(); AlipayClient client = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getApp_id(), alipayConfig.getRsa_private_key(), AlipayConfig.FORMAT, AlipayConfig.CHARSET, alipayConfig.getAlipay_public_key(), AlipayConfig.SIGNTYPE);
payMap.put("service", "mobile.securitypay.pay"); // 接口名称 AlipayTradeAppPayRequest alipay_request = new AlipayTradeAppPayRequest();
payMap.put("partner", alipayConfig.getPartner()); // 合作者身份ID // 封装请求支付信息
payMap.put("_input_charset", "utf-8"); // 参数编码字符集 AlipayTradeAppPayModel model=new AlipayTradeAppPayModel();
payMap.put("notify_url", alipayConfig.getNotify_url()); // 服务器异步通知页面路径 model.setOutTradeNo(payOrderId);
//payMap.put("app_id", ""); // 客户端号 model.setSubject(payOrder.getSubject());
//payMap.put("appenv", ""); // 客户端来源 model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getAmount().toString()));
payMap.put("out_trade_no", payOrderId); // 商户网站唯一订单号 model.setBody(payOrder.getBody());
payMap.put("subject", payOrder.getSubject()); // 商品名称 model.setProductCode("QUICK_MSECURITY_PAY");
payMap.put("payment_type", "1"); // 支付类型 alipay_request.setBizModel(model);
payMap.put("seller_id", alipayConfig.getAli_account()); // 卖家支付宝账号 // 设置异步通知地址
payMap.put("total_fee", AmountUtil.convertCent2Dollar(payOrder.getAmount().toString())); // 总金额,需要分转元. alipay_request.setNotifyUrl(alipayConfig.getNotify_url());
payMap.put("body", payOrder.getBody()); // 商品详情 // 设置同步地址
//payMap.put("goods_type", ""); // 商品类型 alipay_request.setReturnUrl(alipayConfig.getReturn_url());
//payMap.put("hb_fq_param", ""); // 花呗分期参数 String payParams = null;
//payMap.put("rn_check", ""); // 是否发起实名校验
//payMap.put("it_b_pay", "30m"); // 未付款交易的超时时间
//payMap.put("extern_token", ""); // 授权令牌
String signContent = AlipayCore.createLinkString(payMap);
String paySign = RSA.sign(signContent, alipayConfig.getPrivate_key(), AlipayConfig.input_charset);
try { try {
/** payParams = client.sdkExecute(alipay_request).getBody();
* 仅需对sign 做URL编码 } catch (AlipayApiException e) {
*/ e.printStackTrace();
paySign = URLEncoder.encode(paySign, "UTF-8");
} catch (UnsupportedEncodingException e) {
_log.error(e, "URLEncoder AliPay Sign Exception");
} }
_log.info("{}生成请求支付宝签名,sign={}", logPrefix, paySign);
payMap.put("sign_type", "RSA"); // 签名类型
payMap.put("sign", paySign); // 签名
payOrderService.updateStatus4Ing(payOrderId, null); payOrderService.updateStatus4Ing(payOrderId, null);
_log.info("{}生成请求支付宝数据,req={}", logPrefix, payMap); _log.info("{}生成请求支付宝数据,payParams={}", logPrefix, payParams);
_log.info("###### 商户统一下单处理完成 ######"); _log.info("###### 商户统一下单处理完成 ######");
Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null); Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
map.put("payOrderId", payOrderId); map.put("payOrderId", payOrderId);
map.put("payParams", payMap); map.put("payParams", payParams);
return XXPayUtil.makeRetData(map, resKey); return XXPayUtil.makeRetData(map, resKey);
} }
} }
...@@ -159,7 +159,7 @@ public class Mq4PayNotify { ...@@ -159,7 +159,7 @@ public class Mq4PayNotify {
} }
// 修改通知次数 // 修改通知次数
try { try {
int result = payOrderService.updateNotify(orderId); int result = payOrderService.updateNotify(orderId, (byte) 1);
_log.info("修改payOrderId={},通知业务系统次数->{}", orderId, result == 1 ? "成功" : "失败"); _log.info("修改payOrderId={},通知业务系统次数->{}", orderId, result == 1 ? "成功" : "失败");
}catch (Exception e) { }catch (Exception e) {
_log.error(e, "修改通知次数异常"); _log.error(e, "修改通知次数异常");
...@@ -167,20 +167,21 @@ public class Mq4PayNotify { ...@@ -167,20 +167,21 @@ public class Mq4PayNotify {
return ; // 通知成功结束 return ; // 通知成功结束
}else { }else {
// 通知失败,延时再通知 // 通知失败,延时再通知
int cnt = count++; int cnt = count+1;
_log.info("notify count={}", cnt);
if (cnt > 5) { if (cnt > 5) {
_log.info("notify count>5 stop. url={}", respUrl); _log.info("notify count>5 stop. url={}", respUrl);
return ; return ;
} }
// 修改通知次数 // 修改通知次数
try { try {
int result = payOrderService.updateNotify(orderId); int result = payOrderService.updateNotify(orderId, (byte) cnt);
_log.info("修改payOrderId={},通知业务系统次数->{}", orderId, result == 1 ? "成功" : "失败"); _log.info("修改payOrderId={},通知业务系统次数->{}", orderId, result == 1 ? "成功" : "失败");
}catch (Exception e) { }catch (Exception e) {
_log.error(e, "修改通知次数异常"); _log.error(e, "修改通知次数异常");
} }
msgObj.put("count", cnt); msgObj.put("count", cnt);
this.send(msgObj.toJSONString(), cnt*60*1000); this.send(msgObj.toJSONString(), cnt * 60 * 1000);
} }
_log.warn("notify failed. url:{}, response body:{}", respUrl, sb.toString()); _log.warn("notify failed. url:{}, response body:{}", respUrl, sb.toString());
} catch(Exception e) { } catch(Exception e) {
......
...@@ -63,10 +63,10 @@ public class PayOrderService { ...@@ -63,10 +63,10 @@ public class PayOrderService {
return payOrderMapper.updateByExampleSelective(payOrder, example); return payOrderMapper.updateByExampleSelective(payOrder, example);
} }
public int updateNotify(String payOrderId) { public int updateNotify(String payOrderId, byte count) {
PayOrder payOrder = selectPayOrder(payOrderId);
PayOrder newPayOrder = new PayOrder(); PayOrder newPayOrder = new PayOrder();
newPayOrder.setNotifyCount((byte) (payOrder.getNotifyCount()+1)); // TODO 并发下次数问题待解决
newPayOrder.setNotifyCount(count);
newPayOrder.setLastNotifyTime(System.currentTimeMillis()); newPayOrder.setLastNotifyTime(System.currentTimeMillis());
newPayOrder.setPayOrderId(payOrderId); newPayOrder.setPayOrderId(payOrderId);
return payOrderMapper.updateByPrimaryKeySelective(newPayOrder); return payOrderMapper.updateByPrimaryKeySelective(newPayOrder);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment