Prechádzať zdrojové kódy

feat : 微信小程序支付代码提交

bilingfeng 2 rokov pred
rodič
commit
ffb44877ee

+ 2 - 1
game-module/game-sdk/src/main/java/com/zanxiang/sdk/controller/PayController.java

@@ -76,11 +76,12 @@ public class PayController {
         ProductPayParamBO bo = new ProductPayParamBO();
         bo.setGameId(product.getGameId());
         bo.setUserId(userId);
-        bo.setPayDevice(userData.getDeviceType());
+        bo.setPayDevice(product.getPayDevice() == null ? userData.getDeviceType() : product.getPayDevice());
         bo.setDeviceSystem(userData.getDeviceSystem());
         bo.setSpbillCreateIp(IpUtils.getRealIp(request));
         bo.setOutTradeNo(product.getOrderId());
         bo.setPayWay(product.getPayWay());
+        bo.setCode(product.getCode());
         return payService.payCreate(bo);
     }
 

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

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.zanxiang.common.constant.Constants;
 import com.zanxiang.common.domain.ResultMap;
 import com.zanxiang.common.enums.ResEnum;
+import com.zanxiang.common.exception.BaseException;
 import com.zanxiang.common.utils.JsonUtil;
 import com.zanxiang.common.utils.RandomStringUtil;
 import com.zanxiang.common.utils.URIUtil;
@@ -13,13 +14,13 @@ import com.zanxiang.sdk.domain.bo.ProductPayParamBO;
 import com.zanxiang.sdk.domain.bo.WxPayConfigBO;
 import com.zanxiang.sdk.service.OrderPayService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.logging.log4j.util.Strings;
 import org.jdom.JDOMException;
 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 weixin.popular.api.SnsAPI;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -40,7 +41,7 @@ import java.util.TreeMap;
 public class WxPayServiceImpl extends PayService implements OrderPayService {
 
     /**
-     * 二维码支付
+     * pc二维码支付
      */
     private static final String WX_PAY_NATIVE = "NATIVE";
 
@@ -50,7 +51,7 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
     private static final String WX_PAY_MWEB = "MWEB";
 
     /**
-     * JSAPI支付
+     * 小程序支付
      */
     private static final String WX_PAY_JSAPI = "JSAPI";
 
@@ -100,26 +101,19 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
         switch (product.getPayDevice()) {
             case 1:
                 //PC端二维码
-                return this.mobile(product, WX_PAY_NATIVE);
+                return this.pcPay(product);
             case 2:
                 //手机端H5
-                return this.mobile(product, WX_PAY_MWEB);
+                return this.h5Pay(product);
 //            case 3:
             case 4:
-                //微信商城小程序支付
+                //小程序支付
                 return this.miniAppPay(product);
             default:
                 throw new RuntimeException("未知支付方式");
         }
     }
 
-    /**
-     * 异步回调
-     *
-     * @param request
-     * @param response
-     * @return
-     */
     @Override
     public String notify(HttpServletRequest request, HttpServletResponse response) throws IOException, JDOMException {
         // 读取参数
@@ -179,94 +173,87 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
         return null;
     }
 
-    /**
-     * 同步回调
-     *
-     * @param request
-     * @return
-     */
-
     @Override
     public ResultMap synNotify(HttpServletRequest request) {
-        log.info("微信支付同步回调 request:{}", request);
+        log.info("微信支付没有同步回调 request:{}", request);
         return null;
     }
 
+    private ResultMap pcPay(ProductPayParamBO product) {
+        //下单
+        Map<String, String> successMap = this.unifiedOrder(product, WX_PAY_NATIVE, null);
+        //获取二维码链接
+        String urlCode = successMap.get("code_url");
+        //判断是否获取到支付链接
+        if (Strings.isBlank(urlCode)) {
+            log.error("微信PC支付链接urlCode为空, product:{}", JsonUtil.toString(product));
+            throw new BaseException("微信PC支付链接urlCode为空");
+        }
+        //返回结果
+        return ResultMap.ok(product.getPayDevice(), urlCode);
+    }
 
-    /**
-     * 小程序(需要HTTPS)
-     *
-     * @param product
-     * @return
-     */
-    private ResultMap mp(ProductPayParamBO product) {
-        //redirect_uri 需要在微信支付端添加认证网址
-        totalFee = WxPayUtil.subZeroAndDot(this.totalFee);
-        String redirectUri = serverUrl + "/api/sdk/weixinMobile/dopay?outTradeNo=" + product.getOutTradeNo() + "&totalFee=" + totalFee;
-        //也可以通过state传递参数 redirect_uri 后面加参数未经过验证
-        String result = SnsAPI.connectOauth2Authorize(config.getAppId(), redirectUri, true, null);
-        return ResultMap.ok(result);
+    private ResultMap h5Pay(ProductPayParamBO product) {
+        //下单
+        Map<String, String> successMap = this.unifiedOrder(product, WX_PAY_MWEB, null);
+        //获取h5支付链接
+        String urlCode = successMap.get("mweb_url");
+        if (Strings.isBlank(urlCode)) {
+            log.error("微信h5支付链接urlCode为空, product:{}", JsonUtil.toString(product));
+            throw new BaseException("微信h5支付链接urlCode为空");
+        }
+        //转换deepLink
+        String deepLink;
+        try {
+            deepLink = wxPayUtil.readUrl(urlCode, serverUrl);
+        } catch (Exception e) {
+            log.error("微信h5支付urlCode转deepLink异常, urlCode:{}", urlCode);
+            throw new BaseException("微信h5支付urlCode转deepLink异常");
+        }
+        //返回结果
+        return ResultMap.ok(product.getPayDevice(), deepLink);
     }
 
     private ResultMap miniAppPay(ProductPayParamBO product) {
         try {
             Map<Object, Object> miniMap = new HashMap<>(5);
-            // 请求微信服务器,使用code获取openid和session_key
+            // 请求微信服务器,使用code获取openid
             Map<String, String> paramMap = new HashMap<>(4);
             paramMap.put("appid", config.getAppId());
             paramMap.put("secret", config.getAppSecret());
             paramMap.put("js_code", product.getCode());
             paramMap.put("grant_type", "authorization_code");
             // 发送请求
-            String url = URIUtil.fillUrlParams("https://api.weixin.qq.com/sns/jscode2session", paramMap, false);
+            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);
-            // 小程序调取微信支付需要的随机字符串
-            String nonceStr = WxPayUtil.generateNonceStr();
-            //参数
-            Map<String, String> paramData = new HashMap<>(13);
-            paramData.put("appid", config.getAppId());
-            paramData.put("mch_id", config.getMchId());
-            paramData.put("nonce_str", WxPayUtil.generateNonceStr());
-            paramData.put("openid", userMap == null ? null : userMap.get("openid"));
-            paramData.put("body", body);
-            paramData.put("out_trade_no", outTradeNo);
-            paramData.put("fee_type", "CNY");
-            paramData.put("total_fee", totalFee);
-            paramData.put("spbill_create_ip", product.getSpbillCreateIp());
-            paramData.put("notify_url", notifyUrl);
-            paramData.put("trade_type", WX_PAY_JSAPI);
-            paramData.put("sign_type", config.getSignType());
-            paramData.put("sign", WxPayUtil.generateSignature(paramData, config.getApiKey()));
-            // 下单, 获取结果
-            String result = restTemplate.postForObject(WxPayUrl.UNIFIED_ORDER_URL, XMLUtil.mapToXml(paramData), String.class);
-            // 时间戳
-            long timeStamp = System.currentTimeMillis() / 1000;
-            // 这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestPayment方法会报签名错误
-            String createTime = String.valueOf(timeStamp);
-            Map<String, String> successMap = XMLUtil.xmlToMap(result);
-            // 返回状态码
-            String returnCode = successMap.get("return_code");
-            // 结果状态码
-            String resultCode = successMap.get("result_code");
-            String prepayId = successMap.get("prepay_id");
-            // 获取统一下单回调结果;判断并二次签名
-            if (Constants.SUCCESS.equalsIgnoreCase(returnCode) && returnCode.equals(resultCode)) {
-                HashMap<String, String> map = new HashMap<>();
-                map.put("appId", config.getAppId());
-                map.put("timeStamp", createTime);
-                map.put("nonceStr", nonceStr);
-                map.put("package", "prepay_id=" + prepayId);
-                map.put("signType", config.getSignType());
-                // 再次签名sign,这个签名用于小程序端调用支付方法
-                String sign = WxPayUtil.generateSignature(map, config.getApiKey());
-                miniMap.put("paySign", sign);
+            if (userMap == null || Strings.isBlank(userMap.get("openid"))) {
+                throw new BaseException("小程序支付获取用户openId为空");
             }
+            //下单
+            Map<String, String> successMap = this.unifiedOrder(product, WX_PAY_JSAPI, userMap.get("openid"));
+            // 支付参数
+            String prepayId = successMap.get("prepay_id");
+            // 随机字符串
+            String nonceStr = WxPayUtil.generateNonceStr();
+            // 时间戳转化成字符串,否则前端wx.requestPayment方法会报签名错误
+            String createTime = String.valueOf(System.currentTimeMillis() / 1000);
+            // 获取统一下单回调结果, 二次签名
+            HashMap<String, String> map = new HashMap<>(5);
+            map.put("appId", config.getAppId());
+            map.put("timeStamp", createTime);
+            map.put("nonceStr", nonceStr);
+            map.put("package", "prepay_id=" + prepayId);
+            map.put("signType", config.getSignType());
+            // 再次签名sign,这个签名用于小程序端调用支付方法
+            String sign = WxPayUtil.generateSignature(map, config.getApiKey());
+            //组装返回结果
+            miniMap.put("paySign", sign);
             miniMap.put("signType", config.getSignType());
             miniMap.put("timeStamp", createTime);
             miniMap.put("nonceStr", nonceStr);
-            miniMap.put("package", XMLUtil.xmlToMap(result));
+            miniMap.put("package", successMap);
             return ResultMap.ok(miniMap);
         } catch (Exception e) {
             log.error("微信小程序支付通信异常, 订单号:{}, e : {}", product.getOutTradeNo(), e.getMessage());
@@ -340,6 +327,48 @@ public class WxPayServiceImpl extends PayService implements OrderPayService {
         }
     }
 
+    private Map<String, String> unifiedOrder(ProductPayParamBO product, String tradeType, String openId) {
+        try {
+            Map<String, String> paramData = new HashMap<>(13);
+            paramData.put("appid", config.getAppId());
+            paramData.put("mch_id", config.getMchId());
+            paramData.put("nonce_str", WxPayUtil.generateNonceStr());
+            paramData.put("body", body);
+            paramData.put("out_trade_no", outTradeNo);
+            paramData.put("fee_type", "CNY");
+            paramData.put("total_fee", WxPayUtil.subZeroAndDot(this.totalFee));
+            paramData.put("spbill_create_ip", product.getSpbillCreateIp());
+            paramData.put("notify_url", notifyUrl);
+            paramData.put("trade_type", tradeType);
+            paramData.put("attach", JsonUtil.toString(this.attach));
+            paramData.put("sign_type", config.getSignType());
+            //小程序商城下单需要携带openId
+            if (Strings.isNotBlank(openId)) {
+                paramData.put("openid", openId);
+            }
+            //接口签名
+            String sign = WxPayUtil.generateSignature(paramData, config.getApiKey());
+            paramData.put("sign", sign);
+            // 下单, 获取结果
+            String result = restTemplate.postForObject(WxPayUrl.UNIFIED_ORDER_URL, XMLUtil.mapToXml(paramData), String.class);
+            Map<String, String> successMap = XMLUtil.xmlToMap(result);
+            // 返回状态码
+            String returnCode = successMap.get("return_code");
+            // 结果状态码
+            String resultCode = successMap.get("result_code");
+            //成功, 返回结果
+            if (Constants.SUCCESS.equalsIgnoreCase(returnCode) && returnCode.equals(resultCode)) {
+                return successMap;
+            }
+            //下单失败
+            log.error("微信小程序支付通信异常, paramData:{}", JsonUtil.toString(paramData));
+            throw new BaseException("微信小程序支付下单失败");
+        } catch (Exception e) {
+            log.error("微信小程序支付通信异常, 订单号:{}, e : {}", product.getOutTradeNo(), e.getMessage());
+            throw new BaseException("微信小程序支付下单异常");
+        }
+    }
+
     /**
      * 配置初始化
      */