feta: 完善注释,调整状态码处理逻辑

This commit is contained in:
陈泉 2021-11-29 14:16:04 +08:00 committed by StringKE
parent 66f42e85e2
commit 4576597c2f
5 changed files with 51 additions and 27 deletions

View File

@ -32,6 +32,8 @@ public class PppayChannelNoticeService extends AbstractChannelNoticeService {
@Override
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId, NoticeTypeEnum noticeTypeEnum) {
// 同步和异步需要不同的解析方案
// 异步需要从 webhook 中读取所有这里读取方式不太一样
if (noticeTypeEnum == NoticeTypeEnum.DO_NOTIFY) {
JSONObject params = JSONUtil.parseObj(getReqParamJSON().toJSONString());
String orderId = params.getByPath("resource.purchase_units[0].invoice_id", String.class);
@ -65,13 +67,17 @@ public class PppayChannelNoticeService extends AbstractChannelNoticeService {
public ChannelRetMsg doReturn(HttpServletRequest request, Object params, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws IOException {
JSONObject object = (JSONObject) params;
// 获取 Paypal 订单 ID
String ppOrderId = object.getStr("token");
// 统一处理订单
return mchAppConfigContext.getPaypalWrapper().processOrder(ppOrderId, payOrder);
}
public ChannelRetMsg doNotify(HttpServletRequest request, Object params, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws IOException {
JSONObject object = (JSONObject) params;
// 获取 Paypal 订单 ID
String ppOrderId = object.getByPath("resource.id", String.class);
// 统一处理订单
return mchAppConfigContext.getPaypalWrapper().processOrder(ppOrderId, payOrder, true);
}
}

View File

@ -38,6 +38,7 @@ public class PppayChannelRefundNoticeService extends AbstractChannelRefundNotice
@Override
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId, NoticeTypeEnum noticeTypeEnum) {
JSONObject params = JSONUtil.parseObj(getReqParamJSON().toJSONString());
// 获取退款订单 Paypal ID
String orderId = params.getByPath("resource.invoice_id", String.class);
return MutablePair.of(orderId, params);
}
@ -51,6 +52,7 @@ public class PppayChannelRefundNoticeService extends AbstractChannelRefundNotice
PaypalWrapper wrapper = mchAppConfigContext.getPaypalWrapper();
PayPalHttpClient client = wrapper.getClient();
// 查询退款详情以及状态
RefundsGetRequest refundRequest = new RefundsGetRequest(orderId);
HttpResponse<Refund> response = client.execute(refundRequest);

View File

@ -41,6 +41,7 @@ public class PppayRefundService extends AbstractRefundService {
PaypalWrapper paypalWrapper = mchAppConfigContext.getPaypalWrapper();
// 因为退款需要商户 Token 而同步支付回调不会保存订单信息
String ppOrderId = paypalWrapper.processOrder(payOrder.getChannelOrderNo()).get(0);
String ppCatptId = paypalWrapper.processOrder(payOrder.getChannelOrderNo()).get(1);
@ -50,6 +51,7 @@ public class PppayRefundService extends AbstractRefundService {
PayPalHttpClient client = paypalWrapper.getClient();
// 处理金额
long amount = (bizRQ.getRefundAmount() / 100);
String amountStr = Long.toString(amount, 10);
String currency = bizRQ.getCurrency().toUpperCase();

View File

@ -46,6 +46,7 @@ public class PpPc extends PppayPaymentService {
OrderRequest orderRequest = new OrderRequest();
// 配置 Paypal ApplicationContext 也就是支付页面信息
ApplicationContext applicationContext = new ApplicationContext()
.brandName(mchAppConfigContext.getMchApp().getAppName())
.landingPage("NO_PREFERENCE")
@ -59,11 +60,14 @@ public class PpPc extends PppayPaymentService {
List<PurchaseUnitRequest> purchaseUnitRequests = new ArrayList<>();
// 金额换算
long amount = (payOrder.getAmount() / 100);
String amountStr = Long.toString(amount, 10);
String currency = payOrder.getCurrency().toUpperCase();
// 由于 Paypal 是支持订单多商品的这里值添加一个
PurchaseUnitRequest purchaseUnitRequest = new PurchaseUnitRequest()
// 绑定 订单 ID 否则回调和异步较难处理
.customId(payOrder.getPayOrderId())
.invoiceId(payOrder.getPayOrderId())
.amountWithBreakdown(new AmountWithBreakdown()
@ -89,6 +93,7 @@ public class PpPc extends PppayPaymentService {
purchaseUnitRequests.add(purchaseUnitRequest);
orderRequest.purchaseUnits(purchaseUnitRequests);
// 从缓存获取 Paypal 操作工具
PaypalWrapper palApiConfig = mchAppConfigContext.getPaypalWrapper();
OrdersCreateRequest request = new OrdersCreateRequest();
@ -99,11 +104,13 @@ public class PpPc extends PppayPaymentService {
PPPcOrderRS res = new PPPcOrderRS();
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
// 标准返回 HttpPost 需要为 201
if (response.statusCode() == 201) {
Order order = response.result();
String status = response.result().status();
String tradeNo = response.result().id();
// 从返回数据里读取出支付链接
LinkDescription paypalLink = order.links().stream().reduce(null, (result, curr) -> {
if (curr.rel().equalsIgnoreCase("approve") && curr.method().equalsIgnoreCase("get")) {
result = curr;
@ -111,23 +118,12 @@ public class PpPc extends PppayPaymentService {
return result;
});
// 设置返回实体
channelRetMsg.setChannelAttach(JSONUtil.toJsonStr(new Json().serialize(order)));
channelRetMsg.setChannelOrderId(tradeNo + "," + "null");
if (status.equalsIgnoreCase("SAVED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} else if (status.equalsIgnoreCase("APPROVED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} else if (status.equalsIgnoreCase("VOIDED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
} else if (status.equalsIgnoreCase("COMPLETED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
} else if (status.equalsIgnoreCase("PAYER_ACTION_REQUIRED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} else if (status.equalsIgnoreCase("CREATED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
}
channelRetMsg.setChannelOrderId(tradeNo + "," + "null"); // 拼接订单ID
channelRetMsg = palApiConfig.dispatchCode(status, channelRetMsg); // 处理状态码
// 设置支付链接
res.setPayUrl(paypalLink.href());
} else {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);

View File

@ -40,16 +40,15 @@ public class PaypalWrapper {
private String notifyWebhook;
private String refundWebhook;
public ChannelRetMsg processOrder(String token, PayOrder payOrder) throws IOException {
return processOrder(token, payOrder, false);
}
public List<String> processOrder(String order) {
return processOrder(order, "null");
}
// 解析拼接 ID
public List<String> processOrder(String order, String afterOrderId) {
String ppOrderId = "null";
String ppCatptId = "null";
@ -76,7 +75,18 @@ public class PaypalWrapper {
return Arrays.asList(ppOrderId, ppCatptId);
}
/**
* 处理并捕获订单
* 由于 Paypal 创建订单后需要进行一次 Capture(捕获) 才可以正确获取到订单的支付状态
*
* @param token
* @param payOrder
* @param isCapture
* @return
* @throws IOException
*/
public ChannelRetMsg processOrder(String token, PayOrder payOrder, boolean isCapture) throws IOException {
// Paypal 创建订单存在一个 Token当订单捕获之后会有一个 捕获的ID 退款需要用到
String ppOrderId = this.processOrder(payOrder.getChannelOrderNo(), token).get(0);
String ppCatptId = this.processOrder(payOrder.getChannelOrderNo()).get(1);
@ -99,6 +109,7 @@ public class PaypalWrapper {
OrdersCaptureRequest ordersCaptureRequest = new OrdersCaptureRequest(ppOrderId);
ordersCaptureRequest.requestBody(orderRequest);
// 捕获订单
HttpResponse<Order> response = this.getClient().execute(ordersCaptureRequest);
if (response.statusCode() != 201) {
@ -143,24 +154,31 @@ public class PaypalWrapper {
result.setChannelAttach(orderJsonStr); // Capture 响应数据
result.setResponseEntity(textResp("SUCCESS")); // 响应数据
result.setChannelState(ChannelRetMsg.ChannelState.WAITING); // 默认支付中
if (status.equalsIgnoreCase("COMPLETED")) {
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
} else if (status.equalsIgnoreCase("VOIDED")) {
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
}
result = dispatchCode(status, result); // 处理状态码
return result;
}
}
/**
* 处理 Paypal 状态码
*
* @param status 状态码
* @param channelRetMsg 通知信息
* @return 通知信息
*/
public ChannelRetMsg dispatchCode(String status, ChannelRetMsg channelRetMsg) {
if (status.equalsIgnoreCase("CANCELLED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
} else if (status.equalsIgnoreCase("PENDING")) {
if (status.equalsIgnoreCase("SAVED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} else if (status.equalsIgnoreCase("APPROVED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} else if (status.equalsIgnoreCase("VOIDED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
} else if (status.equalsIgnoreCase("COMPLETED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
} else if (status.equalsIgnoreCase("PAYER_ACTION_REQUIRED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} else if (status.equalsIgnoreCase("CREATED")) {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
} else {
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.UNKNOWN);
}