Kaynağa Gözat

feat : 米大师支付代码提交

bilingfeng 2 yıl önce
ebeveyn
işleme
9f5124ece4

+ 3 - 7
game-module/game-sdk/src/main/java/com/zanxiang/sdk/common/miPay/UrlConstants.java → game-module/game-sdk/src/main/java/com/zanxiang/sdk/common/constant/MiPayConstants.java

@@ -1,10 +1,11 @@
-package com.zanxiang.sdk.common.miPay;
+package com.zanxiang.sdk.common.constant;
 
 
 /**
 /**
  * @author xufeng
  * @author xufeng
  * @date 2022/7/14 17:26
  * @date 2022/7/14 17:26
  */
  */
-public class UrlConstants {
+public class MiPayConstants {
+
     /**
     /**
      * 支付
      * 支付
      */
      */
@@ -25,14 +26,9 @@ public class UrlConstants {
      */
      */
     public final static String BALANCE_URL = "https://api.weixin.qq.com/cgi-bin/midas/getbalance";
     public final static String BALANCE_URL = "https://api.weixin.qq.com/cgi-bin/midas/getbalance";
 
 
-
     /**
     /**
      * token获取
      * token获取
      */
      */
     public final static String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
     public final static String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
 
 
-    
-    public final static String CLIENT_CREDENTIAL = "client_credential";
-
-
 }
 }

+ 0 - 125
game-module/game-sdk/src/main/java/com/zanxiang/sdk/common/miPay/MiPayClient.java

@@ -1,125 +0,0 @@
-package com.zanxiang.sdk.common.miPay;
-
-import com.alibaba.fastjson.JSONObject;
-import com.zanxiang.common.enums.HttpStatusEnum;
-import com.zanxiang.common.exception.CustomException;
-import com.zanxiang.common.utils.StringUtils;
-import com.zanxiang.sdk.common.constant.RedisKeyConstant;
-import com.zanxiang.sdk.common.util.HttpUtil;
-import com.zanxiang.sdk.common.util.RedisUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.HashMap;
-import java.util.Objects;
-
-/**
- * 支付
- *
- * @author xufeng
- * @date 2022/7/14 17:39
- */
-@Slf4j
-@Component
-public class MiPayClient {
-
-    private static final Logger logger = LoggerFactory.getLogger(MiPayClient.class);
-    @Autowired
-    private RedisUtil<String> redisUtil;
-
-    private static final String method = "POST";
-
-    private static final String contentType = "application/octet-stream; charset=utf-8";
-
-
-    /**
-     * 获取AccessToken
-     *
-     * @param appId
-     * @param appSecret
-     * @return AccessToken
-     */
-    private String getAccessToken(String appId, String appSecret) {
-        String redisKey = RedisKeyConstant.WEIXIN_ACCESS_TOKEN + appId;
-        String cache = redisUtil.getCache(redisKey);
-        if (StringUtils.isNotEmpty(cache)) {
-            return cache;
-        }
-        HashMap<String, String> param = new HashMap<>();
-        param.put("grant_type", UrlConstants.CLIENT_CREDENTIAL);
-        param.put("appid", appId);
-        param.put("secret", appSecret);
-        String result = HttpUtil.postData(UrlConstants.TOKEN_URL, param);
-        if (StringUtils.isEmpty(result)) {
-            return "";
-        }
-        JSONObject data = JSONObject.parseObject(result);
-        if (Objects.isNull(data)) {
-            return "";
-        }
-        Object accessToken = data.get("access_token");
-        if (Objects.isNull(accessToken)) {
-            return "";
-        }
-        String token = accessToken.toString();
-        redisUtil.setCache(redisKey, token, Long.valueOf(data.get("expires_in").toString()));
-        return token;
-    }
-
-    /**
-     * 接口请求
-     *
-     * @param url         请求路径
-     * @param params      请求参数
-     * @param appSecret   密钥
-     * @param midasAppKey 米大师key
-     * @param sessionKey  session
-     * @return
-     */
-    public HashMap<String, String> api(String url, RequestParam params, String midasAppKey, String sessionKey, String appSecret) {
-        try {
-            if (StringUtils.isEmpty(params.getOpenid()) ||
-                    StringUtils.isEmpty(params.getAppid()) ||
-                    StringUtils.isEmpty(params.getOffer_id()) ||
-                    params.getTs() <= 0 || StringUtils.isEmpty(params.getZone_id())
-            ) {
-                throw new CustomException(HttpStatusEnum.PARAM_IS_NULL.getMsg() + JSONObject.toJSONString(params));
-            }
-            String accessToken = getAccessToken(params.getAppid(), params.getAccess_token());
-            if (StringUtils.isEmpty(accessToken)) {
-                throw new CustomException(HttpStatusEnum.ACCESS_TOKEN_CREATE_ERROR);
-            }
-            //使用沙箱时,沙箱地址替换
-            if (params.getIs_sand() == 1) {
-                url = url.replace("/cgi-bin/midas/", "/cgi-bin/midas/sandbox/");
-            }
-            HashMap<String, String> paramsMap = JSONObject.parseObject(JSONObject.toJSONString(params), HashMap.class);
-            paramsMap.remove("is_sand");
-            String sig = SnsSigCheck.makeSig(method, url, paramsMap, params.getApp_key());
-            params.setSig(sig);
-            params.setAccess_token(accessToken);
-            url += "?access_token=" + accessToken;
-            String result = HttpUtil.postData(url, JSONObject.toJSONString(params), contentType);
-            logger.info("米大师接口调用失败 url:{} params:{} result:{}", url, params, result);
-            if (StringUtils.isEmpty(result)) {
-                throw new CustomException(HttpStatusEnum.MDS_CONNECT_ERROR);
-            }
-            HashMap<String, String> data = JSONObject.parseObject(result, HashMap.class);
-            if (Objects.isNull(data)) {
-                throw new CustomException(HttpStatusEnum.MDS_CONNECT_ERROR);
-            }
-            if (!data.get("errcode").equals("0")) {
-                String errmsg = data.get("errmsg");
-                Integer errcode = Integer.valueOf(data.get("errcode"));
-                throw new CustomException(errmsg, errcode);
-            }
-            return data;
-        } catch (RuntimeException e) {
-            logger.error("米大师接口调用失败 url:{} params:{} e:{}", url, params, e);
-            throw new RuntimeException("米大师接口调用失败");
-        }
-    }
-}

+ 90 - 18
game-module/game-sdk/src/main/java/com/zanxiang/sdk/common/miPay/RequestParam.java

@@ -8,22 +8,94 @@ import lombok.Data;
  */
  */
 @Data
 @Data
 public class RequestParam {
 public class RequestParam {
-    private String openid = ""; /* 用户唯一标识符 */
-    private String appid = ""; /* 小程序 appId*/
-    private String app_key = ""; /* 米大师分配的*/
-    private String offer_id = ""; /* 米大师分配的offer_id */
-    private Long ts = System.currentTimeMillis(); /* UNIX时间戳 */
-    private String zone_id = "1"; /* 游戏服务器大区id,游戏不分大区则默认zoneId ="1",String类型。如过应用选择支持角色,则角色ID接在分区ID号后用"_"连接。 */
-    private String pf = "android"; /* 平台 安卓:android */
-    private String user_ip = ""; /* 用户外网 IP */
-    private String amt = ""; /* 扣除游戏币数量,不能为 0 */
-    private String bill_no = ""; /* 订单号,业务需要保证全局唯一;相同的订单号不会重复扣款。长度不超过63,只能是数字、大小写字母_- */
-    private String pay_item = ""; /* 道具名称 */
-    private String app_remark = ""; /* 备注。会写到账户流水 */
-    private String sig = ""; /* 以上所有参数(含可选最多11个)+uri+米大师密钥,用 HMAC-SHA256签名 */
-    private String access_token = ""; /* 接口调用凭证 */
-    private String mp_sig = ""; /* 以上所有参数(含可选最多11个)+uri+米大师密钥 */
-    private Integer is_sand = 1; /* 1 表示沙盒环境 2 表示正式环境 */
-    private Integer present_counts = 0; /* 赠送游戏币数量,不能为0 */
-    private String method = "POST"; /* 请求方式 */
+
+    /**
+     * 用户唯一标识符
+     */
+    private String openid;
+
+    /**
+     * 小程序 appId
+     */
+    private String appid;
+
+    /**
+     * 米大师appKey
+     */
+    private String app_key;
+
+    /**
+     * 米大师应用id
+     */
+    private String offer_id;
+
+    /**
+     * UNIX时间戳
+     */
+    private Long ts = System.currentTimeMillis() / 1000;
+
+    /**
+     * 游戏服务器大区id,游戏不分大区则默认zoneId ="1",String类型。如过应用选择支持角色,则角色ID接在分区ID号后用"_"连接。
+     */
+    private String zone_id = "1";
+
+    /**
+     * 平台 安卓:android
+     */
+    private String pf = "android";
+
+    /**
+     * 用户外网 IP
+     */
+    private String user_ip;
+
+    /**
+     * 扣除游戏币数量,不能为 0
+     */
+    private String amt;
+
+    /**
+     * 订单号,业务需要保证全局唯一;相同的订单号不会重复扣款。长度不超过63,只能是数字、大小写字母
+     */
+    private String bill_no;
+
+    /**
+     * 道具名称
+     */
+    private String pay_item;
+
+    /**
+     * 备注。会写到账户流水
+     */
+    private String app_remark;
+
+    /**
+     * 以上所有参数(含可选最多11个)+uri+米大师密钥,用 HMAC-SHA256签名
+     */
+    private String sig;
+
+    /**
+     * 接口调用凭证
+     */
+    private String access_token;
+
+    /**
+     * 以上所有参数(含可选最多11个)+uri+米大师密钥
+     */
+    private String mp_sig;
+
+    /**
+     * 1 表示沙盒环境 2 表示正式环境
+     */
+    private Integer is_sand = 1;
+
+    /**
+     * 赠送游戏币数量,不能为0
+     */
+    private Integer present_counts;
+
+    /**
+     * 请求方式
+     */
+    private String method = "POST";
 }
 }

+ 0 - 188
game-module/game-sdk/src/main/java/com/zanxiang/sdk/common/miPay/SnsSigCheck.java

@@ -1,188 +0,0 @@
-package com.zanxiang.sdk.common.miPay;
-
-import com.zanxiang.common.enums.HttpStatusEnum;
-import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
-
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-
-/**
- * 生成签名类
- *
- * @author xufeng
- * @date 2022/7/14 17:39
- */
-
-public class SnsSigCheck {
-
-    /**
-     * URL编码 (符合FRC1738规范)
-     *
-     * @param input 待编码的字符串
-     * @return 编码后的字符串
-     * @throws RuntimeException 不支持指定编码时抛出异常。
-     */
-    public static String encodeUrl(String input) throws RuntimeException {
-        try {
-            return URLEncoder.encode(input, CONTENT_CHARSET).replace("+", "%20").replace("*", "%2A");
-        } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException(HttpStatusEnum.MAKE_SIGNATURE_ERROR.getMsg(), e);
-        }
-    }
-
-    /** 生成签名
-     *
-     * @param method HTTP请求方法 "get" / "post"
-     * @param url_path CGI名字, eg: /v3/user/get_info
-     * @param params URL请求参数
-     * @param secret 密钥
-     * @return 签名值
-     * @throws RuntimeException 不支持指定编码以及不支持指定的加密方法时抛出异常。
-     */
-    public static String makeSig(String method, String url_path, HashMap<String, String> params, String secret) throws RuntimeException {
-        String sig = null;
-        try {
-            Mac mac = Mac.getInstance(HMAC_ALGORITHM);
-            SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(CONTENT_CHARSET), mac.getAlgorithm());
-            mac.init(secretKey);
-            String mk = makeSource(method, url_path, params);
-            byte[] hash = mac.doFinal(mk.getBytes(CONTENT_CHARSET));
-            // base64
-            sig = new String(Base64Coder.encode(hash));
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException(HttpStatusEnum.MAKE_SIGNATURE_ERROR.getMsg(), e);
-        } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException(HttpStatusEnum.MAKE_SIGNATURE_ERROR.getMsg(), e);
-        } catch (InvalidKeyException e) {
-            throw new RuntimeException(HttpStatusEnum.MAKE_SIGNATURE_ERROR.getMsg(), e);
-        }
-        return sig;
-    }
-
-    /** 生成签名所需源串
-     *
-     * @param method HTTP请求方法 "get" / "post"
-     * @param url_path CGI名字, eg: /v3/user/get_info
-     * @param params URL请求参数
-     * @return 签名所需源串
-     * @throws RuntimeException 不支持指定编码以及不支持指定的加密方法时抛出异常。
-     */
-    public static String makeSource(String method, String url_path, HashMap<String, String> params) throws RuntimeException {
-        Object[] keys = params.keySet().toArray();
-
-        Arrays.sort(keys);
-
-        StringBuilder buffer = new StringBuilder(128);
-
-        buffer.append(method.toUpperCase()).append("&").append(encodeUrl(url_path)).append("&");
-
-        StringBuilder buffer2 = new StringBuilder();
-
-        for (int i = 0; i < keys.length; i++) {
-            buffer2.append(keys[i]).append("=").append(params.get(keys[i]));
-
-            if (i != keys.length - 1) {
-                buffer2.append("&");
-            }
-        }
-
-        buffer.append(encodeUrl(buffer2.toString()));
-
-        return buffer.toString();
-    }
-
-    public static boolean verifySig(String method, String url_path, HashMap<String, String> params, String secret, String sig) throws RuntimeException {
-        // 确保不含sig
-        params.remove("sig");
-
-        // 按照发货回调接口的编码规则对value编码
-        codePayValue(params);
-
-        // 计算签名
-        String sig_new = makeSig(method, url_path, params, secret);
-
-        // 对比和腾讯返回的签名
-        return sig_new.equals(sig);
-    }
-
-    /**
-     * 应用发货URL接口对腾讯回调传来的参数value值先进行一次编码方法,用于验签
-     * (编码规则为:除了 0~9 a~z A~Z !*() 之外其他字符按其ASCII码的十六进制加%进行表示,例如“-”编码为“%2D”)
-     * 参考 <回调发货URL的协议说明_V3>
-     *
-     * @param params 腾讯回调传参Map (key,value);
-     */
-    public static void codePayValue(Map<String, String> params) {
-        Set<String> keySet = params.keySet();
-        Iterator<String> itr = keySet.iterator();
-
-        while (itr.hasNext()) {
-            String key = (String) itr.next();
-            String value = (String) params.get(key);
-            value = encodeValue(value);
-            params.put(key, value);
-        }
-    }
-
-    /**
-     * 应用发货URL接口的编码规则
-     *
-     * @param s
-     * @return
-     */
-    public static String encodeValue(String s) {
-        String rexp = "[0-9a-zA-Z!*\\(\\)]";
-        StringBuffer sb = new StringBuffer(s);
-        StringBuffer sbRtn = new StringBuffer();
-        Pattern p = Pattern.compile(rexp);
-        char temp;
-        String tempStr;
-
-        for (int i = 0; i < sb.length(); i++) {
-            temp = sb.charAt(i);
-            tempStr = String.valueOf(temp);
-            Matcher m = p.matcher(tempStr);
-
-            boolean result = m.find();
-            if (!result) {
-                tempStr = hexString(tempStr);
-            }
-            sbRtn.append(tempStr);
-        }
-
-        return sbRtn.toString();
-    }
-
-    /**
-     * 应用发货URL 十六进制编码
-     *
-     * @param s
-     * @return
-     */
-    private static String hexString(String s) {
-        byte[] b = s.getBytes();
-        String retStr = "";
-        for (int i = 0; i < b.length; i++) {
-            String hex = Integer.toHexString(b[i] & 0xFF);
-            if (hex.length() == 1) {
-                hex = '0' + hex;
-            }
-            retStr = "%" + hex.toUpperCase();
-        }
-        return retStr;
-    }
-
-    // 编码方式
-    private static final String CONTENT_CHARSET = "UTF-8";
-
-    // HMAC算法
-    private static final String HMAC_ALGORITHM = "HmacSHA1";
-}

+ 128 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/common/util/MiPayUtil.java

@@ -0,0 +1,128 @@
+package com.zanxiang.sdk.common.util;
+
+import com.zanxiang.common.exception.BaseException;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * 生成签名类
+ *
+ * @author xufeng
+ * @date 2022/7/14 17:39
+ */
+
+public class MiPayUtil {
+
+    /**
+     * 生成签名
+     *
+     * @param method  HTTP请求方法 "get" / "post"
+     * @param urlPath CGI名字, eg: /v3/user/get_info
+     * @param params  URL请求参数
+     * @param secret  密钥
+     * @return 签名值
+     * @throws RuntimeException 不支持指定编码以及不支持指定的加密方法时抛出异常。
+     */
+    public static String miPaySin(String method, String urlPath, Map<String, String> params, String secret) {
+        String sig;
+        Object[] keys = params.keySet().toArray();
+        Arrays.sort(keys);
+        StringBuilder stringBuilder = new StringBuilder();
+        for (int i = 0; i < keys.length; i++) {
+            stringBuilder.append(keys[i]).append("=").append(params.get(keys[i]));
+            if (i != keys.length - 1) {
+                stringBuilder.append("&");
+            }
+        }
+        stringBuilder.append("&org_loc=").append(urlPath)
+                .append("&method=").append(method.toUpperCase())
+                .append("&secret=").append(secret);
+        //加密算法返回
+        try {
+            sig = WxPayUtil.HMACSHA256(stringBuilder.toString(), secret, Boolean.FALSE);
+        } catch (Exception e) {
+            throw new BaseException("米大师签名失败");
+        }
+        return sig;
+    }
+
+
+    /**
+     * 应用发货URL接口对腾讯回调传来的参数value值先进行一次编码方法,用于验签
+     * (编码规则为:除了 0~9 a~z A~Z !*() 之外其他字符按其ASCII码的十六进制加%进行表示,例如“-”编码为“%2D”)
+     * 参考 <回调发货URL的协议说明_V3>
+     *
+     * @param params 腾讯回调传参Map (key,value);
+     */
+    public static void codePayValue(Map<String, String> params) {
+        Set<String> keySet = params.keySet();
+        Iterator<String> itr = keySet.iterator();
+
+        while (itr.hasNext()) {
+            String key = itr.next();
+            String value = params.get(key);
+            value = encodeValue(value);
+            params.put(key, value);
+        }
+    }
+
+    /**
+     * 应用发货URL接口的编码规则
+     *
+     * @param s
+     * @return
+     */
+    public static String encodeValue(String s) {
+        String rexp = "[0-9a-zA-Z!*\\(\\)]";
+        StringBuffer sb = new StringBuffer(s);
+        StringBuffer sbRtn = new StringBuffer();
+        Pattern p = Pattern.compile(rexp);
+        char temp;
+        String tempStr;
+
+        for (int i = 0; i < sb.length(); i++) {
+            temp = sb.charAt(i);
+            tempStr = String.valueOf(temp);
+            Matcher m = p.matcher(tempStr);
+
+            boolean result = m.find();
+            if (!result) {
+                tempStr = hexString(tempStr);
+            }
+            sbRtn.append(tempStr);
+        }
+
+        return sbRtn.toString();
+    }
+
+    /**
+     * 应用发货URL 十六进制编码
+     *
+     * @param s
+     * @return
+     */
+    private static String hexString(String s) {
+        byte[] b = s.getBytes();
+        String retStr = "";
+        for (int i = 0; i < b.length; i++) {
+            String hex = Integer.toHexString(b[i] & 0xFF);
+            if (hex.length() == 1) {
+                hex = '0' + hex;
+            }
+            retStr = "%" + hex.toUpperCase();
+        }
+        return retStr;
+    }
+
+    // 编码方式
+    private static final String CONTENT_CHARSET = "UTF-8";
+
+    // HMAC算法
+    private static final String HMAC_ALGORITHM = "HmacSHA256";
+}

+ 6 - 3
game-module/game-sdk/src/main/java/com/zanxiang/sdk/common/util/WxPayUtil.java

@@ -111,7 +111,7 @@ public class WxPayUtil {
         if (Objects.equals(SIGN_MD5, signType)) {
         if (Objects.equals(SIGN_MD5, signType)) {
             return MD5(sb.toString()).toUpperCase();
             return MD5(sb.toString()).toUpperCase();
         } else if (Objects.equals(SIGN_HMACSHA256, signType)) {
         } else if (Objects.equals(SIGN_HMACSHA256, signType)) {
-            return HMACSHA256(sb.toString(), key);
+            return HMACSHA256(sb.toString(), key, Boolean.TRUE);
         } else {
         } else {
             throw new Exception(String.format("Invalid sign_type: %s", signType));
             throw new Exception(String.format("Invalid sign_type: %s", signType));
         }
         }
@@ -158,7 +158,7 @@ public class WxPayUtil {
      * @return 加密结果
      * @return 加密结果
      * @throws Exception : 异常
      * @throws Exception : 异常
      */
      */
-    private static String HMACSHA256(String data, String key) throws Exception {
+    public static String HMACSHA256(String data, String key, boolean upperCase) throws Exception {
         Mac sha256HMAC = Mac.getInstance("HmacSHA256");
         Mac sha256HMAC = Mac.getInstance("HmacSHA256");
         SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
         SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
         sha256HMAC.init(secretKey);
         sha256HMAC.init(secretKey);
@@ -167,6 +167,9 @@ public class WxPayUtil {
         for (byte item : array) {
         for (byte item : array) {
             sb.append(Integer.toHexString((item & 0xFF) | 0x100), 1, 3);
             sb.append(Integer.toHexString((item & 0xFF) | 0x100), 1, 3);
         }
         }
-        return sb.toString().toUpperCase();
+        if (upperCase) {
+            return sb.toString().toUpperCase();
+        }
+        return sb.toString();
     }
     }
 }
 }

+ 0 - 62
game-module/game-sdk/src/main/java/com/zanxiang/sdk/controller/OrderController.java

@@ -1,27 +1,14 @@
 package com.zanxiang.sdk.controller;
 package com.zanxiang.sdk.controller;
 
 
 import com.zanxiang.common.domain.ResultMap;
 import com.zanxiang.common.domain.ResultMap;
-import com.zanxiang.common.enums.PayDeviceEnum;
-import com.zanxiang.common.enums.PayWayEnum;
-import com.zanxiang.common.utils.JsonUtil;
 import com.zanxiang.common.utils.StringUtils;
 import com.zanxiang.common.utils.StringUtils;
 import com.zanxiang.common.utils.bean.BeanUtils;
 import com.zanxiang.common.utils.bean.BeanUtils;
-import com.zanxiang.mybatis.entity.GamePayWay;
-import com.zanxiang.sdk.common.annotation.ValidLogin;
-import com.zanxiang.sdk.common.miPay.RequestParam;
 import com.zanxiang.sdk.domain.bo.PlatformOrderBO;
 import com.zanxiang.sdk.domain.bo.PlatformOrderBO;
-import com.zanxiang.sdk.domain.dto.PlatformOrderDTO;
-import com.zanxiang.sdk.domain.params.MPayBalanceParam;
-import com.zanxiang.sdk.domain.params.OrderCheckInfoParam;
 import com.zanxiang.sdk.domain.params.PreOrderParam;
 import com.zanxiang.sdk.domain.params.PreOrderParam;
 import com.zanxiang.sdk.domain.params.UserData;
 import com.zanxiang.sdk.domain.params.UserData;
-import com.zanxiang.sdk.domain.vo.MiniAppConfigVO;
-import com.zanxiang.sdk.domain.vo.OrderCheckInfoVO;
-import com.zanxiang.sdk.domain.vo.PreOrderMiPayConfigVO;
 import com.zanxiang.sdk.domain.vo.PreOrderVO;
 import com.zanxiang.sdk.domain.vo.PreOrderVO;
 import com.zanxiang.sdk.service.GamePayWayService;
 import com.zanxiang.sdk.service.GamePayWayService;
 import com.zanxiang.sdk.service.GameStrategyService;
 import com.zanxiang.sdk.service.GameStrategyService;
-import com.zanxiang.sdk.service.MiPayService;
 import com.zanxiang.sdk.service.PlatformOrderService;
 import com.zanxiang.sdk.service.PlatformOrderService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
@@ -34,8 +21,6 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
 
 
-import java.util.Objects;
-
 /**
 /**
  * @author xufeng
  * @author xufeng
  * @date 2022/6/17 17:07
  * @date 2022/6/17 17:07
@@ -50,12 +35,6 @@ public class OrderController {
     @Autowired
     @Autowired
     private GameStrategyService gameStrategyService;
     private GameStrategyService gameStrategyService;
 
 
-    @Autowired
-    private MiPayService miPayService;
-
-    @Autowired
-    private GamePayWayService gamePayWayService;
-
     @ApiOperation(value = "订单生成")
     @ApiOperation(value = "订单生成")
     @PostMapping(value = "/preOrder")
     @PostMapping(value = "/preOrder")
     @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = PreOrderVO.class)})
     @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = PreOrderVO.class)})
@@ -74,49 +53,8 @@ public class OrderController {
         data.setPaySwitch(paySwitch);
         data.setPaySwitch(paySwitch);
         //todo 此处切换与产品定义切换含义不一致 游戏是否切换支付方式临时为true
         //todo 此处切换与产品定义切换含义不一致 游戏是否切换支付方式临时为true
         paySwitch = true;
         paySwitch = true;
-        if (paySwitch) {
-            RequestParam commonParam = miPayService.getCommonParam(Long.valueOf(order.getGameId()), String.valueOf(user.getUserId()));
-            //密钥不返回出去
-            commonParam.setApp_key("");
-            data.setPreOrderMiPayConfigVO(BeanUtils.copy(commonParam, PreOrderMiPayConfigVO.class));
-        }
-        //小程序支付, 返回小程序信息
-        if (Objects.equals(order.getPayDevice(), PayDeviceEnum.MINI_APP_PAY.getCode())) {
-            GamePayWay gamePayWay = gamePayWayService.getPayWayToOrderPay(order.getGameId(), PayWayEnum.WXPAY.getNum());
-            MiniAppConfigVO miniAppConfigVO = JsonUtil.toObj(gamePayWay.getPayConfig(), MiniAppConfigVO.class);
-            data.setMiniAppConfigVO(miniAppConfigVO);
-        }
         orderBo.setIsSwitch(paySwitch);
         orderBo.setIsSwitch(paySwitch);
         return ResultMap.ok(data);
         return ResultMap.ok(data);
     }
     }
 
 
-
-    @ApiOperation(value = "小程序获取跳转支付信息")
-    @PostMapping(value = "/checkInfo")
-    @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = PreOrderVO.class)})
-    public ResultMap checkInfo(@RequestBody OrderCheckInfoParam param, @ValidLogin UserData user) {
-        //不知道干嘛用的,临时放
-        String path = "pages/pay/index";
-        OrderCheckInfoVO result = new OrderCheckInfoVO();
-        result.setPath(path);
-        PlatformOrderDTO orderInfo = orderService.info(param.getOrderId(), param.getUserId());
-        if (PayDeviceEnum.MINI_APP_PAY.getCode().equals(user.getDeviceType())) {
-            RequestParam commonParam = miPayService.getCommonParam(orderInfo.getGameId(), param.getUserId());
-            if (StringUtils.isEmpty(commonParam.getAppid())) {
-                return ResultMap.error("获取小程序appId");
-            }
-            result.setMpId(commonParam.getAppid());
-        }
-        return ResultMap.ok(result);
-    }
-
-
-    @ApiOperation(value = "【米大师】查询余额")
-    @PostMapping(value = "/mPay_balance")
-    @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = PreOrderVO.class)})
-    public ResultMap mPayBalance(@RequestBody MPayBalanceParam mPayBalanceParam, @ValidLogin UserData user) {
-        Boolean result = miPayService.midasGetBalance(user.getUserId(), mPayBalanceParam.getOrderId());
-        return ResultMap.ok(result);
-    }
-
 }
 }

+ 0 - 212
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/MiPayServiceImpl.java

@@ -1,212 +0,0 @@
-package com.zanxiang.sdk.service.Impl;
-
-import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.zanxiang.common.domain.MiPayConfig;
-import com.zanxiang.common.enums.HttpStatusEnum;
-import com.zanxiang.common.enums.StatusEnum;
-import com.zanxiang.common.exception.CustomException;
-import com.zanxiang.common.utils.StringUtils;
-import com.zanxiang.mybatis.entity.GamePayWay;
-import com.zanxiang.mybatis.entity.PayApplication;
-import com.zanxiang.mybatis.entity.PayBox;
-import com.zanxiang.mybatis.mapper.PayApplicationMapper;
-import com.zanxiang.mybatis.mapper.PayBoxMapper;
-import com.zanxiang.sdk.common.constant.RedisKeyConstant;
-import com.zanxiang.sdk.common.miPay.MiPayClient;
-import com.zanxiang.sdk.common.miPay.RequestParam;
-import com.zanxiang.sdk.common.miPay.UrlConstants;
-import com.zanxiang.sdk.common.util.RedisUtil;
-import com.zanxiang.sdk.domain.dto.PlatformOrderDTO;
-import com.zanxiang.sdk.service.GamePayWayService;
-import com.zanxiang.sdk.service.MiPayService;
-import com.zanxiang.sdk.service.PlatformOrderService;
-import lombok.extern.slf4j.Slf4j;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.util.HashMap;
-import java.util.Objects;
-
-/**
- * 米大师服务实现
- *
- * @author xufeng
- * @date 2022/7/14 16:33
- */
-@Service
-@Slf4j
-public class MiPayServiceImpl implements MiPayService {
-    protected final Logger logger = LoggerFactory.getLogger(MiPayServiceImpl.class);
-
-    @Autowired
-    private RedisUtil<String> redisUtil;
-
-    @Autowired
-    private PlatformOrderService platformOrderService;
-
-    @Autowired
-    private GamePayWayService gamePayWayService;
-
-    @Resource
-    private MiPayClient miPayClient;
-
-    @Autowired
-    private PayApplicationMapper payApplicationMapper;
-
-    @Autowired
-    private PayBoxMapper payBoxMapper;
-
-    @Value("${spring.profiles.active}")
-    private String springActive;
-
-
-    @Override
-    public Boolean midasPay(Long userId, String orderId) {
-        PlatformOrderDTO orderInfo = platformOrderService.info(orderId);
-        if (Objects.isNull(orderInfo)) {
-            throw new CustomException(HttpStatusEnum.ORDER_NO_FIND);
-        }
-        if (orderInfo.getGameId() == null || orderInfo.getGameId() == 0) {
-            throw new CustomException(HttpStatusEnum.ORDER_GAME_ID_IS_NULL);
-        }
-        RequestParam commonParam = getCommonParam(orderInfo.getGameId(), orderInfo.getUserId());
-        commonParam.setBill_no(orderId);
-        HashMap<String, String> result = miPayClient.api(UrlConstants.PAY_URL, commonParam, null, null, null);
-        if (Objects.equals(HttpStatusEnum.SUCCESS.getCode().toString(), result.get("code"))) {
-            //成功
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public Boolean midasCancelPay(Long userId, String orderId) {
-        PlatformOrderDTO orderInfo = platformOrderService.info(orderId);
-        if (Objects.isNull(orderInfo)) {
-            throw new CustomException(HttpStatusEnum.ORDER_NO_FIND);
-        }
-        if (orderInfo.getGameId() == null || orderInfo.getGameId() == 0) {
-            throw new CustomException(HttpStatusEnum.ORDER_GAME_ID_IS_NULL);
-        }
-        RequestParam commonParam = getCommonParam(orderInfo.getGameId(), orderInfo.getUserId());
-        commonParam.setBill_no(orderId);
-        HashMap<String, String> result = miPayClient.api(UrlConstants.CANCEL_URL, commonParam, null, null, null);
-        if (Objects.equals(HttpStatusEnum.SUCCESS.getCode().toString(), result.get("code"))) {
-            //成功
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public Boolean midasGetBalance(Long userId, String orderId) {
-        PlatformOrderDTO orderInfo = platformOrderService.info(orderId);
-        if (Objects.isNull(orderInfo)) {
-            throw new CustomException(HttpStatusEnum.ORDER_NO_FIND);
-        }
-        if (orderInfo.getGameId() == null || orderInfo.getGameId() == 0) {
-            throw new CustomException(HttpStatusEnum.ORDER_GAME_ID_IS_NULL);
-        }
-        RequestParam commonParam = getCommonParam(orderInfo.getGameId(), orderInfo.getUserId());
-        commonParam.setBill_no(orderId);
-        commonParam.setPresent_counts(orderInfo.getProductCnt());
-        HashMap<String, String> result = miPayClient.api(UrlConstants.BALANCE_URL, commonParam, null, null, null);
-        if (Objects.equals(HttpStatusEnum.SUCCESS.getCode().toString(), result.get("code"))) {
-            //成功
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public Boolean midasPresent(Long userId, String orderId, Integer presentCounts) {
-        PlatformOrderDTO orderInfo = platformOrderService.info(orderId);
-        if (Objects.isNull(orderInfo)) {
-            throw new CustomException(HttpStatusEnum.ORDER_NO_FIND);
-        }
-        if (orderInfo.getGameId() == null || orderInfo.getGameId() == 0) {
-            throw new CustomException(HttpStatusEnum.ORDER_GAME_ID_IS_NULL);
-        }
-        RequestParam commonParam = getCommonParam(orderInfo.getGameId(), orderInfo.getUserId());
-        commonParam.setBill_no(orderId);
-        commonParam.setPresent_counts(orderInfo.getProductCnt());
-        HashMap<String, String> result = miPayClient.api(UrlConstants.PRESENT_URL, commonParam, null, null, null);
-        if (Objects.equals(HttpStatusEnum.SUCCESS.getCode().toString(), result.get("code"))) {
-            //成功
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public MiPayConfig midasConfig(Long gameId) {
-        GamePayWay one = gamePayWayService.getOne(new LambdaQueryWrapper<GamePayWay>()
-                .eq(GamePayWay::getGameId, gameId)
-                .eq(GamePayWay::getStatus, StatusEnum.YES.getCode())
-                .gt(GamePayWay::getPayBoxId, 0)
-                .last("limit 1")
-        );
-        if (Objects.isNull(one) || StringUtils.isEmpty(one.getPayConfig())) {
-            throw new CustomException(HttpStatusEnum.GET_CONFIG_ERROR);
-        }
-        return JSONObject.parseObject(one.getPayConfig(), MiPayConfig.class);
-    }
-
-
-    /**
-     * 请求通用参数生成
-     *
-     * @param gameId 游戏id
-     * @param userId 玩家
-     * @return RequestParam 请求参数
-     */
-    @Override
-    public RequestParam getCommonParam(Long gameId, String userId) {
-        GamePayWay one = gamePayWayService.getOne(new LambdaQueryWrapper<GamePayWay>()
-                .eq(GamePayWay::getGameId, gameId)
-                .eq(GamePayWay::getStatus, StatusEnum.YES.getCode())
-                .gt(GamePayWay::getPayBoxId, 0)
-                .last("limit 1")
-        );
-        if (Objects.isNull(one) || StringUtils.isEmpty(one.getPayConfig())) {
-            throw new CustomException(HttpStatusEnum.GET_CONFIG_ERROR);
-        }
-        //米大师支付配置
-        MiPayConfig miPayConfig = JSONObject.parseObject(one.getPayConfig(), MiPayConfig.class);
-        PayBox payBoxInfo = payBoxMapper.selectById(one.getPayBoxId());
-        if (Objects.isNull(payBoxInfo) || payBoxInfo.getPayApplicationId() == null || payBoxInfo.getPayApplicationId() <= 0) {
-            throw new CustomException(HttpStatusEnum.GET_PAY_BOX_ERROR);
-        }
-        PayApplication payApplicationInfo = payApplicationMapper.selectById(payBoxInfo.getPayApplicationId());
-        if (payApplicationInfo.getStatus() == StatusEnum.NO.getCode()) {
-            throw new CustomException(HttpStatusEnum.GET_PAY_BOX_ERROR);
-        }
-        String openId = redisUtil.getCache(RedisKeyConstant.WEIXIN_OPEN_ID + userId + "_" + gameId);
-        if (StringUtils.isEmpty(openId)) {
-            //todo 无openId情况
-            if (springActive.equals("dev")) {
-                openId = "1";
-            } else {
-                throw new CustomException(HttpStatusEnum.WEIXIN_OPEN_ID_NULL);
-            }
-        }
-        RequestParam requestParam = new RequestParam();
-        requestParam.setOpenid(openId);
-        requestParam.setAppid(payApplicationInfo.getAppId());
-        //实际上是米大师应用id
-        requestParam.setOffer_id(miPayConfig.getAppId());
-        requestParam.setApp_key(miPayConfig.getAppKey());
-        //沙箱时使用沙箱key
-        if (requestParam.getIs_sand() == 1) {
-            requestParam.setApp_key(miPayConfig.getAppKeyDev());
-        }
-        return requestParam;
-    }
-
-
-}

+ 268 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/pay/MiPayServiceImpl.java

@@ -0,0 +1,268 @@
+package com.zanxiang.sdk.service.Impl.pay;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zanxiang.common.domain.MiPayConfig;
+import com.zanxiang.common.domain.ResultMap;
+import com.zanxiang.common.enums.HttpStatusEnum;
+import com.zanxiang.common.enums.StatusEnum;
+import com.zanxiang.common.exception.BaseException;
+import com.zanxiang.common.exception.CustomException;
+import com.zanxiang.common.utils.JsonUtil;
+import com.zanxiang.common.utils.StringUtils;
+import com.zanxiang.common.utils.URIUtil;
+import com.zanxiang.mybatis.entity.GamePayWay;
+import com.zanxiang.sdk.common.constant.MiPayConstants;
+import com.zanxiang.sdk.common.util.MiPayUtil;
+import com.zanxiang.sdk.common.util.RedisUtil;
+import com.zanxiang.sdk.domain.bo.ProductPayParamBO;
+import com.zanxiang.sdk.domain.dto.PlatformOrderDTO;
+import com.zanxiang.sdk.service.GamePayWayService;
+import com.zanxiang.sdk.service.OrderPayService;
+import com.zanxiang.sdk.service.PlatformOrderService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.logging.log4j.util.Strings;
+import org.jdom.JDOMException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 米大师服务实现
+ *
+ * @author xufeng
+ * @date 2022/7/14 16:33
+ */
+@Component
+@Slf4j
+@Service("MiPayService")
+public class MiPayServiceImpl extends PayService implements OrderPayService {
+    protected final Logger logger = LoggerFactory.getLogger(MiPayServiceImpl.class);
+
+    @Autowired
+    private RedisUtil<String> redisUtil;
+
+    @Autowired
+    private PlatformOrderService platformOrderService;
+
+    @Autowired
+    private GamePayWayService gamePayWayService;
+
+    @Value("${spring.profiles.active}")
+    private String springActive;
+
+    @Autowired
+    private RestTemplate restTemplate;
+
+    private String code;
+
+    private int isSand = 1;
+
+    @Override
+    public ResultMap create(ProductPayParamBO product) {
+        this.code = product.getCode();
+        //查询订单
+        PlatformOrderDTO orderInfo = platformOrderService.info(product.getOutTradeNo());
+        if (Objects.isNull(orderInfo)) {
+            throw new CustomException(HttpStatusEnum.ORDER_NO_FIND);
+        }
+        if (orderInfo.getGameId() == null || orderInfo.getGameId() == 0) {
+            throw new CustomException(HttpStatusEnum.ORDER_GAME_ID_IS_NULL);
+        }
+        this.isSand = Objects.equals(this.springActive, "dev") ? 1 : 2;
+        //查询游戏配置
+        GamePayWay one = gamePayWayService.getOne(new LambdaQueryWrapper<GamePayWay>()
+                .eq(GamePayWay::getGameId, orderInfo.getGameId())
+                .eq(GamePayWay::getStatus, StatusEnum.YES.getCode())
+                .gt(GamePayWay::getPayBoxId, 0)
+                .last("limit 1")
+        );
+        if (Objects.isNull(one) || StringUtils.isEmpty(one.getPayConfig())) {
+            throw new CustomException(HttpStatusEnum.GET_CONFIG_ERROR);
+        }
+        //米大师支付配置
+        MiPayConfig miPayConfig = JSONObject.parseObject(one.getPayConfig(), MiPayConfig.class);
+        String openId = this.getOpenId(code, miPayConfig.getWxAppId());
+        //获取米大师钱包余额
+        Long balance = this.midasGetBalance(openId, miPayConfig);
+        //返回参数
+        Map<String, String> result = new HashMap<>();
+        //余额充足, 直接扣除
+        if (balance >= orderInfo.getAmount().longValue()) {
+            String billNo = this.midasPay(openId, miPayConfig, orderInfo);
+            result.put("status", "0");
+            result.put("billNo", billNo);
+        }
+        //余额不足, 返回订单id, 前端调充值接口, 充值完后再继续支付
+        if (balance < orderInfo.getAmount().longValue()) {
+            result.put("status", "1");
+            result.put("need", orderInfo.getAmount().toString());
+            result.put("balance", String.valueOf(balance));
+        }
+        return ResultMap.ok(result);
+    }
+
+    /**
+     * 查询余额
+     */
+    private Long midasGetBalance(String openId, MiPayConfig miPayConfig) {
+        Map<String, String> paramMap = new HashMap<>();
+        paramMap.put("openid", openId);
+        paramMap.put("appid", miPayConfig.getWxAppId());
+        paramMap.put("offer_id", miPayConfig.getAppId());
+        paramMap.put("ts", String.valueOf(System.currentTimeMillis() / 1000));
+        paramMap.put("zone_id", "1");
+        paramMap.put("pf", "android");
+        String urlPath = this.isSand == 1 ? "/cgi-bin/midas/sandbox/getbalance" : "/cgi-bin/midas/getbalance";
+        String sig = MiPayUtil.miPaySin("POST", urlPath, paramMap, miPayConfig.getAppKey());
+        paramMap.put("sig", sig);
+        Map<String, String> result = this.miPayApi(MiPayConstants.BALANCE_URL, miPayConfig, paramMap);
+        return Long.valueOf(result.get("balance"));
+    }
+
+
+    /**
+     * 虚拟币扣除
+     *
+     * @return
+     */
+    private String midasPay(String openId, MiPayConfig miPayConfig, PlatformOrderDTO orderInfo) {
+        Map<String, String> paramMap = new HashMap<>();
+        paramMap.put("appid", miPayConfig.getWxAppId());
+        paramMap.put("openid", openId);
+        paramMap.put("offer_id", miPayConfig.getAppId());
+        paramMap.put("ts", String.valueOf(System.currentTimeMillis() / 1000));
+        paramMap.put("pf", "android");
+        paramMap.put("zone_id", "1");
+        paramMap.put("amt", orderInfo.getAmount().toString());
+        paramMap.put("bill_no", orderInfo.getId());
+        String urlPath = this.isSand == 1 ? "/cgi-bin/midas/sandbox/getbalance" : "/cgi-bin/midas/getbalance";
+        String sig = MiPayUtil.miPaySin("POST", urlPath, paramMap, miPayConfig.getAppKey());
+        paramMap.put("sig", sig);
+        Map<String, String> result = this.miPayApi(MiPayConstants.PAY_URL, miPayConfig, paramMap);
+        return result.get("bill_no");
+    }
+
+    /**
+     * 获取AccessToken
+     *
+     * @param appId
+     * @param appSecret
+     * @return AccessToken
+     */
+    private String getAccessToken(String appId, String appSecret) {
+//        String redisKey = RedisKeyConstant.WEIXIN_ACCESS_TOKEN + appId;
+//        String cache = redisUtil.getCache(redisKey);
+//        if (StringUtils.isNotEmpty(cache)) {
+//            return cache;
+//        }
+        HashMap<String, String> param = new HashMap<>();
+        param.put("grant_type", "client_credential");
+        param.put("appid", "wxa8ede4e6c65fad30");
+        param.put("secret", "a8df1c1146f89f06d07d1e494f845ede");
+
+        String url = URIUtil.fillUrlParams(MiPayConstants.TOKEN_URL, param, Boolean.FALSE);
+
+        String result = restTemplate.getForObject(url, String.class);
+
+
+        if (StringUtils.isEmpty(result)) {
+            return "";
+        }
+        JSONObject data = JSONObject.parseObject(result);
+        if (Objects.isNull(data)) {
+            return "";
+        }
+        Object accessToken = data.get("access_token");
+        if (Objects.isNull(accessToken)) {
+            return "";
+        }
+        String token = accessToken.toString();
+//        redisUtil.setCache(redisKey, token, Long.valueOf(data.get("expires_in").toString()));
+        return token;
+    }
+
+    /**
+     * 接口请求
+     *
+     * @param url 请求路径
+     * @return
+     */
+    private Map<String, String> miPayApi(String url, MiPayConfig miPayConfig, Map<String, String> paramMap) {
+        try {
+            //使用沙箱时,沙箱地址替换
+            String appKey = miPayConfig.getAppKey();
+            if (this.isSand == 1) {
+                url = url.replace("/cgi-bin/midas/", "/cgi-bin/midas/sandbox/");
+                appKey = miPayConfig.getAppKeyDev();
+            }
+            String accessToken = getAccessToken(miPayConfig.getAppId(), appKey);
+            if (StringUtils.isEmpty(accessToken)) {
+                throw new CustomException(HttpStatusEnum.ACCESS_TOKEN_CREATE_ERROR);
+            }
+
+            url += "?access_token=" + accessToken;
+            String result = restTemplate.postForObject(url, paramMap, String.class);
+            if (StringUtils.isEmpty(result)) {
+                throw new CustomException(HttpStatusEnum.MDS_CONNECT_ERROR);
+            }
+            Map<String, String> data = JsonUtil.toMap(result, Map.class, String.class, String.class);
+            if (Objects.isNull(data)) {
+                throw new CustomException(HttpStatusEnum.MDS_CONNECT_ERROR);
+            }
+            if (!data.get("errcode").equals("0")) {
+                String errmsg = data.get("errmsg");
+                Integer errcode = Integer.valueOf(data.get("errcode"));
+                throw new CustomException(errmsg, errcode);
+            }
+            return data;
+        } catch (RuntimeException e) {
+            throw new RuntimeException("米大师接口调用失败");
+        }
+    }
+
+    private String getOpenId(String code, String appId) {
+        // 请求微信服务器,使用code获取openid
+        Map<String, String> paramMap = new HashMap<>(4);
+        paramMap.put("appid", appId);
+        paramMap.put("secret", "a8df1c1146f89f06d07d1e494f845ede");
+        paramMap.put("js_code", code);
+        paramMap.put("grant_type", "authorization_code");
+        // 发送请求
+        String url = URIUtil.fillUrlParams("https://api.weixin.qq.com/sns/jscode2session", paramMap, Boolean.FALSE);
+        String sr = restTemplate.getForObject(url, String.class);
+        // 解析相应内容(转换成json对象)
+        Map<String, String> userMap = JsonUtil.toMap(sr, Map.class, String.class);
+        if (userMap == null || Strings.isBlank(userMap.get("openid"))) {
+            throw new BaseException("小程序支付获取用户openId为空");
+        }
+        return userMap.get("openid");
+    }
+
+
+    @Override
+    public String notify(HttpServletRequest request, HttpServletResponse response) throws IOException, JDOMException {
+        return null;
+    }
+
+    @Override
+    public ResultMap synNotify(HttpServletRequest request) {
+        return null;
+    }
+
+    @Override
+    public void configInit(String obj) {
+
+    }
+}

+ 40 - 63
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/pay/WxPayServiceImpl.java

@@ -5,7 +5,6 @@ import com.zanxiang.common.domain.ResultMap;
 import com.zanxiang.common.enums.ResEnum;
 import com.zanxiang.common.enums.ResEnum;
 import com.zanxiang.common.exception.BaseException;
 import com.zanxiang.common.exception.BaseException;
 import com.zanxiang.common.utils.JsonUtil;
 import com.zanxiang.common.utils.JsonUtil;
-import com.zanxiang.common.utils.RandomStringUtil;
 import com.zanxiang.common.utils.URIUtil;
 import com.zanxiang.common.utils.URIUtil;
 import com.zanxiang.sdk.common.constant.WxPayConstants;
 import com.zanxiang.sdk.common.constant.WxPayConstants;
 import com.zanxiang.sdk.common.util.PayCommonUtil;
 import com.zanxiang.sdk.common.util.PayCommonUtil;
@@ -16,8 +15,8 @@ import com.zanxiang.sdk.domain.bo.ProductPayParamBO;
 import com.zanxiang.sdk.domain.bo.WxPayConfigBO;
 import com.zanxiang.sdk.domain.bo.WxPayConfigBO;
 import com.zanxiang.sdk.service.OrderPayService;
 import com.zanxiang.sdk.service.OrderPayService;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
 import org.apache.logging.log4j.util.Strings;
 import org.apache.logging.log4j.util.Strings;
-import org.jdom.JDOMException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
@@ -26,7 +25,9 @@ import org.springframework.web.client.RestTemplate;
 
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponse;
-import java.io.*;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
@@ -74,33 +75,23 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
      */
      */
     private WxPayConfigBO config;
     private WxPayConfigBO config;
 
 
-    private String body;
-
-    private String totalFee;
-
-    private String outTradeNo;
-
     @Autowired
     @Autowired
     private RestTemplate restTemplate;
     private RestTemplate restTemplate;
 
 
     @Override
     @Override
     public ResultMap create(ProductPayParamBO product) {
     public ResultMap create(ProductPayParamBO product) {
-        this.body = product.getSubject();
-        this.totalFee = String.valueOf(Float.parseFloat(product.getTotalFee()) * 100);
-        this.outTradeNo = product.getOutTradeNo() + RandomStringUtil.randomNumStr(5);
-        this.attach = product.getAttach();
         //初始化配置
         //初始化配置
         this.configInit(getPayConfig(product.getGameId(), product.getPayWay(), product.getPayDevice()));
         this.configInit(getPayConfig(product.getGameId(), product.getPayWay(), product.getPayDevice()));
+        //不同的支付途径
         switch (product.getPayDevice()) {
         switch (product.getPayDevice()) {
             case 1:
             case 1:
-                //PC端二维码
+                //PC
                 return this.pcPay(product);
                 return this.pcPay(product);
             case 2:
             case 2:
-                //手机端H5
+                //H5
                 return this.h5Pay(product);
                 return this.h5Pay(product);
-//            case 3:
             case 4:
             case 4:
-                //小程序支付
+                //小程序
                 return this.miniAppPay(product);
                 return this.miniAppPay(product);
             default:
             default:
                 throw new RuntimeException("未知支付方式");
                 throw new RuntimeException("未知支付方式");
@@ -108,61 +99,47 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
     }
     }
 
 
     @Override
     @Override
-    public String notify(HttpServletRequest request, HttpServletResponse response) throws IOException, JDOMException {
+    public String notify(HttpServletRequest request, HttpServletResponse response) throws IOException {
         // 读取参数
         // 读取参数
         InputStream inputStream = request.getInputStream();
         InputStream inputStream = request.getInputStream();
-        StringBuffer sb = new StringBuffer();
-        String s;
-        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
-        while ((s = in.readLine()) != null) {
-            sb.append(s);
-        }
-        in.close();
-        inputStream.close();
-        log.info("微信支付回调 body:{}", sb);
+        String requestStr = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+        log.info("微信支付回调 body:{}", requestStr);
         // 解析xml成map
         // 解析xml成map
-        Map m = XmlUtil.xmlToMap(sb.toString());
+        Map<String, String> map = XmlUtil.xmlToMap(requestStr);
         // 过滤空 设置 TreeMap
         // 过滤空 设置 TreeMap
         SortedMap<Object, Object> packageParams = new TreeMap<>();
         SortedMap<Object, Object> packageParams = new TreeMap<>();
-        for (Object parameter : m.keySet()) {
-            String parameterValue = (String) m.get(parameter);
-            String v = "";
-            if (null != parameterValue) {
-                v = parameterValue.trim();
-            }
-            packageParams.put(parameter, v);
-        }
+        map.forEach((key, value) -> packageParams.put(key, value == null ? "" : value.trim()));
         ProductPayAttachParamBO attachBO = JsonUtil.toObj(JsonUtil.toString(packageParams.get("attach")), ProductPayAttachParamBO.class);
         ProductPayAttachParamBO attachBO = JsonUtil.toObj(JsonUtil.toString(packageParams.get("attach")), ProductPayAttachParamBO.class);
         configInit(getPayConfig(attachBO.getGamePayWayId()));
         configInit(getPayConfig(attachBO.getGamePayWayId()));
         // 账号信息
         // 账号信息
         String key = config.getApiKey();
         String key = config.getApiKey();
         // 判断签名是否正确
         // 判断签名是否正确
-        if (PayCommonUtil.isTenPaySign(Constants.UTF8, packageParams, key)) {
-            log.info("微信支付成功回调");
-            // 处理业务开始
-            String resXml;
-            if (Constants.SUCCESS.equalsIgnoreCase(packageParams.get("result_code").toString())) {
-                // 这里是支付成功
-                String orderNo = (String) packageParams.get("out_trade_no");
-                log.info("微信订单号{}付款成功", orderNo);
-                if (paySuccess(attachBO.getOrderId(), String.valueOf(Float.parseFloat(packageParams.get("total_amount").toString()) / 100), packageParams.get("trade_no").toString(), attachBO.getGamePayWayId())) {
-                    log.info("微信异步回调成功 request:{},商户订单号为:{}", request, outTradeNo);
-                    return ResEnum.SUCCESS.getMsg();
-                }
-                // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了
-                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
-            } else {
-                log.info("支付失败,错误信息:{}", packageParams.get("err_code"));
-                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
+        if (!PayCommonUtil.isTenPaySign(Constants.UTF8, packageParams, key)) {
+            log.info("通知签名验证失败");
+            return null;
+        }
+        log.info("微信支付成功回调");
+        // 处理业务开始
+        String resXml;
+
+        if (Constants.SUCCESS.equalsIgnoreCase(packageParams.get("result_code").toString())) {
+            // 这里是支付成功
+            String orderNo = (String) packageParams.get("out_trade_no");
+            log.info("微信订单号{}付款成功", orderNo);
+            if (paySuccess(attachBO.getOrderId(), String.valueOf(Float.parseFloat(packageParams.get("total_amount").toString()) / 100), packageParams.get("trade_no").toString(), attachBO.getGamePayWayId())) {
+                return ResEnum.SUCCESS.getMsg();
             }
             }
-            // 处理业务完毕
-            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
-            out.write(resXml.getBytes());
-            out.flush();
-            out.close();
+            // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了
+            resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
         } else {
         } else {
-            log.info("通知签名验证失败");
+            log.info("支付失败,错误信息:{}", packageParams.get("err_code"));
+            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
         }
         }
+        // 处理业务完毕
+        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
+        out.write(resXml.getBytes());
+        out.flush();
+        out.close();
         return null;
         return null;
     }
     }
 
 
@@ -260,14 +237,14 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
             paramData.put("appid", config.getAppId());
             paramData.put("appid", config.getAppId());
             paramData.put("mch_id", config.getMchId());
             paramData.put("mch_id", config.getMchId());
             paramData.put("nonce_str", WxPayUtil.generateNonceStr());
             paramData.put("nonce_str", WxPayUtil.generateNonceStr());
-            paramData.put("body", body);
-            paramData.put("out_trade_no", outTradeNo);
+            paramData.put("body", product.getSubject());
+            paramData.put("out_trade_no", product.getOutTradeNo());
             paramData.put("fee_type", "CNY");
             paramData.put("fee_type", "CNY");
-            paramData.put("total_fee", WxPayUtil.subZeroAndDot(this.totalFee));
+            paramData.put("total_fee", WxPayUtil.subZeroAndDot(String.valueOf(Float.parseFloat(product.getTotalFee()) * 100)));
             paramData.put("spbill_create_ip", product.getSpbillCreateIp());
             paramData.put("spbill_create_ip", product.getSpbillCreateIp());
             paramData.put("notify_url", notifyUrl);
             paramData.put("notify_url", notifyUrl);
             paramData.put("trade_type", tradeType);
             paramData.put("trade_type", tradeType);
-            paramData.put("attach", JsonUtil.toString(this.attach));
+            paramData.put("attach", JsonUtil.toString(product.getAttach()));
             paramData.put("sign_type", config.getSignType());
             paramData.put("sign_type", config.getSignType());
             //小程序商城下单需要携带openId
             //小程序商城下单需要携带openId
             if (Strings.isNotBlank(openId)) {
             if (Strings.isNotBlank(openId)) {