diff --git a/admin-hanhai-vue/.env.development b/admin-hanhai-vue/.env.development index a7a7eb0..5690da3 100644 --- a/admin-hanhai-vue/.env.development +++ b/admin-hanhai-vue/.env.development @@ -1,5 +1,5 @@ NODE_ENV=development -VUE_APP_API_BASE_URL=http://localhost:8081/api/ +VUE_APP_API_BASE_URL=https://admin.hhlm1688.com/api/ VUE_APP_CAS_BASE_URL=http://cas.example.org:8443/cas VUE_APP_ONLINE_BASE_URL=http://fileview.jeecg.com/onlinePreview diff --git a/admin-hanhai-vue/.env.production b/admin-hanhai-vue/.env.production index 9e94d96..ed67425 100644 --- a/admin-hanhai-vue/.env.production +++ b/admin-hanhai-vue/.env.production @@ -1,4 +1,4 @@ NODE_ENV=production -VUE_APP_API_BASE_URL=http://localhost:8081/api/ +VUE_APP_API_BASE_URL=https://admin.hhlm1688.com/api/ VUE_APP_CAS_BASE_URL=http://localhost:8888/cas VUE_APP_ONLINE_BASE_URL=http://fileview.jeecg.com/onlinePreview \ No newline at end of file diff --git a/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/controller/CityMoneyLogController.java b/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/controller/CityMoneyLogController.java index 2a9bb40..97c54a1 100644 --- a/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/controller/CityMoneyLogController.java +++ b/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/controller/CityMoneyLogController.java @@ -10,6 +10,7 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import lombok.Synchronized; import org.jeecg.config.HttpRequestUtil; import org.jeecg.config.MoneyUtil; import com.alibaba.fastjson.JSONObject; @@ -24,6 +25,7 @@ import org.jeecg.modules.cityMoneyLog.entity.CityMoneyLog; import org.jeecg.modules.cityMoneyLog.req.TransferBatchesDetailsRequest; import org.jeecg.modules.cityMoneyLog.req.TransferBatchesRequest; import org.jeecg.modules.cityMoneyLog.resp.TransferBatchesResp; +import org.jeecg.modules.cityMoneyLog.resp.TransferToUser; import org.jeecg.modules.cityMoneyLog.service.ICityMoneyLogService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -41,6 +43,7 @@ import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; import org.jeecg.common.system.base.controller.JeecgController; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; @@ -118,88 +121,66 @@ public class CityMoneyLogController extends JeecgController edit(@RequestBody CityMoneyLog hanHaiWater) { -// HanHaiMember hanHaiMember = hanHaiMemberService.getById(hanHaiWater.getUserId()); -// Integer n = (Integer) redisUtil.get("WITHDRAWAL:" + hanHaiWater.getId()); -// if (n != null) { -// throw new JeecgBootException("请勿重复点击,后果自负!"); -// } -// redisUtil.set("WITHDRAWAL:" + hanHaiWater.getId(), 1, 5); -// -// //微信-商家转账到零钱 -// -// String idStr = "H" + IdWorker.getIdStr(); -// TransferBatchesRequest transferBatchesRequest = new TransferBatchesRequest(); -// -// transferBatchesRequest.setAppid(appId); -// transferBatchesRequest.setOutBillNo(idStr); -// transferBatchesRequest.setTransferRemark("商家提现"); -// transferBatchesRequest.setOpenid(hanHaiMember.getAppletOpenid()); -// transferBatchesRequest.setTransferSceneId("1005"); -// transferBatchesRequest.setNotifyUrl(withdrawalNotifyUrl); -// String serialNo = null; -// //加密真实姓名 -// try { -// -// X509Certificate certificate = weChatPayConfig2.getVerifier().getValidCertificate(); -// serialNo = certificate.getSerialNumber().toString(16).toUpperCase(); -// //这里放真实姓名,目前你的数据库表没有这个字段 -// String encryptOAEP = RsaCryptoUtil.encryptOAEP(hanHaiWater.getName(), certificate); -// transferBatchesRequest.setUserName(encryptOAEP); -// } catch (Exception e) { -// log.info("真实姓名加密失败"); -// e.printStackTrace(); -// throw new JeecgBootException("真实姓名加密失败"); -// } -// transferBatchesRequest.setTransferAmount(MoneyUtil.Yuan2Fen(hanHaiWater.getPrice().doubleValue())); -// List transferBatchesDetailsRequests = new ArrayList<>(); -// TransferBatchesDetailsRequest transferBatchesDetailsRequest = new TransferBatchesDetailsRequest(); -// transferBatchesDetailsRequest.setInfoType("岗位类型"); -// transferBatchesDetailsRequest.setInfoContent("销售员"); -// TransferBatchesDetailsRequest transferBatchesDetailsRequest2 = new TransferBatchesDetailsRequest(); -// transferBatchesDetailsRequest2.setInfoType("报酬说明"); -// transferBatchesDetailsRequest2.setInfoContent("佣金报酬"); -// -// -// transferBatchesDetailsRequests.add(transferBatchesDetailsRequest); -// transferBatchesDetailsRequests.add(transferBatchesDetailsRequest2); -// transferBatchesRequest.setTransferDetailList(transferBatchesDetailsRequests); -// String jsonString = JSONObject.toJSONString(transferBatchesRequest); -// -// log.info("请求参数:"+jsonString); -// -// String postTransBatRequest = HttpRequestUtil.postTransBatRequest(transferBatchUrl, jsonString, serialNo, wxsSerialNo, mchId, pemPath); -// log.error("返回结果1:" + postTransBatRequest); -// TransferBatchesResp transferBatchesResp = JSON.parseObject(postTransBatRequest, TransferBatchesResp.class); -// log.error("返回结果2:" + transferBatchesResp); -// if (transferBatchesResp == null || org.apache.commons.lang3.StringUtils.isBlank(transferBatchesResp.getOutBillNo()) || transferBatchesResp.getState().equals("FAIL")) { -// throw new JeecgBootException("打款失败"); -// } -// -// //这里写自己的逻辑,比如改变这条记录的状态,变成提现成功 -// -// CityMoneyLog hanHaiWater1 = new CityMoneyLog(); -// hanHaiWater1.setId(hanHaiWater.getId()); -// hanHaiWater1.setState(1); -// hanHaiWater1.setPackageInfo(transferBatchesResp.getPackageInfo()); -// hanHaiWater1.setOutBatchNo(transferBatchesResp.getOutBillNo()); -// hanHaiWater1.setBatchId(transferBatchesResp.getTransferBillNo()); -// cityMoneyLogService.updateById(hanHaiWater1); -// -// -// return Result.OK("提现成功"); -// } -// + + /** + * 编辑 + * + * @param hanHaiWater + * @return + */ + @Transactional + @Synchronized + @AutoLog(value = "佣金流水-编辑") + @ApiOperation(value="佣金流水-编辑", notes="佣金流水-编辑") + @RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST}) + public Result edit(@RequestBody CityMoneyLog hanHaiWater) { + HanHaiMember hanHaiMember = hanHaiMemberService.getById(hanHaiWater.getUserId()); + Integer n = (Integer) redisUtil.get("WITHDRAWAL:" + hanHaiWater.getId()); + if (n != null) { + throw new JeecgBootException("请勿重复点击,后果自负!"); + } + redisUtil.set("WITHDRAWAL:" + hanHaiWater.getId(), 1, 5); + + //查询该流水信息是否存在 + CityMoneyLog one = cityMoneyLogService.getById(hanHaiWater.getId()); + if (one == null) { + throw new JeecgBootException("数据不存在"); + } + + + String mchid = "1673516176"; + String certiticateSerialNo ="525CDBD76E640EFB008288572C97D2715F3F18B2"; + String privateKeyFilePath = "/jeecg-boot-module-system/src/main/resources/apiclient_key_yaodu.pem"; + String wechatPayPublicKeyId = "PUB_KEY_ID_0116735161762025040100448900000949"; + String wechatPayPublicKeyFilePaht = "/jeecg-boot-module-system/src/main/resources/pub_key_yaodu.pem"; + TransferToUser transferToUser = new TransferToUser(mchid, certiticateSerialNo, privateKeyFilePath, wechatPayPublicKeyId, wechatPayPublicKeyFilePaht ); + + //得到openid + String openid = hanHaiMember.getAppletOpenid(); + //得到姓名 + String name = hanHaiWater.getName(); + //得到金额 + Long amount = hanHaiWater.getPrice().longValue() * 100; + System.out.println("提现者信息================="); + System.out.println(openid); + System.out.println(name); + System.out.println(amount); + TransferToUser.TransferToUserResponse run = transferToUser.run(amount, openid, name, hanHaiWater.getId()); + + //这里写自己的逻辑,比如改变这条记录的状态,变成提现成功 + + CityMoneyLog hanHaiWater1 = new CityMoneyLog(); + //查询流水记录 + + hanHaiWater1.setId(hanHaiWater.getId()); + hanHaiWater1.setState(1); + hanHaiWater1.setPackageInfo(run.getPackageInfo()); + hanHaiWater1.setOutBatchNo(run.getOutBillNo()); + hanHaiWater1.setBatchId(run.getTransferBillNo()); + cityMoneyLogService.updateById(hanHaiWater1); + return Result.OK("提现成功"); + } + /** * 通过id删除 * diff --git a/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/entity/CityMoneyLog.java b/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/entity/CityMoneyLog.java index 5edc013..af2b84b 100644 --- a/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/entity/CityMoneyLog.java +++ b/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/entity/CityMoneyLog.java @@ -67,6 +67,11 @@ public class CityMoneyLog implements Serializable { @Excel(name = "金额", width = 15) @ApiModelProperty(value = "金额") private java.math.BigDecimal price; + /**金额*/ + @Excel(name = "实际到账", width = 15) + @ApiModelProperty(value = "实际到账") + private java.math.BigDecimal getPrice; + /**状态*/ @Excel(name = "状态", width = 15, dicCode = "money_pay_state") @Dict(dicCode = "money_pay_state") diff --git a/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/resp/TransferToUser.java b/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/resp/TransferToUser.java new file mode 100644 index 0000000..515d8db --- /dev/null +++ b/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/resp/TransferToUser.java @@ -0,0 +1,234 @@ +package org.jeecg.modules.cityMoneyLog.resp; + +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import com.google.gson.annotations.SerializedName; +import io.swagger.util.Json; +import lombok.Data; +import okhttp3.*; +import org.jeecg.modules.cityMoneyLog.entity.CityMoneyLog; +import org.jeecg.modules.cityMoneyLog.resp.WXPayUtility; +import org.jeecg.modules.cityMoneyLog.service.ICityMoneyLogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.List; + +/** + * 发起转账 + */ +public class TransferToUser { + private static String HOST = "https://api.mch.weixin.qq.com"; + private static String METHOD = "POST"; + private static String PATH = "/v3/fund-app/mch-transfer/transfer-bills"; + + + public TransferToUserResponse run(Long transfer_amount,String openid,String user_name,String waterId){ + String mchid = "1673516176"; + String certiticateSerialNo ="525CDBD76E640EFB008288572C97D2715F3F18B2"; + String privateKeyFilePath = "/jeecg-boot-module-system/src/main/resources/apiclient_key_yaodu.pem"; + String wechatPayPublicKeyId = "PUB_KEY_ID_0116735161762025040100448900000949"; + String wechatPayPublicKeyFilePaht = "/jeecg-boot-module-system/src/main/resources/pub_key_yaodu.pem"; + TransferToUser client = new TransferToUser( + mchid, // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756 + certiticateSerialNo, // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053 + privateKeyFilePath, // 商户API证书私钥文件路径,本地文件路径 + wechatPayPublicKeyId, // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816 + wechatPayPublicKeyFilePaht // 微信支付公钥文件路径,本地文件路径 + ); + + String appid = "wxa4d29e67e8a58d38"; + String notifyUrl = "https://admin.hhlm1688.com/api/cashout/cashoutNotify"; + TransferToUserRequest request = new TransferToUserRequest(); + request.appid = appid; + String idStr = "H" + IdWorker.getIdStr(); + request.out_bill_no = idStr; + request.transfer_scene_id = "1005";//只开通了佣金报酬 + request.openid = openid; + request.user_name = client.encrypt(user_name); + request.transfer_amount = transfer_amount; + request.transfer_remark = "佣金报酬"; + request.notify_url = notifyUrl; + request.userRecvPerception = "劳务报酬"; // 修改用户收款感知描述 + request.transferSceneReportInfos = new ArrayList<>(); + { + TransferSceneReportInfo item0 = new TransferSceneReportInfo(); + item0.infoType = "岗位类型";//固定 + item0.infoContent = "外卖员";//只开通了佣金报酬 + request.transferSceneReportInfos.add(item0); + TransferSceneReportInfo item1 = new TransferSceneReportInfo(); + item1.infoType = "报酬说明";//固定 + item1.infoContent = "高温补贴";//只开通了佣金报酬 + request.transferSceneReportInfos.add(item1); + + + + }; + try { + TransferToUserResponse response = client.run(request); + + + + // TODO: 请求成功,继续业务逻辑 + System.out.println(response); + return response; + } catch (WXPayUtility.ApiException e) { + // TODO: 请求失败,根据状态码执行不同的逻辑 + e.printStackTrace(); + } + return null; + } + + + public TransferToUserResponse run(TransferToUserRequest request) { + String uri = PATH; + String reqBody = WXPayUtility.toJson(request); +// String reqBody = Json.pretty(request); + System.out.println("reqBody========================="); + System.out.println(reqBody); + + Request.Builder reqBuilder = new Request.Builder().url(HOST + uri); + reqBuilder.addHeader("Accept", "application/json"); + reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId); + reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody)); + reqBuilder.addHeader("Content-Type", "application/json"); + RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody); + reqBuilder.method(METHOD, requestBody); + Request httpRequest = reqBuilder.build(); + + // 发送HTTP请求 + OkHttpClient client = new OkHttpClient.Builder().build(); + try (Response httpResponse = client.newCall(httpRequest).execute()) { + String respBody = WXPayUtility.extractBody(httpResponse); + if (httpResponse.code() >= 200 && httpResponse.code() < 300) { + // 2XX 成功,验证应答签名 + WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey, + httpResponse.headers(), respBody); + + // 从HTTP应答报文构建返回数据 + TransferToUserResponse transferToUserResponse = WXPayUtility.fromJson(respBody, TransferToUserResponse.class); + System.out.println("transferToUserResponse========================="); + System.out.println(Json.pretty(transferToUserResponse)); + return transferToUserResponse; + } else { + throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers()); + } + } catch (IOException e) { + throw new UncheckedIOException("Sending request to " + uri + " failed.", e); + } + } + + private final String mchid; + private final String certificateSerialNo; + private final PrivateKey privateKey; + private final String wechatPayPublicKeyId; + private final PublicKey wechatPayPublicKey; + + public TransferToUser(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) { + this.mchid = mchid; + this.certificateSerialNo = certificateSerialNo; + this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath); + this.wechatPayPublicKeyId = wechatPayPublicKeyId; + this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath); + } + + public String encrypt(String plainText) { + return WXPayUtility.encrypt(this.wechatPayPublicKey, plainText); + } + + @Data + public static class TransferToUserResponse { + @SerializedName("out_bill_no") + public String outBillNo; + + @SerializedName("transfer_bill_no") + public String transferBillNo; + + @SerializedName("create_time") + public String createTime; + + @SerializedName("state") + public TransferBillStatus state; + + @SerializedName("package_info") + public String packageInfo; + + + } + + public enum TransferBillStatus { + @SerializedName("ACCEPTED") + ACCEPTED, + @SerializedName("PROCESSING") + PROCESSING, + @SerializedName("WAIT_USER_CONFIRM") + WAIT_USER_CONFIRM, + @SerializedName("TRANSFERING") + TRANSFERING, + @SerializedName("SUCCESS") + SUCCESS, + @SerializedName("FAIL") + FAIL, + @SerializedName("CANCELING") + CANCELING, + @SerializedName("CANCELLED") + CANCELLED + } + + public static class TransferSceneReportInfo { + @SerializedName("info_type") + public String infoType; + + @SerializedName("info_content") + public String infoContent; + } + + public static class TransferToUserRequest { + @SerializedName("appid") + public String appid; + + @SerializedName("out_bill_no") +// public String outBillNo; + public String out_bill_no; + + @SerializedName("transfer_scene_id") +// public String transferSceneId; + public String transfer_scene_id; + + @SerializedName("openid") + public String openid; + + @SerializedName("user_name") +// public String userName; + public String user_name; + + @SerializedName("transfer_amount") +// public Long transferAmount; + public Long transfer_amount; + + @SerializedName("transfer_remark") +// public String transferRemark; + public String transfer_remark; + + + + + @SerializedName("notify_url") +// public String notifyUrl; + public String notify_url; + + @SerializedName("user_recv_perception") + public String userRecvPerception; + + @SerializedName("transfer_scene_report_infos") + public List transferSceneReportInfos; + + } + +} diff --git a/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/resp/WXPayUtility.java b/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/resp/WXPayUtility.java new file mode 100644 index 0000000..0e288b0 --- /dev/null +++ b/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/cityMoneyLog/resp/WXPayUtility.java @@ -0,0 +1,381 @@ +package org.jeecg.modules.cityMoneyLog.resp; + +import com.google.gson.*; +import com.google.gson.annotations.Expose; +import okhttp3.Headers; +import okhttp3.Response; +import okio.BufferedSource; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.*; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.time.DateTimeException; +import java.time.Duration; +import java.time.Instant; +import java.util.Base64; +import java.util.Map; +import java.util.Objects; + +public class WXPayUtility { + private static final Gson gson = new GsonBuilder() + .disableHtmlEscaping() + .addSerializationExclusionStrategy(new ExclusionStrategy() { + @Override + public boolean shouldSkipField(FieldAttributes fieldAttributes) { + final Expose expose = fieldAttributes.getAnnotation(Expose.class); + return expose != null && !expose.serialize(); + } + + @Override + public boolean shouldSkipClass(Class aClass) { + return false; + } + }) + .addDeserializationExclusionStrategy(new ExclusionStrategy() { + @Override + public boolean shouldSkipField(FieldAttributes fieldAttributes) { + final Expose expose = fieldAttributes.getAnnotation(Expose.class); + return expose != null && !expose.deserialize(); + } + + @Override + public boolean shouldSkipClass(Class aClass) { + return false; + } + }) + .create(); + private static final char[] SYMBOLS = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); + private static final SecureRandom random = new SecureRandom(); + + /** + * 将 Object 转换为 JSON 字符串 + */ + public static String toJson(Object object) { + return gson.toJson(object); + } + + /** + * 将 JSON 字符串解析为特定类型的实例 + */ + public static T fromJson(String json, Class classOfT) throws JsonSyntaxException { + return gson.fromJson(json, classOfT); + } + + /** + * 从公私钥文件路径中读取文件内容 + * + * @param keyPath 文件路径 + * @return 文件内容 + */ + private static String readKeyStringFromPath(String keyPath) { + try { + return new String(Files.readAllBytes(Paths.get(keyPath)), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * 读取 PKCS#8 格式的私钥字符串并加载为私钥对象 + * + * @param keyString 私钥文件内容,以 -----BEGIN PRIVATE KEY----- 开头 + * @return PrivateKey 对象 + */ + public static PrivateKey loadPrivateKeyFromString(String keyString) { + try { + keyString = keyString.replace("-----BEGIN PRIVATE KEY-----", "") + .replace("-----END PRIVATE KEY-----", "") + .replaceAll("\\s+", ""); + return KeyFactory.getInstance("RSA").generatePrivate( + new PKCS8EncodedKeySpec(Base64.getDecoder().decode(keyString))); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException(e); + } catch (InvalidKeySpecException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * 从 PKCS#8 格式的私钥文件中加载私钥 + * + * @param keyPath 私钥文件路径 + * @return PrivateKey 对象 + */ + public static PrivateKey loadPrivateKeyFromPath(String keyPath) { + return loadPrivateKeyFromString(readKeyStringFromPath(keyPath)); + } + + /** + * 读取 PKCS#8 格式的公钥字符串并加载为公钥对象 + * + * @param keyString 公钥文件内容,以 -----BEGIN PUBLIC KEY----- 开头 + * @return PublicKey 对象 + */ + public static PublicKey loadPublicKeyFromString(String keyString) { + try { + keyString = keyString.replace("-----BEGIN PUBLIC KEY-----", "") + .replace("-----END PUBLIC KEY-----", "") + .replaceAll("\\s+", ""); + return KeyFactory.getInstance("RSA").generatePublic( + new X509EncodedKeySpec(Base64.getDecoder().decode(keyString))); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException(e); + } catch (InvalidKeySpecException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * 从 PKCS#8 格式的公钥文件中加载公钥 + * + * @param keyPath 公钥文件路径 + * @return PublicKey 对象 + */ + public static PublicKey loadPublicKeyFromPath(String keyPath) { + return loadPublicKeyFromString(readKeyStringFromPath(keyPath)); + } + + /** + * 创建指定长度的随机字符串,字符集为[0-9a-zA-Z],可用于安全相关用途 + */ + public static String createNonce(int length) { + char[] buf = new char[length]; + for (int i = 0; i < length; ++i) { + buf[i] = SYMBOLS[random.nextInt(SYMBOLS.length)]; + } + return new String(buf); + } + + /** + * 使用公钥按照 RSA_PKCS1_OAEP_PADDING 算法进行加密 + * + * @param publicKey 加密用公钥对象 + * @param plaintext 待加密明文 + * @return 加密后密文 + */ + public static String encrypt(PublicKey publicKey, String plaintext) { + final String transformation = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"; + + try { + Cipher cipher = Cipher.getInstance(transformation); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + return Base64.getEncoder().encodeToString(cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8))); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new IllegalArgumentException("The current Java environment does not support " + transformation, e); + } catch (InvalidKeyException e) { + throw new IllegalArgumentException("RSA encryption using an illegal publicKey", e); + } catch (BadPaddingException | IllegalBlockSizeException e) { + throw new IllegalArgumentException("Plaintext is too long", e); + } + } + + /** + * 使用私钥按照指定算法进行签名 + * + * @param message 待签名串 + * @param algorithm 签名算法,如 SHA256withRSA + * @param privateKey 签名用私钥对象 + * @return 签名结果 + */ + public static String sign(String message, String algorithm, PrivateKey privateKey) { + byte[] sign; + try { + Signature signature = Signature.getInstance(algorithm); + signature.initSign(privateKey); + signature.update(message.getBytes(StandardCharsets.UTF_8)); + sign = signature.sign(); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException("The current Java environment does not support " + algorithm, e); + } catch (InvalidKeyException e) { + throw new IllegalArgumentException(algorithm + " signature uses an illegal privateKey.", e); + } catch (SignatureException e) { + throw new RuntimeException("An error occurred during the sign process.", e); + } + return Base64.getEncoder().encodeToString(sign); + } + + /** + * 使用公钥按照特定算法验证签名 + * + * @param message 待签名串 + * @param signature 待验证的签名内容 + * @param algorithm 签名算法,如:SHA256withRSA + * @param publicKey 验签用公钥对象 + * @return 签名验证是否通过 + */ + public static boolean verify(String message, String signature, String algorithm, + PublicKey publicKey) { + try { + Signature sign = Signature.getInstance(algorithm); + sign.initVerify(publicKey); + sign.update(message.getBytes(StandardCharsets.UTF_8)); + return sign.verify(Base64.getDecoder().decode(signature)); + } catch (SignatureException e) { + return false; + } catch (InvalidKeyException e) { + throw new IllegalArgumentException("verify uses an illegal publickey.", e); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException("The current Java environment does not support" + algorithm, e); + } + } + + /** + * 根据微信支付APIv3请求签名规则构造 Authorization 签名 + * + * @param mchid 商户号 + * @param certificateSerialNo 商户API证书序列号 + * @param privateKey 商户API证书私钥 + * @param method 请求接口的HTTP方法,请使用全大写表述,如 GET、POST、PUT、DELETE + * @param uri 请求接口的URL + * @param body 请求接口的Body + * @return 构造好的微信支付APIv3 Authorization 头 + */ + public static String buildAuthorization(String mchid, String certificateSerialNo, + PrivateKey privateKey, + String method, String uri, String body) { + String nonce = createNonce(32); + long timestamp = Instant.now().getEpochSecond(); + + String message = String.format("%s\n%s\n%d\n%s\n%s\n", method, uri, timestamp, nonce, + body == null ? "" : body); + + String signature = sign(message, "SHA256withRSA", privateKey); + + return String.format( + "WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",signature=\"%s\"," + + "timestamp=\"%d\",serial_no=\"%s\"", + mchid, nonce, signature, timestamp, certificateSerialNo); + } + + /** + * 对参数进行 URL 编码 + * + * @param content 参数内容 + * @return 编码后的内容 + */ + public static String urlEncode(String content) { + try { + return URLEncoder.encode(content, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + /** + * 对参数Map进行 URL 编码,生成 QueryString + * + * @param params Query参数Map + * @return QueryString + */ + public static String urlEncode(Map params) { + if (params == null || params.isEmpty()) { + return ""; + } + + int index = 0; + StringBuilder result = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + result.append(entry.getKey()) + .append("=") + .append(urlEncode(entry.getValue().toString())); + index++; + if (index < params.size()) { + result.append("&"); + } + } + return result.toString(); + } + + /** + * 从应答中提取 Body + * + * @param response HTTP 请求应答对象 + * @return 应答中的Body内容,Body为空时返回空字符串 + */ + public static String extractBody(Response response) { + if (response.body() == null) { + return ""; + } + + try { + BufferedSource source = response.body().source(); + return source.readUtf8(); + } catch (IOException e) { + throw new RuntimeException(String.format("An error occurred during reading response body. Status: %d", response.code()), e); + } + } + + /** + * 根据微信支付APIv3应答验签规则对应答签名进行验证,验证不通过时抛出异常 + * + * @param wechatpayPublicKeyId 微信支付公钥ID + * @param wechatpayPublicKey 微信支付公钥对象 + * @param headers 微信支付应答 Header 列表 + * @param body 微信支付应答 Body + */ + public static void validateResponse(String wechatpayPublicKeyId, PublicKey wechatpayPublicKey, + Headers headers, + String body) { + String timestamp = headers.get("Wechatpay-Timestamp"); + try { + Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestamp)); + // 拒绝过期请求 + if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= 5) { + throw new IllegalArgumentException( + String.format("Validate http response,timestamp[%s] of httpResponse is expires, " + + "request-id[%s]", + timestamp, headers.get("Request-ID"))); + } + } catch (DateTimeException | NumberFormatException e) { + throw new IllegalArgumentException( + String.format("Validate http response,timestamp[%s] of httpResponse is invalid, " + + "request-id[%s]", timestamp, + headers.get("Request-ID"))); + } + String message = String.format("%s\n%s\n%s\n", timestamp, headers.get("Wechatpay-Nonce"), + body == null ? "" : body); + String serialNumber = headers.get("Wechatpay-Serial"); + if (!Objects.equals(serialNumber, wechatpayPublicKeyId)) { + throw new IllegalArgumentException( + String.format("Invalid Wechatpay-Serial, Local: %s, Remote: %s", wechatpayPublicKeyId, + serialNumber)); + } + String signature = headers.get("Wechatpay-Signature"); + + boolean success = verify(message, signature, "SHA256withRSA", wechatpayPublicKey); + if (!success) { + throw new IllegalArgumentException( + String.format("Validate response failed,the WechatPay signature is incorrect.%n" + + "Request-ID[%s]\tresponseHeader[%s]\tresponseBody[%.1024s]", + headers.get("Request-ID"), headers, body)); + } + } + + /** + * 微信支付API错误异常,发送HTTP请求成功,但返回状态码不是 2XX 时抛出本异常 + */ + public static class ApiException extends RuntimeException { + public final int statusCode; + public final String body; + public final Headers headers; + public ApiException(int statusCode, String body, Headers headers) { + super(String.format("微信支付API访问失败,StatusCode: %s, Body: %s", statusCode, body)); + this.statusCode = statusCode; + this.body = body; + this.headers = headers; + } + } +} diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/CashoutService.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/CashoutService.java index f6e8903..bc374d8 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/CashoutService.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/CashoutService.java @@ -9,12 +9,15 @@ import org.springframework.web.bind.annotation.RequestMethod; public interface CashoutService { //会员中心-开通会员 - @ApiOperation(value="测试提现-提现", notes="测试提现-提现") - @RequestMapping(value = "/cashout", method = {RequestMethod.POST}) + public Result cashout(); //开通会员支付回调 //支付回调 - @PostMapping("/cashoutNotify") + public Object cashoutNotify(@RequestBody String requestBody); + + + //领取提现接口 + Result getMoney(String token,String id); } diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/LoginApiService.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/LoginApiService.java index 2c8d8e1..cd2db26 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/LoginApiService.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/LoginApiService.java @@ -17,4 +17,11 @@ public interface LoginApiService { //查询所有配置信息 Result getConfigInfo(); + + /** + * 微信小程序登录绑定手机号码接口 + * @param code + * @return + */ + Result bindPhone(String code); } diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/YaoDuApiService.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/YaoDuApiService.java index e1f4563..f0390e5 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/YaoDuApiService.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/YaoDuApiService.java @@ -115,6 +115,9 @@ public interface YaoDuApiService { //个人认证 Result personalAuthentication(String token, CitiyUserAuthentication object); + //获取个人认证信息 + Result getPersonalAuthentication(String token); + //企业认证 Result companyAuthentication(String token, CitiyShopAuthentication object); @@ -208,7 +211,7 @@ public interface YaoDuApiService { Result getSignRecord(String token,PageBean pageBean); //查看钱包流水 - Result getWalletFlow(String token,PageBean pageBean); + Result getWalletFlow(String token,String name,PageBean pageBean); //提现 diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/CashoutServiceImpl.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/CashoutServiceImpl.java index 26fae4c..f214a1a 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/CashoutServiceImpl.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/CashoutServiceImpl.java @@ -1,21 +1,39 @@ package org.jeecg.modules.api.service.impl; +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import lombok.extern.slf4j.Slf4j; import org.jeecg.common.api.vo.Result; +import org.jeecg.config.shiro.ShiroRealm; import org.jeecg.modules.api.service.CashoutService; +import org.jeecg.modules.cityMoneyLog.entity.CityMoneyLog; +import org.jeecg.modules.cityMoneyLog.service.ICityMoneyLogService; +import org.jeecg.modules.hanHaiMember.entity.HanHaiMember; +import org.jeecg.modules.pay.MpWxPayService; import org.jeecg.modules.transferTest.TransferToUser; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.util.Date; + @Slf4j @Service public class CashoutServiceImpl implements CashoutService { + //权限配置 + @Resource + private ShiroRealm shiroRealm; + //支付接口 + @Autowired + private MpWxPayService mpWxPayService; + @Autowired + private ICityMoneyLogService cityMoneyLogService; @Override public Result cashout() { String mchid = "1673516176"; String certiticateSerialNo ="525CDBD76E640EFB008288572C97D2715F3F18B2"; - String privateKeyFilePath = "jeecg-boot-module-system/src/main/resources/apiclient_key_yaodu.pem"; + String privateKeyFilePath = "/jeecg-boot-module-system/src/main/resources/apiclient_key_yaodu.pem"; String wechatPayPublicKeyId = "PUB_KEY_ID_0116735161762025040100448900000949"; - String wechatPayPublicKeyFilePaht = "jeecg-boot-module-system/src/main/resources/pub_key_yaodu.pem"; + String wechatPayPublicKeyFilePaht = "/jeecg-boot-module-system/src/main/resources/pub_key_yaodu.pem"; TransferToUser transferToUser = new TransferToUser(mchid, certiticateSerialNo, privateKeyFilePath, wechatPayPublicKeyId, wechatPayPublicKeyFilePaht ); transferToUser.run(); return Result.OK("测试提现结束"); @@ -24,6 +42,28 @@ public class CashoutServiceImpl implements CashoutService { @Override public Object cashoutNotify(String requestBody) { System.out.println("测试提现回调"); - return Result.OK("测试回调"); + System.out.println(requestBody); + + return Result.OK("测试回调结束"); + } + + + //领取提现接口 + @Override + public Result getMoney(String token,String id){ + HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token); + CityMoneyLog cityMoneyLog = cityMoneyLogService.lambdaQuery() + .eq(CityMoneyLog::getId,id) + .eq(CityMoneyLog::getUserId,hanHaiMember.getId()) + .eq(CityMoneyLog::getState,1) + .one(); + if(cityMoneyLog != null){ + cityMoneyLog.setState(2); + cityMoneyLog.setSuccesstime(new Date()); + cityMoneyLogService.updateById(cityMoneyLog); + }else{ + return Result.error("提现不存在"); + } + return Result.OK("领取提现结束"); } } diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/LoginApiServiceImpl.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/LoginApiServiceImpl.java index 9d10ea3..2e50dbe 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/LoginApiServiceImpl.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/LoginApiServiceImpl.java @@ -1,14 +1,23 @@ package org.jeecg.modules.api.service.impl; +import com.alibaba.fastjson.JSONObject; import org.jeecg.common.api.vo.Result; import org.jeecg.modules.api.service.LoginApiService; import org.jeecg.modules.bean.LoginReq; import org.jeecg.modules.cityConf.entity.CityConf; import org.jeecg.modules.cityConf.service.ICityConfService; import org.jeecg.modules.service.AppletLoginService; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.List; @Service @@ -19,6 +28,14 @@ public class LoginApiServiceImpl implements LoginApiService { @Resource private ICityConfService cityConfService; + + @Value("${wechat.mpAppId}") + private String mpAppId; + @Value("${wechat.mpAppSecret}") + private String mpAppSecret; + + + //小程序-登录接口 @Override public Result login(LoginReq loginReq) @@ -62,4 +79,67 @@ public class LoginApiServiceImpl implements LoginApiService { return Result.OK(list); } + + @Transactional(rollbackFor = Exception.class) + @Override + public Result bindPhone(String code) { + try { + String phoneNumber = this.getPhoneNumber(code); + return Result.OK(phoneNumber); + }catch (Exception e){ + return Result.error(e.getMessage()); + } + } + + private static final String API_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber"; + + public String getPhoneNumber(String code) throws Exception { + URL url = new URL(API_URL + "?access_token=" + this.getAccessToken()); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "application/json; utf-8"); + conn.setRequestProperty("Accept", "application/json"); + conn.setDoOutput(true); + + JSONObject jsonInput = new JSONObject(); + jsonInput.put("code", code); + + try (DataOutputStream os = new DataOutputStream(conn.getOutputStream())) { + byte[] input = jsonInput.toString().getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + + try (BufferedReader br = new BufferedReader( + new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) { + StringBuilder response = new StringBuilder(); + String responseLine; + while ((responseLine = br.readLine()) != null) { + response.append(responseLine.trim()); + } + //获取手机号码 + return response.toString(); + } + } + + + private static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"; + + public String getAccessToken() throws Exception { + String requestUrl = String.format(TOKEN_URL, mpAppId, mpAppSecret); + URL url = new URL(requestUrl); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + + try (BufferedReader br = new BufferedReader( + new InputStreamReader(conn.getInputStream(), "UTF-8"))) { + StringBuilder response = new StringBuilder(); + String responseLine; + while ((responseLine = br.readLine()) != null) { + response.append(responseLine.trim()); + } + + org.json.JSONObject jsonResponse = new org.json.JSONObject(response.toString()); + return jsonResponse.getString("access_token"); + } + } } diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/YaoDuApiServiceImpl.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/YaoDuApiServiceImpl.java index d49073e..1311004 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/YaoDuApiServiceImpl.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/service/impl/YaoDuApiServiceImpl.java @@ -106,7 +106,9 @@ import java.util.*; public class YaoDuApiServiceImpl implements YaoDuApiService { - + //查询配置 + @Resource + private ICityConfService cityConfService; //获取开通区域相关地址 @Resource private ICityAddrService cityService; @@ -160,9 +162,7 @@ public class YaoDuApiServiceImpl implements YaoDuApiService { //用户信息 @Resource private IHanHaiMemberService hanHaiMemberService; - //获取配置信息 - @Resource - private ICityConfService cityConfService; + //获取商城列表 @Resource private ICityShoppingService cityShoppingService; @@ -767,6 +767,17 @@ public class YaoDuApiServiceImpl implements YaoDuApiService { return Result.OK("提交成功,等待审核"); } + //获取个人认证信息 + @Override + public Result getPersonalAuthentication(String token){ + HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token); + CitiyUserAuthentication one = cityUserAuthenticationService. + lambdaQuery() + .eq(CitiyUserAuthentication::getUserId,hanHaiMember.getId()) + .one(); + return Result.OK(one); + } + //企业认证 @Override public Result companyAuthentication(String token, CitiyShopAuthentication object){ @@ -1540,6 +1551,7 @@ public class YaoDuApiServiceImpl implements YaoDuApiService { Page page = new Page(pageBean.getPageNo(), pageBean.getPageSize()); Page page1 = cityIntgerWaterService.lambdaQuery() .eq(CityIntgerWater::getUserId, hanHaiMember.getId()) + .orderByDesc(CityIntgerWater::getCreateTime) .page(page); return Result.OK(page1); @@ -1547,12 +1559,13 @@ public class YaoDuApiServiceImpl implements YaoDuApiService { //查看钱包流水 @Override - public Result getWalletFlow(String token,PageBean pageBean){ + public Result getWalletFlow(String token,String name,PageBean pageBean){ HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token); Page page = new Page(pageBean.getPageNo(), pageBean.getPageSize()); Page page1 = cityMoneyLogService .lambdaQuery() .eq(CityMoneyLog::getUserId, hanHaiMember.getId()) + .eq(StringUtils.isNotEmpty(name), CityMoneyLog::getName,name) .orderByDesc(CityMoneyLog::getCreateTime) .page(page); return Result.OK(page1); @@ -1563,13 +1576,32 @@ public class YaoDuApiServiceImpl implements YaoDuApiService { @Override public Result withdraw(String token, CityMoneyLog bean){ HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token); + //查询用户是否实名认证 + CitiyUserAuthentication one = cityUserAuthenticationService.lambdaQuery() + .eq(CitiyUserAuthentication::getUserId, hanHaiMember.getId()) + .one(); + if(one==null){ + return Result.error("请先实名认证"); + } + + //获取配置表中的提现手续费 + CityConf cityConf = cityConfService + .lambdaQuery() + .eq(CityConf::getKeyIcon, "withdraw_money") + .one(); + //得到提现手续费 + BigDecimal money = cityConf.getKeyMoney(); + money = money.multiply(bean.getPrice()); + + + if(bean.getPrice().compareTo(hanHaiMember.getPrice())>0){ return Result.error("余额不足"); } - //姓名不能为空 - if(StringUtils.isEmpty(bean.getName())){ - return Result.error("请填写姓名"); - } +// //姓名不能为空 +// if(StringUtils.isEmpty(bean.getName())){ +// return Result.error("请填写姓名"); +// } //金额不能为空 if(bean.getPrice().compareTo(new BigDecimal(0))<=0){ return Result.error("请填写金额"); @@ -1578,18 +1610,34 @@ public class YaoDuApiServiceImpl implements YaoDuApiService { if(bean.getPrice().scale()>0){ return Result.error("请填写整数金额"); } - //提现金额要大于1 - if(bean.getPrice().compareTo(new BigDecimal(1))<=0){ - return Result.error("请填写大于1的整数金额"); + //提现金额大于0的整数 + if(bean.getPrice().compareTo(new BigDecimal(0))<=0){ + return Result.error("请填写正确的金额"); } CityMoneyLog cityMoneyLog = new CityMoneyLog(); cityMoneyLog.setUserId(hanHaiMember.getId()); - cityMoneyLog.setName(bean.getName()); + + //提现者姓名 + if (StringUtils.isBlank(bean.getName())) { + cityMoneyLog.setName(bean.getName()); + }else{ + cityMoneyLog.setName(one.getName()); + } + + cityMoneyLog.setPrice(bean.getPrice()); cityMoneyLog.setState(0); cityMoneyLog.setType(0); cityMoneyLog.setTitle("用户提现"); cityMoneyLog.setCreateTime(new Date()); + + //实际到账金额 + cityMoneyLog.setGetPrice(bean.getPrice().subtract(money)); + + + + + cityMoneyLogService.save(cityMoneyLog); hanHaiMember.setPrice(hanHaiMember.getPrice().subtract(bean.getPrice())); hanHaiMemberService.updateById(hanHaiMember); diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/CashoutController.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/CashoutController.java index 4b55af1..fe633e3 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/CashoutController.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/CashoutController.java @@ -19,12 +19,12 @@ public class CashoutController { @Resource private CashoutService cashoutService; /******************************************************************************************************************/ - //会员中心-开通会员 - @ApiOperation(value="测试提现-提现", notes="测试提现-提现") - @RequestMapping(value = "/cashout", method = {RequestMethod.POST}) - public Result cashout(){ - return cashoutService.cashout(); - } +// //会员中心-开通会员 +// @ApiOperation(value="测试提现-提现", notes="测试提现-提现") +// @RequestMapping(value = "/cashout", method = {RequestMethod.POST}) +// public Result cashout(){ +// return cashoutService.cashout(); +// } //提现回调 @PostMapping("/cashoutNotify") @@ -32,4 +32,12 @@ public class CashoutController { return cashoutService.cashoutNotify(requestBody); } + + + //领取提现接口 + @ApiOperation(value="领取提现接口", notes="领取提现接口") + @RequestMapping(value = "/getMoney", method = {RequestMethod.GET}) + public Result getMoney(@RequestHeader("X-Access-Token") String token,String id){ + return cashoutService.getMoney(token,id); + } } diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/YaoDuApiTokenController.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/YaoDuApiTokenController.java index 7584feb..1f828fb 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/YaoDuApiTokenController.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/YaoDuApiTokenController.java @@ -92,6 +92,14 @@ public class YaoDuApiTokenController { return yaoDuApiService.personalAuthentication(token,object); } + + //获取个人认证信息 + @GetMapping(value = "/getPersonalAuthentication") + @ApiOperation(value="获取个人认证信息") + public Result getPersonalAuthentication(@RequestHeader("X-Access-Token") String token) { + return yaoDuApiService.getPersonalAuthentication(token); + } + //店铺认证 @PostMapping(value = "/companyAuthentication") @ApiOperation(value="店铺认证") @@ -257,9 +265,9 @@ public class YaoDuApiTokenController { //查看钱包流水 @ApiOperation(value="查看钱包流水") @GetMapping("/getWalletFlow") - public Result getWalletFlow(@RequestHeader("X-Access-Token") String token, PageBean pageBean) + public Result getWalletFlow(@RequestHeader("X-Access-Token") String token,String name, PageBean pageBean) { - return yaoDuApiService.getWalletFlow(token,pageBean); + return yaoDuApiService.getWalletFlow(token,name,pageBean); } diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/YaoDuLoginController.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/YaoDuLoginController.java index 96d7dfd..28c884c 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/YaoDuLoginController.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/api/yaoduapi/YaoDuLoginController.java @@ -55,4 +55,10 @@ public class YaoDuLoginController { } + //绑定手机号码 + @ApiOperation(value="绑定手机号码", notes="绑定手机号码") + @GetMapping(value = "/bindPhone") + public Result bindPhone(String phoneCode){ + return loginApiService.bindPhone(phoneCode); + } } diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/transferTest/TransferToUser.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/transferTest/TransferToUser.java index 558681b..b0d5f32 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/transferTest/TransferToUser.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/transferTest/TransferToUser.java @@ -81,9 +81,9 @@ public class TransferToUser { public void run(){ String mchid = "1673516176"; String certiticateSerialNo ="525CDBD76E640EFB008288572C97D2715F3F18B2"; - String privateKeyFilePath = "jeecg-boot-module-system/src/main/resources/apiclient_key_yaodu.pem"; + String privateKeyFilePath = "/jeecg-boot-module-system/src/main/resources/apiclient_key_yaodu.pem"; String wechatPayPublicKeyId = "PUB_KEY_ID_0116735161762025040100448900000949"; - String wechatPayPublicKeyFilePaht = "jeecg-boot-module-system/src/main/resources/pub_key_yaodu.pem"; + String wechatPayPublicKeyFilePaht = "/jeecg-boot-module-system/src/main/resources/pub_key_yaodu.pem"; TransferToUser client = new TransferToUser( mchid, // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756 certiticateSerialNo, // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053 @@ -94,7 +94,7 @@ public class TransferToUser { String appid = "wxa4d29e67e8a58d38"; String openid = "oFzrW4tqZUvN9T0RQzWPdCT1St68"; - String notifyUrl = "https://admin.hhlm1688.com/api/cashout/cashout/"; + String notifyUrl = "https://admin.hhlm1688.com/api/cashout/cashoutNotify"; TransferToUserRequest request = new TransferToUserRequest(); request.appid = appid; String idStr = "H" + IdWorker.getIdStr(); diff --git a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/transferTest/test.java b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/transferTest/test.java index 8dcae59..6ffb12a 100644 --- a/jeecg-boot-module-system/src/main/java/org/jeecg/modules/transferTest/test.java +++ b/jeecg-boot-module-system/src/main/java/org/jeecg/modules/transferTest/test.java @@ -4,9 +4,9 @@ public class test { public static void main(String[] args) { String mchid = "1673516176"; String certiticateSerialNo ="525CDBD76E640EFB008288572C97D2715F3F18B2"; - String privateKeyFilePath = "jeecg-boot-module-system/src/main/resources/apiclient_key_yaodu.pem"; + String privateKeyFilePath = "/jeecg-boot-module-system/src/main/resources/apiclient_key_yaodu.pem"; String wechatPayPublicKeyId = "PUB_KEY_ID_0116735161762025040100448900000949"; - String wechatPayPublicKeyFilePaht = "jeecg-boot-module-system/src/main/resources/pub_key_yaodu.pem"; + String wechatPayPublicKeyFilePaht = "/jeecg-boot-module-system/src/main/resources/pub_key_yaodu.pem"; TransferToUser transferToUser = new TransferToUser(mchid, certiticateSerialNo, privateKeyFilePath, wechatPayPublicKeyId, wechatPayPublicKeyFilePaht ); transferToUser.run(); } diff --git a/jeecg-boot-module-system/src/main/resources/application-dev.yml b/jeecg-boot-module-system/src/main/resources/application-dev.yml index 7a58ab9..a6afd56 100644 --- a/jeecg-boot-module-system/src/main/resources/application-dev.yml +++ b/jeecg-boot-module-system/src/main/resources/application-dev.yml @@ -1,5 +1,5 @@ server: - port: 8081 + port: 8000 tomcat: max-swallow-size: -1 error: