当前位置 : 主页 > 编程语言 > java >

支付功能3

来源:互联网 收集:自由互联 发布时间:2023-09-06
1.内网穿透完整测试程序180 我们使用ngrok,直接注册一个账号开通隧道即可,简单方便 KuaiQianService181 micr-pay //服务器接收支付结果的后台地址,该参数务必填写,不能为空。//String bgUrl

1. 内网穿透完整测试程序  180

我们使用ngrok,直接注册一个账号开通隧道即可,简单方便

KuaiQianService  181

micr-pay

支付功能3_apache

//服务器接收支付结果的后台地址,该参数务必填写,不能为空。
//String bgUrl = "http://localhost:9000/pay/kq/rece/notify";
String bgUrl = "http://oayunshang3.v1.idcfengye.com/pay/kq/rece/notify";//内网穿透地址   181

KuaiQianController   181

micr-pay

//接收快钱给商家的支付结果 , 快钱以get方式,发送请求给商家  170
    @GetMapping("/rece/notify")
    @ResponseBody
    public String payResultNotify(HttpServletRequest request){
        System.out.println("==============接收快钱的异步通知============");//181
        kQService.kqNotify(request);
        return "<result>1</result><redirecturl>http://localhost:8080/</redirecturl>";
    }

测试   181

启动micr-datasevice、micr-web、micr-pay

运行ngrok内网穿透

启动redis

启动zookeeper

支付功能3_java_02

测试我们用到的信息

测试银行卡:
可用的银行卡:
6214 6800 3838 7096 北京银行的

姓名:张峰

身份证  110101199105149839

测试环境:不对卡,姓名,身份证做检查, 正式环境会检查。

支付一分钱,点击支付

支付功能3_java_03

跳转到快钱支付界面,更换信息

支付功能3_apache_04

支付功能3_apache_05

支付功能3_java_06

点击返回商家

支付功能3_java_07

成功

支付功能3_java_08

看看后台输出,没问题

支付功能3_java_09

看看数据库资金表,增加了一分钱

支付功能3_java_10

充值记录表也没问题

支付功能3_apache_11

再次进入用户中心,查询到一条充值记录

支付功能3_java_12

至此我们整个支付程序,成功

2. 补单处理   182

支付功能3_apache_13

补单查询快钱响应的数据格式

我们主要是获取这部分数据

支付功能3_java_14

{
 "recordCount": "30",
 "pageCount": "1",
 "orderDetail": [
         {
         "orderId": "1642244020946593",
         "orderAmount": 3,
         "orderTime": "20120605012740",
         "dealTime": "20120605013104",
         "payResult": "10",
         "payType": "10",
         "payAmount": 3,
         "fee": 1,
         "dealId": "23023847",
         "signInfo": 
        "jGf9%2F7vKOUkK%2B93ZcTxT9IOFoEhxSEDHmwKbdtEJuEHd4DhPU3BlotuujtHIHlaEPHp48t8c0uj78TzD
        M%2FUQeaH15o5DNmdRencMD0mo%2FmSRNEHtqgOZfY3H3VR4SbYUDgIf7YVAspBoK3re3feroGGUA8%2BKue8
        %2BgzPOjp%2Fgkkeh4GuA4KAAnunTuxELc82rsP0CuosawodILiHTvDwoyF1EgAIQqEChgdHbpQUtiCevluYK
        ORmwZJlN804L8GPmobMZXr4CVtVTYcGuOIUXzz4ImXEnfesCP2f6BOoJD14SIxU%2BrWHppByEKtKodUCJ7FA
        0pxCB6uqHUE3eNHuw1Q%3D%3D"
         }
     ],
     "signMsg": 
     "f3oEXOdTflGvJScrHZbjQQgz3RTwSnLTvHTJn0GUHcAAIjnXfN2rV79gWbEwRExkFfFq%2FEXl29%2Fw5ID3
     cfalx4hGqktXARUqf0WYKTz%2B3Un8%2Bv2vtcMXzfQAopKnPSAawZJ2CTWwSq9xkWxlTZj%2B7%2Bj1n9maa
     dCAVwsaNUFZN%2FT4t%2BqqMsI8wAfk%2FFcSwcwo2CDr%2F%2Bp2WQ3sQbVYDBd4hFa3s3Q24zeH9u7x9cZp
     2gNS7UdERTe7ksBjuhImnoJahNOP5WIzxZaXNpDFNwa0qjRhVFzMs97T7aa8M4LOhaI%2F8mesYGa8D50VlvY
     8GtApr%2F3CebFKRf8uU1XGqfZsXA%3D%3D",
     "signType": 2,
     "pageSize": "30",
     "merchantAcctId": "1001162931901",
     "errCode": "",
  "currentPage": "1", 
  "version": "v2.0"
}

2.1 业务接口实现类KuaiQianService   183

工具类HttpUtil   183

micr-pay

资源在E:\java学习\盈利宝\资料\资料\10-快钱支付\人民币网关\DEMO\JAVA\人民币网关支付、退款查询\HttpQuery\src\com\query\Test

支付功能3_apache_15

package com.bjpowernode.util;

import java.net.SocketTimeoutException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

/**
 * HttpUtil 工具类
 */
public class HttpUtil {

    private static final Log LOGGER = LogFactory.getLog(HttpUtil.class);

    private static PoolingHttpClientConnectionManager connManager;
    private static RequestConfig requestConfig;

    static{
        try {
            SSLContext sslcontext = createIgnoreVerifySSL();
            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(null, null, null);
            SSLContext.setDefault(sslContext);
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
                    .<ConnectionSocketFactory> create().register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", new SSLConnectionSocketFactory(sslcontext)).build();
            connManager = new PoolingHttpClientConnectionManager(
                    socketFactoryRegistry);
            // 连接池超时时间使用connect超时时间
            requestConfig = RequestConfig.custom()
                    .setConnectionRequestTimeout(1000)
                    .setConnectTimeout(1000)
                    .setSocketTimeout(5000).build();
        } catch (Exception e) {
            LOGGER.error(" [XPAY-SDK] init connectionManager or requestConfig error !!! ",e);
            e.printStackTrace();
        }
    }

    public static String doPostJsonRequest(String reqeustString, String url,
                                           int connectTimeout, int socketTimeOut) throws Exception {

        CloseableHttpResponse response = null;
        try {

            changeRequestConfig(connectTimeout,socketTimeOut);
            CloseableHttpClient httpclient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.setConfig(requestConfig);
            httpPost.setEntity(new StringEntity(reqeustString, ContentType.APPLICATION_JSON));
            response = httpclient.execute(httpPost);
            // get http status code
            int resStatu = response.getStatusLine().getStatusCode();
            String responseString = null;
            if (resStatu == HttpStatus.SC_OK) {
                responseString = EntityUtils.toString(response.getEntity());
            } else {
                throw new Exception(url + ",the statusCode is " + resStatu);
            }
            return responseString;
        } catch (ConnectTimeoutException e) {
            e.printStackTrace();
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                    response.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return url;
    }

    /**
     * 绕过验证
     *
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    private static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sc = SSLContext.getInstance("TLSv1.2");
        // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
        X509TrustManager trustManager = new X509TrustManager() {

            public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                                           String paramString) throws CertificateException {}


            public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                                           String paramString) throws CertificateException {}


            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        sc.init(null, new TrustManager[] { trustManager }, null);
        return sc;
    }

    public static String doPostJsonRequestByHttps(String reqeustString, String url,
                                                  int connectTimeout, int socketTimeOut) {
        long startTime = System.currentTimeMillis();
        CloseableHttpResponse response = null;
        String responseString = null;
        try {

            changeRequestConfig(connectTimeout,socketTimeOut);
            CloseableHttpClient httpsClient = HttpClients.custom().setConnectionManager(connManager).build();
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.setConfig(requestConfig);
            httpPost.setEntity(new StringEntity(reqeustString, ContentType.APPLICATION_JSON));
            response = httpsClient.execute(httpPost);
            // get http status code
            int resStatu = response.getStatusLine().getStatusCode();
            responseString = null;
            if (resStatu == HttpStatus.SC_OK) {
                responseString = EntityUtils.toString(response.getEntity());
            } else {
                throw new Exception(url + ",the statusCode is " + resStatu);
            }
            LOGGER.info(String.format("response data : [ %s ] , time consuming : [ %s ] ms !! ",responseString
                    ,(System.currentTimeMillis()- startTime)));
            return responseString;
        }catch (ConnectTimeoutException e) {
            e.printStackTrace();
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                    response.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return responseString;
    }

    /**
     * 修改默认超时时间
     * @param connectionTime
     * @param soTimeout
     */
    private static void changeRequestConfig(int connectionTime,int soTimeout){
        if(connectionTime != requestConfig.getConnectionRequestTimeout()
                || soTimeout != requestConfig.getSocketTimeout()){
            requestConfig = RequestConfig.custom()
                    .setConnectionRequestTimeout(connectionTime)
                    .setConnectTimeout(connectionTime)
                    .setSocketTimeout(soTimeout).build();
        }
    }
}

KuaiQianService  183

micr-pay

//补单操作  调用快钱的查询接口   183
    public void handleQueryOrder() {

        //1.从redis获取订单号
        //range(0, -1)代表取所有
        Set<String> orders = stringRedisTemplate
                .boundZSetOps(RedisKey.KEY_ORDERID_SET).range(0, -1);

        //2.循环订单号
        orders.forEach( orderId -> {
            //3.每个订单,调用查询接口
            doQuery(orderId);
        });
    }

    //查询接口  183
    private void doQuery(String orderId){
        Map<String, Object> request = new HashMap<String, Object>();
        //固定值:1代表UTF-8;
        String inputCharset = "1";
        //固定值:v2.0 必填
        String version = "v2.0";
        //1代表Md5,2 代表PKI加密方式  必填
        String signType = "2";
        //人民币账号 membcode+01  必填
        String merchantAcctId = "1001214035601";
        //固定值:0 按商户订单号单笔查询,1 按交易结束时间批量查询必填
        String queryType = "0";
        //固定值:1	代表简单查询 必填
        String queryMode = "1";
        //数字串,格式为:年[4 位]月[2 位]日[2 位]时[2 位]分[2 位]秒[2位],例如:20071117020101
        String startTime = "";
        ////数字串,格式为:年[4 位]月[2 位]日[2 位]时[2 位]分[2 位]秒[2位],例如:20071117020101
        String endTime = "";
        String requestPage = "";
        String key = "27YKWKBKHT2IZSQ4";

        request.put("inputCharset", inputCharset);
        request.put("version", version);
        request.put("signType", signType);
        request.put("merchantAcctId", merchantAcctId);
        request.put("queryType", queryType);
        request.put("queryMode", queryMode);
        request.put("startTime", startTime);
        request.put("endTime", endTime);
        request.put("requestPage", requestPage);
        request.put("orderId", orderId);

        String message="";
        message = appendParam(message,"inputCharset",inputCharset,null);
        message = appendParam(message,"version",version,null);
        message = appendParam(message,"signType",signType,null);
        message = appendParam(message,"merchantAcctId",merchantAcctId,null);
        message = appendParam(message,"queryType",queryType,null);
        message = appendParam(message,"queryMode",queryMode,null);
        message = appendParam(message,"startTime",startTime,null);
        message = appendParam(message,"endTime",endTime,null);
        message = appendParam(message,"requestPage",requestPage,null);
        message = appendParam(message,"orderId",orderId,null);
        message = appendParam(message,"key",key,null);

        Pkipair pki = new Pkipair();
        String sign = pki.signMsg(message);
        request.put("signMsg", sign);

        System.out.println("请求json串===" + JSON.toJSONString(request));

        //sandbox提交地址
        String reqUrl = "https://sandbox.99bill.com/gatewayapi/gatewayOrderQuery.do";
        String response = "";
        try {
            response = HttpUtil.doPostJsonRequestByHttps(JSON.toJSONString(request), reqUrl, 3000, 8000);
            //解析response   183-184
            if(StringUtils.isNotBlank(response)){
                Object detailObject = JSONObject.parseObject(response).get("orderDetail");
                System.out.println("detailObject===="+detailObject);
                if( detailObject != null){
                    //把查询的Object转为JSONArray
                    //解释orderDetail部分数据,本身是一个数组被放在了json中
                    ///我们将得到的detailObject对象转为json的数组形式
                    JSONArray array = (JSONArray)detailObject;
                    //取出json数组的第一个元素   184
                    JSONObject detailJsonObject = array.getJSONObject(0);
                    if( detailJsonObject != null){
                        //处理充值结果,和异步通知一样   184
                        int result = rechargeService.handleKQNotify(
                                detailJsonObject.getString("orderId"),//订单号
                                detailJsonObject.getString("payAmount"),//实付金额
                                detailJsonObject.getString("payResult")//支付结果
                        );
                        System.out.println("处理的订单号是:"+orderId+",处理结果:"+result);
                    }
                }
            }
            //删除redis中的订单   184
            stringRedisTemplate.boundZSetOps(RedisKey.KEY_ORDERID_SET).remove(orderId);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
    }

2.2 控制controller   183

KuaiQianController

micr-pay

//补单操作  183
    //从定时任务,调用接口  183
    @GetMapping("/rece/query")
    @ResponseBody
    public String queryKQOrder(){
        kQService.handlerQueryOrder();
        return "接收了查询的请求";
    }

2.3 在定时任务中掉用   184

TaskManager   184

micr-task

//调用查询补单接口  184
    @Scheduled(cron = "0 0/20 * * * ?")//每隔20分钟查询一次
    public void invokeKuaiQianQuery(){
        try {
            String url = "http://localhost:9000/pay/kq/rece/query";
            HttpClientUtils.doGet(url);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

启动类  184

micr-task

支付功能3_apache_16

2.4 测试   185

为了方便测试我们从数据库中拷贝一个已经处理过的订单

支付功能3_apache_17

将订单号拷贝进redis

支付功能3_java_18

支付功能3_java_19

启动micr-datasevice、micr-web、micr-task、debug启动micr-pay

运行ngrok内网穿透

启动redis

启动zookeeper

在程序遍历第一个订单时也就是红框,因为这个数据没有向快钱发起过支付请求,所以补单查询响应回来的数据orderDetail为空

支付功能3_java_20

当遍历到尾号819时,因为这个订单号是之前处理的,所以

支付功能3_java_21

处理结果为3证明已经处理过了,所以即便是orderDetail有数据,也不会处理

支付功能3_java_22

支付功能3_java_23

看看redis,存储订单的redis消失了,成功(因为我们程序设计的即使从redis去一个进行查询补单,就删除一个)

支付功能3_apache_24

看看数据库819数据没有任何影响

支付功能3_apache_25

资金表,资金也没有变化,成功

支付功能3_java_26

至此,本项目完结

3. 总结   186   

支付功能3_apache_27

4. 项目总体测试

4.1 启动redis

支付功能3_apache_28

4.2 启动zookeeper

支付功能3_java_29

4.3 首先启动micr-dataservice、micr-web、micr-pay

支付功能3_java_30

4.4 启动内网穿透

(注意自己内网穿透使用的地址,要注意内网过期,过期的话就不要使用内网穿透了,去程序汇中修改KuaiQianService类的generateFormData的bgUrl属性就是了

支付功能3_java_31

4.5 启动前端

支付功能3_java_32

4.6 测试

浏览器输入http://localhost:8080/

支付功能3_apache_33

后续测试不在演示

上一篇:微服务架构的优缺点
下一篇:没有了
网友评论