微信 企业付款到零钱

微信相关配置

1、公众平台

授权域名回调

2、商户平台

路径:商户平台:账户中心 》 账户设置 》API安全
1、api 安全配置 (指的是:允许调用接口的白名单配置)
2、证书下载 (本次代码主要使用的是 p12 证书)

企业付款到零钱,是需要 open_id 参数的,open_id 参数的获取,参考其他文章,此处不做记录

主要发起支付的代码

工具类

import com.alibaba.fastjson.JSONObject;
import com.hoohui.project.richeng.model.WeChatEntity;
import com.hoohui.project.richeng.util.PathUtil;
import com.hoohui.util.http.HttpRequestUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class WeChatUtils {
    private byte[] certData;

    public InputStream getCertStream() {
        FileInputStream instream = null;
        try {
            //此处为 p12 证书文件路径
            instream = new FileInputStream(new File(PathUtil.getClassResources() + "/weChat/apiclient_cert.p12"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return instream;
    }
    /**
    * 随机串
    */
    public static String getNonceStr() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replace("-", "");
    }
    /**
     * 方法用途: 对所有传入参数按照字段名的Unicode码从小到大排序(字典序),并且生成url参数串<br>
     * 实现步骤: <br>
     *
     * @param paraMap    要排序的Map对象
     * @param urlEncode  是否需要URLENCODE
     * @param keyToLower 是否需要将Key转换为全小写
     *                   true:key转化成小写,false:不转化
     * @return
     */
    public static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower) {
        String buff = "";
        Map<String, String> tmpMap = paraMap;
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet());
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
                @Override
                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });
            // 构造URL 键值对的格式
            StringBuilder buf = new StringBuilder();
            for (Map.Entry<String, String> item : infoIds) {
                if (StringUtils.isNotBlank(item.getKey())) {
                    String key = item.getKey();
                    String val = item.getValue();
                    if (urlEncode) {
                        val = URLEncoder.encode(val, "utf-8");
                    }
                    if (keyToLower) {
                        buf.append(key.toLowerCase() + "=" + val);
                    } else {
                        buf.append(key + "=" + val);
                    }
                    buf.append("&");
                }

            }
            buff = buf.toString();
            if (buff.isEmpty() == false) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {
            return null;
        }
        return buff;
    }
}

发起打款的主要方法:

    public void toPay() throws Exception {
        //1. 调用发起支付的方法
        String str = mainPay(map, 3000, 3000, true);
        //2. xml 转成 map的 方法
        Map<String,String> resultMap = XmlUtil.xml2Map(str);
        //3. 根据 result_code 判断是否支付成功
        if(resultMap.containsKey("result_code") && StringUtils.equals("SUCCESS",resultMap.getOrDefault("result_code",""))){
            // TODO: 2019/9/19 表示支付成功 后进行的操作
          
        }else{
            // TODO: 2019/9/19表示支付失败
          
        }
    }

    /**
     * 主要发起支付的方法
     */
    public static String mainPay(Map<String,String> params, int connectTimeoutMs, int readTimeoutMs,boolean useCert) throws Exception{
        Map<String, String> paraMap = new HashMap<>();
        //微信 app_id
        paraMap.put("mch_appid", WeChatConfig.APP_ID);
        //微信 mch_id
        paraMap.put("mchid",WeChatConfig.MCH_ID);
        //随机字符串
        paraMap.put("nonce_str", WeChatUtils.getNonceStr());
        //订单号 可以按照自己的规则生成,不重复即可
        paraMap.put("partner_trade_no","wx"+params.getOrDefault("id","")+ DateUtils.getDate("yyyyMMddHHmmss"));
        //用户的 open_id 
        paraMap.put("openid",params.getOrDefault("openid",""));
        // 校验用户姓名选项 NO_CHECK:不校验真实姓名  FORCE_CHECK:强校验真实姓名
        paraMap.put("check_name","FORCE_CHECK");
        // 微信的真实姓名
        paraMap.put("re_user_name",params.getOrDefault("re_user_name",""));
        //金额值,单位为 分
        paraMap.put("amount",params.getOrDefault("amount",""));
        //企业付款操作说明信息
        paraMap.put("desc",params.getOrDefault("desc",""));
        //跟白名单没有关系 ,这样写就可以
        paraMap.put("spbill_create_ip", InetAddress.getLocalHost().getHostAddress());
        //将参数排序,并 拼接成字符串
        String url = WeChatUtils.formatUrlMap(paraMap, false, false);
        //最后加上  商户 api_key
        url = url + "&key=" + WeChatConfig.API_KEY; //生成签名 使用商户 key
        //md5 加密,转大写
        String sign = Md5Utils.md5(url).toUpperCase();
        //拼接成xml
        StringBuffer xml = new StringBuffer();
        xml.append("<xml>");
        for (Map.Entry<String, String> entry : paraMap.entrySet()) {
            xml.append("<" + entry.getKey() + ">");
            xml.append(entry.getValue());
            xml.append("</" + entry.getKey() + ">" + "\n");
        }
        xml.append("<sign>");
        xml.append(sign);
        xml.append("</sign>");
        xml.append("</xml>");
        logger.info("xml {} ", xml.toString());
        BasicHttpClientConnectionManager connManager;
        if (useCert) {
            // 证书
            char[] password = WeChatConfig.MCH_ID.toCharArray();
            //这一步调用获取证书内容
            InputStream certStream =  new WeChatUtils().getCertStream();
            KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(certStream, password);

            // 实例化密钥库 & 初始化密钥工厂
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(ks, password);

            // 创建 SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());

            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                    sslContext,
                    new String[]{"TLSv1"},
                    null,
                    new org.apache.http.conn.ssl.DefaultHostnameVerifier());

            connManager = new BasicHttpClientConnectionManager(
                    RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", sslConnectionSocketFactory)
                            .build(),
                    null,
                    null,
                    null
            );
        } else {
            connManager = new BasicHttpClientConnectionManager(
                    RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", SSLConnectionSocketFactory.getSocketFactory())
                            .build(),
                    null,
                    null,
                    null
            );
        }
        org.apache.http.client.HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();
        HttpPost httpPost = new HttpPost(WeChatConfig.MACH_PAY_URL);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();
        httpPost.setConfig(requestConfig);

        StringEntity postEntity = new StringEntity(xml.toString(), "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.addHeader("User-Agent", "wxpay sdk java v1.0 " + WeChatConfig.MCH_ID);  // TODO: 很重要,用来检测 sdk 的使用情况,要不要加上商户信息?
        httpPost.setEntity(postEntity);
        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        return EntityUtils.toString(httpEntity, "UTF-8");
    }
Image placeholder
啦啦啦
未设置
  42人点赞

没有讨论,发表一下自己的看法吧

推荐文章
和大型企业相比,小企业可能并不是安全的薄弱环节

拥有250名或更少员工的企业通常比规模较大的企业使用更高比例的安全从业人员。小型企业经常因为成为大型企业供应链攻击的门户而声名狼藉。但从一份关于小型企业安全的报告中可以看出,情况可能并非如此。作为(I

专为中小企业量身定制 H3C ER3200G2企业路由

随着互联网+战略的持续推进,中小企业网络上承载的业务种类和流量与时俱增。如何保障网络的畅通无阻,实现效率和资源的最大化,是我们共同关注的问题。本文,针对中小企业组网问题,给大家推荐一款企业级路由器。H

🚀 Hyperf 发布 v1.1.8 版本 | 企业级的 PHP 微服务云原生协程框架

更新内容 新增 #965新增RedisLua模块,用于管理Lua脚本; #1023hyperf/metric组件的Prometheus驱动新增CUSTOM_MODE模式; 修复 #1013修复Js

🚀 Hyperf 发布 v1.1.9 版本 | 企业级的 PHP 微服务云原生协程框架

更新内容 本周更新主要为DI组件新增了懒加载功能,配置为懒加载后,注入的对象为一个代理对象,在使用到时,才会实现对象的初始化。以及为DIContainer增加了set和define方法来动态的增加对象

🚀 Hyperf 发布 v1.1.9 版本 | 企业级的 PHP 微服务云原生协程框架

更新内容本周更新主要为DI组件新增了懒加载功能,配置为懒加载后,注入的对象为一个代理对象,在使用到时,才会实现对象的初始化。以及为DIContainer增加了set和define方法来动态的增加对象管

欧盟发布2018全球企业研发费用榜单:华为超苹果跃居第5,BAT排名50开外

大数据文摘出品作者:王嘉仪、魏子敏华为的迅速增长并不是一蹴而就的,至少从近几年的研发投入上看,它比中国任何一家公司都努力。欧盟下属联合研究中心近日公布了2018年度全球企业R&D研发投资排行榜(EUI

2018Q4全球企业WLAN市场加速增长

据IDC发布的全球无线局域网季度跟踪报告显示,2018年第四季度(4Q18),全球消费者和企业全球无线局域网(WLAN)市场同比增长8.9%,全年增长4.3%。企业板块同比增长10.3%,达到17亿美

企业数字化管理平台 “让老树开新花”

在叉车领域,安徽合力(以下简称合力)是一家接近百年的老厂,已成立61年。一般遇到这种“老字号企业”,我们的敬佩之情会油然而生!能在商海沉浮中坚持这么久,这本身就是值得骄傲,说明这家企业一定掌握着某种独

存-管-用 联想企业网盘融云一体机让协同办公变得简单

云计算、大数据、人工智能的兴起给中小企业带来更大的发展机遇。恰当的IT投入,能够帮助中小企业构建更为灵活且可靠的业务模式与业务平台,为中小企业带来更多业务机会。对于正在部署和开展数字化业务的中小型企业

平台+生态,华为凭什么为企业安全保驾护航?

当网络成为企业刚需,安全问题也不得不引起大家的重视。尤其是近年来,各种网络安全问题接连不断发生,给企业带来了严重不良后果。由此可见,企业亟需安全有效的解决方案来完善自己的网络。2019年3月21日,华

周鸿祎:360回归企业安全 携手安全生态打好网络攻坚战

8月19日,主题为“应对网络战、共建大生态、同筑大安全”的第七届互联网安全大会在北京雁栖湖国际会展中心隆重开幕,来自国内外的百余位专家共同讨论全球网络安全的最新形势,从战略、产业和技术等多个层面,探讨

企业的数字化转型方法论

文/张涵诚用区块链从新定义生产关系,用云量、用数量、移动指数、物联网指数、数据的应用和开放能力重新定义生产力,实现现代企业的五化管理工作移动化、数据产品化、分析可视化、管理云化、业务社交化。笔者认为这

41%的企业高层领导表示,数字化转型是在“浪费时间”

国外Celonis公司最近发布的一份调查报告称,近半数的高管在没有明确计划的情况下启动了数字化转型项目。报告显示,大多数企业都在进行数字化转型项目,虽然这样做的目的是为了提高企业效率和降低成本,但其实

博通终归还是下手了 作价107亿美元收购赛门铁克企业安全业务!

说起财大气粗,博通绝对是排的上号的企业,早在去年,博通就曾试图斥资1170亿美元收购竞争对手高通,最终特朗普政府以国家安全为由阻止了收购。而后博通在2018年7月斥资189亿美元收购了IT管理软件和解

云服务已占企业网络流量的85%

来自云安全公司Netskope的一份报告显示,云服务目前已占企业网络流量的85%。云服务落地加快,主要由跨组织的协作驱动,需要多个云服务来支撑。在前20个云服务中,云存储和协作应用占据了榜单首位,一些

企业备份软件选型指南:这三点是必关注项

企业备份软件,简单来说可以将数据和应用程序从主存储平台转移到二级存储。过去,磁带和磁盘常被用作二级存储媒介。如今,越来越多的供应商也把支持公有云存储作为一项长期战略。在现代IT实践中,备份工具已经从仅

关于网络安全防御,每个中小企业应该知道的5件事

根据美国商业促进局(BBB)的数据显示,你可能会惊讶地发现,小型企业占北美所有企业的97%以上。根据这个统计数字,我认为好消息是,在所有网络攻击中,针对小企业的攻击不到一半。坏消息是,当中小企业受到攻

面向企业的私有5G网络

许多人认为,5G网络是面向消费者部署的焦点。但是迄今为止,企业私有的5G网络已经出现。对于IT经理来说,他们可以在园区网络中替代有线局域网。私有5G网络有望吸引寻求私有系统的企业IT经理的注意,这些系

2019年第一季度企业WLAN市场同比增长7.1%

2019年第一季度(1Q19),消费者和企业全球无线局域网(WLAN)市场份额同比增长6.9%,达到24亿美元。根据IDC发布的全球季度WLAN追踪结果显示,企业级WLAN市场在1Q19同比增长7.1

运通集团:护航企业安全,不为信息化而信息化

曾经有人做出过总结,现代人忙碌奔波在物质上无非为了几“子”:车子、房子和票子。房和车可以说是很多现代人生活中的刚需。也正因如此,房地产商和汽车厂商近年来如鱼得水,得以开展各种业务,而运通集团就是典型代

当中小企业决定上云,真的像你们说的那么简单吗?

题图:fromZoommy四季度历来是一年中最忙碌的时期,辛苦了一年,各项工作都在收官,千头万绪、环环相扣,再加上绩效考核的开展,不但烧脑,而且还烧心。同时,最后一个季度又肩负着为来年开局而打基础的艰

英特尔第二代至强与傲腾,为企业IT带来了什么?

在企业IT基础设施领域,英特尔第二代至强可扩展处理器与傲腾数据中心级持久内存名声在外,是英特尔以数据为中心的产品组合中的代表之作。于今年4月份发布的第二代英特尔至强可扩展处理器,以强大的平台能力,实现

长城汽车张小斌:企业数字化不是选择,而是唯一的出路

长城汽车集团云计算总监张小斌20年IT行业经验。西安交通大学计算机专业毕业,中科院计算所硕士,曾在朗讯贝尔实验室、美国硅谷、HP、赛门铁克、Websense担任架构师、主任工程师、研发经理等职务,负责

面对网络风险 企业应当如何部署安全策略?

有关数据泄露和漏洞的突发层出不穷,这些数据泄露和漏洞对企业的财务和声誉有着非常大的影响。企业高管似乎无法摆脱预警头条的抨击,以及由专家组成的轰炸,这些专家就如何避免这些网络安全攻击提出了一些建议。尽管

谈PaaS平台建设:如何应对企业架构多元异构资源的挑战

据forbes预测,在2020年到来之前,83%的IT资源都会迁移上云。整个云的生态中,PaaS是最具有抽象属性的云形态,落地较晚也迟迟没有形成统一的标准。近几年,随着SaaS层业务的成熟,以及Iaa