开发流程概述

开通企业付款到余额功能
去商户后台获取商户账号appid、商户号、证书
生成签名
生成请求XML
向微信请求付款
付款结果分析保存
1、开通企业付款到余额功能
可以参照官方教程

2、获取商户相关信息
方法自行百度

3、生成签名和请求XML
生成签名的官方教程链接
下面是具体的方法

/**
     * 生成请求XML
     * @param code   订单编号
     * @param openid 微信用户的openid
     * @param amount 提现金额(分)
     * @return
     */
private String createXml(String code, String openid, String amount) {
        String[] arr = new String[9];
        arr[0] = "mch_appid=" + APP_ID;                      //商户账号appid
        arr[1] = "mchid=" + MCH_ID;                            //商户号
        arr[2] = "nonce_str=" + NONCE_STR;            //随机字符串
        arr[3] = "partner_trade_no=" + code;                 //订单编号
        arr[4] = "openid=" + openid;                            //用户openid
        arr[5] = "check_name=NO_CHECK";                //NO_CHECK:不校验真实姓名
        arr[6] = "amount=" + amount;//金额
        arr[7] = "desc=企业付款到余额";                        //企业付款备注
        arr[8] = "spbill_create_ip=192.168.**.****";        //Ip地址
        Arrays.sort(arr);
        String param = "";
        for (int i = 0; i < arr.length; i++) {
            param += arr[i] + "&";
        }
        param += "key=569C626880EF3EFFBB91A1E138EEC150"; //API密钥
        String sign = MD5Util.MD5Encode(param, null).toUpperCase();
        String xml = StringUtils.join(
                "<xml>",
                "<mch_appid>" + APP_ID + "</mch_appid>",
                "<mchid>" + MCH_ID + "</mchid>",
                "<nonce_str>" + NONCE_STR + "</nonce_str>",
                "<partner_trade_no>" + code + "</partner_trade_no>",
                "<openid>" + openid + "</openid>",
                "<check_name>NO_CHECK</check_name>",
                "<amount>" + amount + "</amount>",
                "<desc>景芝云店余额提现</desc>",
                "<spbill_create_ip>192.168.**.****</spbill_create_ip>",
                "<sign>" + sign + "</sign>",
                "</xml>"
        );
        return xml;
    }
加密算法

import java.security.MessageDigest;

public class MD5Util {
    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname)) {
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes()));
            } else {
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes(charsetname)));
            }
        } catch (Exception exception) {
        }
        return resultString;
    }
4、向微信请求付款

public class ClientCustomSSL {
    /**
     * 企业付款到余额
     * @param url
     * @param data
     * @return
     * @throws Exception
     */
    public String doPay(String url, String data,String sslcertPath,String mch_id) throws Exception {
        /**
         * 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的
         */

KeyStore keyStore = KeyStore.getInstance("PKCS12");
        /**
         *此处要改
         *wxconfig.SSLCERT_PATH : 指向你的证书的绝对路径,带着证书去访问
         */

FileInputStream instream = new FileInputStream(new File(sslcertPath));//P12文件目录
        try {
            /**
             * 此处要改
             *
             * 下载证书时的密码、默认密码是你的MCHID mch_id
             * */
            keyStore.load(instream, mch_id.toCharArray());//这里写密码
        } finally {
            instream.close();
        }

// Trust own CA and all self-signed certs
        /**
         * 此处要改
         * 下载证书时的密码、默认密码是你的MCHID mch_id
         * */
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, mch_id.toCharArray())//这里也是写密码的
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[]{"TLSv1"},
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
        try {
            HttpPost httpost = new HttpPost(url); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();

String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }

}
5、付款结果分析保存
EnterpriceToCustomer refundResult = parseXmlToMapEnterpriceToCustomer(result);
if (SUCCESS.equalsIgnoreCase(refundResult.getResult_code()) && SUCCESS.equalsIgnoreCase(refundResult.getReturn_code())) {
            //8表示成功
        } else {
            //9 表示失败
        }

返回结果实体类

/**
 * 企业 付款到 客户 结果 实体类
 *
 * @author CHQ
 * @create 2018-10-19 18:56
 **/
public class EnterpriceToCustomer {

/*    <xml>
        <return_code><![CDATA[SUCCESS]]></return_code>
        <return_msg><![CDATA[]]></return_msg>
        <mchid><![CDATA[1488323162]]></mchid>
        <nonce_str><![CDATA[o9fcpfvqow1aks48a2omvayu1ne7c709]]></nonce_str>
        <result_code><![CDATA[SUCCESS]]></result_code>
        <partner_trade_no><![CDATA[xvuct0087w4t1dpr87iqj98w5f71ljae]]></partner_trade_no>
        <payment_no><![CDATA[1000018301201801163213961289]]></payment_no>
        <payment_time><![CDATA[2018-01-16 14:52:16]]></payment_time>
        </xml>
    */
    private String return_code;
    private String return_msg;
    private String mchid;
    private String nonce_str;
    private String result_code;
    private String partner_trade_no;
    private String payment_no;
    private String payment_time;

/*
     * 支付错误时,返回的代码
     *  key是:return_code,值是:SUCCESS
        key是:return_msg,值是:支付失败
        key是:mch_appid,值是:wx49c22ad731b679c3
        key是:mchid,值是:1488323162
        key是:result_code,值是:FAIL
        key是:err_code,值是:AMOUNT_LIMIT
        key是:err_code_des,值是:付款金额超出限制。低于最小金额1.00元或累计超过20000.00元。
     *
     */
    private String err_code;

private String err_code_des;

public String getErr_code() {
        return err_code;
    }

public void setErr_code(String errCode) {
        err_code = errCode;
    }

public String getErr_code_des() {
        return err_code_des;
    }

public void setErr_code_des(String errCodeDes) {
        err_code_des = errCodeDes;
    }

public String getReturn_code() {
        return return_code;
    }

public void setReturn_code(String returnCode) {
        return_code = returnCode;
    }

public String getReturn_msg() {
        return return_msg;
    }

public void setReturn_msg(String returnMsg) {
        return_msg = returnMsg;
    }

public String getMchid() {
        return mchid;
    }

public void setMchid(String mchid) {
        this.mchid = mchid;
    }

public String getNonce_str() {
        return nonce_str;
    }

public void setNonce_str(String nonceStr) {
        nonce_str = nonceStr;
    }

public String getResult_code() {
        return result_code;
    }

public void setResult_code(String resultCode) {
        result_code = resultCode;
    }

public String getPartner_trade_no() {
        return partner_trade_no;
    }

public void setPartner_trade_no(String partnerTradeNo) {
        partner_trade_no = partnerTradeNo;
    }

public String getPayment_no() {
        return payment_no;
    }

public void setPayment_no(String paymentNo) {
        payment_no = paymentNo;
    }

public String getPayment_time() {
        return payment_time;
    }

public void setPayment_time(String paymentTime) {
        payment_time = paymentTime;
    }

@Override
    public String toString() {
        return "EnterpriceToCustomer [err_code=" + err_code + ", err_code_des="
                + err_code_des + ", mchid=" + mchid + ", nonce_str="
                + nonce_str + ", partner_trade_no=" + partner_trade_no
                + ", payment_no=" + payment_no + ", payment_time="
                + payment_time + ", result_code=" + result_code
                + ", return_code=" + return_code + ", return_msg=" + return_msg
                + "]";
    }

结果解析方法

/**
     * 下面是需要通过跟节点,找找到对应的类属性,手动把它set进去。因此API返回的参数不一样。需要写每个返回的Bean。
     * 解析企业支付申请
     * 解析的时候自动去掉CDMA
     *
     * @param xml
     */
    public static EnterpriceToCustomer parseXmlToMapEnterpriceToCustomer(String xml) {
        EnterpriceToCustomer enterpriceToCustomer = new EnterpriceToCustomer();
        try {
            StringReader read = new StringReader(xml);
            // 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
            InputSource source = new InputSource(read);
            // 创建一个新的SAXBuilder
            SAXBuilder sb = new SAXBuilder();
            // 通过输入源构造一个Document
            Document doc;
            doc = (Document) sb.build(source);

Element root = doc.getRootElement();// 指向根节点
            List<Element> list = root.getChildren();

if (list != null && list.size() > 0) {
                for (Element element : list) {
                    System.out.println("key是:" + element.getName() + ",值是:" + element.getText());
                    if ("return_code".equals(element.getName())) {
                        enterpriceToCustomer.setReturn_code(element.getText());
                    }

if ("return_msg".equals(element.getName())) {
                        enterpriceToCustomer.setReturn_msg(element.getText());
                    }

if ("mchid".equals(element.getName())) {
                        enterpriceToCustomer.setMchid(element.getText());
                    }

if ("nonce_str".equals(element.getName())) {
                        enterpriceToCustomer.setNonce_str(element.getText());
                    }
                    if ("result_code".equals(element.getName())) {
                        enterpriceToCustomer.setResult_code(element.getText());
                    }
                    if ("partner_trade_no".equals(element.getName())) {
                        enterpriceToCustomer.setPartner_trade_no(element.getText());
                    }
                    if ("payment_no".equals(element.getName())) {
                        enterpriceToCustomer.setPayment_no(element.getText());
                    }
                    if ("payment_time".equals(element.getName())) {
                        enterpriceToCustomer.setPayment_time(element.getText());
                    }
                    if ("err_code".equals(element.getName())) {
                        enterpriceToCustomer.setErr_code(element.getText());
                    }
                    if ("err_code_des".equals(element.getName())) {
                        enterpriceToCustomer.setErr_code_des(element.getText());
                    }

}
            }
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

return enterpriceToCustomer;
    }

如果正确会返回如下信息

<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[]]></return_msg>
<mch_appid><![CDATA[wxc496d2a]]></mch_appid>
<mchid><![CDATA[10478671]]></mchid>
<nonce_str><![CDATA[5K8264ILTTCU16CQ2NMTM67VS]]></nonce_str>
<result_code><![CDATA[SUCCESS]]></result_code>
<partner_trade_no><![CDATA[TX154000445301]]></partner_trade_no>
<payment_no><![CDATA[100001830129966]]></payment_no>
<payment_time><![CDATA[2018-10-21 09:04:23]]></payment_time>
</xml>
1
2
3
4
5
6
7
8
9
10
11
如果按照上面的方法应该能成功
参考文章:
https://blog.csdn.net/xiaozhegaa/article/details/79178751
https://blog.csdn.net/xiaozhegaa/article/details/79127283

微信 企业付款到余额 开发 教程相关推荐

  1. php 微信企业付款到余额

    public function tixian($openid,$money,$id){$name = '余额';$appid = '';//商户账号appid$secret = "##### ...

  2. 企业付款php 接口,微信企业付款接口PHP开发需要注意的两个地方

    curl拓展 curl_setopt($ch, CURLOPT_SSLCERT, getcwd().'/cert/mycert.pem'); 在做微信支付接口双向验证的时候,需要pem证书文件,然而在 ...

  3. 微信零钱数据在服务器,关于微信企业付款到零钱X509Certificate2读取证书信息,发布到服务器访问不到的解决方案...

    前言: 最近做了一个通过调用微信企业付款到用户零钱的功能,真的挺奇怪的,在我本地调试的时候都没有问题,但是当我发布到服务上的时候却一直无法读取到我的证书信息.读取的代码如下,使用的是微信官方文档提供的 ...

  4. PHP实现微信企业付款

    一.封装微信企业付款类WeiXinPayToUser,如下图代码所示: class WeixinPayToUser {/*** API 参数* @var array* 'mch_appid' # 公众 ...

  5. 【跟我做】简单两部使用laravel-easy-WeChat包快速实现微信企业付款到用户零钱包功能...

    2019独角兽企业重金招聘Python工程师标准>>> 最近在使用laravel框架做一款小程序后台,要使用到微信用户提现到零钱包功能,在网上翻了一下大多都是用户下单支付给企业的教程 ...

  6. 微信企业付款至零钱包实现详细流程Demo

    微信企业付款实现详细流程Demo 大家好,我是 梦辛工作室的灵,下面来讲一下微信企业付款实现的流程 1.准备数据 微信企业付款需要 准备 微信支付API秘钥.支付证书:下面是获取流程: 先登录微信支付 ...

  7. Java 微信企业付款到个人钱包

    Java 微信企业付款到个人钱包 希望可以帮助到你 文章目录 **Java 微信企业付款到个人钱包** 前言 一.需要准备的配置 二.开发 总结 前言 微信企业付款到个人钱包,此功能模块需要提前在微信 ...

  8. JAVA微信企业付款到零钱(十分钟搞定),附完整DEMO下载

    最近帮朋友做了一个简单的微分销系统,实现从企业付款到零钱分润的功能,简单记录一下微信提现功能开发的流程, 主要就是按规则封装好请求参数调用微信接口,涉及一些签名校验: A.接口流程 获取用户OPENI ...

  9. 微信企业付款到银行卡

    第一次做微信企业付款到银行卡,特地记录下来,因为这个功能自己用了2-3天,这中间的坑主要是再rsa加密那块.自己记录下来,供朋友参考.自己用的php开发 第一,首先你需要开通企业的微信认证公众号平台, ...

最新文章

  1. R构建径向核支持向量机分类器实战代码(Radial kernel Support Vector Classifier)
  2. XMPP iOS客户端实现三:登录、注册
  3. MySQL多字段排序乱_Mysql ORDER BY 中文排序错乱问题
  4. php 递归分销角色,PHP递归无限分类
  5. C#知多少 | 每个版本都更新了什么?
  6. 你怎么了珍妮,你醒醒啊珍妮~ | 今日最佳
  7. Java实现并发线程中线程范围内共享数据
  8. firebase连接不上_如何在Firebase上托管Blazor应用程序
  9. 20.校准相机——介绍,使用已知点进行校正,直接线性校准均匀性第1部分,直接线性校准均匀性第2部分_1
  10. 笔记本显示网络电缆被拔出怎么解决_电脑显示“网络电缆被拔出”怎么办?
  11. 使用 nginx 的 stream模块的TCP 转发实现内网SSH
  12. 毕设 JAVA北京旅游网系统论文
  13. 3g无线图传点到点模式与服务器模式比较,4G网络的几个关键技术指标 - 3G和4G LTE网络架构之间的区别...
  14. mysql 在线语法检查工具,符合多个数据库的在线SQL语法检查器
  15. 陪着时光,走过羊肠阡陌
  16. ISO认证包括哪些?
  17. linux 启动 grub 修复工具,当Ubuntu无法启动时,如何修复GRUB2?
  18. 【MATLAB教程案例26】图像特征点提取算法matlab仿真与分析——sift,surf,kaze,corner,BRISK等
  19. “三屏融合”或比“三网融合”更不现实
  20. 将eclipse配置成可迁移,即直接复制就可以使用

热门文章

  1. 小白如何入门全栈开发
  2. 【QT】QSS美化——主窗体
  3. Android P版本非SDK接口管控特性,参考华为
  4. ag-grid 自适应大小
  5. 计划任务linux时间,系统运维|在 Linux 中怎么使用 cron 计划任务
  6. python图片字符画教程_手把手教你用python将图片做成字符画!
  7. WINDOW -- 电脑没有无线网卡驱动
  8. Word之打字覆盖后面的字怎么办
  9. 中型企业VDI实现方案
  10. 山荣PHP-900油墨,翼装飞行天门山:天堂和地狱的分叉口