• 微信商户支付


      先吐槽下微信,完全就是个坑,文档确实有,但是个别细节没有提,有些得自己试。

      下面总结下微信商户支付的开发,用处一般是用户从商户提现。

      首先,要获取提现用户的openId,openId是用户对于公众号的唯一标识,openId是用户在公众 号中的唯一标识,一个openId只属于一个公众号。openId在用户关注公众号之类的活动中可以得到。

      接下来按照微信的文档,准备需要提交的参数:

      

            Map<String, Object> paras = new HashMap<>();
            paras.put("mch_appid" , "*******");
        ......    

      然后是根据参数生成签名:

      生成前要对参数根据参数名的ascii码顺序排序:

      

            List<Map.Entry<String, Object>> list = new ArrayList<>(paras.entrySet());
            Collections.sort(list, new Comparator<Map.Entry<String, Object>>() {
                public int compare(Map.Entry<String, Object> kv1, Map.Entry<String, Object> kv2) {
                    return kv1.getKey().compareTo(kv2.getKey());
                }
            });    

      生成签名:

        private String getSign(List<Map.Entry<String, Object>> list) {
            StringBuffer para = new StringBuffer();
    
            if (!list.isEmpty()) {
                for (Map.Entry<String, Object> one : list) {
                    String value = String.valueOf(one.getValue());
                    if (isNotEmpty(value)){
                        para.append("&")
                                .append(one.getKey())
                                .append("=")
                                .append(one.getValue());
                    }
                }
                para.deleteCharAt(0);
                para.append("&key=" + WXConstants.SECRET_KEY);
            }
    
            return Md5Util.encodeUpper(para.toString());
        }

      注意:所有参数后需要加入秘钥,并且key一定要放在最后,秘钥在商户后台的API安全中设置

      然后要以同样的顺序生成xml格式的参数,这个参数里要加入签名sign,key是不需要加进来的。

      

        private String getWXPara(List<Map.Entry<String, Object>> list){
            StringBuffer para = new StringBuffer();
            para.append("<xml>");
    
            for (Map.Entry<String, Object> one : list){
                para.append(String.format("<%s>", one.getKey()))
                        .append(String.format("<![CDATA[%s]]>", one.getValue()))
                        .append(String.format("</%s>", one.getKey()));
            }
    
            para.append("</xml>");
            return para.toString();
        }

      有了参数就可以通过微信提供的接口提交数据了,提交时是需要证书的,证书在商户平台API安全中下载。

      带着证书发送:

            public String post(String para, String pathCA, String key) throws CertificateException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, IOException {
            log.info("wx.post, {} : request {} & para : {}
    ", this.name, this.url, para);
            StringEntity entity = new StringEntity(para, EscapeUtil.CHARSET_UTF8);
            HttpPost post = new HttpPost(url);
            post.setEntity(entity);
    
            CloseableHttpClient client = getSSLClient(pathCA, key);
            CloseableHttpResponse response = client.execute(post);
    
            int httpCode = response.getStatusLine().getStatusCode();
            byte[] bs = EntityUtils.toByteArray(response.getEntity());
            String result = new String(bs, EscapeUtil.CHARSET_UTF8);
            if (httpCode != 200){
                log.warn("wx.post.httpCodeErr, {} : return {} & httpCode : {} & content : {} & para : {}
    ", this.name, httpCode, result, this.url, para);
            }
            log.info("wx.post, {} : return {} & para : {}
    ", this.name, result, para);
            return content;
        }
        private CloseableHttpClient getSSLClient(final String pathCA, final String key) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
            KeyStore keyStore  = KeyStore.getInstance(WXConstants.CERT_TYPE);
            FileInputStream instream = new FileInputStream(new File(pathCA));try {
                keyStore.load(is, key.toCharArray());
            } finally {
                is.close();
            }
    
            // Trust own CA and all self-signed certs
            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, key.toCharArray())
                    .build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[] { WXConstants.SSL_PROTOCOL },
                    null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .build();
            return httpclient;
        }

      如果人品还过得去,一般就可以了,不过还有一个小坑,微信文档上说返回成功的时候返回值中会有sign,不过实际上其实是没有的。。。

  • 相关阅读:
    PHP json_decode()解析失败 返回NULL 错误是4
    PHP 合并两个二维数组 array_map 和 array_walk 的区别
    PHP二维数组指定字段进行排序
    常用正则汇总
    PHP中json_encode()使用须知,JSON数组和JSON对象
    PHPExcel大文件块级别读取 速度快 减少占用资源
    移动端border-radius失效
    JavaScript滑动页面到顶部
    软键盘把底部div顶上去
    JavaScript滚动div
  • 原文地址:https://www.cnblogs.com/saaav/p/4514915.html
Copyright © 2020-2023  润新知