首页 > 其他分享 >支付功能3

支付功能3

时间:2023-09-06 13:01:17浏览次数:50  
标签:功能 http String 支付 import message null response

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_apache_03

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

支付功能3_java_04

支付功能3_apache_05

支付功能3_java_06

点击返回商家

支付功能3_java_07

成功

支付功能3_apache_08

看看后台输出,没问题

支付功能3_java_09

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

支付功能3_apache_10

充值记录表也没问题

支付功能3_java_11

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

支付功能3_apache_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_java_16

2.4 测试   185

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

支付功能3_java_17

将订单号拷贝进redis

支付功能3_apache_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_apache_23

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

支付功能3_apache_24

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

支付功能3_apache_25

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

支付功能3_apache_26

至此,本项目完结

3. 总结   186   

支付功能3_java_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_apache_32

4.6 测试

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

支付功能3_apache_33

后续测试不在演示

标签:功能,http,String,支付,import,message,null,response
From: https://blog.51cto.com/u_15784725/7385546

相关文章

  • gitlab-- pages 功能实战
    pages介绍在我们日常使用gitlab的过程中,会产生一些产物,自己做的一些小网站,小页面之类,一般都是在本地调试访问,一旦我们想让其他朋友也可以随时访问,就需要单独在公有云上买一个服务器去部署,一是需要付费,二是我们调试页面访问量不多,单独搞个服务器部署有点浪费。使用GitLabPag......
  • 【全套】源支付5.18最新版协议去授权全套三端开源源码_客户端+云端+监控+协议三网免挂
    推荐系统为:CentOS7.6Linux系统环境:Nginx1.20.1+MySQL5.6.50+PHP-7.2+Redis将商户后台源码上传解压运行目录为Public伪静态为thinkphp访问域名傻瓜模式安装后台安装完了sudorpm-Uvhhttps://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm完成后输......
  • 视频集中存储/直播点播平台EasyDSS点播文件分类功能新升级
    视频推拉流EasyDSS视频直播点播平台,集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体,可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务。TSINGSEE青犀视频的EasyDSS平台具有点播文件分类展示方法,有两种实现方式可供用户自由选择,今......
  • O2OA(翱途)平台新版本流程平台新增退回功能、新增关联文档功能、新增业务数据变更记录
    尊敬的O2OA(翱途)平台合作伙伴、用户以及亲爱的开发小伙伴们,平台V8.1版本已正式发布。此次,为了更好的服务于业务场景,我们根据在项目中遇到的一些实际问题,重点也对流程平台和流程引擎做了细节上的优化,本篇将重点介绍流程平台中优化的一些细节,大家一起来看看。 ​ O2OA(翱途......
  • IU5200集成30V的OVP功能,支持I2C接口,3A充电电流,1~4节锂电池升降压充电芯片
    IU5200D是一款自动申请快充输入,开关模式升降压充电管理IC,用于1~4节锂离子电池和锂聚合物电池,以及1~5节磷酸铁锂电池。芯片集成包括4开关MOSFET、输入和充电电流感应电路、电池以及升降压转换器的环路补偿。芯片具有3A的充电电流能力,充电电流可以通过外部电阻灵活可调。IU5200D内置......
  • element table 表格控件实现单选功能
      <el-table:data="tableData"borderstriperef="tableData"@row-click="singleElection"><el-table-columnlabel=""width="65"><templateslot-scope="......
  • 医用胶片打印终端产品的作用和功能
    医用胶片打印终端是一款适用于医院放射科的自助打印设备,集成胶片打印机和智能取片机功能,为医院影像中心提供了新的服务模式,为患者获取影像胶片和诊断报告提供了便利。产品功能1、胶片自助打印2、支持条码扫面,就诊卡读取3、诊断报告单打印4、定时开关机,语音提示,灯光提示功能产品优势......
  • dotnet 读 WPF 源代码笔记 GlyphRun 的 DeviceFontName 的功能是什么
    在WPF里面的GlyphRun里,有一个令人迷惑的DeviceFontName属性,似乎给这个属性传入什么值,结果都不会有变更。通过阅读源代码,可以了解到,这是一个没什么用途的属性。本文将告诉大家这个属性的细节逻辑在上一篇博客WPF简单聊聊如何使用DrawGlyphRun绘制文本里面就提到如何创......
  • photoshop下载-Photoshop(ps)下载免费中文版 软件新功能
    PhotoshopCS6中文版整合了Adobe专有的Mercury图像引擎,拥有最强悍的图片编辑能力。Content-Aware新功能让用户更为轻松方便的进行选取区域,抠图等操作。PhotoshopCS6中文版可说是最受平面设计人员欢迎的软件!软件地址:看置顶贴软件特色1、支撑多种图画格局2、支撑多种色彩形式3、供......
  • ps中文版下载-Adobe正版 软件新功能
    AdobePhotoshop2021官方官方版是一款非常好用的图像处理软件。这款软件可以帮助用户快速的美化图片。软件为用户提供了大量的免费处理图片的工具,而且这款软件经过大神的优化,直接安装就可以使用,无需单独。有需要的小伙伴快来下载吧。软件地址:看置顶贴安装教程1、在本站下载并解压,......