xinquan-modules/xinquan-order/src/main/java/com/xinquan/order/controller/client/ClientOrderController.java
@@ -1,6 +1,8 @@ package com.xinquan.order.controller.client; import cn.hutool.json.JSON; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson2.JSONObject; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; @@ -31,6 +33,7 @@ import com.xinquan.order.service.OrderPaymentRecordService; import com.xinquan.order.service.OrderService; import com.xinquan.course.api.domain.OrderCourseVO; import com.xinquan.order.utils.IosVerifyUtil; import com.xinquan.order.utils.OrderUtil; import com.xinquan.system.api.domain.AppUser; import com.xinquan.system.api.domain.AppUserCourse; @@ -52,6 +55,8 @@ import javax.annotation.Resource; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; @@ -94,7 +99,7 @@ private SysUserClient sysUserClient; @Autowired private TokenService tokenService; private static final String certificateUrl = "https://buy.itunes.apple.com/verifyReceipt"; @ResponseBody @PostMapping("/queryPayment") @ApiOperation(value = "查询订单支付状态", tags = "查询订单支付状态") @@ -466,6 +471,21 @@ return R.ok(); } private static final TrustManager myX509TrustManager = new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } }; @ResponseBody @PostMapping("/placeOrderApple") @ApiOperation(value = "苹果支付", notes = "苹果支付") @@ -476,6 +496,7 @@ @ApiImplicitParam(name = "balanceFlag", value = "是否使用余额抵扣 1=是 2=否", dataType = "Integer", required = false), @ApiImplicitParam(name = "amount", value = "购买会员的金额/充值金额", dataType = "BigDecimal", required = false), @ApiImplicitParam(name = "transactionIdentifier", value = "苹果订单id"), @ApiImplicitParam(name = "originTransactionIdentifier", value = "原苹果订单id"), @ApiImplicitParam(name = "vipType", value = "订单类型为会员时 必传 会员类型 1月度 2季度 3年度", dataType = "Integer", required = false), }) public R placeOrderApple( @@ -485,12 +506,213 @@ @RequestParam(value = "balanceFlag", required = false) Integer balanceFlag, @RequestParam(value = "amount", required = false) BigDecimal amount, @RequestParam(value = "vipType", required = false) Integer vipType, @RequestParam(value = "transactionIdentifier")String transactionIdentifier) @RequestParam(value = "transactionIdentifier")String transactionIdentifier, @RequestParam(value = "originTransactionIdentifier", required = false)String originTransactionIdentifier, @RequestParam(value = "receipt", required = false)String receipt ) throws Exception { System.err.println("普通:"+transactionIdentifier); System.err.println("原:"+originTransactionIdentifier); System.err.println("receipt:"+receipt); return R.ok(orderService.placeOrderApple(targetId, orderFrom, receiverId, balanceFlag,amount,vipType,transactionIdentifier)); balanceFlag,amount,vipType,transactionIdentifier,originTransactionIdentifier,receipt)); } @ResponseBody @PostMapping("/queryPlaceOrderApple") @ApiOperation(value = "查询苹果支付结果", notes = "查询苹果支付结果") @ApiImplicitParams({ @ApiImplicitParam(name = "transactionId", value = "苹果流水号", dataType = "Long", required = false), @ApiImplicitParam(name = "receipt", value = "支付凭证", dataType = "Integer", required = true), }) public R queryPlaceOrderApple( @RequestParam(value = "transactionId") String transactionId, @RequestParam(value = "receipt") String receipt) { System.err.println("手动查询苹果流水号"+transactionId); String verifyResult = IosVerifyUtil.buyAppVerify(receipt, 1); //苹果服务器没有返回验证结果 if (verifyResult == null) { return R.fail("未查询到订单信息"); } // 苹果验证有返回结果 System.err.println("线上,苹果平台返回JSON:" + verifyResult); JSON job = JSONUtil.parse(verifyResult); String states = job.getByPath("status").toString(); //0 正常 //21000 App Store不能读取你提供的JSON对象 //21002 receipt-data域的数据有问题 //21003 receipt无法通过验证 //21004 提供的shared secret不匹配你账号中的shared secret //21005 receipt服务器当前不可用 //21006 receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送 //21007 receipt是Sandbox receipt,但却发送至生产系统的验证服务 //21008 receipt是生产receipt,但却发送至Sandbox环境的验证服务 if ("21007".equals(states)) { //是沙盒环境,应沙盒测试,否则执行下面 //2.再沙盒测试 发送平台验证 verifyResult = IosVerifyUtil.buyAppVerify(receipt, 0); System.err.println("沙盒环境,苹果平台返回JSON:" + verifyResult); job = JSONUtil.parse(verifyResult); states = job.getByPath("status").toString(); } System.err.println("苹果平台返回值:job" + job); if (states.equals("0")) { // 前端所提供的收据是有效的 验证成功 JSON inAppJson = JSONUtil.parse(JSONUtil.getByPath(job, "receipt.in_app")); List<JSON> jsons = JSONUtil.toList(inAppJson.toString(), JSON.class); System.err.println("支付订单列表"+jsons); //所有支付成功的订单号 List<String> transaction_id = jsons.stream().map(t -> t.getByPath("transaction_id").toString()) .distinct().collect(Collectors.toList()); if(transaction_id.contains(transactionId)){ OrderPaymentRecord two = orderPaymentRecordService.lambdaQuery() .eq(OrderPaymentRecord::getPayOrderNo, transactionId).ne(OrderPaymentRecord::getPaymentStatus, 2).one(); if (two != null) { Order one = orderService.getById(two.getOrderId()); if (one.getPaymentStatus() == 2) { return R.ok("当前订单已完成支付"); } one.setPaymentStatus(2); one.setPaymentTime(LocalDateTime.now()); orderService.updateById(one); OrderPaymentRecord one2 = orderPaymentRecordService.lambdaQuery().eq(OrderPaymentRecord::getOrderId, one.getId()) .ne(OrderPaymentRecord::getPaymentType, 4).one(); if (one2 != null) { one2.setPaymentStatus(2); orderPaymentRecordService.updateById(one2); } // 实际支付金额 BigDecimal realPayAmount = one.getRealPayAmount(); // 判断订单所属用户是否有上级 是否需要做分佣处理 AppUser data9 = remoteAppUserService.getAppUserById(one.getAppUserId() + "").getData(); if (one.getGiveUserId() != null) { remoteAppUserService.addNotice(one.getGiveUserId() + "", one.getBusinessId() + "", one.getAppUserId() + "", one.getTotalAmount() + ""); } if (data9.getInviteUserId() != null) { if (one.getOrderFrom() == 1 || one.getOrderFrom() == 2 || one.getOrderFrom() == 3) { // 查询实际支付价格 不包含余额抵扣价格 OrderPaymentRecord one1 = orderPaymentRecordService.lambdaQuery().eq(OrderPaymentRecord::getOrderId, one.getId()) .ne(OrderPaymentRecord::getPaymentType, 4).one(); // 分佣给上级 先远程查询分佣比例 CommissionRule data1 = sysUserClient.getCommission().getData(); if (data1 != null) { if (data1.getProportion() != null) { BigDecimal bigDecimal = one1.getPayAmount().multiply(data1.getProportion()).divide(new BigDecimal("100")) .setScale(2, BigDecimal.ROUND_DOWN); // 上级获取的分佣金额 AppUser appUserById = remoteAppUserService.getAppUserById(data9.getInviteUserId() + "").getData(); // 更新用户余额 // remoteAppUserService.updateAppUser( // AppUserDTO.builder().balance( // appUserById.getBalance().add(bigDecimal)) // .build(), SecurityConstants.INNER); // 新增分佣流水明细 AppUserWalletRecord appUserWalletRecord = new AppUserWalletRecord(); appUserWalletRecord.setAppUserId(data9.getInviteUserId()); appUserWalletRecord.setChangeType(1); appUserWalletRecord.setReason("分佣收益"); appUserWalletRecord.setAmount(bigDecimal); appUserWalletRecord.setChildAppUserId(one.getAppUserId()); appUserWalletRecord.setOrderId(one.getId()); remoteAppUserService.addBalanceRecord(appUserWalletRecord); one.setCommissionAmount(bigDecimal); one.setCommissionId(data9.getInviteUserId()); orderService.updateById(one); } } } } if (one.getPayType() == 4 || one.getPayType() == 5 || one.getPayType() == 6 || one.getPayType() == 7) { // 涉及到余额支付 新增一条余额支付记录 OrderPaymentRecord one1 = orderPaymentRecordService.lambdaQuery().eq(OrderPaymentRecord::getOrderId, one.getId()) .eq(OrderPaymentRecord::getPaymentType, 4).one(); AppUserWalletRecord appUserWalletRecord = new AppUserWalletRecord(); appUserWalletRecord.setAppUserId(data9.getInviteUserId()); String reason = null; switch (one.getOrderFrom()) { case 1: Meditation data1 = remoteMeditationService.getMeditationById(one.getBusinessId()).getData(); appUserWalletRecord.setChangeType(2); reason = "购买疗愈【" + data1.getMeditationTitle() + "】"; break; case 2: Course data2 = remoteCourseService.getCourseById(one.getBusinessId()).getData(); reason = "购买课程【" + data2.getCourseTitle() + "】"; appUserWalletRecord.setChangeType(2); // 增加用户与课程的关系表 if (one.getGiveUserId() != null) { remoteAppUserService.addAppUserCourse(one.getBusinessId(), one.getGiveUserId(), one.getId(), 1); } else { // 自己购买 remoteAppUserService.addAppUserCourse(one.getBusinessId(), one.getAppUserId(), one.getId(), 2); } break; case 3: // 会员 reason = "购买会员【" + one.getBuyContent() + "】"; appUserWalletRecord.setChangeType(2); break; case 4: // 充值 reason = "充值"; appUserWalletRecord.setChangeType(1); break; } appUserWalletRecord.setReason(reason); appUserWalletRecord.setAmount(one1.getPayAmount()); appUserWalletRecord.setChildAppUserId(one.getAppUserId()); appUserWalletRecord.setOrderId(one.getId()); remoteAppUserService.addBalanceRecord(appUserWalletRecord); } else { switch (one.getOrderFrom()) { case 2: Course data2 = remoteCourseService.getCourseById(one.getBusinessId()).getData(); // 增加用户与课程的关系表 if (one.getGiveUserId() != null) { remoteAppUserService.addAppUserCourse(one.getBusinessId(), one.getGiveUserId(), one.getId(), 1); } else { // 自己购买 remoteAppUserService.addAppUserCourse(one.getBusinessId(), one.getAppUserId(), one.getId(), 2); } break; case 3: // 会员 if (one.getBuyContent().contains("月")) { remoteAppUserService.addVipExpireTime(one.getAppUserId(), 1); } else if (one.getBuyContent().contains("季")) { remoteAppUserService.addVipExpireTime(one.getAppUserId(), 2); } else if (one.getBuyContent().contains("年")) { remoteAppUserService.addVipExpireTime(one.getAppUserId(), 3); } break; case 4: System.err.println("进入充值"); remoteAppUserService.addBalance(one.getAppUserId(), one.getTotalAmount()); AppUserWalletRecord appUserWalletRecord = new AppUserWalletRecord(); appUserWalletRecord.setAppUserId(one.getAppUserId()); appUserWalletRecord.setChangeType(1); appUserWalletRecord.setReason("充值"); appUserWalletRecord.setAmount(one.getTotalAmount()); appUserWalletRecord.setChildAppUserId(one.getAppUserId()); appUserWalletRecord.setOrderId(one.getId()); remoteAppUserService.addBalanceRecord(appUserWalletRecord); break; } } } return R.ok("支付成功"); }else{ return R.fail("未查询到订单信息"); } } else { return R.fail("支付凭证receipt无效"); } } @ResponseBody @PostMapping("/gvieCourse") xinquan-modules/xinquan-order/src/main/java/com/xinquan/order/domain/OrderPaymentRecord.java
@@ -50,4 +50,8 @@ @ApiModelProperty(value = "支付状态 1=待支付 2=已完成 3=已取消") @TableField("payment_status") private Integer paymentStatus; @ApiModelProperty(value = "MD5加密后的支付凭证 ios验证支付使用") @TableField("receipt") private String receipt; } xinquan-modules/xinquan-order/src/main/java/com/xinquan/order/service/OrderService.java
@@ -40,7 +40,11 @@ */ List<Order> getOrderListByType(Long userId, Integer orderFrom); String placeOrderApple(Long targetId, Integer orderFrom, Long receiverId, Integer balanceFlag, BigDecimal amount, Integer vipType, String transactionIdentifier); String placeOrderApple(Long targetId, Integer orderFrom, Long receiverId, Integer balanceFlag, BigDecimal amount, Integer vipType, String transactionIdentifier, String originTransactionIdentifier,String receipt); String refund(Long uid) throws Exception; } xinquan-modules/xinquan-order/src/main/java/com/xinquan/order/service/impl/OrderServiceImpl.java
@@ -21,6 +21,7 @@ import com.xinquan.order.service.OrderPaymentRecordService; import com.xinquan.order.service.OrderService; import com.xinquan.common.core.utils.JuHeFuUtil; import com.xinquan.order.utils.MD5Generator; import com.xinquan.order.utils.OrderUtil; import com.xinquan.system.api.domain.AppUser; import com.xinquan.system.api.domain.AppUserWalletRecord; @@ -448,7 +449,10 @@ @Override public String placeOrderApple(Long targetId, Integer orderFrom, Long receiverId, Integer balanceFlag, BigDecimal amount, Integer vipType, String transactionIdentifier) { BigDecimal amount, Integer vipType, String transactionIdentifier ,String originTransactionIdentifier,String receipt) { // String s = MD5Generator.generateMD5(receipt); // 获取当前登录用户id Long userId = tokenService.getLoginUser().getUserid(); // 获取用户信息 @@ -494,6 +498,7 @@ paymentRecord.setOrderId(orderId); paymentRecord.setPaymentType(PaymentTypeEnum.IOS_PAY.getCode()); paymentRecord.setPaymentStatus(PaymentStatusEnum.TO_BE_PAID.getCode()); // paymentRecord.setReceipt(s); orderPaymentRecordService.save(paymentRecord); } @@ -507,6 +512,8 @@ paymentRecord.setOrderId(orderId); paymentRecord.setPaymentType(PaymentTypeEnum.IOS_PAY.getCode()); paymentRecord.setPaymentStatus(PaymentStatusEnum.TO_BE_PAID.getCode()); // paymentRecord.setReceipt(s); orderPaymentRecordService.save(paymentRecord); } } @@ -548,6 +555,8 @@ paymentRecord.setOrderId(orderId); paymentRecord.setPaymentType(PaymentTypeEnum.IOS_PAY.getCode()); paymentRecord.setPaymentStatus(PaymentStatusEnum.TO_BE_PAID.getCode()); // paymentRecord.setReceipt(s); orderPaymentRecordService.save(paymentRecord); } } else { @@ -560,6 +569,8 @@ paymentRecord.setOrderId(orderId); paymentRecord.setPaymentType(PaymentTypeEnum.IOS_PAY.getCode()); paymentRecord.setPaymentStatus(PaymentStatusEnum.TO_BE_PAID.getCode()); // paymentRecord.setReceipt(s); orderPaymentRecordService.save(paymentRecord); } } @@ -586,7 +597,6 @@ order.setBuyContent(vipType1); this.save(order); Long orderId = order.getId(); order.setPayType(3); this.updateById(order); // 创建支付订单 @@ -596,6 +606,8 @@ paymentRecord.setOrderId(orderId); paymentRecord.setPaymentType(PaymentTypeEnum.IOS_PAY.getCode()); paymentRecord.setPaymentStatus(PaymentStatusEnum.TO_BE_PAID.getCode()); // paymentRecord.setReceipt(s); orderPaymentRecordService.save(paymentRecord); }else { // 充值 @@ -607,7 +619,6 @@ order.setAppUserId(userId); order.setTotalAmount(amount); order.setRealPayAmount(amount); order.setBuyContent("充值"); this.save(order); Long orderId = order.getId(); @@ -620,6 +631,7 @@ paymentRecord.setOrderId(orderId); paymentRecord.setPaymentType(PaymentTypeEnum.IOS_PAY.getCode()); paymentRecord.setPaymentStatus(PaymentStatusEnum.TO_BE_PAID.getCode()); // paymentRecord.setReceipt(s); orderPaymentRecordService.save(paymentRecord); } return order.getId()+""; xinquan-modules/xinquan-order/src/main/java/com/xinquan/order/utils/IosVerifyUtil.java
New file @@ -0,0 +1,115 @@ package com.xinquan.order.utils; import javax.net.ssl.*; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Locale; /** * @desc: 苹果IAP内购验证工具类 * @author: hwm * @date: 2019/9/3 17:11 */ public class IosVerifyUtil { private static class TrustAnyTrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } } private static class TrustAnyHostnameVerifier implements HostnameVerifier { public boolean verify(String hostname, SSLSession session) { return true; } } // 沙盒环境 private static final String url_sandbox = "https://sandbox.itunes.apple.com/verifyReceipt"; // 生产环境 private static final String url_verify = "https://buy.itunes.apple.com/verifyReceipt"; public static void main(String[] args) { System.err.println(buyAppVerify("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",0)); } /** * 苹果服务器验证 * * @param receipt 账单 * @return null 或返回结果 沙盒 https://sandbox.itunes.apple.com/verifyReceipt * @url 要验证的地址 */ public static String buyAppVerify(String receipt, int type) { //环境判断 线上/开发环境用不同的请求链接 String url = ""; if (type == 0) { url = url_sandbox; //沙盒测试 } else { url = url_verify; //线上测试 } //String url = EnvUtils.isOnline() ?url_verify : url_sandbox; try { SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom()); URL console = new URL(url); HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); conn.setSSLSocketFactory(sc.getSocketFactory()); conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); conn.setRequestMethod("POST"); // conn.setRequestProperty("content-type", "text/json"); conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Proxy-Connection", "Keep-Alive"); conn.setDoInput(true); conn.setDoOutput(true); BufferedOutputStream hurlBufOus = new BufferedOutputStream(conn.getOutputStream()); String str = String.format(Locale.CHINA, "{\"receipt-data\":\"" + receipt + "\"}");//拼成固定的格式传给平台 hurlBufOus.write(str.getBytes()); hurlBufOus.flush(); InputStream is = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String line = null; StringBuffer sb = new StringBuffer(); while ((line = reader.readLine()) != null) { sb.append(line); } return sb.toString(); } catch (Exception ex) { System.out.println("苹果服务器异常"); ex.printStackTrace(); } return null; } /** * 用BASE64加密 * * @param str * @return */ public static String getBASE64(String str) { byte[] b = str.getBytes(); String s = null; if (b != null) { s = new sun.misc.BASE64Encoder().encode(b); } return s; } } xinquan-modules/xinquan-order/src/main/java/com/xinquan/order/utils/MD5Generator.java
New file @@ -0,0 +1,32 @@ package com.xinquan.order.utils; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5Generator { public static String generateMD5(String input) { try { // Create MD5 Hash MessageDigest digest = MessageDigest.getInstance("MD5"); digest.update(input.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuilder hexString = new StringBuilder(); for (byte aMessageDigest : messageDigest) { String h = Integer.toHexString(0xFF & aMessageDigest); while (h.length() < 2) h = "0" + h; hexString.append(h); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } public static void main(String[] args) { String myString = "968484"; System.err.println("MD5 of '" + myString + "' is: " + generateMD5(myString)); } }