精华内容
下载资源
问答
  • 第三方支付对接

    千次阅读 2018-11-28 17:13:30
    第三方支付对接第一步:准备所需的对接文档第二步:获取订单信息第三步:根据接口文档填写数据第四步:回调 第一步:准备所需的对接文档 向第三方平台索取支付文档,商户号及密匙. 第二步:获取订单信息 获取系统生成的订单...

    第一步:准备所需的对接文档

    向第三方平台索取支付文档,商户号及密匙.

    第二步:获取订单信息

    获取系统生成的订单

    第三步:根据接口文档填写数据

    $params = array(
                'userId' => self::$userId,
                'timestamp' => time().'000',
                'orderNo' => $order['out_trade_no'],
                'amount' => $order['amount']*100,
                'bankCode' => $extend["bankCode"],
    //            'bankCode' => '102100099996',
                'bankName' => $extend['bankName'],
    //            'bankName' => '中国工商银行',
                'cardType' => '2',
                'payType' => 'KJ_WEB',
                'callBackUrl' => 'http://'.C('site_url').'/index.php/Pay/RongYaoPay/fastPay_notify',
    
    
            );
    

    常见需要填写订单号,金额,金额可能有以分为单位.商户号,密匙,支付方式,常见的有快捷支付和网关支付等,获取到数据之后,对数据进行处理,可能需要md加密以及按照阿西克吗顺序排序.;

    private function createSign($params = [])
        {
            $validParams = [];
            foreach($params as $key => $val) {
                if ($val !== '') {
                    $validParams[$key] = $val;
                }
            }
            ksort($validParams, 0);
            $string = ''; // concat query string
            foreach($validParams as $k=>$v) {
                $string .= '&'.$k.'='.$v;
            }
            $stringKey = substr($string, 1, strlen($string)).'&key='.$this->key;
            $sign = md5($stringKey);
            return $sign;
        }
    
    

    根据所需进行操作.然后通过curl进行调用第三方接口.

        function curlPost($url, $data = ''){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
            curl_setopt($ch, CURLOPT_TIMEOUT, 60);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
            curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSLVERSION, 1);//这个值不设置有时会出现error 35情况
            return curl_exec($ch);
        }
    

    关于curl自行网上查询.如果能跳转到第三方支付界面.则第三方直接调用成功.

    第四步:回调

    通常在下单参数里面有需要填写回调地址,如诺没有则需要跟第三方支付报备回调地址.回调地址是支付成功系统执行的步骤,通常是修改订单状态,更改用户信息等.在进行这些操作可能需要获取对应参数.如订单号,金额,还得进行签名验证等.只有签名验证通过后才能证明订单已被支付等.

    展开全文
  • 和第三方接口对接总结

    万次阅读 多人点赞 2018-09-30 16:46:46
    接口对接分为两种形式: 我A公司提供接口给B公司,B公司进行一些操作时调用我们的接口进行实现。 例:A开发会员等级同步接口,供B同步会员等级到B系统。B会员等级的变动需要调用A接口主动推送给A(即更新会员卡...

    接口对接分为两种形式:

    1. 我方A公司提供接口给B公司,B公司进行一些操作时调用我们的接口进行实现。

    例:A开发会员等级同步接口,供B同步会员等级到B系统。B会员等级的变动需要调用A接口主动推送给A(即更新会员卡等级)。

    我们首先要做的就是按照对方的要求,在对方调用我们的接口,我方成功处理之后,按照对方所需要的返回数据以及格式反馈给他们信息。

    在写本接口中,因为我们会员卡等级的字段是不一样的,所以我们对此主要处理的就是这个事情,1.例如对方传来修改后的卡等级是金卡,因为我们数据库中是分为vipcard和cardgrade两张表的,所以首先我们要去写一个方法,查询cardgrade表中所有的卡等级的id,返回一个list集合,再利用B公司传过来的数据for循环遍历比较,如果相等,则拿到金卡等级在我方A公司的ID,代码如下:

     

    再根据B公司提供的会员卡号在我们查询到该条会员并拿到id;

    最后就可以根据拿到跟新后的等级id和该会员的id进行更新了,任务完成!代码如下:

     

     

     

    2.B公司开发会员查询接口,A公司调用B公司接口,实时查询会员

    调对方接口和对方调我方的接口稍微有些不同,因为中间涉及到安全问题,所以还要满足对方要求我方传入的参数,不然对方不给通过,参数要求如下:

    其中AppID,Args,AppSystem是与对方提供给我方特有的,timestamp是当前时间,我们只需获取当前时间按照他的格式生成,这个较简单,稍微复杂点的就是sign的生成了,要做的就是进行加签/验签,按照对方的要求,我们需要将AppId、Timestamp、Token(客户端保存),按照参数名在英文字典中的顺序排序,然后重新拼成一个标准的query string。然后采用sha1或者md5算法对此加密生成sign,代码如下:

    参数都好了之后,对方要求以form表单的形式将参数传过去,这又是一个坑,哎。。,网上找了很久,代码如下:

    Url是对方给的方法路径,param是放入的5个参数,然后要处理的就是把对方参数对应转成我方的参数形式,采用set/get即可。

    供一起刚入坑的参考。

    展开全文
  • 第三方对接-支付宝支付

    千次阅读 2018-06-03 14:43:16
    应用场景:商户出售商品,用户购买支付,商户接入第三方支付平台支付宝对接要求:1、先创建网页&移动应用点击打开链接,提交并且通过审核后才能进行对接2、开发者调用接口前需要先生成RSA2密钥,RSA密钥包含...

    应用场景:

    商户出售商品,用户购买支付,商户接入第三方支付平台支付宝

    对接要求:

    1、先创建网页&移动应用点击打开链接提交并且通过审核后才能进行对接

    2、开发者调用接口前需要先生成RSA2密钥,RSA密钥包含应用私钥(APP_PRIVATE_KEY)、应用公钥(APP_PUBLIC_KEY)。生成密钥后在开放平台管理中心进行密钥配置,配置完成后可以获取支付宝公钥(ALIPAY_PUBLIC_KEY) 

    3、搭建和配置开发环境

    下载服务端SDK:

    <!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java -->
    <dependency>
        <groupId>com.alipay.sdk</groupId>
        <artifactId>alipay-sdk-java</artifactId>
        <version>3.0.0</version>
    </dependency>

    对接流程:

    1、封装参数,申请接入支付宝支付,会有APPID,公钥私钥等参数。

    2、支付流程

      1. 发起一个支付请求(携带订单号,价格等参数)到支付宝统一下单接口,生成预支付路径,响应给客户端浏览器。
      2. 用户进行扫码或者在页面登录支付宝支付。
      3. 服务端异步接收支付结果。

    ①:发起支付请求

    @RequestMapping("gotoPay")
    public void gotoPay(HttpServletRequest httpRequest,HttpServletResponse httpResponse) throws ServletException, IOException {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE); //获得初始化的AlipayClient
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();//创建API对应的request
        alipayRequest.setReturnUrl("http://domain.com/CallBack/returnURL.html");//回跳地址
        alipayRequest.setNotifyUrl("http://domain.com/CallBack/notifyURL.html");//通知地址
        alipayRequest.setBizContent("{" +
            " \"out_trade_no\":\"20150320010101001\"," +                                        //订单号(支付宝要求商户订单号必须唯一)
            " \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +                                   //销售产品码,与支付宝签约的产品码名称,目前仅支持FAST_INSTANT_TRADE_PAY。
            " \"total_amount\":88.88," +                                                        //价格
            " \"subject\":\"Iphone6 16G\"," +                                                   //订单标题
            " \"body\":\"Iphone6 16G\"," +                                                      //订单描述
            " \"passback_params\":\"merchantBizType%3d3C%26merchantBizNo%3d2016010101111\"," +  //公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝只会在异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝
            " \"extend_params\":{" +                                                            //业务扩展参数
            " \"sys_service_provider_id\":\"2088511833207846\"" +                                //系统商编号,该参数作为系统商返佣数据提取的依据,请填写系统商签约协议的PID
            " }"+
            " }");//填充业务参数
        String form="";
        try {
            form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        httpResponse.setContentType("text/html;charset=" + CHARSET);
        httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
    }

    ②、用户确认支付后,支付宝get请求returnUrl(将网页重定向到何处)

    @RequestMapping(value = "returnURL", method = RequestMethod.GET)
    public String returnURL(Device device) {
        System.out.println("支付宝处理完毕后返回商户网站");
        if (device.isNormal()) {
            return "shop/alipay/payResult";
        } else {
            return "mobile/alipay/payResult";
        }
    }

    ③、交易成功后,支付宝post请求notifyUrl

    @RequestMapping(value = "notifyURL", method = RequestMethod.POST)
    public void notifyURL(HttpServletRequest httpRequest){
        //将异步通知中收到的所有参数都存放到map中 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
        Map<String, String> paramsMap = MapUtil.map();
    		Map<String, String[]> requestParams = request.getParameterMap();
        for (Object element : requestParams.keySet()) {
            String name = (String) element;
            String[] values = requestParams.get(name);
            StringBuilder valueStr = new StringBuilder();
            for (int i = 0; i < values.length; i++) {
                valueStr.append((i == values.length - 1) ? values[i] : values[i] + ",");
            }
            params.put(name, valueStr.toString());
        }
        //将异步通知中收到的所有参数都存放到map中 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
       
        boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, ALIPAY_PUBLIC_KEY, CHARSET, SIGN_TYPE) //调用SDK验证签名
        if(signVerfied){
            // TODO 验签成功后,按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,校验成功后在response中返回success并继续商户自身业务处理,校验失败返回failure
        }else{
            // TODO 验签失败则记录异常日志,并在response中返回failure.
        }
    }

    ④、若由于网络等问题异步通知没有到达,商户可自行调用alipay.trade.query接口进行查询,根据查询接口获取交易以及支付信息(商户也可以直接调用查询接口,不需要依赖异步通知)。

    public void query(){
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent("{" +
            "\"out_trade_no\":\"20150320010101001\"," +                        //订单支付时传入的商户订单号,和支付宝交易号不能同时为空。 
            "\"trade_no\":\"2014112611001004680 073956707\"" +                 //支付宝交易号,和商户订单号不能同时为空
            "  }");
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            //获取支付信息
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
        }
    }

    ⑤、交易发生后一段时间内,如果用户想退款,买家可以通过退款接口将支付款退给买家。

    public void refund() throws AlipayApiException {
            AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            request.setBizContent("{" +
                "\"out_trade_no\":\"20150320010101001\"," + 
                "\"trade_no\":\"2014112611001004680073956707\"," +
                "\"refund_amount\":200.12," +
                "\"refund_currency\":\"USD\"," +
                "\"refund_reason\":\"正常退款\"," +
                "\"out_request_no\":\"HZ01RF001\"," +
                "\"operator_id\":\"OP001\"," +
                "\"store_id\":\"NJ_S_001\"," +
                "\"terminal_id\":\"NJ_T_001\"," +
                "      \"goods_detail\":[{" +
                "        \"goods_id\":\"apple-01\"," +
                "\"alipay_goods_id\":\"20010001\"," +
                "\"goods_name\":\"ipad\"," +
                "\"quantity\":1," +
                "\"price\":2000," +
                "\"goods_category\":\"34543238\"," +
                "\"body\":\"特价手机\"," +
                "\"show_url\":\"http://www.alipay.com/xxx.jpg\"" +
                "        }]" +
                "  }");
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            if(response.isSuccess()){
                System.out.println("调用成功");
            } else {
                System.out.println("调用失败");
            }
    }

    ⑥、统一收单交易退款查询

    public void queryRefund(){
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
        request.setBizContent("{" +
           "\"trade_no\":\"20150320010101001\"," +
           "\"out_trade_no\":\"2014112611001004680073956707\"," +
           "\"out_request_no\":\"2014112611001004680073956707\"" +
           "  }");
        AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
        }
    }

    ⑦、统一收单交易关闭接口(用于交易创建后,用户在一定时间内未进行支付,可调用该接口直接将未付款的交易进行关闭。)

    public void tradeClose(){
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        request.setBizContent("{" +
            "\"out_trade_no\":\"20150320010101001\"," +
            "\"trade_no\":\"2014112611001004680073956707\"," +
            "\"refund_amount\":200.12," +
            "\"refund_currency\":\"USD\"," +
            "\"refund_reason\":\"正常退款\"," +
            "\"out_request_no\":\"HZ01RF001\"," +
            "\"operator_id\":\"OP001\"," +
            "\"store_id\":\"NJ_S_001\"," +
            "\"terminal_id\":\"NJ_T_001\"," +
            "      \"goods_detail\":[{" +
            "        \"goods_id\":\"apple-01\"," +
            "\"alipay_goods_id\":\"20010001\"," +
            "\"goods_name\":\"ipad\"," +
            "\"quantity\":1," +
            "\"price\":2000," +
            "\"goods_category\":\"34543238\"," +
            "\"body\":\"特价手机\"," +
            "\"show_url\":\"http://www.alipay.com/xxx.jpg\"" +
            "        }]" +
            "  }");
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
        }
    }
    真心话,支付宝对接的API比微信写的强太多了支付宝官方API

    展开全文
  • 第三方接口对接之鉴权

    千次阅读 2019-04-24 15:06:47
    记录一次和第三方接口对接的过程。 对接要求 对方的接口做了加密验证,需要将参数进行加密生成一个Signature签名。然后对方也会根据参数做一样的步骤来比对签名是否相等来判断参数是否被篡改或者判断身份是否一致。 ...

    第三方接口对接

    鉴权

    记录一次和第三方接口对接的过程。

    对接要求

    对方的接口做了加密验证,需要将参数进行加密生成一个Signature签名。然后对方也会根据参数做一样的步骤来比对签名是否相等来判断参数是否被篡改或者判断身份是否一致。

    对方提供了以下几个参数:

    • accessKey : 和参数进行混合的key
    • accessSecret: 进行base64编码的时候的密码
    • dateTime : 密钥生成的时间,对方文档会标注根据该时间来判断接口的有效时间。比如5分钟内该参数是有效的,超过5分钟对方就认为这个请求已经过期了。
    • randomNumbers : 随机数
    • password : DES加密的密码

    加密的类型:

    明文参数:

    • 手机号码 : 需要通过DES进行加密,加密的密码为上面提供的password。

    密文参数:

    • 首先拿到明文参数

    • 参数的顺序必须一致:例如一段json字符串数据,里面的key必须按照a-z不区分大小写的顺序进行排列。

    • 除了业务参数,还有通用参数:accessKeydateTimerandomNumbers等等加入到参数字符串中。

    • 所有的key对应的value必须要经过URLEncoder进行编码,避免出现中文乱码的情况。

    • 将所有参数通过字符串拼接成一个整的字符串,类似于URL中GET请求参数的样子。然后将得到的这个参数值进行HMACSHA1加密,加密的密钥为accessSecret

    • 最后通过Base64生成密钥。

    • 将这个密钥加入到请求的header头中。

    • header头也需要带上通用参数。

    以上加密的方式主要是为了保证,参数不能被篡改,调用方的身份验证。两边加密和解密的步骤是一致的。否则就会鉴权失败。

    另外简单描述一下各个加密的用处:

    HMACSHA1 : 是从 SHA1 哈希函数构造的一种键控哈希算法,被用作 HMAC(基于哈希的消息验证代码)。 此 HMAC 进程将密钥与消息数据混合,使用哈希函数对混合结果进行哈希计算,将所得哈希值与该密钥混合,然后再次应用哈希函数。 输出的哈希值长度为 160 位。

    在发送方和接收方共享机密密钥的前提下,HMAC 可用于确定通过不安全信道发送的消息是否已被篡改。 发送方计算原始数据的哈希值,并将原始数据和哈希值放在一个消息中同时传送。 接收方重新计算所接收消息的哈希值,并检查计算所得的 HMAC 是否与传送的 HMAC 匹配。

    Base64 : 是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。

    DES加密 : 双方约定一致的key进行加密,生成64位的明码形式进行传输,各方可以通过key进行解密

    关键代码展示:

    HMACSHA1 :

    import javax.crypto.Mac;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    public class HMACSHA1 {
     
    	private static final String MAC_NAME = "HmacSHA1";  
        private static final String ENCODING = "UTF-8";  
        
    	/*
    	 * 展示了一个生成指定算法密钥的过程 初始化HMAC密钥 
    	 * @return 
    	 * @throws Exception
    	 * 
    	  public static String initMacKey() throws Exception {
    	  //得到一个 指定算法密钥的密钥生成器
    	  KeyGenerator KeyGenerator keyGenerator =KeyGenerator.getInstance(MAC_NAME); 
    	  //生成一个密钥
    	  SecretKey secretKey =keyGenerator.generateKey();
    	  return null;
    	  }
    	 */
        
        /** 
         * 使用 HMAC-SHA1 签名方法对对encryptText进行签名 
         * @param encryptText 被签名的字符串 
         * @param encryptKey  密钥 
         * @return 
         * @throws Exception 
         */  
        public static byte[] HmacSHA1Encrypt(String encryptText, String encryptKey) throws Exception   
        {         
        	byte[] data=encryptKey.getBytes(ENCODING);
        	//根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
            SecretKey secretKey = new SecretKeySpec(data, MAC_NAME); 
            //生成一个指定 Mac 算法 的 Mac 对象
            Mac mac = Mac.getInstance(MAC_NAME); 
            //用给定密钥初始化 Mac 对象
            mac.init(secretKey);  
            
            byte[] text = encryptText.getBytes(ENCODING);  
            //完成 Mac 操作 
            return mac.doFinal(text);  
        }
    }
    

    DESUtils:

    import sun.misc.BASE64Encoder;
    
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESKeySpec;
    import java.security.SecureRandom;
    
    public class DESUtils {
    
        /**
         * @param data
         * @return
         * @throws Exception
         * @Method: encrypt
         * @Description: 加密数据
         * @date 2016年7月26日
         */
        public static String encrypt(String data, String password) {  //对string进行BASE64Encoder转换
            byte[] bt = encryptByKey(data.getBytes(), password);
            BASE64Encoder base64en = new BASE64Encoder();
            String strs = new String(base64en.encode(bt));
            return strs;
        }
    
        /**
         * @param data
         * @return
         * @throws Exception
         * @Method: encrypt
         * @Description: 解密数据
         * @date 2016年7月26日
         */
        public static String decryptor(String data, String password) throws Exception {  //对string进行BASE64Encoder转换
            sun.misc.BASE64Decoder base64en = new sun.misc.BASE64Decoder();
            byte[] bt = decrypt(base64en.decodeBuffer(data), password);
            String strs = new String(bt);
            return strs;
        }
    
        /**
         * 加密
         *
         * @param datasource byte[]
         * @param key        String
         * @return byte[]
         */
        public static byte[] encryptByKey(byte[] datasource, String key) {
            try {
                SecureRandom random = new SecureRandom();
    
                DESKeySpec desKey = new DESKeySpec(key.getBytes());
                //创建一个密匙工厂,然后用它把DESKeySpec转换成
                SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
                SecretKey securekey = keyFactory.generateSecret(desKey);
                //Cipher对象实际完成加密操作
                Cipher cipher = Cipher.getInstance("DES");
                //用密匙初始化Cipher对象
                cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
                //现在,获取数据并加密
                //正式执行加密操作
                return cipher.doFinal(datasource);
            } catch (Throwable e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 解密
         *
         * @param src byte[]
         * @param key String
         * @return byte[]
         * @throws Exception
         */
        public static byte[] decrypt(byte[] src, String key) throws Exception {
            // DES算法要求有一个可信任的随机数源
            SecureRandom random = new SecureRandom();
            // 创建一个DESKeySpec对象
            DESKeySpec desKey = new DESKeySpec(key.getBytes());
            // 创建一个密匙工厂
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            // 将DESKeySpec对象转换成SecretKey对象
            SecretKey securekey = keyFactory.generateSecret(desKey);
            // Cipher对象实际完成解密操作
            Cipher cipher = Cipher.getInstance("DES");
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, securekey, random);
            // 真正开始解密操作
            return cipher.doFinal(src);
        }
    }
    

    参数顺序 : 不区分大小写

    import com.alibaba.fastjson.JSON;
    import com.elab.core.utils.ObjectUtils;
    import org.apache.catalina.util.URLEncoder;
    import org.apache.commons.net.util.Base64;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.cglib.beans.BeanMap;
    
    import java.nio.charset.Charset;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;
    import java.util.TreeMap;
    import java.util.concurrent.atomic.AtomicBoolean;
    
    /**
     * 数据对接数据处理
     *
     * @author : liukx
     * @time : 2019/4/22 - 16:24
     */
    public class DataUtils {
    
        private static Logger logger = LoggerFactory.getLogger(JMFDataUtils.class);
    
        /**
         * 通用参数中要带
         */
        public static String accessKey = "xxxxxxxxxxxxxxx";
        /**
         * 同整个参数进行加密
         */
        public static String accessSecret = "xxxxxxxxxxxxxxxxx";
    
        /**
         * 将对象装换为map
         *
         * @param bean
         * @return
         */
        public static <T> Map<String, Object> beanToMap(Object bean, boolean isFirstCase) {
            Map<String, Object> map = new TreeMap<>();
            try {
                if (bean != null) {
                    BeanMap beanMap = BeanMap.create(bean);
                    for (Object key : beanMap.keySet()) {
                        if (Objects.nonNull(beanMap.get(key))) {
                            if (isFirstCase) {
                                map.put(toUpperCaseFirstOne(key + ""), beanMap.get(key).toString());
                            } else {
                                map.put(key + "", beanMap.get(key).toString());
                            }
                        }
                    }
                }
                return map;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 首字母大写
         *
         * @param value 值
         * @return
         */
        public static String toUpperCaseFirstOne(String value) {
            if (Character.isUpperCase(value.charAt(0)))
                return value;
            else
                return (new StringBuilder()).append(Character.toUpperCase(value.charAt(0))).append(value.substring(1)).toString();
        }
    
        /**
         * 鉴权
         *
         * @param randomString 随机字符串
         * @param dateTime     时间
         * @param obj          参数
         * @param isFirstCase  是否首字母大写
         * @return
         * @throws Exception
         */
        public static String getJMFSignature(String randomString, String dateTime, Object obj, boolean isFirstCase) throws
                Exception {
            logger.info("明文 : " + JSON.toJSONString(obj));
            StringBuffer sb = new StringBuffer();
            Map<String, Object> paramsMap = null;
            if (obj instanceof Map) {
                paramsMap = (Map<String, Object>) obj;
            } else {
                paramsMap = beanToMap(obj, isFirstCase);
            }
            // 通过treemap对key的属性进行排序,
            TreeMap<String, Object> sortMap = new TreeMap<>(String::compareToIgnoreCase);
            sortMap.putAll(paramsMap);
            sortMap.put("accessKey", accessKey);
            sortMap.put("dateTime", dateTime);
            sortMap.put("randomNumbers", randomString);
            AtomicBoolean isFirst = new AtomicBoolean(true);
            sortMap.forEach((K, V) -> {
                if (!isFirst.get()) {
                    sb.append("&");
                }
                isFirst.set(false);
                if (ObjectUtils.isNotEmpty(V)) {
                    if (V instanceof List) {
                        V = JSON.toJSONString(V);
                    }
                    sb.append(K + "=" + getEncoderValue(V.toString()).replaceAll("==", "%3D%3D"));
                } else {
                    sb.append(K + "=");
                }
            });
            logger.info("编码后的明文 : " + sb.toString());
            byte[] bytes = HMACSHA1.HmacSHA1Encrypt(sb.toString(), accessSecret);
            String encode = Base64.encodeBase64String(bytes, false);
            logger.info("得到的密钥串 : " + encode);
            return encode;
        }
    
        private static String getEncoderValue(String value) {
            return URLEncoder.QUERY.encode(value, Charset.forName("UTF-8")).toUpperCase();
        }
    }
    

    以上代码只是展现思路。

    如果有不正确的地方请指正。

    展开全文
  • 第三方接口对接规范

    2020-11-13 17:21:19
    如果项目是属于那种集成项目,那么对接各种第三方平台在所难免。根据亲身经历,暂定如下对接规范。 1 自定义异常 针对第三方的异常,大致可以分为第三方内部异常、第三方传入参数异常、自身调用异常、登录异常。 ...
  • 网上商城在交易过程中,有个支付环节,该环节需要对接第三方支付接口或者银行接口,才能完成整个交易。支付接口如何对接呢?下面介绍一些对接支付接口的经验,以第三方支付接口为例。 第一步:签订合约通过第三方拿...
  • 这个微信对接类似,比微信还简单一点,如果你对接过微信,相信这个很简单。 采用本地映射外部链接方式(ngrok工具) 1、一步写客户端代码 采用SpringMVC+Spring框架 @Controller public class OneNoteController {...
  • 第三方支付对接流程

    千次阅读 2017-10-25 09:38:34
    第三方支付对接流程
  • C# 第三方接口对接

    千次阅读 2019-01-08 22:28:00
    一般与第三方接口对接的常见方式:①WebServer ②第三方接口商提供dll ③Web API 转载于:https://www.cnblogs.com/ZJCCoder/p/10241812.html
  • 2019年12月到 2020年04月,小编参与到公司项目与第三方OA的对接,即华为云WeLink市场的对接工作,华为云市场、WeLink市场两部分对接工作,我负责华为云市场项目对接接口、另一个同事负责WeLink对接。主要经历了四个...
  • java对接第三方接口

    千次阅读 2019-11-19 10:02:58
    1.准备与第三方接口对接的账号 配置到了Apollo上面 @Value("${taofake.appId}") private String appId; @Value("${taofake.url}") private String url; @Value("${taofake.appSecret}") private String app...
  • 实现对接第三方接口,可以使用HttpClient(年岁较久),也可以使用SpringBoot RestTemplate(新生代)。可根据个人喜好选择适当的方式进行对接,个人推荐使用SpringBoot RestTemplate。 具体使用如下: 自定义配置类: ...
  • 第三方物流对接

    千次阅读 2019-04-29 20:02:24
    第三方物流推荐: 阿里物流:https://market.aliyun.com/products/56928004/cmapi021863.html?spm=5176.730005.productlist.d_cmapi021863.5bc035249BXRO3&innerSource=search_%E7%89%A9%E6%B5%81#sku=yuncode...
  • Spring 使用 Oauth2的第三方对接和token

    千次阅读 2017-11-07 11:57:45
    本文章不对token的验证操作,只是第三方的模块对Oauth2的使用,使用场景,对一整套系统进行模块化开发,子模块的api采用主枝模块的Oauth2进行安全性验证 在pom.xml中添加依赖 org.springframework.security....
  •  URL(服务器地址):为第三方的的URL服务器的地址  Token(令牌):为微信公众平台的Token  AppID:登录到可以获得  AppSecret:登录到可以获得  原始ID:用于发送模板消息,登录到可以获得 微信公众平台: ...
  • 第三方商城对接架构设计

    千次阅读 2018-01-04 15:26:53
    1 概述由于业务需要,公司需要将原来的积分兑换商品功能由人工下单改为直接对接第三方商城对接,考虑到以后可能会对接多个第三方商城平台,所以采用统一接口门户调用,不同渠道调用不同实现类的设计方式,方便以后...
  • OneNET数据推送的实现(第三方对接)

    万次阅读 热门讨论 2018-12-23 17:19:59
    一、 准备 花生壳等端口映射工具(有公网IP最好): http://**********.la/ SDK下载: ... 花生壳设置好映射端口(NGROK等类似的端口映射工具都是可以的) ...二、对接 ...OneNET平台的对接URL为: ...、效果
  • 第三方平台对接达达配送

    千次阅读 2020-01-25 12:24:06
    第三方平台对接达达配送 一.百度搜索达达开放平台注册好开发者账号,将开发者的app_keyapp_secret填入到第三方平台数据库中 二.封装公共类调用 private static $dmerchhant; //注册商户 private static $...
  • 1、以下称对外开放接口的商城为主商城,对接商城接口的系统为第三方商城 2、传统的做法是第三方商城定时去查询主商城的商品数据,达到更新库存规格相关信息,这样做的有个很大的弊端就是资源浪费,很多查询都是...
  • p2p 跟第三方对接 流程

    千次阅读 2017-08-08 15:25:00
    我们对接的是第三方的平台,业务部门与第三方进行签约,第三方平台提供接口文档、支付环境认证、商户号(商户秘钥)等,我方按照接口规范开发客户端,调用第三方的服务端 在调用过程中一般会出现如下几个问题: ...
  • 如何高效对接第三方支付

    千次阅读 2020-05-24 17:41:24
    目前我们已经服务30个国家地区,不同国家往往需要对接不同的第三方支付公司,所以最近两年,研发组对接了大量的第三方支付公司,积累了一定的经验。 本文主要分享如何对接第三方支付,以及在生产上实际遇到的一些...
  • 第三方API对接常见问题

    万次阅读 2018-08-17 18:01:02
    JAVA项目中通常会需要通过对接第三方API来扩展项目业务,如支付,风控,语音识别,图像处理等。但看似简单的发送/接收请求却包含了Http请求,数据加密/解密,签名加签/验签,数据处理等内容。这次通过对接某公司API...
  • 对接支付宝支付接口,官方文档已经写的很清楚了,但是也有很多小白,一次对接支付宝支付接口,会有些迷茫,所以我在此写下这篇文章。 如果你已经支付宝对应 一步:创建应用与配置密钥已经熟悉了,这里可以不用...
  • 第三方平台对接UU跑腿

    千次阅读 2020-05-19 19:23:12
    第三方平台对接UU跑腿 1.注册UU跑腿开放平台账号(open.uupt.com) 2.注册成功后登录,进入“我的首页” 3…点击“申请成为开发者” 4.填写真实信息,并等待工作人员审核 5.点击“我的应用” 6.添加需要对接的网站、...
  • 第三方对接-支付宝支付接入教程

    千次阅读 2019-09-17 05:46:54
    对接支付宝支付接口,官方文档已经写的很清楚了,但是也有很多小白,一次对接支付宝支付接口,会有些迷茫,所以我在此写下这篇文章。 如果你已经支付宝对应 一步:创建应用与配置密钥已经熟悉了,这里可以不用...
  • 因为业务关系,要许多不同第三方公司进行对接。这些服务商都提供基于http的api。但是每家公司提供api具体细节差别很大。有的基于RESTFUL规范,有的基于传统的http规范;有的需要再header里放置签名,有的需要SSL的...
  • 提供信息: ...接口方给接口文档 使用环境: ...1.调用第三方提供的接口getPaymentUrl(每家公司定义不同) 这个接口的作用是,我这边把基础参数以json格式,传递给ecpay那边的这个接口中,他们会处理...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 48,254
精华内容 19,301
关键字:

和第三方对接方式