feat 增加充值模块
This commit is contained in:
parent
d44dc4e799
commit
56f0b88c7c
|
|
@ -119,7 +119,11 @@
|
|||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
<version>4.38.72.ALL</version>
|
||||
</dependency>
|
||||
<!-- Gson工具 -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
|
@ -61,13 +61,13 @@ public class WxMnpConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public WxMpService wxOaService() {
|
||||
Map<String, String> config = this.getChannelConfig("oa_channel");
|
||||
Map<String, String> 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);
|
||||
|
|
|
|||
|
|
@ -85,8 +85,8 @@ public class WxPayConfiguration {
|
|||
.last("limit 1"));
|
||||
|
||||
Config systemConfig = systemConfigMapper.selectOne(new QueryWrapper<Config>()
|
||||
.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();
|
||||
|
|
|
|||
|
|
@ -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<Integer> typeList = getUserMoneyChangeType();
|
||||
if (typeList.contains(changeType)) {
|
||||
return UM.getCode();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态码
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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<UserAccountLog> {
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -65,13 +65,13 @@ public class WxMnpDriver {
|
|||
* @return WxMpService
|
||||
*/
|
||||
public static WxMpService oa() {
|
||||
Map<String, String> config = ConfigUtils.get("oa_channel");
|
||||
Map<String, String> 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;
|
||||
|
|
|
|||
|
|
@ -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<String, String> 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);
|
||||
|
|
|
|||
|
|
@ -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<DevPayConfig>()
|
||||
.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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Object> 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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<String, String> 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<RechargeOrder>()
|
||||
.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<RechargeOrder>()
|
||||
.eq("order_sn", outTradeNo)
|
||||
.eq("sn", outTradeNo).isNull("delete_time")
|
||||
.last("limit 1"));
|
||||
|
||||
if (StringUtils.isNull(rechargeOrder)) {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public class WechatServiceImpl implements IWechatService {
|
|||
|
||||
@Override
|
||||
public Map<String, Object> 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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,4 +80,7 @@ sa-token:
|
|||
is-share: false # 多人同登账号共用token
|
||||
token-style: random-64 # token生成的风格
|
||||
is-print: false # 打印版本字符画
|
||||
is-log: false # 是否输出操作日志
|
||||
is-log: false # 是否输出操作日志
|
||||
ali:
|
||||
pay:
|
||||
order-notify-url: /api/pay/ali/notify/order
|
||||
Loading…
Reference in New Issue