diff --git a/mcwl-admin/pom.xml b/mcwl-admin/pom.xml index 8b347e3..bbeea53 100644 --- a/mcwl-admin/pom.xml +++ b/mcwl-admin/pom.xml @@ -135,6 +135,11 @@ test + + org.springframework.boot + spring-boot-starter-thymeleaf + + com.aliyun aliyun-java-sdk-core diff --git a/mcwl-admin/src/main/java/com/mcwl/web/controller/pay/AliPay/AliPayController.java b/mcwl-admin/src/main/java/com/mcwl/web/controller/pay/AliPay/AliPayController.java index eff5d41..3bdb9fa 100644 --- a/mcwl-admin/src/main/java/com/mcwl/web/controller/pay/AliPay/AliPayController.java +++ b/mcwl-admin/src/main/java/com/mcwl/web/controller/pay/AliPay/AliPayController.java @@ -1,25 +1,20 @@ package com.mcwl.web.controller.pay.AliPay; import cn.hutool.core.lang.UUID; -import cn.hutool.core.util.RandomUtil; import cn.hutool.extra.qrcode.QrCodeUtil; import cn.hutool.json.JSONUtil; import com.alipay.easysdk.factory.Factory; -import com.alipay.easysdk.kernel.Config; -import com.alipay.easysdk.payment.common.models.AlipayTradeQueryResponse; -import com.mcwl.common.JSONUtils; import com.mcwl.common.annotation.Anonymous; import com.mcwl.common.core.controller.BaseController; -import com.mcwl.common.core.domain.AjaxResult; -import com.mcwl.common.core.page.TableDataInfo; import com.mcwl.common.core.redis.RedisCache; -import com.mcwl.common.domain.IdsParam; import com.mcwl.common.utils.SecurityUtils; +import com.mcwl.common.utils.ShareCodeUtils; import com.mcwl.pay.domain.OrderTrade; import com.mcwl.pay.domain.OrderTradeDto; import com.mcwl.pay.service.AliPayService; import com.mcwl.pay.service.OrderTradeService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -27,7 +22,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.net.URLEncoder; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -39,7 +33,7 @@ import java.util.Map; * @Date:2025/1/3 14:46 */ -@RestController +@Controller @RequestMapping("/ali/pay") @Validated public class AliPayController extends BaseController { @@ -63,12 +57,13 @@ public class AliPayController extends BaseController { @GetMapping("/generateQrCode") public void generateQrCode(HttpServletResponse response) throws Exception { String scope = "auth_user"; // 需要获取用户信息 - String state = RandomUtil.randomString(3); // 防止CSRF攻击 + String appId = "2021005114616085"; + String state = ShareCodeUtils.idToCode(SecurityUtils.getUserId()); // 防止CSRF攻击 String encodedRedirectUri = URLEncoder.encode("https://3195d9a3.r27.cpolar.top/ali/pay/callback", "UTF-8"); String authUrl = String.format( "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=%s&scope=%s&redirect_uri=%s&state=%s", - "2021005114616085", scope, encodedRedirectUri, state + appId, scope, encodedRedirectUri, state ); QrCodeUtil.generate(authUrl, 300, 300, "png", response.getOutputStream()); @@ -79,11 +74,15 @@ public class AliPayController extends BaseController { * @param authCode 授权码 */ @GetMapping("/callback") - public void callback(@RequestParam("auth_code") String authCode) { + public String callback(@RequestParam("auth_code") String authCode, String state) { System.out.println("authCode = " + authCode); - aliPayService.bindingCallback(authCode); - + String result = aliPayService.bindingCallback(authCode, state); + if ("success".equals(result)) { + return "binding-success"; + } else { + return "binding-fail"; + } } @@ -110,14 +109,6 @@ public class AliPayController extends BaseController { QrCodeUtil.generate(qrUrl, 300, 300, "png", response.getOutputStream()); } - /** - * 查看余额 - */ - @GetMapping("/balance") - public void balance() throws Exception { - aliPayService.balance(); - } - /** * 提现接口 */ @@ -141,6 +132,7 @@ public class AliPayController extends BaseController { */ @Anonymous @PostMapping("/notify") // 注意这里必须是POST接口 + @ResponseBody public String payNotify(HttpServletRequest request) throws Exception { diff --git a/mcwl-admin/src/main/resources/templates/binding-fail.html b/mcwl-admin/src/main/resources/templates/binding-fail.html new file mode 100644 index 0000000..6a3efc1 --- /dev/null +++ b/mcwl-admin/src/main/resources/templates/binding-fail.html @@ -0,0 +1,11 @@ + + + + + 绑定失败 + + +

支付宝账号绑定失败!

+

请检查您的网络或稍后重试。

+ + \ No newline at end of file diff --git a/mcwl-admin/src/main/resources/templates/binding-success.html b/mcwl-admin/src/main/resources/templates/binding-success.html new file mode 100644 index 0000000..da73c50 --- /dev/null +++ b/mcwl-admin/src/main/resources/templates/binding-success.html @@ -0,0 +1,11 @@ + + + + + 绑定成功 + + +

支付宝账号绑定成功!

+

您可以返回用户中心继续操作。

+ + \ No newline at end of file diff --git a/mcwl-common/src/main/java/com/mcwl/common/handler/MyMetaObjectHandler.java b/mcwl-common/src/main/java/com/mcwl/common/handler/MyMetaObjectHandler.java index 90ecc26..02160c5 100644 --- a/mcwl-common/src/main/java/com/mcwl/common/handler/MyMetaObjectHandler.java +++ b/mcwl-common/src/main/java/com/mcwl/common/handler/MyMetaObjectHandler.java @@ -20,9 +20,17 @@ public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { - this.strictInsertFill(metaObject, "createBy", String.class, SecurityUtils.getUsername()); + try { + this.strictInsertFill(metaObject, "createBy", String.class, SecurityUtils.getUsername()); + } catch (Exception e) { + this.strictInsertFill(metaObject, "createBy", String.class, ""); + } this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); - this.strictInsertFill(metaObject, "tenantId", Long.class, SecurityUtils.getUserId()); + try { + this.strictInsertFill(metaObject, "tenantId", Long.class, SecurityUtils.getUserId()); + } catch (Exception e) { + this.strictInsertFill(metaObject, "tenantId", Long.class, -1L); + } } @Override diff --git a/mcwl-framework/src/main/java/com/mcwl/framework/config/SecurityConfig.java b/mcwl-framework/src/main/java/com/mcwl/framework/config/SecurityConfig.java index ffc5676..936e217 100644 --- a/mcwl-framework/src/main/java/com/mcwl/framework/config/SecurityConfig.java +++ b/mcwl-framework/src/main/java/com/mcwl/framework/config/SecurityConfig.java @@ -130,7 +130,7 @@ public class SecurityConfig permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll()); // 对于登录login 注册register 验证码captchaImage 允许匿名访问 requests.antMatchers("/login", "/register", "/captchaImage","/ali/pay/doPay","/ali/pay/notify", - "/ali/pay/generateQrCode","/ali/pay/callback").permitAll() + "/ali/pay/callback").permitAll() // 静态资源,可匿名访问 .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() diff --git a/mcwl-pay/src/main/java/com/mcwl/pay/service/AliPayService.java b/mcwl-pay/src/main/java/com/mcwl/pay/service/AliPayService.java index 882096d..a6e3686 100644 --- a/mcwl-pay/src/main/java/com/mcwl/pay/service/AliPayService.java +++ b/mcwl-pay/src/main/java/com/mcwl/pay/service/AliPayService.java @@ -1,16 +1,15 @@ package com.mcwl.pay.service; import com.alipay.api.AlipayApiException; +import com.mcwl.common.core.domain.AjaxResult; import com.mcwl.pay.domain.OrderTradeDto; public interface AliPayService { - void bindingCallback(String authCode); + String bindingCallback(String authCode, String state); String memberPay(OrderTradeDto orderTradeDto) throws Exception; String pointsPay(Double paymentAmount) throws Exception; - void balance() throws Exception; - String transfer(String outBizNo, String payerUserId, String payeeUserId, String amount) throws AlipayApiException; } diff --git a/mcwl-pay/src/main/java/com/mcwl/pay/service/impl/AliPayServiceImpl.java b/mcwl-pay/src/main/java/com/mcwl/pay/service/impl/AliPayServiceImpl.java index ae8358e..5ff9d2d 100644 --- a/mcwl-pay/src/main/java/com/mcwl/pay/service/impl/AliPayServiceImpl.java +++ b/mcwl-pay/src/main/java/com/mcwl/pay/service/impl/AliPayServiceImpl.java @@ -21,19 +21,25 @@ import com.alipay.easysdk.base.oauth.models.AlipaySystemOauthTokenResponse; import com.alipay.easysdk.factory.Factory; import com.alipay.easysdk.kernel.Config; import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse; +import com.mcwl.common.core.domain.AjaxResult; import com.mcwl.common.core.redis.RedisCache; +import com.mcwl.common.exception.BusinessException; import com.mcwl.common.exception.ServiceException; import com.mcwl.common.utils.SecurityUtils; +import com.mcwl.common.utils.ShareCodeUtils; import com.mcwl.memberCenter.domain.MemberLevel; import com.mcwl.memberCenter.service.MemberLevelService; import com.mcwl.pay.config.AliConfig; import com.mcwl.pay.domain.OrderTrade; import com.mcwl.pay.domain.OrderTradeDto; import com.mcwl.pay.service.AliPayService; +import com.mcwl.system.domain.SysUserPayAccount; +import com.mcwl.system.service.ISysUserPayAccountService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.Objects; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -55,6 +61,9 @@ public class AliPayServiceImpl implements AliPayService { @Autowired private AliConfig aliConfig; + @Autowired + private ISysUserPayAccountService sysUserPayAccountService; + public AliPayServiceImpl(Config config) { Factory.setOptions(config); @@ -183,10 +192,11 @@ public class AliPayServiceImpl implements AliPayService { /** * 支付宝转账方法 - * @param outBizNo 外部业务单号 + * + * @param outBizNo 外部业务单号 * @param payerUserId 付款方用户ID * @param payeeUserId 收款方用户ID - * @param amount 转账金额 + * @param amount 转账金额 * @return 返回支付宝转账响应的内容 */ @Override @@ -238,53 +248,14 @@ public class AliPayServiceImpl implements AliPayService { } else { System.out.println("调用失败"); // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接 - String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response); - System.out.println(diagnosisUrl); + String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response); + System.out.println(diagnosisUrl); } return response.getBody(); } - /** - * 查看余额 - */ - @Override - public void balance() throws Exception { - - AlipaySystemOauthTokenResponse token = Factory.Base.OAuth().getToken("code"); - - - // 初始化SDK - AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig()); - - // 构造请求参数以调用接口 - AlipayFundAccountQueryRequest request = new AlipayFundAccountQueryRequest(); - AlipayFundAccountQueryModel model = new AlipayFundAccountQueryModel(); - - // uid参数未来计划废弃,存量商户可继续使用,新商户请使用openid。请根据应用-开发配置-openid配置选择支持的字段。 - // model.setAlipayUserId("2088301409188095"); - - // 设置支付宝openId - model.setAlipayOpenId("061P6NAblcWDWJoDRxSVvOYz-ufp-3wQaA4E_szQyMFTXse"); - - // 设置查询的账号类型 - model.setAccountType("ACCTRANS_ACCOUNT"); - - request.setBizModel(model); - AlipayFundAccountQueryResponse response = alipayClient.execute(request); - System.out.println(response.getBody()); - - if (response.isSuccess()) { - System.out.println("调用成功"); - } else { - System.out.println("调用失败"); - // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接 - // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response); - // System.out.println(diagnosisUrl); - } - } - private AlipayConfig getAlipayConfig() { - String privateKey = aliConfig.getPrivateKey(); + String privateKey = aliConfig.getPrivateKey(); String alipayPublicKey = aliConfig.getPublicKey(); AlipayConfig alipayConfig = new AlipayConfig(); alipayConfig.setServerUrl(aliConfig.getGatewayUrl()); @@ -297,25 +268,46 @@ public class AliPayServiceImpl implements AliPayService { return alipayConfig; } - //TODO 绑定回调,获取openId,保存到数据库 @Override - public void bindingCallback(String authCode) { + public String bindingCallback(String authCode, String state) { try { + Long userId = ShareCodeUtils.codeToId(state); + if (Objects.isNull(userId)) { + return "fail"; + } AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig()); AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest(); request.setCode(authCode); request.setGrantType("authorization_code"); com.alipay.api.response.AlipaySystemOauthTokenResponse response = alipayClient.execute(request); if (response.isSuccess()) { - String openId = response.getOpenId(); // 支付宝用户唯一ID - // 将openId与当前商城用户绑定(保存到数据库) + // 支付宝用户唯一ID + String openId = response.getOpenId(); + // 判断是否已经绑定过 + SysUserPayAccount sysUserPayAccount = sysUserPayAccountService.lambdaQuery() + .eq(SysUserPayAccount::getUserId, userId) + .eq(SysUserPayAccount::getOpenId, openId) + .eq(SysUserPayAccount::getType, 0) + .one(); + if (Objects.nonNull(sysUserPayAccount)) { + // 已经绑定过,直接返回 + return "success"; + } System.out.println("绑定成功!openId:" + openId); + // 将openId与当前商城用户绑定(保存到数据库) + SysUserPayAccount userPayAccount = new SysUserPayAccount(); + userPayAccount.setUserId(userId); + userPayAccount.setOpenId(openId); + userPayAccount.setType(0); + sysUserPayAccountService.save(userPayAccount); + return "success"; } else { System.out.println("绑定失败:" + response.getSubMsg()); + return "fail"; } - } catch (AlipayApiException e) { - throw new RuntimeException(e); + return "fail"; } + } } diff --git a/mcwl-system/src/main/java/com/mcwl/system/domain/SysUserPayAccount.java b/mcwl-system/src/main/java/com/mcwl/system/domain/SysUserPayAccount.java new file mode 100644 index 0000000..2439a6b --- /dev/null +++ b/mcwl-system/src/main/java/com/mcwl/system/domain/SysUserPayAccount.java @@ -0,0 +1,36 @@ +package com.mcwl.system.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.mcwl.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 消息通知 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("sys_user_pay_account") +public class SysUserPayAccount extends BaseEntity { + + @TableId + private Long id; + + /** + * 用户id + */ + private Long userId; + /** + * 账号唯一标识 + */ + private String openId; + /** + * 账号类型 0 支付宝 1 微信 2 QQ + */ + private Integer type; + + + + +} diff --git a/mcwl-system/src/main/java/com/mcwl/system/mapper/SysUserPayAccountMapper.java b/mcwl-system/src/main/java/com/mcwl/system/mapper/SysUserPayAccountMapper.java new file mode 100644 index 0000000..9596d06 --- /dev/null +++ b/mcwl-system/src/main/java/com/mcwl/system/mapper/SysUserPayAccountMapper.java @@ -0,0 +1,13 @@ +package com.mcwl.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.mcwl.system.domain.SysUserPayAccount; +import org.apache.ibatis.annotations.Mapper; + +/** + * 用户支付账户 + */ +@Mapper +public interface SysUserPayAccountMapper extends BaseMapper { + +} diff --git a/mcwl-system/src/main/java/com/mcwl/system/service/ISysUserPayAccountService.java b/mcwl-system/src/main/java/com/mcwl/system/service/ISysUserPayAccountService.java new file mode 100644 index 0000000..98056a3 --- /dev/null +++ b/mcwl-system/src/main/java/com/mcwl/system/service/ISysUserPayAccountService.java @@ -0,0 +1,14 @@ +package com.mcwl.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.mcwl.system.domain.SysUserPayAccount; + +/** + * 用户支付账户 服务层 + * + * @author mcwl + */ +public interface ISysUserPayAccountService extends IService { + + +} diff --git a/mcwl-system/src/main/java/com/mcwl/system/service/impl/SysUserPayAccountServiceImpl.java b/mcwl-system/src/main/java/com/mcwl/system/service/impl/SysUserPayAccountServiceImpl.java new file mode 100644 index 0000000..16d49b6 --- /dev/null +++ b/mcwl-system/src/main/java/com/mcwl/system/service/impl/SysUserPayAccountServiceImpl.java @@ -0,0 +1,18 @@ +package com.mcwl.system.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.mcwl.system.domain.SysUserPayAccount; +import com.mcwl.system.mapper.SysUserPayAccountMapper; +import com.mcwl.system.service.ISysUserPayAccountService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 用户支付账户 业务层处理 + */ +@Service +public class SysUserPayAccountServiceImpl extends ServiceImpl implements ISysUserPayAccountService { + + +}