diff --git a/server/like-common/pom.xml b/server/like-common/pom.xml index a6698199..a17e3467 100644 --- a/server/like-common/pom.xml +++ b/server/like-common/pom.xml @@ -119,7 +119,11 @@ com.alibaba.fastjson2 fastjson2 - + + com.alipay.sdk + alipay-sdk-java + 4.38.72.ALL + com.google.code.gson diff --git a/server/like-common/src/main/java/com/mdd/common/config/AlipayConfig.java b/server/like-common/src/main/java/com/mdd/common/config/AlipayConfig.java new file mode 100644 index 00000000..99032a0f --- /dev/null +++ b/server/like-common/src/main/java/com/mdd/common/config/AlipayConfig.java @@ -0,0 +1,26 @@ +package com.mdd.common.config; + +public class AlipayConfig +{ + + // 支付宝网关 + public static String GATEWAY_URL = "https://openapi.alipay.com/gateway.do"; + public static String GATEWAY_URL_DEBUG = "https://openapi-sandbox.dl.alipaydev.com/gateway.do"; + // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号 + public static String APP_ID = ""; + // 商户私钥,您的PKCS8格式RSA2私钥 + public static String MERCHANT_PRIVATE_KEY = ""; + // https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。 + public static String ALIPAY_PUBLIC_KEY = ""; + // 服务器异步通知页面路径 需http://格式的完整路径,由自己系统开发实现 + public static String NOTIFY_URL = ""; + + // 页面跳转同步通知页面路径 需http://格式的完整路径,由自己系统开发实现 + public static String RETURN_URL = ""; + + // 签名方式 + public static String SIGN_TYPE = "RSA2"; + + // 字符编码格式 + public static String CHARSET = "utf-8"; +} diff --git a/server/like-common/src/main/java/com/mdd/common/config/wechat/WxMnpConfiguration.java b/server/like-common/src/main/java/com/mdd/common/config/wechat/WxMnpConfiguration.java index 94dc1115..d6309492 100644 --- a/server/like-common/src/main/java/com/mdd/common/config/wechat/WxMnpConfiguration.java +++ b/server/like-common/src/main/java/com/mdd/common/config/wechat/WxMnpConfiguration.java @@ -61,13 +61,13 @@ public class WxMnpConfiguration { @Bean @ConditionalOnMissingBean public WxMpService wxOaService() { - Map config = this.getChannelConfig("oa_channel"); + Map config = this.getChannelConfig("oa_setting"); WxMpDefaultConfigImpl wxMpDefaultConfig = new WxMpDefaultConfigImpl(); - wxMpDefaultConfig.setAppId(config.getOrDefault("appId", "").trim()); - wxMpDefaultConfig.setSecret(config.getOrDefault("appSecret", "").trim()); + wxMpDefaultConfig.setAppId(config.getOrDefault("app_id", "").trim()); + wxMpDefaultConfig.setSecret(config.getOrDefault("app_secret", "").trim()); wxMpDefaultConfig.setToken(config.getOrDefault("token", "").trim()); - wxMpDefaultConfig.setAesKey(config.getOrDefault("encodingAesKey", "").trim()); + wxMpDefaultConfig.setAesKey(config.getOrDefault("encoding_aes_key", "").trim()); WxMpService wxService = new WxMpServiceImpl(); wxService.setWxMpConfigStorage(wxMpDefaultConfig); diff --git a/server/like-common/src/main/java/com/mdd/common/config/wechat/WxPayConfiguration.java b/server/like-common/src/main/java/com/mdd/common/config/wechat/WxPayConfiguration.java index 24b61deb..1cd132ef 100644 --- a/server/like-common/src/main/java/com/mdd/common/config/wechat/WxPayConfiguration.java +++ b/server/like-common/src/main/java/com/mdd/common/config/wechat/WxPayConfiguration.java @@ -85,8 +85,8 @@ public class WxPayConfiguration { .last("limit 1")); Config systemConfig = systemConfigMapper.selectOne(new QueryWrapper() - .eq("name", "appId") - .eq("type", "oa_channel") + .eq("name", "app_id") + .eq("type", "oa_setting") .last("limit 1")); String paramJson = StringUtils.isNull(config.getConfig()) ? "{}" : config.getConfig().toString(); diff --git a/server/like-common/src/main/java/com/mdd/common/enums/AccountLogEnum.java b/server/like-common/src/main/java/com/mdd/common/enums/AccountLogEnum.java index 7c55ed82..5c5e2d58 100644 --- a/server/like-common/src/main/java/com/mdd/common/enums/AccountLogEnum.java +++ b/server/like-common/src/main/java/com/mdd/common/enums/AccountLogEnum.java @@ -59,6 +59,21 @@ public enum AccountLogEnum { return ret.getString(String.valueOf(changeType)); } + /** + * @notes 获取变动对象 + * @param changeType + * @return false + * @author damonyuan + */ + public static Integer getChangeObject(Integer changeType) { + List typeList = getUserMoneyChangeType(); + if (typeList.contains(changeType)) { + return UM.getCode(); + } else { + return 0; + } + } + /** * 获取状态码 * diff --git a/server/like-common/src/main/java/com/mdd/common/mapper/log/UserAccountLogMapper.java b/server/like-common/src/main/java/com/mdd/common/mapper/log/UserAccountLogMapper.java index 169b4cbe..8712a2fc 100644 --- a/server/like-common/src/main/java/com/mdd/common/mapper/log/UserAccountLogMapper.java +++ b/server/like-common/src/main/java/com/mdd/common/mapper/log/UserAccountLogMapper.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.mdd.common.core.basics.IBaseMapper; import com.mdd.common.entity.log.UserAccountLog; import com.mdd.common.entity.user.User; +import com.mdd.common.enums.AccountLogEnum; import com.mdd.common.mapper.user.UserMapper; import com.mdd.common.util.SpringUtils; import com.mdd.common.util.StringUtils; @@ -40,11 +41,14 @@ public interface UserAccountLogMapper extends IBaseMapper { break; } + Integer changeObject = AccountLogEnum.getChangeObject(changeType); + BigDecimal leftAmount = user.getUserMoney().add(changeAmount); UserAccountLog logMoney = new UserAccountLog(); logMoney.setSn(this.randMakeOrderSn()); logMoney.setUserId(userId); logMoney.setSourceSn(sourceSn); + logMoney.setChangeObject(changeObject); logMoney.setChangeType(changeType); logMoney.setChangeAmount(changeAmount); logMoney.setLeftAmount(leftAmount); diff --git a/server/like-common/src/main/java/com/mdd/common/plugin/wechat/WxMnpDriver.java b/server/like-common/src/main/java/com/mdd/common/plugin/wechat/WxMnpDriver.java index d1b22db0..4bfdbdd7 100644 --- a/server/like-common/src/main/java/com/mdd/common/plugin/wechat/WxMnpDriver.java +++ b/server/like-common/src/main/java/com/mdd/common/plugin/wechat/WxMnpDriver.java @@ -65,13 +65,13 @@ public class WxMnpDriver { * @return WxMpService */ public static WxMpService oa() { - Map config = ConfigUtils.get("oa_channel"); + Map config = ConfigUtils.get("oa_setting"); WxMpDefaultConfigImpl wxMpDefaultConfig = new WxMpDefaultConfigImpl(); - wxMpDefaultConfig.setAppId(config.getOrDefault("appId", "").trim()); - wxMpDefaultConfig.setSecret(config.getOrDefault("appSecret", "").trim()); + wxMpDefaultConfig.setAppId(config.getOrDefault("app_id", "").trim()); + wxMpDefaultConfig.setSecret(config.getOrDefault("app_secret", "").trim()); wxMpDefaultConfig.setToken(config.getOrDefault("token", "").trim()); - wxMpDefaultConfig.setAesKey(config.getOrDefault("encodingAesKey", "").trim()); + wxMpDefaultConfig.setAesKey(config.getOrDefault("encoding_aes_key", "").trim()); wxMpService.setWxMpConfigStorage(wxMpDefaultConfig); return wxMpService; diff --git a/server/like-common/src/main/java/com/mdd/common/plugin/wechat/WxPayDriver.java b/server/like-common/src/main/java/com/mdd/common/plugin/wechat/WxPayDriver.java index 2dc475fc..75afd401 100644 --- a/server/like-common/src/main/java/com/mdd/common/plugin/wechat/WxPayDriver.java +++ b/server/like-common/src/main/java/com/mdd/common/plugin/wechat/WxPayDriver.java @@ -161,14 +161,14 @@ public class WxPayDriver { .eq("pay_way", 2) .last("limit 1")); - String scene = type.equals("oa") ? "oa_channel" : "mp_channel"; - String appId = ConfigUtils.get(scene, "appId", ""); + String scene = type.equals("oa") ? "oa_setting" : "mnp_setting"; + String appId = ConfigUtils.get(scene, "app_id", ""); Map params = MapUtils.jsonToMap(config.getConfig().toString()); String mchId = params.get("mch_id"); String paySignKey = params.get("pay_sign_key"); - byte[] privateCert = params.getOrDefault("private_cert", "").getBytes(); - byte[] privateKey = params.getOrDefault("private_key", "").getBytes(); + byte[] privateCert = params.getOrDefault("apiclient_cert", "").getBytes(); + byte[] privateKey = params.getOrDefault("apiclient_key", "").getBytes(); WxPayConfig payConfig = new WxPayConfig(); payConfig.setAppId(appId); diff --git a/server/like-common/src/main/java/com/mdd/common/util/ConfigUtils.java b/server/like-common/src/main/java/com/mdd/common/util/ConfigUtils.java index 0766c1e3..bbc4597c 100644 --- a/server/like-common/src/main/java/com/mdd/common/util/ConfigUtils.java +++ b/server/like-common/src/main/java/com/mdd/common/util/ConfigUtils.java @@ -1,9 +1,13 @@ package com.mdd.common.util; +import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.mdd.common.cache.ConfigCache; import com.mdd.common.entity.Config; +import com.mdd.common.entity.setting.DevPayConfig; +import com.mdd.common.enums.PaymentEnum; import com.mdd.common.mapper.ConfigMapper; +import com.mdd.common.mapper.setting.DevPayConfigMapper; import java.util.LinkedHashMap; import java.util.List; @@ -163,4 +167,18 @@ public class ConfigUtils { ConfigCache.set(); } + //返回支付宝配置信息 + public static String getAliDevPay(String field) { + DevPayConfigMapper model = SpringUtils.getBean(DevPayConfigMapper.class); + DevPayConfig devPay = model.selectOne( + new QueryWrapper() + .eq("way", PaymentEnum.ALI_PAY.getCode())); + if (StringUtils.isNull(devPay)) { + return ""; + } else { + JSONObject jsonObject = JSONObject.parseObject(devPay.getConfig().toString()); + return StringUtils.isNull(jsonObject.getString(field)) ? "" : jsonObject.getString(field); + } + + } } diff --git a/server/like-common/src/main/java/com/mdd/common/util/UrlUtils.java b/server/like-common/src/main/java/com/mdd/common/util/UrlUtils.java index 27d56549..9162a54c 100644 --- a/server/like-common/src/main/java/com/mdd/common/util/UrlUtils.java +++ b/server/like-common/src/main/java/com/mdd/common/util/UrlUtils.java @@ -100,4 +100,26 @@ public class UrlUtils { return ""; } + /** + * 获取域名 + * 示例: https://127.0.0.1/ + * + * @author fzr + * @return String + */ + public static String localDomain(String url){ + return RequestUtils.uri() + url; + } + + /** + * 为了避免负载均衡而导致的域名失效,增加该方法 + * @return + */ + public static String getRequestUrl() { + if (StringUtils.isNull(YmlUtils.get("like.url"))) { + return RequestUtils.uri(); + } else { + return YmlUtils.get("like.url"); + } + } } diff --git a/server/like-front/src/main/java/com/mdd/front/controller/PayController.java b/server/like-front/src/main/java/com/mdd/front/controller/PayController.java index 25de8edf..64f94ae1 100644 --- a/server/like-front/src/main/java/com/mdd/front/controller/PayController.java +++ b/server/like-front/src/main/java/com/mdd/front/controller/PayController.java @@ -12,6 +12,7 @@ import com.mdd.common.enums.PaymentEnum; import com.mdd.common.exception.OperateException; import com.mdd.common.mapper.RechargeOrderMapper; import com.mdd.common.plugin.wechat.WxPayDriver; +import com.mdd.common.util.StringUtils; import com.mdd.front.LikeFrontThreadLocal; import com.mdd.front.service.IPayService; import com.mdd.front.validate.PaymentValidate; @@ -60,10 +61,14 @@ public class PayController { @ApiOperation("发起支付") public AjaxResult prepay(@Validated @RequestBody PaymentValidate requestObj) { // 接收参数 + if (StringUtils.isNull(requestObj.getScene())) { + requestObj.setScene("recharge"); + } String scene = requestObj.getScene(); Integer payWay = requestObj.getPayWay(); Integer orderId = requestObj.getOrderId(); Integer terminal = LikeFrontThreadLocal.getTerminal(); + requestObj.setTerminal(terminal); // 订单处理 int payStatus = 0; diff --git a/server/like-front/src/main/java/com/mdd/front/service/IPayService.java b/server/like-front/src/main/java/com/mdd/front/service/IPayService.java index 0e46b682..32a26c88 100644 --- a/server/like-front/src/main/java/com/mdd/front/service/IPayService.java +++ b/server/like-front/src/main/java/com/mdd/front/service/IPayService.java @@ -1,5 +1,7 @@ package com.mdd.front.service; +import com.alibaba.fastjson2.JSONObject; +import com.alipay.api.AlipayApiException; import com.github.binarywang.wxpay.exception.WxPayException; import com.mdd.front.validate.PaymentValidate; import com.mdd.front.vo.pay.PayStatusVo; @@ -52,4 +54,6 @@ public interface IPayService { */ void handlePaidNotify(String attach, String outTradeNo, String transactionId) throws WxPayException; + JSONObject createAliH5Order(PaymentValidate params) throws AlipayApiException; + } diff --git a/server/like-front/src/main/java/com/mdd/front/service/impl/PayServiceImpl.java b/server/like-front/src/main/java/com/mdd/front/service/impl/PayServiceImpl.java index 8b84c579..912e0252 100644 --- a/server/like-front/src/main/java/com/mdd/front/service/impl/PayServiceImpl.java +++ b/server/like-front/src/main/java/com/mdd/front/service/impl/PayServiceImpl.java @@ -1,6 +1,13 @@ package com.mdd.front.service.impl; +import com.alibaba.fastjson2.JSONObject; +import com.alipay.api.AlipayApiException; +import com.alipay.api.AlipayClient; +import com.alipay.api.DefaultAlipayClient; +import com.alipay.api.request.AlipayTradePagePayRequest; +import com.alipay.api.request.AlipayTradeWapPayRequest; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.mdd.common.config.AlipayConfig; import com.mdd.common.entity.RechargeOrder; import com.mdd.common.entity.setting.DevPayConfig; import com.mdd.common.entity.setting.DevPayWay; @@ -27,11 +34,13 @@ import com.mdd.front.vo.pay.PayStatusVo; import com.mdd.front.vo.pay.PayWayInfoVo; import com.mdd.front.vo.pay.PayWayListVo; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import javax.annotation.Resource; +import java.math.BigDecimal; import java.util.*; @Slf4j @@ -55,6 +64,8 @@ public class PayServiceImpl implements IPayService { @Resource UserAccountLogMapper logMoneyMapper; + @Value("${ali.pay.order-notify-url}") + private String aliPayNotifyUrl; /** * 支付方式 @@ -180,13 +191,15 @@ public class PayServiceImpl implements IPayService { requestV3.setDescription(params.getDescription()); Object result = WxPayDriver.unifiedOrder(requestV3); if (terminal == ClientEnum.H5.getCode()) { - Assert.notNull(params.getRedirectUrl(), "redirectUrl参数缺失"); + Assert.notNull(params.getRedirect(), "redirectUrl参数缺失"); Map map = new LinkedHashMap<>(); String h5Url = result.toString(); map.put("url", h5Url); return map; } return WxPayDriver.unifiedOrder(requestV3); + case 3: //支付宝 + return this.createAliH5Order(params); } } catch (Exception e) { throw new PaymentException(e.getMessage()); @@ -215,6 +228,89 @@ public class PayServiceImpl implements IPayService { } } + @Override + public JSONObject createAliH5Order(PaymentValidate params) throws AlipayApiException { + JSONObject ret = new JSONObject(); + // 订单编号 + String orderSn = ""; + // 订单状态 + Integer orderStatus = 0; + // 订单金额 + BigDecimal orderAmount = BigDecimal.ZERO; + Long orderId = 0L; + String payReturnUrl = ""; + switch (params.getScene()){ + case "member": + break; + case "recharge": + RechargeOrder rechargeOrder = rechargeOrderMapper.selectOne(new QueryWrapper() + .eq("id", params.getOrderId()) + .eq("pay_status", PaymentEnum.UN_PAID.getCode()) + .eq("user_id", params.getUserId()) + .last("limit 1")); + orderSn = rechargeOrder.getSn(); + orderStatus = rechargeOrder.getPayStatus(); + orderAmount = rechargeOrder.getOrderAmount(); + orderId = Long.valueOf(rechargeOrder.getId()); + payReturnUrl = UrlUtils.localDomain(params.getRedirect()); + Assert.notNull(rechargeOrder, "订单不存在"); + break; + default: + throw new OperateException("不支持当前订单类型"); + } + + Assert.isTrue(orderStatus != null && orderStatus == PaymentEnum.UN_PAID.getCode(), "订单非待支付状态,不能创建支付单"); + + String gateWay = StringUtils.isNotNull(YmlUtils.get("like.alidebug")) && YmlUtils.get("like.alidebug").equals("true") ? AlipayConfig.GATEWAY_URL_DEBUG : AlipayConfig.GATEWAY_URL; + AlipayClient alipayClient = new DefaultAlipayClient(gateWay, ConfigUtils.getAliDevPay("app_id"), ConfigUtils.getAliDevPay("private_key"), "json", AlipayConfig.CHARSET, ConfigUtils.getAliDevPay("ali_public_key"), AlipayConfig.SIGN_TYPE); + //2、封装 Request + String form = ""; + JSONObject bizContent = new JSONObject(); + bizContent.put("out_trade_no", orderSn); + bizContent.put("total_amount", orderAmount); + bizContent.put("subject", params.getDescription()); + bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY"); + bizContent.put("app_pay", "Y"); + bizContent.put("passback_params", JSONObject.toJSONString(new JSONObject(){{ + put("from", params.getScene()); + }})); + if (params.getTerminal().equals(ClientEnum.H5.getCode())) { + AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest(); + + //alipayRequest.setNotifyUrl("hhttp://bq93pv.natappfree.cc" + aliPayNotifyUrl); + alipayRequest.setNotifyUrl(UrlUtils.getRequestUrl() + aliPayNotifyUrl); + + alipayRequest.setReturnUrl(payReturnUrl); + alipayRequest.setBizContent(bizContent.toString()); + + try { + form = alipayClient.pageExecute(alipayRequest).getBody(); + ret.put("config", form); + ret.put("pay_way", params.getPayWay()); + return ret; + } catch (Exception e) { + throw new PaymentException(e.getMessage()); + //throw new OperateException(e.getMessage()); + + } + } else { + AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); + //alipayRequest.setNotifyUrl("http://bq93pv.natappfree.cc" + aliPayNotifyUrl); + alipayRequest.setNotifyUrl(UrlUtils.getRequestUrl() + aliPayNotifyUrl); + alipayRequest.setReturnUrl(payReturnUrl); + alipayRequest.setBizContent(bizContent.toString()); + + try { + form = alipayClient.pageExecute(alipayRequest).getBody(); + ret.put("config", form); + ret.put("pay_way", params.getPayWay()); + return ret; + } catch (Exception e) { + throw new PaymentException(e.getMessage()); + } + } + } + /** * 余额充值回调 * @@ -226,7 +322,7 @@ public class PayServiceImpl implements IPayService { for (int i=0; i<=0; i++) { RechargeOrder rechargeOrder = rechargeOrderMapper.selectOne( new QueryWrapper() - .eq("order_sn", outTradeNo) + .eq("sn", outTradeNo).isNull("delete_time") .last("limit 1")); if (StringUtils.isNull(rechargeOrder)) { diff --git a/server/like-front/src/main/java/com/mdd/front/service/impl/WechatServiceImpl.java b/server/like-front/src/main/java/com/mdd/front/service/impl/WechatServiceImpl.java index 28ac7d1f..cb50ce93 100644 --- a/server/like-front/src/main/java/com/mdd/front/service/impl/WechatServiceImpl.java +++ b/server/like-front/src/main/java/com/mdd/front/service/impl/WechatServiceImpl.java @@ -12,7 +12,7 @@ public class WechatServiceImpl implements IWechatService { @Override public Map jsConfig(String url) throws Exception { - String appId = ConfigUtils.get("oa_channel", "appId"); + String appId = ConfigUtils.get("oa_setting", "app_id"); String accessToken = WxMnpDriver.mnp().getAccessToken(); String jsapiTicket = WxMnpDriver.getJsSdkGetTicket(accessToken); String timestamp = Long.toString(System.currentTimeMillis() / 1000); diff --git a/server/like-front/src/main/java/com/mdd/front/validate/PaymentValidate.java b/server/like-front/src/main/java/com/mdd/front/validate/PaymentValidate.java index 292ad037..15e45753 100644 --- a/server/like-front/src/main/java/com/mdd/front/validate/PaymentValidate.java +++ b/server/like-front/src/main/java/com/mdd/front/validate/PaymentValidate.java @@ -14,7 +14,7 @@ public class PaymentValidate implements Serializable { private static final long serialVersionUID = 1L; - @NotNull(message = "scene参数缺失") + //@NotNull(message = "scene参数缺失") @ApiModelProperty("支付场景: [recharge=充值,order=普通订单]") private String scene; @@ -27,7 +27,7 @@ public class PaymentValidate implements Serializable { private Integer orderId; @ApiModelProperty(value = "重定向链接: H5端需要") - private String redirectUrl; + private String redirect; @ApiModelProperty(value = "用户ID", notes = "该参数无需传递") private Integer userId; @@ -44,4 +44,7 @@ public class PaymentValidate implements Serializable { @ApiModelProperty(value = "用户描述", notes = "该参数无需传递") private String description; + @ApiModelProperty(value = "Terminal") + private Integer Terminal; + } diff --git a/server/like-front/src/main/resources/application.yml b/server/like-front/src/main/resources/application.yml index 0fba8652..5b17f383 100644 --- a/server/like-front/src/main/resources/application.yml +++ b/server/like-front/src/main/resources/application.yml @@ -80,4 +80,7 @@ sa-token: is-share: false # 多人同登账号共用token token-style: random-64 # token生成的风格 is-print: false # 打印版本字符画 - is-log: false # 是否输出操作日志 \ No newline at end of file + is-log: false # 是否输出操作日志 +ali: + pay: + order-notify-url: /api/pay/ali/notify/order \ No newline at end of file