| 
					
				 | 
			
			
				@@ -1,20 +1,35 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 package com.zanxiang.sdk.service.pay; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.common.enums.HttpStatusEnum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.common.enums.OrderStateEnum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.zanxiang.common.exception.BaseException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.common.exception.CustomException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.common.utils.StringUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.zanxiang.common.utils.URIUtil; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.zanxiang.module.util.JsonUtil; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.module.util.pojo.ResultVO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.mybatis.entity.Order; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.sdk.domain.bo.ProductPayParamBO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.sdk.domain.dto.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.sdk.service.IGameAppletService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.sdk.service.IOrderService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.sdk.service.IUserService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.zanxiang.sdk.service.api.WxApiService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import lombok.extern.slf4j.Slf4j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import org.apache.logging.log4j.util.Strings; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.beans.factory.annotation.Autowired; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.beans.factory.annotation.Value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.stereotype.Service; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.web.client.RestTemplate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import javax.crypto.Mac; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import javax.crypto.spec.SecretKeySpec; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import javax.servlet.http.HttpServletRequest; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import javax.servlet.http.HttpServletResponse; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.nio.charset.StandardCharsets; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.security.InvalidKeyException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.security.NoSuchAlgorithmException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.HashMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.Map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Objects; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * @author : lingfeng 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -23,76 +38,191 @@ import java.util.Map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 @Slf4j 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 @Service 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public class MiPay2Service { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public void test() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String appId = "wx79b493916563c377"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String secret = "e5b1825a288ea5b54b724c64cc57e5a4"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String miPayAppId = "1450050301"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String miPaySecret = "ZAksvG2Y2v7pVvRmbahZh4HR4aaCdpnE"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String openId = "oA-YO5YY2VVhwuSGst1gHfDBGo6s"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String sessionKey = "mnO0qqRHI6JOmAr0P5WbNA=="; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Map<String, Object> postBodyMap = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        postBodyMap.put("offer_id", miPayAppId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        postBodyMap.put("openid", openId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        postBodyMap.put("ts", System.currentTimeMillis() / 1000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        postBodyMap.put("zone_id", "1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        postBodyMap.put("env", 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String postBody = JsonUtil.toString(postBodyMap); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+public class MiPay2Service extends PayBaseService { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //接口token 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            String accessToken = getAccessToken(appId, secret); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //登录签名 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            String signature = calcSignature(postBody, sessionKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private static final String SIGN_HMACSHA256 = "HMACSHA256"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //支付签名 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            String paySig = calcPaySig("/wxa/game/getbalance", postBody, miPaySecret); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private static final String MI_PAY_HOST = "https://api.weixin.qq.com"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private static final String BALANCE_URL = "/wxa/game/getbalance"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            Map<String, String> headParamMap = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            headParamMap.put("access_token", accessToken); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            headParamMap.put("signature", signature); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            headParamMap.put("pay_sig", paySig); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private static final String PAY_URL = "/wxa/game/pay"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Value("${payConfig.miPay.isSand}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private Integer isSand; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //调用接口获取余额 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            RestTemplate restTemplate = new RestTemplate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private IOrderService orderService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            String url = URIUtil.fillUrlParams("https://api.weixin.qq.com/wxa/game/getbalance", headParamMap, Boolean.FALSE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private IGameAppletService gameAppletService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private RestTemplate restTemplate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            System.out.println("url : ------>" + url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private WxApiService wxApiService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private IUserService userService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            String result = restTemplate.postForObject(url, postBody, String.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 支付配置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private MiPayConfigDTO config; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public Map<String, Object> create(ProductPayParamBO product, GamePayWayDTO gamePayWayDTO) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //查询订单 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        PlatformOrderDTO orderInfo = orderService.getByOrderId(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.configInit(product.getGameId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //获取用户openId 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        UserDTO userDTO = userService.getUserByUserId(product.getUserId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String openId = userDTO.getOpenId(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String sessionKey = userDTO.getSessionKey(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //获取米大师钱包余额 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Long balance = this.midasGetBalance(openId, sessionKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //返回参数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Map<String, Object> payParamMap = new HashMap<>(9); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //余额充足, 直接扣除 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (balance >= orderInfo.getAmount().longValue()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            String billNo = this.midasPay(openId, sessionKey, orderInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payParamMap.put("status", "0"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payParamMap.put("billNo", billNo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //支付成功 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.paySuccess(product.getOutTradeNo(), orderInfo.getAmount().toString(), config.getAppId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //余额不足, 返回订单id, 前端调充值接口, 充值完后再继续支付 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payParamMap.put("currencyType", "CNY"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payParamMap.put("mode", "game"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payParamMap.put("zoneId", "1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payParamMap.put("offerId", config.getAppId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payParamMap.put("env", String.valueOf(this.isSand)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payParamMap.put("buyQuantity", orderInfo.getAmount().toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payParamMap.put("status", "1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payParamMap.put("balance", String.valueOf(balance)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payParamMap.put("orderId", product.getOutTradeNo()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //更新订单商户信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            orderService.update(new LambdaUpdateWrapper<Order>() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .set(Order::getMerchantNo, config.getAppId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .set(Order::getStatus, OrderStateEnum.WAIT_PAY.getCode()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    .eq(Order::getOrderId, product.getOutTradeNo())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return payParamMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            System.out.println("result -----> " + result); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private Long midasGetBalance(String openId, String sessionKey) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //接口参数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Map<String, Object> postBodyMap = new HashMap<>(5); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("offer_id", config.getAppId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("openid", openId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("ts", System.currentTimeMillis() / 1000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("zone_id", "1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("env", this.isSand); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String postBody = JsonUtil.toString(postBodyMap); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //接口token 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String accessToken = wxApiService.getAccessToken(config.getAppId(), config.getSecret()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //登录签名 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String signature = calcSignature(postBody, sessionKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //支付签名 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String paySig = calcPaySig(MiPay2Service.BALANCE_URL, postBody, config.getAppKeyByIsSand(this.isSand)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //请求头参数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Map<String, String> headParamMap = new HashMap<>(3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        headParamMap.put("access_token", accessToken); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        headParamMap.put("signature", signature); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        headParamMap.put("pay_sig", paySig); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //调接口返回 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String url = URIUtil.fillUrlParams(MiPay2Service.MI_PAY_HOST + MiPay2Service.BALANCE_URL, headParamMap, Boolean.FALSE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Map<String, String> resultMap = this.miPayApi(url, postBody); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return Long.valueOf(resultMap.get("balance")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } catch (Exception ignored) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private String midasPay(String openId, String sessionKey, PlatformOrderDTO orderInfo) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //接口参数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Map<String, Object> postBodyMap = new HashMap<>(7); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("openid", openId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("offer_id", config.getAppId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("ts", System.currentTimeMillis() / 1000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("zone_id", "1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("env", this.isSand); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("amount", orderInfo.getAmount()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        postBodyMap.put("bill_no", orderInfo.getOrderId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String postBody = JsonUtil.toString(postBodyMap); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //接口token 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String accessToken = wxApiService.getAccessToken(config.getAppId(), config.getSecret()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //登录签名 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String signature = this.calcSignature(postBody, sessionKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //支付签名 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String paySig = this.calcPaySig(MiPay2Service.PAY_URL, postBody, config.getAppKeyByIsSand(this.isSand)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //请求头参数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Map<String, String> headParamMap = new HashMap<>(3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        headParamMap.put("access_token", accessToken); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        headParamMap.put("signature", signature); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        headParamMap.put("pay_sig", paySig); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //调接口返回 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String url = URIUtil.fillUrlParams(MiPay2Service.MI_PAY_HOST + MiPay2Service.PAY_URL, headParamMap, Boolean.FALSE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Map<String, String> resultMap = this.miPayApi(url, postBody); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return resultMap.get("bill_no"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private Map<String, String> miPayApi(String url, String postBody) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result = restTemplate.postForObject(url, postBody, String.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.error("米大师接口调用异常, url : {}, postBody : {}, e : {}", url, postBody, e.getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new BaseException("米大师接口调用异常"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (StringUtils.isEmpty(result)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.error("米大师接口调用失败, 返回结果为空, url : {}, postBody : {}", url, postBody); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new BaseException("米大师接口调用失败, 返回结果为空"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Map<String, String> resultMap = JsonUtil.toMap(result, Map.class, String.class, String.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //返回结果成功 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (Objects.equals("0", resultMap.get("errcode"))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return resultMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //返回结果失败 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.error("米大师接口调用返回结果失败, url : {}, postBody : {}, errcode : {}, errmsg : {}", url, postBody, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                resultMap.get("errcode"), resultMap.get("errmsg")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        throw new BaseException("米大师接口调用返回结果失败"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private void configInit(Long gameId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //查询游戏小程序信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        GameAppletDTO gameAppletDTO = gameAppletService.getByGameId(gameId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //支付配置赋值 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.config = MiPayConfigDTO.builder() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .appId(gameAppletDTO.getAppId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .secret(gameAppletDTO.getAppSecret()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .offerId(gameAppletDTO.getMiPayAppId()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .appKey(gameAppletDTO.getMiPayAppKey()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .appKeyDev(gameAppletDTO.getMiPayAppKeyDev()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .build(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private String calcPaySig(String uri, String postBody, String appKey) throws NoSuchAlgorithmException, InvalidKeyException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private String calcPaySig(String uri, String postBody, String appKey) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String needSignMsg = uri + "&" + postBody; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mac hmacSha256 = Mac.getInstance("HmacSHA256"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        SecretKeySpec secretKey = new SecretKeySpec(appKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        hmacSha256.init(secretKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        byte[] signatureBytes = hmacSha256.doFinal(needSignMsg.getBytes(StandardCharsets.UTF_8)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return bytesToHex(signatureBytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return this.calcSignature(needSignMsg, appKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private String calcSignature(String postBody, String sessionKey) throws NoSuchAlgorithmException, InvalidKeyException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mac hmacSha256 = Mac.getInstance("HmacSHA256"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        SecretKeySpec secretKey = new SecretKeySpec(sessionKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        hmacSha256.init(secretKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        byte[] signatureBytes = hmacSha256.doFinal(postBody.getBytes(StandardCharsets.UTF_8)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return bytesToHex(signatureBytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private String calcSignature(String postBody, String sessionKey) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Mac hmacSha256 = Mac.getInstance(MiPay2Service.SIGN_HMACSHA256); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            SecretKeySpec secretKey = new SecretKeySpec(sessionKey.getBytes(StandardCharsets.UTF_8), MiPay2Service.SIGN_HMACSHA256); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            hmacSha256.init(secretKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            byte[] signatureBytes = hmacSha256.doFinal(postBody.getBytes(StandardCharsets.UTF_8)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return bytesToHex(signatureBytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.error("米大师签名计算异常, postBody : {}, sessionKey : {}", postBody, sessionKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new BaseException("米大师签名计算异常"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private String bytesToHex(byte[] bytes) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -107,27 +237,18 @@ public class MiPay2Service { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return hexString.toString(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * 获取访问令牌 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param appId  应用程序id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @param secret 秘密 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     * @return {@link String} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private String getAccessToken(String appId, String secret) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Map<String, String> paramMap = new HashMap<>(4); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        paramMap.put("appid", appId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        paramMap.put("secret", secret); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        paramMap.put("grant_type", "client_credential"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // 发送请求 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String url = URIUtil.fillUrlParams("https://api.weixin.qq.com/cgi-bin/token", paramMap, Boolean.FALSE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        RestTemplate restTemplate = new RestTemplate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        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("access_token"))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            throw new BaseException("获取应用token失败"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return userMap.get("access_token"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public String notify(HttpServletRequest request, HttpServletResponse response) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        throw new BaseException("米大师支付不存在异步回调"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public ResultVO synNotify(HttpServletRequest request) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        throw new BaseException("米大师支付不存在同步回调"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public void closeOrder(PlatformOrderDTO platformOrderDTO) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.error("米大师支付不存在取消订单"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |