From 9f0b6b2856b6d06053953da4d3804f3329fff7ba Mon Sep 17 00:00:00 2001
From: xiaoyong931011 <15274802129@163.com>
Date: Wed, 19 Apr 2023 17:57:17 +0800
Subject: [PATCH] 拉卡拉支付

---
 src/main/java/cc/mrbird/febs/pay/service/impl/LaKaLaServiceImpl.java |  357 ++++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 254 insertions(+), 103 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/pay/service/impl/LaKaLaServiceImpl.java b/src/main/java/cc/mrbird/febs/pay/service/impl/LaKaLaServiceImpl.java
index 404782c..36489c4 100644
--- a/src/main/java/cc/mrbird/febs/pay/service/impl/LaKaLaServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/pay/service/impl/LaKaLaServiceImpl.java
@@ -1,6 +1,20 @@
 package cc.mrbird.febs.pay.service.impl;
 
+import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
+import cc.mrbird.febs.common.enumerates.OrderStatusEnum;
+import cc.mrbird.febs.mall.entity.MallMqRecord;
+import cc.mrbird.febs.mall.entity.MallOrderInfo;
+import cc.mrbird.febs.mall.mapper.MallMqRecordMapper;
+import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper;
+import cc.mrbird.febs.mall.service.ICommonService;
+import cc.mrbird.febs.pay.model.LaKaLaBasicReqDate;
+import cc.mrbird.febs.pay.model.LaKaLaCreateOrderReqDate;
 import cc.mrbird.febs.pay.service.LaKaLaService;
+import cc.mrbird.febs.rabbit.producter.AgentProducer;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.io.IOUtils;
@@ -13,6 +27,10 @@
 import org.apache.http.conn.ssl.SSLSocketFactory;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.DefaultHttpClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.ResourceLoader;
 import org.springframework.stereotype.Service;
 
 import javax.net.ssl.SSLContext;
@@ -23,12 +41,30 @@
 import java.security.cert.*;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Date;
+import java.util.HashMap;
 
 @Slf4j
 @Service
 public class LaKaLaServiceImpl implements LaKaLaService {
 
+    @Autowired
+    private ICommonService commonService;
 
+    @Autowired
+    private MallOrderInfoMapper orderInfoMapper;
+
+    @Autowired
+    private MallMqRecordMapper mallMqRecordMapper;
+
+    @Autowired
+    private AgentProducer agentProducer;
+
+    @Autowired
+    ResourceLoader resourceLoader;
+
+    @Value("${spring.profiles.active}")
+    private String active;
 
     /**
      * 字符集固定 utf-8
@@ -44,63 +80,112 @@
      * 接入 appid
      */
     public static final String appid = "OP00000418";
-//    public static final String appid = "800000010334001";
+
+    public static final String appid_prd = "OP00000418";
 
     /**
      * 商户证书序列号,和商户私钥对应
      */
-//    public static final String mchSerialNo = "017d6ae9ad6e";
     public static final String mchSerialNo = "01848940fd41";
+
+    public static final String mchSerialNo_prd = "01848940fd41";
+
+    /**
+     * 商户号
+     */
+    public static final String merchant_no = "8222900701107M5";
+
+    public static final String merchant_no_prd = "8222900701107M5";
 
     /**
      * 商户证书私钥,用于请求签名
      */
-    public static final String merchantPrivateKeyPath = "./src/api_private_key.pem";
+    public static final String merchantPrivateKeyPathName = "classpath:lkl/api_private_key.pem";
+
+    public static final String merchantPrivateKeyPathName_prd = "classpath:lkl/prd/api_private_key.pem";
 
     /**
      * 拉卡拉公钥证书,用于response签名验证,务必区分测试环境和生产环境证书
      */
-    public static final String lklCertificatePath = "./src/lkl-apigw-v2.cer";
+    public static final String lklCertificatePathName = "classpath:lkl/lkl-apigw-v2.cer";
+
+    public static final String lklCertificatePathName_prd = "classpath:lkl/prd/lkl-apigw-v2.cer";
 
     /**
      * api请求地址
      */
-    public final static String apiUrl = "https://test.wsmsd.cn/sit";
+    public final static String apiUrlCreate = "https://test.wsmsd.cn/sit/api/v3/ccss/counter/order/create";
+
+    public final static String apiUrlCreate_prd = "https://s2.lakala.com/api/v3/ccss/counter/order/create";
+    /**
+     * 支付回调地址
+     */
+    public final static String notify_url = "http://120.27.238.55:8185/api/pay/laKaLaPayCallBack";
+
+    public final static String notify_url_prd = "https://hlm.meiao.biz/api/pay/laKaLaPayCallBack";
 
     private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
     private static final SecureRandom RANDOM = new SecureRandom();
 
-
     @Override
-    public boolean verifyCreateOrder() {
-        try {
-            String apiPath = "/api/v3/labs/trans/micropay";
-            String body = "{\n" +
-                    "    \"req_time\": \"20210907150256\",\n" +
-                    "    \"version\": \"3.0\",\n" +
-                    "    \"out_org_code\": \"OP00000003\",\n" +
-                    "    \"req_data\": {\n" +
-                    "        \"merchant_no\": \"8222900701107M5\",\n" +
-                    "        \"term_no\": \"A1062976\",\n" +
-                    "        \"out_trade_no\": \"FD660E1FAA3A4470933CDEDAE1EC1D8E\",\n" +
-                    "        \"auth_code\": \"135178236713755038\",\n" +
-                    "        \"total_amount\": \"23\",\n" +
-                    "        \"location_info\": {\n" +
-                    "            \"request_ip\": \"10.176.1.192\",\n" +
-                    "            \"location\": \"+37.123456789,-121.123456789\"\n" +
-                    "        },\n" +
-                    "        \"out_order_no\": \"08F4542EEC6A4497BC419161747A92FA1\"\n" +
-                    "    }\n" +
-                    "}";
+    public String verifyCreateOrder(LaKaLaCreateOrderReqDate laKaLaCreateOrderReqDateInfo) {
+        /**
+         * {"req_time":"20221026100323",
+         * "version":"1.0",
+         * "req_data":{
+         *      "out_order_no":"GHSNVDY8033038232443530",
+         *      "merchant_no":"8222900701107M5",
+         *      "vpos_id":"627872798014865408",
+         *      "total_amount":1,
+         *      "order_efficient_time":"20221118220823",
+         *      "notify_url":"",
+         *      "support_cancel":0,
+         *      "support_refund":1,
+         *      "support_repeat_pay":1,
+         *      "order_info":"测试"}}
+         */
+        HashMap<String, Object> objectObjectHashMap = new HashMap<>();
+        String yyyyMMddHHmmss = DateUtil.format(new Date(), "yyyyMMddHHmmss");
+        //过期时间
+        String order_efficient_time = DateUtil.format(DateUtil.offsetHour(new Date(),1), "yyyyMMddHHmmss");
+        LaKaLaCreateOrderReqDate laKaLaCreateOrderReqDate = new LaKaLaCreateOrderReqDate();
+        laKaLaCreateOrderReqDate.setOut_order_no(laKaLaCreateOrderReqDateInfo.getOut_order_no());
+        laKaLaCreateOrderReqDate.setTotal_amount(laKaLaCreateOrderReqDateInfo.getTotal_amount());
+        laKaLaCreateOrderReqDate.setOrder_efficient_time(order_efficient_time);
 
+        if ("dev".equals(active) || "test".equals(active)) {
+            laKaLaCreateOrderReqDate.setNotify_url(notify_url);
+            laKaLaCreateOrderReqDate.setMerchant_no(merchant_no);
+        }else{
+            laKaLaCreateOrderReqDate.setNotify_url(notify_url_prd);
+            laKaLaCreateOrderReqDate.setMerchant_no(merchant_no_prd);
+        }
+        laKaLaCreateOrderReqDate.setSupport_cancel(0);
+        laKaLaCreateOrderReqDate.setSupport_refund(1);
+        laKaLaCreateOrderReqDate.setSupport_repeat_pay(1);
+        laKaLaCreateOrderReqDate.setOrder_info(laKaLaCreateOrderReqDateInfo.getOrder_info());
+
+        LaKaLaBasicReqDate laKaLaBasicReqDate = new LaKaLaBasicReqDate();
+        laKaLaBasicReqDate.setReq_time(yyyyMMddHHmmss);
+        laKaLaBasicReqDate.setVersion("3.0");
+        JSONObject jsonObject = JSONUtil.parseObj(laKaLaCreateOrderReqDate);
+        laKaLaBasicReqDate.setReq_data(jsonObject);
+        try {
+            String body = JSONUtil.parseObj(laKaLaBasicReqDate).toString();
 
             String authorization = getAuthorization(body);
-            HttpResponse response = post(apiUrl + apiPath, body, authorization);
+
+            String apiUrlCreateHttp = "";
+            if ("dev".equals(active) || "test".equals(active)) {
+                apiUrlCreateHttp = apiUrlCreate;
+            }else{
+                apiUrlCreateHttp = apiUrlCreate_prd;
+            }
+            HttpResponse response = post(apiUrlCreateHttp , body, authorization);
             if (response.getStatusLine().getStatusCode() != 200) {
-                System.out.println("请求失败,statusCode  " + response.getStatusLine()
-                        + IOUtils.toString(response.getEntity().getContent(), ENCODING));
-                return false;
+                objectObjectHashMap.put("code","false");
+                return JSONUtil.parseObj(objectObjectHashMap).toString();
             }
 
             String appid = getHeadValue(response, "Lklapi-Appid");
@@ -109,92 +194,141 @@
             String nonce = getHeadValue(response, "Lklapi-Nonce");
             String signature = getHeadValue(response, "Lklapi-Signature");
             String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);
-
             System.out.println("responseStr  " + responseStr);
 
             String source = appid + "\n" + lklapiSerial + "\n" + timestamp + "\n" + nonce + "\n" + responseStr + "\n";
 
             System.out.println("source  " + source);
-
-            X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(lklCertificatePath)));
-
+            String lklCertificatePathNameStr = "";
+            if ("dev".equals(active) || "test".equals(active)) {
+                lklCertificatePathNameStr = lklCertificatePathName;
+            }else{
+                lklCertificatePathNameStr = lklCertificatePathName_prd;
+            }
+            InputStream fileInputStream = resourceLoader.getResource(lklCertificatePathNameStr).getInputStream();
+            X509Certificate lklCertificate = loadCertificate(fileInputStream);
             boolean verify = verify(lklCertificate, source.getBytes(ENCODING), signature);
 
             if (verify) {
                 System.out.println("验签成功");
-                return true;
+                JSONObject parseObj = JSONUtil.parseObj(responseStr);
+                String code = parseObj.get("code").toString();
+                if("000000".equals(code)){
+                    Object respData = parseObj.get("resp_data");
+                    JSONObject respDataChild = JSONUtil.parseObj(respData);
+                    String counterUrl = respDataChild.get("counter_url").toString();
+                    String payOrderNo = respDataChild.get("pay_order_no").toString();
+                    objectObjectHashMap.put("code","true");
+                    objectObjectHashMap.put("counterUrl",counterUrl);
+                    objectObjectHashMap.put("payOrderNo",payOrderNo);
+                }else{
+                    objectObjectHashMap.put("code","false");
+                }
+                return JSONUtil.parseObj(objectObjectHashMap).toString();
             } else {
                 System.err.println("验签失败");
-                return false;
+                objectObjectHashMap.put("code","false");
+                return JSONUtil.parseObj(objectObjectHashMap).toString();
             }
         } catch (Exception e) {
             e.printStackTrace();
         }
-        return false;
+        objectObjectHashMap.put("code","false");
+        return JSONUtil.parseObj(objectObjectHashMap).toString();
     }
 
-//    public static void main(String[] args) {
-//        try {
-//            String apiPath = "/api/v3/labs/trans/micropay";
-//
-//            String body = "{\n" +
-//                    "    \"req_time\": \"20210907150256\",\n" +
-//                    "    \"version\": \"3.0\",\n" +
-//                    "    \"out_org_code\": \"OP00000003\",\n" +
-//                    "    \"req_data\": {\n" +
-//                    "        \"merchant_no\": \"822290070111135\",\n" +
-//                    "        \"term_no\": \"29034705\",\n" +
-//                    "        \"out_trade_no\": \"FD660E1FAA3A4470933CDEDAE1EC1D8E\",\n" +
-//                    "        \"auth_code\": \"135178236713755038\",\n" +
-//                    "        \"total_amount\": \"123\",\n" +
-//                    "        \"location_info\": {\n" +
-//                    "            \"request_ip\": \"10.176.1.192\",\n" +
-//                    "            \"location\": \"+37.123456789,-121.123456789\"\n" +
-//                    "        },\n" +
-//                    "        \"out_order_no\": \"08F4542EEC6A4497BC419161747A92FA\"\n" +
-//                    "    }\n" +
-//                    "}";
-//
-//
-//            String authorization = getAuthorization(body);
-//            HttpResponse response = post(apiUrl + apiPath, body, authorization);
-//            if (response.getStatusLine().getStatusCode() != 200) {
-//                System.out.println("请求失败,statusCode  " + response.getStatusLine()
-//                        + IOUtils.toString(response.getEntity().getContent(), ENCODING));
-//                return;
-//            }
-//
-//            String appid = getHeadValue(response, "Lklapi-Appid");
-//            String lklapiSerial = getHeadValue(response, "Lklapi-Serial");
-//            String timestamp = getHeadValue(response, "Lklapi-Timestamp");
-//            String nonce = getHeadValue(response, "Lklapi-Nonce");
-//            String signature = getHeadValue(response, "Lklapi-Signature");
-//            String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING);
-//
-//            System.out.println("responseStr  " + responseStr);
-//
-//            String source = appid + "\n" + lklapiSerial + "\n" + timestamp + "\n" + nonce + "\n" + responseStr + "\n";
-//
-//            System.out.println("source  " + source);
-//
-//            X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(lklCertificatePath)));
-//
-//            boolean verify = verify(lklCertificate, source.getBytes(ENCODING), signature);
-//
-//            if (verify) {
-//                System.out.println("验签成功");
-//
-//                // TODO: 业务处理
-//
-//            } else {
-//                System.err.println("验签失败");
-//            }
-//
-//        } catch (Exception e) {
-//            e.printStackTrace();
-//        }
-//
-//    }
+    @Override
+    public String payCallback(JSONObject jsonObject) {
+        String orderStatus = jsonObject.get("order_status").toString();
+        if(2 != Integer.parseInt(orderStatus)){
+            return "FAIL";
+        }
+
+        String orderNo = jsonObject.get("out_order_no").toString();
+
+        LambdaQueryWrapper<MallOrderInfo> query = new LambdaQueryWrapper<>();
+        query.eq(MallOrderInfo::getOrderNo, orderNo);
+        MallOrderInfo orderInfo = this.orderInfoMapper.selectOne(query);
+        if ("1".equals(orderInfo.getPayResult())) {
+            return "SUCCESS";
+        }
+
+        orderInfo.setStatus(OrderStatusEnum.WAIT_SHIPPING.getValue());
+        orderInfo.setPayResult("1");
+        orderInfo.setPayTime(new Date());
+        String payOrderNo = jsonObject.get("pay_order_no").toString();
+        orderInfo.setPayTradeNo(payOrderNo);
+        orderInfoMapper.updateById(orderInfo);
+
+        commonService.changeWallet(orderInfo.getId(), FlowTypeEnum.WECHAT.getValue());
+
+        /**
+         * 插入一条待处理记录
+         * mq处理之后,更新状态
+         */
+        MallMqRecord mallMqRecord = new MallMqRecord();
+        mallMqRecord.setOrderId(orderInfo.getId());
+        mallMqRecord.setState(2);
+        mallMqRecord.setRetryTimes(2);
+        mallMqRecordMapper.insert(mallMqRecord);
+        //发送补贴消息
+        agentProducer.sendPerkMoneyMsg(orderInfo.getId());
+        //发送代理自动升级消息
+        agentProducer.sendAutoLevelUpMsg(orderInfo.getMemberId());
+
+        return "SUCCESS";
+    }
+
+    public static void main(String[] args) {
+
+    /**
+     * {"req_time":"20221026100323",
+     * "version":"1.0",
+     * "req_data":{
+     *      "out_order_no":"GHSNVDY8033038232443530",
+     *      "merchant_no":"8222900701107M5",
+     *      "total_amount":1,
+     *      "order_efficient_time":"20221118220823",
+     *      "notify_url":"",
+     *      "support_cancel":0,
+     *      "support_refund":1,
+     *      "support_repeat_pay":1,
+     *      "order_info":"测试"}}
+     */
+        LaKaLaCreateOrderReqDate laKaLaCreateOrderReqDate = new LaKaLaCreateOrderReqDate();
+        laKaLaCreateOrderReqDate.setOut_order_no("GHSNVDY8033038232443530");
+
+        LaKaLaBasicReqDate laKaLaBasicReqDate = new LaKaLaBasicReqDate();
+        laKaLaBasicReqDate.setReq_time(DateUtil.format(new Date(),"yyyyMMddHHmmss"));
+        laKaLaBasicReqDate.setVersion("3.0");
+        JSONObject jsonObject = JSONUtil.parseObj(laKaLaCreateOrderReqDate);
+        laKaLaBasicReqDate.setReq_data(jsonObject);
+
+        String s = "{\n" +
+                "    \"code\":\"000000\",\n" +
+                "    \"msg\":\"操作成功\",\n" +
+                "    \"resp_time\":\"20230419151705\",\n" +
+                "    \"resp_data\":{\n" +
+                "        \"merchant_no\":\"8222900701107M5\",\n" +
+                "        \"channel_id\":\"95\",\n" +
+                "        \"out_order_no\":\"HLM20230419151704\",\n" +
+                "        \"order_create_time\":\"20230419151705\",\n" +
+                "        \"order_efficient_time\":\"20230419161704\",\n" +
+                "        \"pay_order_no\":\"23041911012001101011000965837\",\n" +
+                "        \"total_amount\":\"1\",\n" +
+                "        \"counter_url\":\"http://q.huijingcai.top/r/0000?pageStyle%3DV2%26token%3DCCSSIZlwnaqWmBw3FHY5U40nGcX7pxoKuxVhhVI7XyulHEUboR1I0VTIqJRMAjgj3IjCMWvoWjp9%2BXHpkA%3D%3D%26amount%3D1%26payOrderNo%3D23041911012001101011000965837\"\n" +
+                "    }\n" +
+                "}";
+
+        JSONObject parseObj = JSONUtil.parseObj(s);
+
+        Object respData = parseObj.get("resp_data");
+
+        JSONObject respDataChild = JSONUtil.parseObj(respData);
+        String counterUrl = respDataChild.get("counter_url").toString();
+        System.out.println(counterUrl);
+
+    }
 
     public HttpResponse post(String url, String message, String authorization) throws Exception {
         SSLContext ctx = SSLContext.getInstance("TLS");
@@ -237,15 +371,32 @@
         String nonceStr = generateNonceStr();
         long timestamp = generateTimestamp();
 
-        String message = appid + "\n" + mchSerialNo + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
+
+        String appidStr = "";
+        String mchSerialNoStr = "";
+        if ("dev".equals(active) || "test".equals(active)) {
+            appidStr = appid;
+            mchSerialNoStr = mchSerialNo;
+        }else{
+            appidStr = appid_prd;
+            mchSerialNoStr = mchSerialNo_prd;
+        }
+
+        String message = appidStr + "\n" + mchSerialNoStr + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
 
         System.out.println("getToken message :  " + message);
 
-        PrivateKey merchantPrivateKey = loadPrivateKey(new FileInputStream(new File(merchantPrivateKeyPath)));
+        String merchantPrivateKeyPathNameStr = "";
+        if ("dev".equals(active) || "test".equals(active)) {
+            merchantPrivateKeyPathNameStr = merchantPrivateKeyPathName;
+        }else{
+            merchantPrivateKeyPathNameStr = merchantPrivateKeyPathName_prd;
+        }
+        InputStream fileInputStream = resourceLoader.getResource(merchantPrivateKeyPathNameStr).getInputStream();
+        PrivateKey merchantPrivateKey = loadPrivateKey(fileInputStream);
 
         String signature = this.sign(message.getBytes(ENCODING), merchantPrivateKey);
-
-        String authorization = "appid=\"" + appid + "\"," + "serial_no=\"" + mchSerialNo + "\"," + "timestamp=\""
+        String authorization = "appid=\"" + appidStr + "\"," + "serial_no=\"" + mchSerialNoStr + "\"," + "timestamp=\""
                 + timestamp + "\"," + "nonce_str=\"" + nonceStr + "\"," + "signature=\"" + signature + "\"";
         System.out.println("authorization message :" + authorization);
 

--
Gitblit v1.9.1