xiongzhu 3 年 前
コミット
76d79ba77e

+ 2 - 0
src/main/java/com/izouma/nineth/config/RedisKeys.java

@@ -40,4 +40,6 @@ public class RedisKeys {
     public static final String BIND_CARD = "bindCard::";
 
     public static final String PAY_TMP = "payTmp::";
+
+    public static final String FACE_AUTH = "faceAuth::";
 }

+ 28 - 0
src/main/java/com/izouma/nineth/domain/FaceAuth.java

@@ -0,0 +1,28 @@
+package com.izouma.nineth.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class FaceAuth extends BaseEntity {
+
+    private String name;
+
+    private String idNo;
+
+    private String certifyId;
+
+    private boolean finish;
+
+    private boolean pass;
+
+    private Long userId;
+}

+ 9 - 0
src/main/java/com/izouma/nineth/repo/FaceAuthRepo.java

@@ -0,0 +1,9 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.FaceAuth;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface FaceAuthRepo extends JpaRepository<FaceAuth, Long>, JpaSpecificationExecutor<FaceAuth> {
+    FaceAuth findByCertifyId(String certifyId);
+}

+ 1 - 0
src/main/java/com/izouma/nineth/security/WebSecurityConfig.java

@@ -127,6 +127,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/user/collectionInvitorList").permitAll()
                 .antMatchers("/payOrder/v2/**/sandQuick").permitAll()
                 .antMatchers("/pay/v2/**/sandQuick").permitAll()
+                .antMatchers("/user/faceAuthNotify").permitAll()
                 // all other requests need to be authenticated
                 .anyRequest().authenticated().and()
                 // make sure we use stateless session; session won't be used to

+ 81 - 4
src/main/java/com/izouma/nineth/service/UserService.java

@@ -11,8 +11,11 @@ import com.alipay.api.AlipayClient;
 import com.alipay.api.DefaultAlipayClient;
 import com.alipay.api.request.AlipayUserCertifyOpenCertifyRequest;
 import com.alipay.api.request.AlipayUserCertifyOpenInitializeRequest;
+import com.alipay.api.request.AlipayUserCertifyOpenQueryRequest;
 import com.alipay.api.response.AlipayUserCertifyOpenCertifyResponse;
 import com.alipay.api.response.AlipayUserCertifyOpenInitializeResponse;
+import com.alipay.api.response.AlipayUserCertifyOpenQueryResponse;
+import com.github.kevinsawicki.http.HttpRequest;
 import com.huifu.adapay.core.exception.BaseAdaPayException;
 import com.izouma.nineth.TokenHistory;
 import com.izouma.nineth.config.AlipayProperties;
@@ -100,6 +103,7 @@ public class UserService {
     private TradingAccountRepo            tradingAccountRepo;
     private AlipayClient                  alipayClient;
     private SnowflakeIdWorker             snowflakeIdWorker;
+    private FaceAuthRepo                  faceAuthRepo;
 
     public User update(User user) {
         if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN)) {
@@ -974,10 +978,11 @@ public class UserService {
         return map;
     }
 
-    public String prepareAliAuth(String type, String name, String no) throws AlipayApiException {
+    public String prepareAliAuth(String type, Long userId, String name, String no) throws AlipayApiException {
+        String aliAuthId = snowflakeIdWorker.nextId() + "";
         AlipayUserCertifyOpenInitializeRequest request = new AlipayUserCertifyOpenInitializeRequest();
         JSONObject biz = new JSONObject();
-        biz.put("outer_order_no", snowflakeIdWorker.nextId() + "");
+        biz.put("outer_order_no", aliAuthId);
         biz.put("biz_code", "FACE");
         JSONObject identity_param = new JSONObject();
         identity_param.put("identity_type", "CERT_INFO");
@@ -986,13 +991,20 @@ public class UserService {
         identity_param.put("cert_no", no);
         biz.put("identity_param", identity_param);
         JSONObject merchant_config = new JSONObject();
-        merchant_config.put("return_url", "https://www.raex.vip/");
+        merchant_config.put("return_url", "alipays://platformapi/startapp?saId=10000007&qrcode=https://www.raex.vip");
         biz.put("merchant_config", merchant_config);
         log.info(JSON.toJSONString(biz, true));
         request.setBizContent(biz.toJSONString());
         AlipayUserCertifyOpenInitializeResponse response = alipayClient.execute(request);
         if (response.isSuccess()) {
-            return response.getCertifyId();
+            String certifyId = response.getCertifyId();
+            faceAuthRepo.save(FaceAuth.builder()
+                    .userId(userId)
+                    .name(name)
+                    .idNo(no)
+                    .certifyId(certifyId)
+                    .build());
+            return certifyId;
         }
         throw new BusinessException(response.getMsg());
     }
@@ -1008,4 +1020,69 @@ public class UserService {
         }
         throw new BusinessException(response.getMsg());
     }
+
+    public User oneKeyLogin(String umengKey, String token) {
+        String phone = UmengUtils.getMobile(umengKey, token);
+        if (StringUtils.isBlank(phone)) {
+            throw new BusinessException("登录失败,请尝试其他方式");
+        }
+        User user = userRepo.findByPhoneAndDelFalse(phone).orElse(null);
+        if (user == null) {
+            String name = "0x" + RandomStringUtils.randomAlphabetic(8);
+            user = create(UserRegister.builder()
+                    .authorities(Collections.singleton(Authority.get(AuthorityName.ROLE_USER)))
+                    .username(name)
+                    .nickname(name)
+                    .avatar(Constants.DEFAULT_AVATAR)
+                    .phone(phone)
+                    .build());
+        }
+        return user;
+    }
+
+    public Map<String, Object> checkFaceAuth(String certifyId) throws AlipayApiException {
+        AlipayUserCertifyOpenQueryRequest request = new AlipayUserCertifyOpenQueryRequest();
+        JSONObject biz = new JSONObject();
+        biz.put("certify_id", certifyId);
+        request.setBizContent(biz.toJSONString());
+        AlipayUserCertifyOpenQueryResponse response = alipayClient.execute(request);
+        Map<String, Object> map = new HashMap<>();
+        if (response.isSuccess()) {
+            System.out.println("调用成功");
+        } else {
+            System.out.println("调用失败");
+        }
+        return map;
+    }
+
+    public void faceAuthNotify(String certifyId) {
+        try {
+            AlipayUserCertifyOpenQueryRequest request = new AlipayUserCertifyOpenQueryRequest();
+            JSONObject biz = new JSONObject();
+            biz.put("certify_id", certifyId);
+            request.setBizContent(biz.toJSONString());
+            AlipayUserCertifyOpenQueryResponse response = alipayClient.execute(request);
+            if (response.isSuccess()) {
+                JSONObject jsonObject = JSONObject.parseObject(response.getBody());
+                if (StringUtils.equals(jsonObject.getString("passed"), "T")) {
+                    FaceAuth faceAuth = faceAuthRepo.findByCertifyId(certifyId);
+                    if (faceAuth != null) {
+                        User user = userRepo.findById(faceAuth.getUserId()).orElse(null);
+                        if (user != null) {
+                            IdentityAuth identityAuth = identityAuthRepo.save(IdentityAuth.builder()
+                                    .userId(user.getId())
+                                    .idNo(faceAuth.getIdNo())
+                                    .realName(faceAuth.getName())
+                                    .build());
+                            user.setAuthStatus(AuthStatus.SUCCESS);
+                            user.setAuthId(identityAuth.getId());
+                            save(user);
+                        }
+                    }
+                }
+            }
+        } catch (AlipayApiException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }

+ 92 - 0
src/main/java/com/izouma/nineth/utils/UmengUtils.java

@@ -0,0 +1,92 @@
+package com.izouma.nineth.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.http.Header;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class UmengUtils {
+    public static String getMobile(String umAppkey, String token) {
+        try {
+            String appKey = "204040835";
+            String appSecret = "WjzUZpHTeMGIC0G1nIFTSlxIr9oeHngU";
+            // 下面的url要和阿里云云市场购买的商品对应
+            String url = "https://verify5.market.alicloudapi.com/api/v1/mobile/info?appkey=" + umAppkey;
+            HttpPost httpPost = new HttpPost(url);
+            /**
+             * body
+             */
+            JSONObject object = new JSONObject();
+            object.put("token", token);
+            StringEntity stringEntity = new StringEntity(object.toJSONString(), StandardCharsets.UTF_8);
+            httpPost.setEntity(stringEntity);
+            /**
+             * header
+             */
+            httpPost.setHeader("Content-Type", "application/json; charset=UTF-8");
+            httpPost.setHeader("Accept", "application/json");
+            httpPost.setHeader("X-Ca-Version", "1");
+            httpPost.setHeader("X-Ca-Signature-Headers", "X-Ca-Version,X-Ca-Stage,X-Ca-Key,X-Ca-Timestamp");
+            httpPost.setHeader("X-Ca-Stage", "RELEASE");
+            httpPost.setHeader("X-Ca-Key", appKey);
+            httpPost.setHeader("X-Ca-Timestamp", String.valueOf(System.currentTimeMillis()));
+            httpPost.setHeader("X-Ca-Nonce", UUID.randomUUID().toString());
+            httpPost.setHeader("Content-MD5", Base64.encodeBase64String(DigestUtils.md5(object.toJSONString())));
+            /**
+             * sign
+             */
+            String stringToSign = getSignString(httpPost);
+            Mac hmacSha256 = Mac.getInstance("HmacSHA256");
+            byte[] keyBytes = appSecret.getBytes(StandardCharsets.UTF_8);
+            hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, "HmacSHA256"));
+            String sign = new String(Base64.encodeBase64(hmacSha256.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8))));
+            httpPost.setHeader("X-Ca-Signature", sign);
+            /**
+             * execute
+             */
+            CloseableHttpClient httpclient = HttpClients.createDefault();
+            CloseableHttpResponse response = httpclient.execute(httpPost);
+            String body = EntityUtils.toString(response.getEntity(), "UTF-8");
+            System.out.println(body);
+            JSONObject res = JSONObject.parseObject(body);
+            if (res.getBoolean("success")) {
+                return res.getJSONObject("data").getString("mobile");
+            }
+        } catch (Exception e) {
+
+        }
+        return null;
+    }
+
+    private static String getSignString(HttpPost httpPost) {
+        Header[] headers = httpPost.getAllHeaders();
+        Map<String, String> map = new HashMap<>();
+        for (Header header : headers) {
+            map.put(header.getName(), header.getValue());
+        }
+        return httpPost.getMethod() + "\n" +
+                map.get("Accept") + "\n" +
+                map.get("Content-MD5") + "\n" +
+                map.get("Content-Type") + "\n\n" +
+                "X-Ca-Key:" + map.get("X-Ca-Key") + "\n" +
+                "X-Ca-Stage:" + map.get("X-Ca-Stage") + "\n" +
+                "X-Ca-Timestamp:" + map.get("X-Ca-Timestamp") + "\n" +
+                "X-Ca-Version:" + map.get("X-Ca-Version") + "\n" +
+                httpPost.getURI().getPath() + "?" + httpPost.getURI().getQuery();
+    }
+}

+ 5 - 1
src/main/java/com/izouma/nineth/web/AuthenticationController.java

@@ -122,5 +122,9 @@ public class AuthenticationController {
         return System.currentTimeMillis();
     }
 
-
+    @PostMapping("/oneKeyLogin")
+    public String oneKeyLogin(String umengKey, String token) {
+        User user = userService.oneKeyLogin(umengKey, token);
+        return jwtTokenUtil.generateToken(JwtUserFactory.create(user));
+    }
 }

+ 49 - 0
src/main/java/com/izouma/nineth/web/UserController.java

@@ -1,5 +1,6 @@
 package com.izouma.nineth.web;
 
+import com.alipay.api.AlipayApiException;
 import com.huifu.adapay.core.exception.BaseAdaPayException;
 import com.izouma.nineth.domain.User;
 import com.izouma.nineth.dto.*;
@@ -335,6 +336,54 @@ public class UserController extends BaseController {
         return userService.companyList(pageQuery);
     }
 
+    @PostMapping("/faceAuth")
+    public Map<String, String> faceAuth(@RequestParam String name, @RequestParam String idNo) throws AlipayApiException {
+        String certifyId = userService.prepareAliAuth("IDENTITY_CARD",
+                SecurityUtils.getAuthenticatedUser().getId(), name, idNo);
+        String url = userService.getAliAuthUrl(certifyId);
+        Map<String, String> map = new HashMap<>();
+        map.put("certifyId", certifyId);
+        map.put("url", url);
+        return map;
+    }
+
+    @GetMapping("/checkFaceAuth")
+    public Map<String, Object> checkFaceAuth(@RequestParam String certifyId) throws AlipayApiException {
+        return userService.checkFaceAuth(certifyId);
+    }
+
+    @GetMapping(value = "/faceAuthNotify/{certifyId}", produces = "text/html")
+    public String faceAuthNotify(@PathVariable String certifyId) {
+        userService.faceAuthNotify(certifyId);
+        return "<!DOCTYPE html>\n" +
+                "<html lang=\"en\">\n" +
+                "\n" +
+                "<head>\n" +
+                "    <meta charset=\"UTF-8\">\n" +
+                "    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n" +
+                "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" +
+                "    <title>认证完成</title>\n" +
+                "</head>\n" +
+                "\n" +
+                "<body>\n" +
+                "    <script>\n" +
+                "        function ready(callback) {\n" +
+                "            // 如果jsbridge已经注入则直接调用\n" +
+                "            if (window.AlipayJSBridge) {\n" +
+                "                callback && callback();\n" +
+                "            } else {\n" +
+                "                // 如果没有注入则监听注入的事件\n" +
+                "                document.addEventListener('AlipayJSBridgeReady', callback, false);\n" +
+                "            }\n" +
+                "        }\n" +
+                "        ready(function () {\n" +
+                "            AlipayJSBridge.call('exitApp');\n" +
+                "        });\n" +
+                "    </script>\n" +
+                "</body>\n" +
+                "\n" +
+                "</html>";
+    }
 }
 
 

+ 10 - 6
src/test/java/com/izouma/nineth/CommonTest.java

@@ -18,10 +18,7 @@ import com.izouma.nineth.dto.SandPaySettle;
 import com.izouma.nineth.dto.UserWithdraw;
 import com.izouma.nineth.service.IdentityAuthService;
 import com.izouma.nineth.service.UserService;
-import com.izouma.nineth.utils.AESEncryptUtil;
-import com.izouma.nineth.utils.DateTimeUtils;
-import com.izouma.nineth.utils.SnowflakeIdWorker;
-import com.izouma.nineth.utils.TokenUtils;
+import com.izouma.nineth.utils.*;
 import com.izouma.nineth.web.BaseController;
 import io.ipfs.api.IPFS;
 import io.ipfs.api.MerkleNode;
@@ -648,10 +645,12 @@ public class CommonTest {
 
     @Test
     public void match() throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
-        byte[] byteKey = java.util.Base64.getDecoder().decode(Files.readAllBytes(Path.of("/Users/drew/Downloads/hmpay_app_public_key.txt")));
+        byte[] byteKey = java.util.Base64.getDecoder()
+                .decode(Files.readAllBytes(Path.of("/Users/drew/Downloads/hmpay_app_public_key.txt")));
         PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(byteKey));
         System.out.println(publicKey);
-        byte[] bytePriv = java.util.Base64.getDecoder().decode(Files.readAllBytes(Path.of("/Users/drew/Downloads/hmpay_app_private_key.txt")));
+        byte[] bytePriv = java.util.Base64.getDecoder()
+                .decode(Files.readAllBytes(Path.of("/Users/drew/Downloads/hmpay_app_private_key.txt")));
         PrivateKey privKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(bytePriv));
         System.out.println(privKey);
     }
@@ -731,4 +730,9 @@ public class CommonTest {
                 + RandomStringUtils.randomAlphabetic(8) + "&appId=1&returnPrivateKey=true").body());
         System.out.println(JSON.toJSONString(jsonObject, true));
     }
+
+    @Test
+    public void testOneKey() {
+        UmengUtils.getMobile("62b8106188ccdf4b7eaba3e8", "eyJjIjoibEVjUGh6WXhwdE5FTHVjQ1p0XC9TREZuMGpLSzlZenZhblBaeUxPUWFrRlJUaFwvaWdrUFA2NU1GZGFDd3F3cjdZVGlPWXhEOVRnWGx3XG5PbGI5MytnN29aaGFpV24rbmd2Q1MxUE1vem5cLzVIQ1BveEk4WG94Zkd3Nkozc3pjMk95NUdFZjBsak9Qd09nMk1iVDBWRjl3Y05zMFxuc2NScGVTd0VoSXh1elpwZ2c5dk5xQlliN2toNWF0cmRtRHQzanZNTHBjUm5OeCtwMXdKS1wvN1VlYTN4b3FJajhSakRuVnFZVmJrcm1cbmtKSDhkNUxrbEEzSzhXU2pVeEF5bkZlSVRWbGNpRlJHTUhvZTBYM1ppZ0pDa0pQWk80VVFGVktSaWlRcFpQbGVGTEhNOHRpTnlTQ0Ncbm1ESmQ1OEM3eWdmWktcLzJcL1ZUc1ZkdFpYUktcL0FqVjNGbk84QnhTZWZQZjVmZEI0YThJQzE2SVFINW91Y2U3NERRbG96SGVIVjhSMldcbmQzaHFRZVh4UFkwd09mdW51elFGSHRscUxnSXlWUDA2bFRaZ0VYdTZpbjJDWDlSUndpa3RxUU81NkRjYzdCeWEzdXQyN0ZcL0VzUmRjXG5Vc3J3ZjVkNE41K0N6cFlBSlpWZmh4ZUlYMUZUVmJPZmFEcWQ0RUpPSTFnclwvTkpXUW9uSG14cUZvXC81WEM2dGwzSG5lQWZwM3dGejJcbk1qQ3d4aWF1ZTJ6OWVpNXZpb1F6Z0lhTWREckJ0eFFPcDU3RW5sZm50NGF1NG8yNGJSQTBSSzI2THZwRzVEakRiZWRTY2xZVEZSY2tcbjBITlUzUFdiQ1hrPVxuIiwiayI6IlQwd0hqc3JiSlV6XC9YRGNUSDVcL0Q5QkpcLzZaVzZmR1BGckdQcmRjdEZDR1Z0NGtcLzdTTzJ6TGU5dlVcL0JlUitcL0VYcDNTWFlLcWhLYXh2QW1vazZjY3FveGk3aE1xckcySHNwbUxLWEtkXC9CbUlHMHhDUjVPWm42SWJvK1BhU2djWlk0MUJic01zRm9RVmRmYUIrZitTVkdJQU50K2lNdm5SRkJpUXNja1N0SVZFd0hvZFgwVkZwd2xVN1UwRTBER01qclJLclI2eGRsMFlSZURIbTVuN3hqaVppOVg1ZTQzZ1UxYk9GOVwvelJwa2ZVd05sN3g2a0tpS25XQ25TU2FuQjhDbHJiNTZ0Qll2czdcL3pKdDJsYXh6UGVMb0Jielp1N0lLTHlUcnc4ZVwvVlNmaUlPYmI5dVNqeXFLRU12dXNQRHFmNmNlQUpRUzlIcW1nQk0wbWZiOVE9PSIsIm8iOiJBbmRyb2lkIn0=");
+    }
 }

+ 7 - 1
src/test/java/com/izouma/nineth/service/UserServiceTest.java

@@ -199,9 +199,15 @@ public class UserServiceTest extends ApplicationTests {
 
     @Test
     public void aliAuth() throws AlipayApiException {
-        String certifyId = userService.prepareAliAuth("IDENTITY_CARD", "熊竹", "321002199408304614");
+        String certifyId = userService.prepareAliAuth("IDENTITY_CARD", 1L, "熊竹", "321002199408304614");
         log.info(certifyId);
         String url = userService.getAliAuthUrl(certifyId);
         log.info(url);
+        userService.checkFaceAuth(certifyId);
+    }
+
+    @Test
+    public void checkauth() throws AlipayApiException {
+        userService.checkFaceAuth("7160e6a875cb67648bc7a3cce6e5397e");
     }
 }