mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 09:11:52 +08:00
Merge remote-tracking branch 'origin/pay_extension' into pay_extension
This commit is contained in:
commit
38f1d6428f
@ -982,6 +982,7 @@ CREATE TABLE `pay_channel` (
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `pay_channel` VALUES (9, 'wx_pub', 0, NULL, 1, 1, 6, '{\"@class\":\"cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig\",\"appId\":\"wx041349c6f39b268b\",\"mchId\":\"1545083881\",\"apiVersion\":\"v2\",\"mchKey\":\"0alL64UDQdlCwiKZ73ib7ypaIjMns06p\",\"privateKeyContent\":\"-----BEGIN PRIVATE KEY-----\\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5q2hYE3loOQoH\\nl/2kh/epuj17W8VpV5vBl7ysJWAbBXux6mlq4gKTHD0QUQdiKtDEUm/bKC9Bi6VU\\nuklM5Y8oCaCbhjklHRbET8jsgd9phSNGviHclYRLsQRO8oXnN89kN0y7DYKm0hYd\\nmaiS12Z3v8VaImSTr4HVeHlC/z3S6mdwSr263stKt931YTcbTj/QFH7znsv9Na0u\\nX6LaMBEEAsJctWdm8Ndrd1tGh9Fzf0DA5VRXsJR3kkWspy+IwiDTPV/FDKOU9NJC\\nSxMmDePerTfkoZ2s1rltqBK0ykDJrXtxR+hTzEsKZ/KpNi8tyYpfNZsviHIlUsLP\\nFJ5UvUhpAgMBAAECggEAd90NltazqTIxpGdeCwrwOzWNnYbIclJprlhMKIJUgf1P\\nNrPTbHoOGXTAgzkcYCat8iAaMEzH/TOu/3zn92m3uqxEcEL9v1UBLqknWHAbkB6w\\ngGocqDAqYUcdNe5hvbyM+fCta5C0SQgV2PQrHOlMMICwYpkTfzhtxCdreXIYMoGg\\nJEIRkZWgrm/N7LTtNgizznuUjy6OURWjXaWKPcs3b3j6G1gLj9Vp++z4y0u51nqM\\n4R6fcvl8M6BjlcC8zo6DbOvCW8cXtuXsnru+2TPrUnsGeybJok4fEQsfW1BvpvPo\\nief38rYJn4OWxIrHcpWrhNtXtgRPeiMGFfIsEQDmVQKBgQDzXK6Nn3Nr3TFfGVTy\\n8QYrzOuY2NqzH8nnsLL6qn3HoKxTv+PcFKOTPsi6f4hIYCzBP0esRrPv0ffMu9oQ\\nJvFtCJvMmcKGtp0Q5hcj0y/XkbC3AWuahJtBv8lhKXVnQXSL0j3+ombljw4/8yN0\\nAzgBz+j/skQQgZ3sN5h+DHGtgwKBgQDDT784/2pd4m86c/uBmrwYfqu6MJo0eHJh\\n1XPtE+u8pOHyNTFk77rKobKDqN5VlrF0uEmBc/08LKhyxJ3vh/zAbcmqT1Mq778y\\nAKKUtVmvcaVDrvSQHsnhj0zt4SHGmmU34U2b9hV+nocq5VszX6/jp//HJi9bs3We\\ndAzfFCmaowKBgC1MmDVGc+6lCraf+X8LPFHU4Bnga70h8qxM6NPd/nG1R76DHn/t\\n25DiA+0rJgwK0unZxJadxoqic9TJNssA5Lmd+5o3GM2Imm311mLVwbcHqHQ4MHZf\\nrqKrd2m9lNv2hCIurVmDk1Gxsj5XHMdQfhFgSQengCHubp30r07vNA3PAoGAUEAE\\nIjdQTSMs8KeXP7mEb8wcY3R05/pVhT1fVJpK0kgtTofss7yM05V88/v+3sv8Pik6\\niqZN9tuimwWOn00Q3UA/DGtrkMjRlooMQ24AW8YmUZkhg9YivTtUMKnAZwopbLx2\\nVw7V5iDdCRMUVheK/c+ZmQpnixZBzcmBQGfYcGECgYBjEq3Mem+Aw6pXOu6+0FwH\\n9y6Xi4HhBkq0OOZZuXFtWVry7YrD3pBgzWVAZJqJCkyPKKZzCzwdbFd3u0lYBs35\\nzYgx7ug4hR+wfI980a3vxjcWGOqnOUUnUJ7ucIa+KDgnYV/bBy4jqpVreXmWAJXl\\nfyjG3eLWBrtrsI9YX6zeAA==\\n-----END PRIVATE KEY-----\\n\",\"privateCertContent\":\"-----BEGIN CERTIFICATE-----\\nMIID6TCCAtGgAwIBAgIUNkEHq6aQcF80NSYqWS58ybsJzI4wDQYJKoZIhvcNAQEL\\nBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\\nFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\\nQ0EwHhcNMjExMDIxMDU0NTQxWhcNMjYxMDIwMDU0NTQxWjB7MRMwEQYDVQQDDAox\\nNTQ1MDgzODgxMRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xJzAlBgNVBAsM\\nHuWOhuWfjuWMuuWkp+adjuWwp+aXpeeUqOWTgeW6lzELMAkGA1UEBgwCQ04xETAP\\nBgNVBAcMCFNoZW5aaGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\\nuatoWBN5aDkKB5f9pIf3qbo9e1vFaVebwZe8rCVgGwV7seppauICkxw9EFEHYirQ\\nxFJv2ygvQYulVLpJTOWPKAmgm4Y5JR0WxE/I7IHfaYUjRr4h3JWES7EETvKF5zfP\\nZDdMuw2CptIWHZmoktdmd7/FWiJkk6+B1Xh5Qv890upncEq9ut7LSrfd9WE3G04/\\n0BR+857L/TWtLl+i2jARBALCXLVnZvDXa3dbRofRc39AwOVUV7CUd5JFrKcviMIg\\n0z1fxQyjlPTSQksTJg3j3q035KGdrNa5bagStMpAya17cUfoU8xLCmfyqTYvLcmK\\nXzWbL4hyJVLCzxSeVL1IaQIDAQABo4GBMH8wCQYDVR0TBAIwADALBgNVHQ8EBAMC\\nBPAwZQYDVR0fBF4wXDBaoFigVoZUaHR0cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1\\nYmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0NkMw\\nMUMzRThFQkQyMA0GCSqGSIb3DQEBCwUAA4IBAQBe7XgncAY/1PLbCsnMsYt11k3V\\n2cdNZ+yuCxhlOEKk3nHE6WCTL6zL0qWlTKKpnw1rE/+4OS76Tg72wWXcHfHDAOgt\\n9icp62cKx1WO3QweeZpSvLDmtdLgKKrqeIWh+rL8+ZhuAOxSkaRwcsMTWDaLeDOi\\n0pGeqvfG8WNhPxkkaSI8xbiTK641Yg9WT/Q4yfHS7Q6wg1dj9YQdo0dvVB0S2Nir\\nX9IK6PUaHDnQeFKDmKgLkDGLaKaiijEvC91wMEE6qB8b0eNhciaxq2YhGHcFmSRP\\nWUyc5CmBadt7wIOH5Z3bfuwWGxqxKjNw/baM/d+nk7hlDr01YL9c0g16B9MW\\n-----END CERTIFICATE-----\\n\",\"apiV3Key\":\"joerVi8y5DJ3o4ttA0o1uH47Xz1u2Ase\"}', NULL, '2021-10-23 17:12:10', NULL, '2021-10-23 17:12:10', b'0');
|
||||
INSERT INTO `pay_channel` VALUES (10, 'alipay_wap', 0, NULL, 1, 1, 6, '{\"@class\":\"cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig\",\"serverUrl\":\"https://openapi.alipaydev.com/gateway.do\",\"appId\":\"2021000118641792\",\"signType\":\"RSA2\",\"mode\":1,\"privateKey\":\"MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDV+VmQ1FiAG1IOESPpZjDFYqkFptjck3KS8uTKk/QItz8KAKcRhL6X8x2hmIiel9SIWuZjmrBO0sCHRwNpfvbNNeIcFCK7cNf/VXO4vTiokeFb5htuAeKkprWE0NTZYW0L5BIt1ogJxDRhUUQM2JWchJmbMLKl2RU7FSrmsLFwIHq85LueWGyF7zTLvurtEYWv1DflGf7cZqtW0JvWMR4PJVFdbIJ/5KgxQ5j/BJLKwapgfEZWvdsLO2AuQjCYv5yb/SvyRuUV48zAvLcIHaim/qHm5GmnZNynBeovzfBjTmVZrx0HI6S5B0yLOoRes4GBBCQpFXL8Ov9uowHHwpH9AgMBAAECggEAIQteCqDQfhA6DtQU0LGobIM9CRNoQEBBHHKIZMSOll3+TUQmiO0QJhU0iUUuLBfUia5IEC/OdI3Vj86mtz8VTEG7Bo0RhBL8OIFw2qHWQyosPG3/5HBEGRtpwvYhOOTz2zdAm3WbEq8LS9AqCzXTfRV5R18w563runEda/zzmhYRo8INr09G3HYLo83i3LPLAVMi+ndOqxtKamNc3hCehezo/34DleA2/1/giQLhqhzHzEM0KwYPmBRoij3/jnPSZFwe8sXS8PwVX9bmiXtIEluvzwMylsMqMcmL89reFRRiskbVAVV8zWqa/06wjqbSARNTTZYJa6LQ8sjsdGAJvQKBgQD0Ka0Zu77+axgy6AzXvLx0KaC+0iwobr2g8X5R07ZyqoBlPlLUcHC6nRRHIYhZLfEYBFfFpUj8osReKDWJ2euonevGFGr8OxmZe1BX+LPf+9hVWDhTmbD++ZSdgOQMJ9a4BJF4YHkYcCfWwYnsg8ZUlrmeh4+SbkgRp1x0xLswiwKBgQDgWP+YVxQz3AmRQmIAtZbqfiDzOntHJyrJC1tDEX3Q/dA6PopWUYaSqFJuGJYvUW1ycBl2skKYFlxVGQgUB3ZrhuumzINc24XSWMQoNpkewMG54qXfuSA57PzNXmHcvyLL2HQxISCD9yNJul6ecsGnPUWuaDLC16ZF/Q3ChrjQlwKBgGKCAgW02qz49k1rk+riicHwHZt/XjN94mHxrL5ExYJjyeOPDooJR2HzCABexgz83R2MewER222aGdHHNTqFwm9IL5y+Fh/nlD95IgQsIh5HFJPyQN9xzZhBh7U4EEnbNOUPasV/Xrv+XARoF0ZmL/lmykLsfH9eoRMGS+YMjV1bAoGAFttaZxXwG/x+CQufWn0lvAxPpRg/OReXd1Yt3R5qGCHT1itLAtJZiJWXmFnu6zE7ml4rafltaXtVuuHK/edovDnJxnutoodHEhAzI/m0DfsLgbnCtpFw5BXuB6pnBAuBKw2JgPvkCS3jrX5MZ44/hp9qewNosIsyCI1omnoJWE8CgYBUR1L5i1Z9sQdIw8E4MOzbc5uliTX2nJVG65bLc/+Cp3W3YoQw7RK8qiTv8XoOICMJXCBww2roM4HkbwJ3knQbbTiMyksRyLHvDuTg4UdH4pkNDxGsQND9sUd3bR5fayH0Z/QBohuLOFHP/C7WaHPwa4hZBKavibiWhmDtzdmOIw==\",\"alipayPublicKey\":\"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv5w0ByG2xxiw///4NJiynTyjvZOX9Xb1p+A2TMJdOdwx1eWrYHv4mW7rvKfpxD5shZtU1lxzXLT3EGCAnW8f8SVDj+v+UAu3HEaKDgyqO6WA1ZLVSrCLPTb4u1C3ozbKaim88sl9+TxeaNUwuIpWshLDYoseMgRYp/VLUfpMNkueGKczkDkGH/4BY8lj/dsIItLqU9Px4PIpGCztm0vrg7mvH4XlSk5b5ui9uQ05AhS+PHTGrloY9AOrtjQTZmVebEUHf1pVmoofUr0q1TqhS9HQU1XIkxRnxOvmOcscH4rE2qMKajk4dR5rgnuNPRWSj24xwbNf3nSHDTAH7PDogwIDAQAB\",\"appCertContent\":null,\"alipayPublicCertContent\":null,\"rootCertContent\":null}', NULL, '2021-11-02 17:12:10', NULL, '2021-11-02 17:12:10', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -1250,7 +1251,7 @@ CREATE TABLE `pay_order_extension` (
|
||||
`user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户 IP',
|
||||
`status` tinyint NOT NULL COMMENT '支付状态',
|
||||
`channel_extras` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '支付渠道的额外参数',
|
||||
`channel_notify_data` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '支付渠道异步通知的内容',
|
||||
`channel_notify_data` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '支付渠道异步通知的内容',
|
||||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
|
@ -1,9 +1,11 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
@ -46,6 +48,6 @@ public interface PayOrderCoreService {
|
||||
* @param channelCode 渠道编码
|
||||
* @param notifyData 通知数据
|
||||
*/
|
||||
void notifyPayOrder(Long channelId, String channelCode, String notifyData) throws Exception;
|
||||
void notifyPayOrder(Long channelId, String channelCode, NotifyDataDTO notifyData) throws Exception;
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreS
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
|
||||
@ -26,6 +27,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.pay.config.PayProperties;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -135,9 +137,11 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
// 调用三方接口
|
||||
PayOrderUnifiedReqDTO unifiedOrderReqDTO = PayOrderCoreConvert.INSTANCE.convert2(reqDTO);
|
||||
// 商户相关字段
|
||||
//TODO jason @芋艿 是否加一个属性 如tradeNo 支付订单号, 用这个merchantOrderId让人迷糊
|
||||
unifiedOrderReqDTO.setMerchantOrderId(orderExtension.getNo()) // 注意,此处使用的是 PayOrderExtensionDO.no 属性!
|
||||
.setSubject(order.getSubject()).setBody(order.getBody())
|
||||
.setNotifyUrl(genChannelPayNotifyUrl(channel));
|
||||
.setNotifyUrl(genChannelPayNotifyUrl(channel))
|
||||
.setReturnUrl(genChannelReturnUrl(channel));
|
||||
// 订单相关字段
|
||||
unifiedOrderReqDTO.setAmount(order.getAmount()).setExpireTime(order.getExpireTime());
|
||||
CommonResult<?> unifiedOrderResult = client.unifiedOrder(unifiedOrderReqDTO);
|
||||
@ -149,6 +153,16 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
.setInvokeResponse(unifiedOrderResult.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据支付渠道的编码,生成支付渠道的返回地址
|
||||
* @param channel
|
||||
* @return
|
||||
*/
|
||||
private String genChannelReturnUrl(PayChannelDO channel) {
|
||||
return payProperties.getReturnUrl() + "/" + StrUtil.replace(channel.getCode(), "_", "-")
|
||||
+ "/" + channel.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据支付渠道的编码,生成支付渠道的回调地址
|
||||
*
|
||||
@ -181,9 +195,9 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void notifyPayOrder(Long channelId, String channelCode, String notifyData) throws Exception {
|
||||
public void notifyPayOrder(Long channelId, String channelCode, NotifyDataDTO notifyData) throws Exception {
|
||||
// TODO 芋艿,记录回调日志
|
||||
log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData);
|
||||
log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData.getOrigData());
|
||||
|
||||
// 校验支付渠道是否有效
|
||||
PayChannelDO channel = payChannelCoreService.validPayChannel(channelId);
|
||||
@ -193,6 +207,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
|
||||
throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
|
||||
}
|
||||
//TODO @jason 校验 是否支付宝调用。 使用 支付宝publickey 或者payclient 加一个校验方法
|
||||
// 解析支付结果
|
||||
PayOrderNotifyRespDTO notifyRespDTO = client.parseOrderNotify(notifyData);
|
||||
|
||||
@ -207,9 +222,10 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
// 1.2 更新 PayOrderExtensionDO
|
||||
//TODO @jason notifyRespDTO.getTradeStatus() 需要根据不同的状态更新成不同的值 PayOrderStatusEnum
|
||||
int updateCounts = payOrderExtensionCoreMapper.updateByIdAndStatus(orderExtension.getId(),
|
||||
PayOrderStatusEnum.WAITING.getStatus(), PayOrderExtensionDO.builder().id(orderExtension.getId())
|
||||
.status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(notifyData).build());
|
||||
.status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(notifyData.getOrigData()).build());
|
||||
if (updateCounts == 0) { // 校验状态,必须是待支付
|
||||
throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
|
@ -6,8 +6,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.Duration;
|
||||
|
||||
@ConfigurationProperties(prefix = "yudao.pay")
|
||||
@Validated
|
||||
@ -25,8 +23,15 @@ public class PayProperties {
|
||||
* 退款回调地址
|
||||
* 注意点,同 {@link #payNotifyUrl} 属性
|
||||
*/
|
||||
@NotNull(message = "短信发送频率不能为空")
|
||||
@NotEmpty(message = "短信发送频率不能为空")
|
||||
@URL(message = "退款回调地址的格式必须是 URL")
|
||||
private String refundNotifyUrl;
|
||||
|
||||
// TODO @jason:改成 payReturnUrl 。另外,可以加个 @NotEmpty,避免未填写
|
||||
/**
|
||||
* 支付完成的返回地址
|
||||
*/
|
||||
@URL(message = "支付返回的地址的格式必须是 URL")
|
||||
private String returnUrl;
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.framework.pay.core.client;
|
||||
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
||||
|
||||
@ -32,6 +33,6 @@ public interface PayClient {
|
||||
* @return 解析结果
|
||||
* @throws Exception 解析失败,抛出异常
|
||||
*/
|
||||
PayOrderNotifyRespDTO parseOrderNotify(String data) throws Exception;
|
||||
PayOrderNotifyRespDTO parseOrderNotify(NotifyDataDTO data) throws Exception;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.framework.pay.core.client.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
// TODO @jason:NotifyDataDTO=》PayNotifyDataDTO。另外注释记得加起来哈
|
||||
@Data
|
||||
@ToString
|
||||
@Builder
|
||||
public class NotifyDataDTO {
|
||||
|
||||
// TODO @jason:这个字段,改成 body
|
||||
private String origData;
|
||||
// TODO @jason:这个字段如果暂时没用,可以去掉。
|
||||
//1:xml 2:form
|
||||
private int format;
|
||||
|
||||
//form 格式的 data;
|
||||
private Map<String,String> params;
|
||||
}
|
@ -42,4 +42,14 @@ public class PayOrderNotifyRespDTO {
|
||||
*/
|
||||
private String data;
|
||||
|
||||
|
||||
/**
|
||||
* TODO @jason 结合其他的渠道定义成枚举,
|
||||
* alipay
|
||||
* TRADE_CLOSED,未付款交易超时关闭,或支付完成后全额退款。
|
||||
* TRADE_SUCCESS, 交易支付成功
|
||||
* TRADE_FINISHED 交易结束,不可退款。
|
||||
*/
|
||||
private String tradeStatus;
|
||||
|
||||
}
|
||||
|
@ -44,11 +44,16 @@ public class PayOrderUnifiedReqDTO {
|
||||
@Length(max = 128, message = "商品描述信息长度不能超过128")
|
||||
private String body;
|
||||
/**
|
||||
* 支付结果的回调地址
|
||||
* 支付结果的 notify 回调地址
|
||||
*/
|
||||
@NotEmpty(message = "支付结果的回调地址不能为空")
|
||||
@URL(message = "支付结果的回调地址必须是 URL 格式")
|
||||
@URL(message = "支付结果的 notify 回调地址必须是 URL 格式")
|
||||
private String notifyUrl;
|
||||
/**
|
||||
* 支付结果的 return 回调地址
|
||||
*/
|
||||
@URL(message = "支付结果的 return 回调地址必须是 URL 格式")
|
||||
private String returnUrl;
|
||||
|
||||
// ========== 订单相关字段 ==========
|
||||
|
||||
|
@ -18,6 +18,10 @@ public class AlipayPayCodeMapping extends AbstractPayCodeMapping {
|
||||
if (Objects.equals(apiCode, "10000")) {
|
||||
return GlobalErrorCodeConstants.SUCCESS;
|
||||
}
|
||||
// alipay wap api code 返回为null, 暂时定为-9999
|
||||
if(Objects.equals(apiCode, "-9999")){ // TODO @jason:空格要注意哈。if () {
|
||||
return GlobalErrorCodeConstants.SUCCESS;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
|
||||
@ -68,7 +69,7 @@ public class AlipayQrPayClient extends AbstractPayClient<AlipayPayClientConfig>
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayOrderNotifyRespDTO parseOrderNotify(String data) throws Exception {
|
||||
public PayOrderNotifyRespDTO parseOrderNotify(NotifyDataDTO data) throws Exception {
|
||||
// TODO 芋艿:待完成
|
||||
return null;
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
|
||||
@ -14,6 +16,9 @@ import com.alipay.api.request.AlipayTradeWapPayRequest;
|
||||
import com.alipay.api.response.AlipayTradeWapPayResponse;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 支付宝【手机网站】的 PayClient 实现类
|
||||
* 文档:https://opendocs.alipay.com/apis/api_1/alipay.trade.wap.pay
|
||||
@ -45,12 +50,16 @@ public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig>
|
||||
model.setBody(reqDTO.getBody());
|
||||
model.setTotalAmount(calculateAmount(reqDTO.getAmount()).toString());
|
||||
model.setProductCode("QUICK_WAP_PAY"); // TODO 芋艿:这里咋整
|
||||
model.setSellerId("2088102147948060"); // TODO 芋艿:这里咋整
|
||||
// TODO 芋艿:userIp + expireTime
|
||||
//TODO 芋艿:这里咋整 jason @芋艿 可以去掉吧,
|
||||
// TODO @jason: 这个支付方式,需要有 sellerId 么?
|
||||
//model.setSellerId("2088102147948060");
|
||||
model.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(),"yyyy-MM-dd HH:mm:ss"));
|
||||
// TODO 芋艿:userIp
|
||||
// 构建 AlipayTradeWapPayRequest
|
||||
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
|
||||
request.setBizModel(model);
|
||||
|
||||
request.setNotifyUrl(reqDTO.getNotifyUrl());
|
||||
request.setReturnUrl(reqDTO.getReturnUrl());
|
||||
// 执行请求
|
||||
AlipayTradeWapPayResponse response;
|
||||
try {
|
||||
@ -58,13 +67,31 @@ public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig>
|
||||
} catch (AlipayApiException e) {
|
||||
return PayCommonResult.build(e.getErrCode(), e.getErrMsg(), null, codeMapping);
|
||||
}
|
||||
|
||||
// TODO 芋艿:sub Code
|
||||
if(response.isSuccess() && Objects.isNull(response.getCode()) && Objects.nonNull(response.getBody())){
|
||||
//成功alipay wap 成功 code 为 null , body 为form 表单
|
||||
return PayCommonResult.build("-9999", "Success", response, codeMapping);
|
||||
}else {
|
||||
return PayCommonResult.build(response.getCode(), response.getMsg(), response, codeMapping);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO @jason: 注释记得补下哈
|
||||
/**
|
||||
* //https://opendocs.alipay.com/open/203/105286
|
||||
* @param data 通知结果
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public PayOrderNotifyRespDTO parseOrderNotify(String data) throws Exception {
|
||||
// TODO 芋艿:待完成
|
||||
return null;
|
||||
public PayOrderNotifyRespDTO parseOrderNotify(NotifyDataDTO data) throws Exception {
|
||||
Map<String, String> params = data.getParams();
|
||||
return PayOrderNotifyRespDTO.builder().orderExtensionNo(params.get("out_trade_no"))
|
||||
.channelOrderNo(params.get("trade_no")).channelUserId(params.get("seller_id"))
|
||||
.tradeStatus(params.get("trade_status"))
|
||||
.successTime(DateUtil.parse(params.get("notify_time"), "yyyy-MM-dd HH:mm:ss"))
|
||||
.data(data.getOrigData()).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
|
||||
@ -131,14 +132,14 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayOrderNotifyRespDTO parseOrderNotify(String data) throws WxPayException {
|
||||
WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data);
|
||||
public PayOrderNotifyRespDTO parseOrderNotify(NotifyDataDTO data) throws WxPayException {
|
||||
WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getOrigData());
|
||||
Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS");
|
||||
// 转换结果
|
||||
return PayOrderNotifyRespDTO.builder().orderExtensionNo(notifyResult.getOutTradeNo())
|
||||
.channelOrderNo(notifyResult.getTransactionId()).channelUserId(notifyResult.getOpenid())
|
||||
.successTime(DateUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss"))
|
||||
.data(data).build();
|
||||
.data(data.getOrigData()).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,17 +6,21 @@ import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreServic
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||
import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitReqVO;
|
||||
import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitRespVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||
|
||||
@ -54,7 +58,7 @@ public class PayOrderController {
|
||||
@ApiOperation("通知微信公众号支付的结果")
|
||||
public String notifyWxPayOrder(@PathVariable("channelId") Long channelId,
|
||||
@RequestBody String xmlData) throws Exception {
|
||||
payOrderCoreService.notifyPayOrder(channelId, PayChannelEnum.WX_PUB.getCode(), xmlData);
|
||||
payOrderCoreService.notifyPayOrder(channelId, PayChannelEnum.WX_PUB.getCode(), NotifyDataDTO.builder().origData(xmlData).build());
|
||||
return "success";
|
||||
}
|
||||
|
||||
@ -72,4 +76,28 @@ public class PayOrderController {
|
||||
return "success";
|
||||
}
|
||||
|
||||
@PostMapping(value = "/notify/alipay-wap/{channelId}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
@ApiOperation("支付宝wap页面回调")
|
||||
public String notifyAliPayWapPayOrder(@PathVariable("channelId") Long channelId,
|
||||
@RequestParam Map<String, String> params,
|
||||
@RequestBody String originData) throws Exception {
|
||||
//TODO @jason 校验 是否支付宝调用。 使用 支付宝publickey payclient 或许加一个校验方法
|
||||
payOrderCoreService.notifyPayOrder(channelId, PayChannelEnum.ALIPAY_WAP.getCode(), NotifyDataDTO.builder().params(params).origData(originData).build());
|
||||
return "success";
|
||||
}
|
||||
|
||||
// TODO @jason 如果有些字段不注释,可以删除哈。不然 IDEA 会报警
|
||||
/**
|
||||
* https://opendocs.alipay.com/open/203/105285#%E5%89%8D%E5%8F%B0%E5%9B%9E%E8%B7%B3%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E
|
||||
* @param channelId
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@GetMapping(value = "/return/alipay-wap/{channelId}")
|
||||
@ApiOperation("支付宝wap页面回跳")
|
||||
public String returnAliPayWapPayOrder(@PathVariable("channelId") Long channelId){
|
||||
//TODO @jason 校验 是否支付宝调用。 支付宝publickey 可以根据 appId 跳转不同的页面
|
||||
return "支付成功";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -153,5 +153,6 @@ yudao:
|
||||
- ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
|
||||
demo: false # 关闭演示模式
|
||||
pay:
|
||||
pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify
|
||||
refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify
|
||||
pay-notify-url: http://jg6rde.natappfree.cc/api/pay/order/notify
|
||||
refund-notify-url: http://jg6rde.natappfree.cc/api/pay/refund/notify
|
||||
return-url: http://jg6rde.natappfree.cc/api/pay/order/return
|
||||
|
@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
|
||||
<title>支付测试页</title>
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div>点击如下按钮,发起支付的测试</div>
|
||||
<div>
|
||||
<button id="alipay_wap">支付宝h5</button>
|
||||
</div>
|
||||
<div id="dynamic_form"></div>
|
||||
</body>
|
||||
<script>
|
||||
// TODO @jason:copy 过来后,有些注释要改过来哈
|
||||
let shopOrderId = undefined;
|
||||
let payOrderId = undefined;
|
||||
let server = 'http://127.0.0.1:28080';
|
||||
//let server = 'http://niubi.natapp1.cc';
|
||||
// TODO openid
|
||||
//let openid = "ockUAwIZ-0OeMZl9ogcZ4ILrGba0";
|
||||
$(function() {
|
||||
// 自动发起商城订单编号
|
||||
$.ajax({
|
||||
url: server + "/api/shop/order/create",
|
||||
method: 'POST',
|
||||
success: function( result ) {
|
||||
if (result.code !== 0) {
|
||||
alert('创建商城订单失败,原因:' + result.msg)
|
||||
return;
|
||||
}
|
||||
shopOrderId = result.data.id;
|
||||
payOrderId = result.data.payOrderId;
|
||||
console.log("商城订单:" + shopOrderId)
|
||||
console.log("支付订单:" + payOrderId)
|
||||
}
|
||||
})
|
||||
});
|
||||
// 微信公众号
|
||||
$( "#alipay_wap").on( "click", function() {
|
||||
// 提交支付
|
||||
$.ajax({
|
||||
url: server + "/api/pay/order/submit",
|
||||
method: 'POST',
|
||||
dataType: "json",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
"id": payOrderId,
|
||||
"channelCode": 'alipay_wap'
|
||||
}),
|
||||
success: function( result ) {
|
||||
if (result.code !== 0) {
|
||||
alert('提交支付订单失败,原因:' + result.msg)
|
||||
return;
|
||||
}
|
||||
alert('点击确定,开始支付');
|
||||
// 开始调用微信支付
|
||||
let data = result.data.invokeResponse;
|
||||
$("#dynamic_form").html(data.body);
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user