精华内容
下载资源
问答
  • 微信支付、微信企业支付到个人,微信企业付款到零钱,微信支付apiJSAPI支付 刷卡支付 扫码支付 订单退款 订单查询 退款查询 下载账单
  • c#微信支付、微信企业支付到个人,微信企业付款到零钱, 代码DEMO.rar.rar c#微信支付、微信企业支付到个人,微信企业付款到零钱, 代码DEMO.rar.rar c#微信支付、微信企业支付到个人,微信企业付款到零钱, 代码...
  • 微信支付、企业支付、微信企业支付到个人,微信企业付款到零钱, 代码DEMO 供大家参考 微信支付apiJSAPI支付 刷卡支付 扫码支付 订单退款 订单查询 退款查询 下载账单
  • 微信企业付款到零钱

    2021-04-02 14:58:46
    企业付款 直接上代码 关键入参 package cn.country.cunyue.app.pojo.dto.weixin; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @Desc ...

    官方文档

    企业付款

    直接上代码

    关键入参

    package cn.country.cunyue.app.pojo.dto.weixin;
    
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    /**
     * @Desc https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
     */
    @Data
    @ApiModel(value = "net.mondelez.scan.microservice.entity.vo.WxMchPayB2c", description = "微信商户平台-微信支付-企业付款到零钱")
    public class WxMchPayB2c {
    
        @ApiModelProperty(value = "申请商户号的appid或商户号绑定的appid", required = true)
        private String mch_appid;
    
        @ApiModelProperty(value = "微信支付分配的商户号", required = true)
        private String mchid;
    
        @ApiModelProperty(value = "微信支付分配的终端设备号", required = false)
        private String device_info;
    
        @ApiModelProperty(value = "随机字符串,不长于32位", required = true)
        private String nonce_str;
    
        @ApiModelProperty(value = "签名,签名算法:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=4_3", required = true)
        private String sign;
    
        @ApiModelProperty(value = "商户订单号,需保持唯一性(只能是字母或者数字,不能包含有其它字符)", required = true)
        private String partner_trade_no;
    
        @ApiModelProperty(value = "商户appid下,某用户的openid", required = true)
        private String openid;
    
        @ApiModelProperty(value = "校验用户姓名选项,NO_CHECK:不校验真实姓名,FORCE_CHECK:强校验真实姓名", required = true)
        private String check_name = "NO_CHECK";
    
        @ApiModelProperty(value = "收款用户真实姓名,如果check_name设置为FORCE_CHECK,则必填用户真实姓名,如需电子回单,需要传入收款用户姓名", required = false)
        private String re_user_name;
    
        @ApiModelProperty(value = "企业付款金额,单位为分", required = true)
        private Integer amount;
    
        @ApiModelProperty(value = "企业付款备注,必填。注意:备注中的敏感词会被转成字符*", required = true)
        private String desc;
    
        @ApiModelProperty(value = "Ip地址,该IP同在商户平台设置的IP白名单中的IP没有关联,该IP可传用户端或者服务端的IP", required = false)
        private String spbill_create_ip;
    }
    
    

    帮助方法

    package cn.country.cunyue.app.application.utils;
    
    import cn.country.cunyue.app.pojo.dto.weixin.WxMchPayB2c;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.HttpStatus;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.conn.ConnectTimeoutException;
    import org.apache.http.conn.ConnectionPoolTimeoutException;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.ssl.SSLContexts;
    import org.apache.http.util.EntityUtils;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSession;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.lang.reflect.Field;
    import java.net.SocketTimeoutException;
    import java.security.*;
    import java.security.cert.CertificateException;
    import java.util.Set;
    import java.util.SortedMap;
    import java.util.TreeMap;
    
    /**
     * 微信支付工具类
     *
     * @author: joker
     * @date: 2021-3-25 14:28:40
     */
    @Slf4j
    public class WeixinPayUtils {
    
        /**
         * 企业付款到零钱接口URL.
         */
        private static final String TRANS_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
    
        private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
    
        /**
         * 微信支付签名算法sign
         *
         * @param parameters 参数集合
         * @return 返回md5签名
         */
        public static String createSign(String signKey, SortedMap<Object, Object> parameters) {
            StringBuffer sb = new StringBuffer();
            Set es = parameters.keySet();                 // 所有参与传参的key按照accsii排序(升序)
            for (Object set : es) {
                String k = set.toString();
                Object v = parameters.get(k);
                sb.append(k).append("=").append(v.toString()).append("&");
            }
            sb.append("key=").append(signKey);
            return str2MD5(sb.toString(), "utf-8").toUpperCase();
        }
    
        /**
         * MD5加密
         *
         * @param data   要加密的数据
         * @param encode 加密的编码
         * @return md5字符串
         */
        public static String str2MD5(String data, String encode) {
            String resultString = null;
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                if (encode == null || "".equals(encode))
                    resultString = byteArrayToHexString(md.digest(data.getBytes()));
                else {
                    resultString = byteArrayToHexString(md.digest(data.getBytes(encode)));
                }
            } catch (Exception exception) {
            }
            return resultString;
        }
    
        /**
         * byte数组转换16进制字符串
         *
         * @param b 要转换的byte数组
         * @return 16进制字符串
         */
        private static String byteArrayToHexString(byte b[]) {
            StringBuffer resultSb = new StringBuffer();
            for (int i = 0; i < b.length; i++) {
                resultSb.append(byteToHexString(b[i]));
            }
            return resultSb.toString();
        }
    
        /**
         * byte转换成16进制字符串
         *
         * @param b 要转换的byte
         * @return byte对应的16进制字符串
         */
        private static String byteToHexString(byte b) {
            int n = b;
            if (n < 0) {
                n += 256;
            }
            int d1 = n / 16;
            int d2 = n % 16;
            return hexDigits[d1] + hexDigits[d2];
        }
    
        /**
         * map集合参数转换为xml格式
         *
         * @param dataMap 要转换的map对象
         * @return XML格式的字符串
         */
        public static String map2XML(SortedMap<Object, Object> dataMap) {
            StringBuffer sb = new StringBuffer();
            Set<Object> objSet = dataMap.keySet();
            sb.append("<xml>\n");
            for (Object key : objSet) {
                if (key == null) {
                    continue;
                }
                Object value = dataMap.get(key);
                sb.append("<").append(key.toString()).append(">").append(value).append("</").append(key.toString()).append(">\n");
            }
            sb.append("</xml>");
            return sb.toString();
        }
    
        /**
         * 生成随机数.
         *
         * @param count 要生成的随机数位数
         * @return 随机数字符串
         */
        private String createNonceStr(int count) {
            String[] nums = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
            int maxIndex = nums.length - 1;
            int numIndex;
            StringBuilder builder = new StringBuilder(count);
            for (int i = 0; i < count; i++) {
                numIndex = (int) (Math.random() * maxIndex);
                builder.append(nums[numIndex]);
            }
            return builder.toString();
        }
    
        /**
         * 生成签名和xml参数的main方法测试.
         * see https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=4_3
         *
         * @param args
         */
        public static void main(String[] args) {
            String key = "192006250b4c09247ec02edce69f6a2d";
            SortedMap<Object, Object> map = new TreeMap<>();
            map.put("appid", "wxd930ea5d5a258f4f");
            map.put("mch_id", "10000100");
            map.put("device_info", "1000");
            map.put("body", "test");
            map.put("nonce_str", "ibuaiVcKdpRxkhJA");           // 这里为了跟文档的结果对应,直接使用文档的随机数
            String sign = WeixinPayUtils.createSign(key, map);
            map.put("sign", sign);
            String xmlParam = WeixinPayUtils.map2XML(map);
            System.out.println(xmlParam);
        }
    
        /**
         * 以下是http请求相关接口方法.
         */
    
        /**
         * 加载证书.
         *
         * @param certPath 证书文件绝对路径
         * @param mchid    商户id
         */
        private static KeyStore initCert(String certPath, String mchid) {
            KeyStore keyStore = null;
            // 加载本地的证书进行https加密传输
            FileInputStream instream = null;
            try {
                keyStore = KeyStore.getInstance("PKCS12");
                instream = new FileInputStream(new File(certPath));
                keyStore.load(instream, mchid.toCharArray()); // 加载证书密码,默认为商户ID
            } catch (KeyStoreException e) {
                log.error(e.getMessage(), e);
            } catch (FileNotFoundException e) {
                log.error(e.getMessage(), e);
            } catch (NoSuchAlgorithmException e) {
                log.error(e.getMessage(), e);
            } catch (CertificateException e) {
                log.error(e.getMessage(), e);
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            } finally {
                if (instream != null) {
                    try {
                        instream.close();
                    } catch (IOException e) {
                        log.error(e.getMessage(), e);
                    }
                }
            }
            return keyStore;
        }
    
        /**
         * 创建CloseableHttpClient.
         *
         * @param keyStore
         * @param keyPassword
         * @return
         */
        private static CloseableHttpClient createHttpClient(KeyStore keyStore, char[] keyPassword) {
            // Trust own CA and all self-signed certs
            SSLContext sslcontext = null;
            try {
                sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, keyPassword).build();
            } catch (NoSuchAlgorithmException e) {
                log.error(e.getMessage(), e);
            } catch (KeyManagementException e) {
                log.error(e.getMessage(), e);
            } catch (KeyStoreException e) {
                log.error(e.getMessage(), e);
            } catch (UnrecoverableKeyException e) {
                log.error(e.getMessage(), e);
            }
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[]{"TLSv1"}, null,
                    new HostnameVerifier() {
                        @Override
                        public boolean verify(String hostname, SSLSession sslSession) {
                            // 微信商户平台的支付接口验证直接通过
                            if ("api.mch.weixin.qq.com".equals(hostname)) {
                                return true;
                            } else {
                                HostnameVerifier hv = SSLConnectionSocketFactory.getDefaultHostnameVerifier();
                                return hv.verify(hostname, sslSession);
                            }
                        }
                    });
            CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            // 根据默认超时限制初始化requestConfig
            return httpClient;
        }
    
        /**
         * post传输xml数据.
         *
         * @param url      传输url
         * @param xmlObj   xml参数
         * @param mchid    商户id
         * @param certPath 证书文件的绝对路径
         * @return
         */
        public static String post(String url, String xmlObj, String mchid, String certPath) {
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(10000).build();
            // 加载证书
            KeyStore keyStore = initCert(certPath, mchid);
            CloseableHttpClient httpClient = createHttpClient(keyStore, mchid.toCharArray());
            String result = null;
            HttpPost httpPost = new HttpPost(url);
            // 得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
            String defaultCharset = "UTF-8";
            StringEntity postEntity = new StringEntity(xmlObj, defaultCharset);
            httpPost.addHeader("Content-Type", "text/xml");
            httpPost.setEntity(postEntity);
            // 设置请求器的配置
            httpPost.setConfig(requestConfig);
            try {
                HttpResponse res = httpClient.execute(httpPost);
                if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    HttpEntity entity = res.getEntity();
                    result = EntityUtils.toString(entity, defaultCharset);
                }
            } catch (ConnectionPoolTimeoutException e) {
                log.error(e.getMessage(), e);
            } catch (ConnectTimeoutException e) {
                log.error(e.getMessage(), e);
            } catch (SocketTimeoutException e) {
                log.error(e.getMessage(), e);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            } finally {
                httpPost.abort();
            }
            return result;
        }
    
        /**
         * 发送请求.
         *
         * @param key      密钥
         * @param certPath API证书证书apiclient_cert.p12
         * @param model    企业付款到零钱接口所需参数
         * @return String
         */
        public static String doTransfers(String key, String certPath, WxMchPayB2c model) throws IllegalAccessException {
            SortedMap<Object, Object> map = new TreeMap<>();
            Field[] declaredFields = model.getClass().getDeclaredFields();
            for (Field field : declaredFields) {
                field.setAccessible(true);
                String k = field.getName();
                Object v = field.get(model);
                if (v != null) {
                    map.put(k, v);
                }
            }
            String sign = WeixinPayUtils.createSign(key, map);
            map.put("sign", sign);
            String xmlParam = WeixinPayUtils.map2XML(map);
            String result = post(TRANS_URL, xmlParam, model.getMchid(), certPath);
            return result;
        }
    }
    
    
    展开全文
  • 主要为大家详细介绍了Thinkphp 5.0实现微信企业付款到零钱,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 微信企业付款到零钱实战操作指南,包含了一部分代码,如有不清楚的,可以联系我。远程解决问题,需要微信企业付款到零钱php版本的,也可以联系我。
  • 关于微信企业付款到零钱

    万次阅读 热门讨论 2018-07-19 13:12:46
    近日,在开发“微信企业付款到零钱”的功能。之前有过微信开发的经验,但是第一次接触“付款到零钱“这一块的业务,查询了很多的博客资料以及走了很多的弯路。也发现“企业付款到零钱”分享的博客并不多。特地写了该...

    近日,在开发“微信企业付款到零钱”的功能。之前有过微信开发的经验,但是第一次接触“付款到零钱“这一块的业务,查询了很多的博客资料以及走了很多的弯路。也发现“企业付款到零钱”分享的博客并不多。特地写了该博客,希望对你们有帮助。个人浅薄的见解


    这里写图片描述
    【稍微提一下:】上一篇博客分享了“企业付款到银行卡API~~”文章,有位博友留言了,遇到了“产品权限验证失败 请查看您当前是否具有该产品的权限”。这是因为没有在微信商务后台开通对应的功能。API里面已经明确提示了。这里我是建议:大家一定要先去看文档,看完再来看这篇文章。文档也就三四页而已,也就20分钟
    这里写图片描述
    一、企业付款到零钱API
    https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1
    【建议还是看看】
    这里写图片描述
    二、开发准备
    (1)证书的准备:java开发需要用到:apiclient_cert.p12证书的,在微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>证书中下载的 。
    这里写图片描述

    【何时用到证书?】与支付不一样,企业支付功能在发送post请求的时候,需要加载自己的一个证书之后,带着证书去请求退款才可以。这里使用到证书–很多人不知道证书在哪里使用
    (2)了解好数字签名 — 简单来解释,就是对自己要发送的数据进行加密处理、换句话说假如说你要传递A/B/C,就对这三者进行加密。初开发者的误区:不知道该加密什么数据、观看网上的博客胡乱进行签名,导致签名错误
    【温馨提示:】数字签名是一般开发人员容易遇到的错误,记住“你没遇到数字签名错误,都不好意思说自己做过微信退款支付订单查询等功能”。 签名工具类见:我这里就不贴出来了
    耐心解决就行

     

    三、API截图解释
    ~~ 开通条件:
    这里写图片描述
    ~ 接口说明 + 是否需要证书
    这里写图片描述

    ~ 证书说明 java开发只需要:apiclient_cert.p12
    这里写图片描述

    四、开发步骤如下
    这里写图片描述

    1、拼凑所需要传递的参数 map集合
    2、根据要传递的参数生成自己的签名
    3、把签名放到map集合中【因为签名也要传递过去,看API】
    4、将当前的map结合转化成xml格式
    5、发送请求到企业付款到零钱的Api。发送请求是一个方法来的POST
    6、解析返回的xml数据===》map集合

    7、根据map中的result_code AND return_code来判断是否成功与失败
     

    @SuppressWarnings("unchecked") 
        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()); 
                            }   
                            //错误的编码
                            /*
                               private String err_code;
                               private String err_code_des;
                             * */
                            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; 
            } 
    @Test
        public void OldBook(){
            //1.0 拼凑企业支付需要的参数
            String appid = wxconfig.AppID;  //微信公众号的appid
            String mch_id = wxconfig.mch_id; //商户号
            String nonce_str = RandomStringGenerator.getRandomStringByLength(32); //生成随机数
            String partner_trade_no =  RandomStringGenerator.getRandomStringByLength(32); //生成商户订单号
            String openid = "oYiAh0ypHoaYFoVFhAsnv1aJ****"; // 支付给用户openid
            String check_name = "NO_CHECK"; //是否验证真实姓名呢
            String re_user_name = "小郑";   //收款用户姓名
            String amount = "100";              //企业付款金额,单位为分
            String desc = "测试开发,稍后会还给公司的";   //企业付款操作说明信息。必填。
            String spbill_create_ip = "192.168.**.****;     //
    
            //2.0 生成map集合
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>(); 
            packageParams.put("mch_appid", appid);         //微信公众号的appid
            packageParams.put("mchid", mch_id);       //商务号
            packageParams.put("nonce_str",nonce_str);  //随机生成后数字,保证安全性
    
            packageParams.put("partner_trade_no",partner_trade_no); //生成商户订单号
            packageParams.put("openid",openid);            // 支付给用户openid
            packageParams.put("check_name",check_name);    //是否验证真实姓名呢
            packageParams.put("re_user_name",re_user_name);//收款用户姓名
            packageParams.put("amount",amount);            //企业付款金额,单位为分
            packageParams.put("desc",desc);                //企业付款操作说明信息。必填。
            packageParams.put("spbill_create_ip",spbill_create_ip); //调用接口的机器Ip地址
    
    
            //3.0 生成自己的签名
            String sign  = WeixinPayBack.createSign("utf-8",packageParams);
    
            //4.0 封装退款对象
            packageParams.put("sign", sign);
    
            //5.0将当前的map结合转化成xml格式
            String reuqestXml = WXPayUtil.getRequestXml(packageParams);
    
            //6.0获取需要发送的url地址
            String wxUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; //获取退款的api接口
    
            try {
                String weixinPost = ClientCustomSSL.doRefund(wxUrl, reuqestXml).toString();
                //7.0 解析返回的xml数据
                com.fh.entity.nrb.xiaozheng.EnterpriceToCustomer refundResult = WeixinPayBack.parseXmlToMapEnterpriceToCustomer(weixinPost);
                if("SUCCESS".equalsIgnoreCase(refundResult.getResult_code()) && "SUCCESS".equalsIgnoreCase(refundResult.getReturn_code())){
                    //8表示退款成功
                    //TODO 执行成功付款后的业务逻辑
                    //return successPayMoneyByBankCard(submitMoney,cmms_amt,enterpriceToCustomerByCard,applyId,companyId);
                }else{
                    //9 表示退款失败
                    //TODO 调用service的方法 ,存储失败提现的记录咯
                    //failToPayMoneyByBankCard(enterpriceToCustomerByCard,applyId);
    
    
                }
    
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
    
        }

    这里写图片描述

    五、结果演示
    这里写图片描述
    自此,我们就学会了“企业付款到个人零钱”的开发,希望对你们有帮助
    具体的、在调用改方法自己加上自己的业务逻辑就行了。希望对大家有帮助

    展开全文
  • 微信企业付款到零钱API

    千次阅读 2018-04-17 19:22:02
    由于项目需求老大叫我开发“微信企业付款到零钱”的功能,这之前我做过一些微信支付的相关东西,对我而言微信封装的东西感觉比ALI难过一些。言归正传,在没有找到微信官方的API的情况下就只能借鉴之前写过的各位大佬...

    由于项目需求老大叫我开发“微信企业付款到零钱”的功能,这之前我做过一些微信支付的相关东西,对我而言微信封装的东西感觉比ALI难过一些。言归正传,在没有找到微信官方的API的情况下就只能借鉴之前写过的各位大佬的了,但是结合自身的水平发现有很多东西还是借鉴的。

        1.开发“微信企业付款到零钱”的功能,首先需要登录微信商户-->产品中心-->查看“企业付款到零钱”是否开通

    如果未开通,则需要开通。

    2.仔细阅读-->企业付款到零钱API

        https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1    (必看)

    3.证书的准备:java开发需要用到:apiclient_cert.p12证书的,在微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>证书中下载的 。 




    4.关于证书和参数

    https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=4_3    (建议看看)

    5.相关代码

        
    @Controller
    @RequestMapping("/transfer")
    public class TransferController {
    
    	private static final Logger LOG = Logger.getLogger(TransferController.class);
    	// 获取需要发送的url地址
    	private static final String TRANSFERS_PAY = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; 
    	// 企业付款查询
    	private static final String TRANSFERS_PAY_QUERY = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo"; 
    
    	@Autowired
    	TokenMapper tokenMapper;
    	
    	/**
    	 * 企业向个人支付转账
    	 * 
    	 * @param request
    	 * @param response
    	 * @param openid
    	 *            用户openid
    	 * @param callback
    	 * @throws MyException
    	 */
    	@RequestMapping(value = "pay")
    	@ResponseBody
    	public Object transferPay(HttpServletRequest request, HttpServletResponse response, String token,BigDecimal amount) throws MyException {
    		LOG.info("[/transfer/pay]");
    		Map<Object, Object> map = new HashMap<Object, Object>();
    		/**
    		 * 这里我是原来微信三方登录时获取openId存入数据库的,所有可以直接读出来
    		 *     根据你的业务逻辑来获取openId
    		 */
    //		Map<String, Object> map2  = tokenMapper.queryUserByToken(token);	
    //		String openid = (String) map2.get("openId");
    //		// 业务判断 openid是否有收款资格
    //		if (openid == null) {
    //			throw new MyException("尚未使用过微信支付,无法用微信提现!");	
    //		}
    		Map<String, String> restmap = null;
    		try {
    			Map<String, String> parm = new HashMap<String, String>();
    			parm.put("mch_appid", ConfigUtil.APPID); // 公众账号appid
    			parm.put("mchid", ConfigUtil.MCH_ID); // 商户号
    			parm.put("nonce_str", PayUtil.getNonceStr()); // 随机字符串
    			parm.put("partner_trade_no", PayUtil.getTransferNo()); // 生成商户订单号
    			parm.put("openid", openid); // 用户openid
    			parm.put("check_name", "NO_CHECK"); // 是否验证真实姓名--校验用户姓名选项 OPTION_CHECK
    			parm.put("re_user_name", "张三"); //收款用户姓名---check_name设置为FORCE_CHECK或OPTION_CHECK,则必填
    			parm.put("amount", "100"); // 转账金额
    			parm.put("desc", "测试企业付款到零钱"); // 企业付款描述信息
    			parm.put("spbill_create_ip", PayUtil.getLocalIp(request)); // Ip地址
    			parm.put("sign", PayUtil.getSign(parm, ConfigUtil.API_KEY));
    
    			String restxml = HttpUtils.posts(TRANSFERS_PAY, XmlUtils.xmlFormat(parm, false));
    			restmap = XmlUtils.xmlParse(restxml);
    		} catch (Exception e) {
    			LOG.error(e.getMessage(), e);
    		}
    
    		if (CollectionUtil.isNotEmpty(restmap) && "SUCCESS".equals(restmap.get("result_code"))) {
    			LOG.info("转账成功:" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
    			Map<String, String> transferMap = new HashMap<>();
    			transferMap.put("partner_trade_no", restmap.get("partner_trade_no"));// 商户转账订单号
    			transferMap.put("payment_no", restmap.get("payment_no")); // 微信订单号
    			transferMap.put("payment_time", restmap.get("payment_time")); // 微信支付成功时间
    			WebUtil.response(response, WebUtil.packJsonp(null, JSON.toJSONString(
    					new JsonResult(1, "转账成功", new ResponseData(null, transferMap)), SerializerFeatureUtil.FEATURES)));
    		} else {
    			if (CollectionUtil.isNotEmpty(restmap)) {
    				LOG.info("转账失败:" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
    			}
    			WebUtil.response(response, WebUtil.packJsonp(null,
    					JSON.toJSONString(new JsonResult(-1, "转账失败", new ResponseData()), SerializerFeatureUtil.FEATURES)));
    		}
    		map.put("code", 200);
    		map.put("msg", "提现成功!");
    		return map;
    	}
    这里需要着重注意这个方法
    String restxml = HttpUtils.posts(TRANSFERS_PAY, XmlUtils.xmlFormat(parm, false));
    方法Post进去
    /**
    	 * @description 功能描述: post https请求,服务器双向证书验证
    	 * @param url 请求地址
    	 * @param s 参数xml
    	 * @return 请求失败返回null
    	 */
    	public static String posts(String url, String s) {
    		CloseableHttpClient httpClient = null;
    		HttpPost httpPost = new HttpPost(url);
    		String body = null;
    		CloseableHttpResponse response = null;
    		try {
    			httpClient = HttpClients.custom()
    					.setDefaultRequestConfig(REQUEST_CONFIG)
    					.setSSLSocketFactory(getSSLConnectionSocket())
    					.build();
    			httpPost.setEntity(new StringEntity(s, DEFAULT_CHARSET)); 
    			response = httpClient.execute(httpPost);
    			body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (response != null) {
    				try {
    					response.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    
    			if (httpClient != null) {
    				try {
    					httpClient.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		return body;
    	}
    会有httpClient请求,这里是需要配置编码格式,链接超时时间,微信支付ssl证书(就是之前下载的证书)
    httpClient = HttpClients.custom().setDefaultRequestConfig(REQUEST_CONFIG)
    				 .setSSLSocketFactory(getSSLConnectionSocket())
    				 .build();
    进入配置类,这里的ClassPathResource里表示你证书的放置路径。
    public class HttpUtils {
    
    	private static final String DEFAULT_CHARSET = "UTF-8";
    	
    	private static final int CONNECT_TIME_OUT = 5000; //链接超时时间3秒
    	
    	private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom().setConnectTimeout(CONNECT_TIME_OUT).build();
    	
    	private static SSLContext wx_ssl_context = null; //微信支付ssl证书
    	
    	static{
    		Resource resource = new ClassPathResource("spring/apiclient_cert.p12");
    		try {
    			KeyStore keystore = KeyStore.getInstance("PKCS12");
    			char[] keyPassword = "1494252162".toCharArray(); //证书密码
    			keystore.load(resource.getInputStream(), keyPassword);
    			wx_ssl_context = SSLContexts.custom().loadKeyMaterial(keystore, keyPassword).build();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }

    我的路径(注意如果直接放在resources下面就是项目的根路径:ClassPathResource("apiclient_cert.p12")):


    照理来说到这里项目就可以正常运行了,但是我在完成这些的后还遇见了另外一个错误:

    [2018-04-17 19:01:06][ERROR] - caused by: org.xmlpull.v1.XmlPullParserException: resource not found: /META-INF/services/org.xmlpull.v1.XmlPullParserFactory make sure that parser implementing XmlPull API is available
    org.xmlpull.v1.XmlPullParserException: caused by: org.xmlpull.v1.XmlPullParserException: resource not found: /META-INF/services/org.xmlpull.v1.XmlPullParserFactory make sure that parser implementing XmlPull API is available
    	at org.xmlpull.v1.XmlPullParserFactory.newInstance(XmlPullParserFactory.java:294)
    	at org.xmlpull.v1.XmlPullParserFactory.newInstance(XmlPullParserFactory.java:259)
    	at com.ejar.shop.utils.wxpay.XmlUtils.xmlParse(XmlUtils.java:73)
    	at com.ejar.shop.controller.front.TransferController.transferPay(TransferController.java:83)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:498)
    	at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
    	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    	at com.ejar.shop.utils.strideAcross.SimpleCORSFilter.doFilter(SimpleCORSFilter.java:47)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:509)
    	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1104)
    	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
    	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
    	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    	at java.lang.Thread.run(Thread.java:745)
    四月 17, 2018 7:01:06 下午 org.apache.catalina.core.StandardWrapperValve invoke
    严重: Servlet.service() for servlet [shop] in context with path [/shop] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: getWriter() has already been called for this response] with root cause
    java.lang.IllegalStateException: getWriter() has already been called for this response

    做为一个小白刚开始确实很懵逼,网上资料也不多,就试着用deBug跑找问题出现在哪里,又在网上找相关资料,最后发现是少了一个kxml2-2.3.0.jar的包,导进去就OK了。


    最后是相关API的下载链接:

    https://download.csdn.net/download/qq_41187907/10355702

    做为小白第一次写文章,有什么不足之处望各位多多包涵。


    展开全文
  • 本文实例为大家分享了Thinkphp 5.0 微信企业付款到零钱的具体代码,供大家参考,具体内容如下【微信支付】企业付款到零钱:官方文档注意:1,证书路径一定要写绝对路径,且使用函数getcwd()。function transfer($...

    本文实例为大家分享了Thinkphp 5.0 微信企业付款到零钱的具体代码,供大家参考,具体内容如下

    【微信支付】企业付款到零钱:官方文档

    注意:1,证书路径一定要写绝对路径,且使用函数getcwd()。

    a7097e7206b5ed4fb0ddc0c7826c6750.png

    function transfer($data){

    //支付信息

    $wxchat['appid'] = WxPayConfig::$appid;

    $wxchat['mchid'] = WxPayConfig::$mchid;

    $webdata = array(

    'mch_appid' => $wxchat['appid'],//商户账号appid

    'mchid' => $wxchat['mchid'],//商户号

    'nonce_str' => md5(time()),//随机字符串

    'partner_trade_no'=> date('YmdHis'), //商户订单号,需要唯一

    'openid' => $data['openid'],//转账用户的openid

    'check_name'=> 'NO_CHECK', //OPTION_CHECK不强制校验真实姓名, FORCE_CHECK:强制 NO_CHECK:

    'amount' => $data['money']*100, //付款金额单位为分

    'desc' => '微信企业付款到零钱',//企业付款描述信息

    'spbill_create_ip' => request()->ip(),//获取IP

    );

    foreach ($webdata as $k => $v) {

    $tarr[] =$k.'='.$v;

    }

    sort($tarr);

    $sign = implode($tarr, '&');

    $sign .= '&key='.WxPayConfig::$key;

    $webdata['sign']=strtoupper(md5($sign));

    $wget = $this->ArrToXml($webdata);//数组转XML

    $pay_url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';//api地址

    $res = $this->postData($pay_url,$wget);//发送数据

    if(!$res){

    return array('status'=>1, 'msg'=>"Can't connect the server" );

    }

    $content = simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA);

    if(strval($content->return_code) == 'FAIL'){

    return array('status'=>1, 'msg'=>strval($content->return_msg));

    }

    if(strval($content->result_code) == 'FAIL'){

    return array('status'=>1, 'msg'=>strval($content->err_code),':'.strval($content->err_code_des));

    }

    $rdata = array(

    'mch_appid' => strval($content->mch_appid),

    'mchid' => strval($content->mchid),

    'device_info' => strval($content->device_info),

    'nonce_str' => strval($content->nonce_str),

    'result_code' => strval($content->result_code),

    'partner_trade_no' => strval($content->partner_trade_no),

    'payment_no' => strval($content->payment_no),

    'payment_time' => strval($content->payment_time),

    );

    return $rdata;

    }

    //数组转XML

    function ArrToXml($arr)

    {

    if(!is_array($arr) || count($arr) == 0) return '';

    $xml = "";

    foreach ($arr as $key=>$val)

    {

    if (is_numeric($val)){

    $xml.="".$val."".$key.">";

    }else{

    $xml.="".$key.">";

    }

    }

    $xml.="";

    return $xml;

    }

    //发送数据

    function postData($url,$postfields){

    $ch = curl_init();

    $params[CURLOPT_URL] = $url; //请求url地址

    $params[CURLOPT_HEADER] = false; //是否返回响应头信息

    $params[CURLOPT_RETURNTRANSFER] = true; //是否将结果返回

    $params[CURLOPT_FOLLOWLOCATION] = true; //是否重定向

    $params[CURLOPT_POST] = true;

    $params[CURLOPT_POSTFIELDS] = $postfields;

    $params[CURLOPT_SSL_VERIFYPEER] = false;

    $params[CURLOPT_SSL_VERIFYHOST] = false;

    //以下是证书相关代码

    $params[CURLOPT_SSLCERTTYPE] = 'PEM';

    $params[CURLOPT_SSLCERT] = getcwd().'/plugins/payment/weixin/cert/apiclient_cert.pem';//绝对路径

    $params[CURLOPT_SSLKEYTYPE] = 'PEM';

    $params[CURLOPT_SSLKEY] = getcwd().'/plugins/payment/weixin/cert/apiclient_key.pem';//绝对路径

    curl_setopt_array($ch, $params); //传入curl参数

    $content = curl_exec($ch); //执行

    curl_close($ch); //关闭连接

    return $content;

    }

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    展开全文
  • 开发微信企业付款到零钱步骤详解

    千次阅读 2018-08-07 15:09:30
    上篇博文《开发微信企业付款到零钱步骤详解》已经进行对这些功能进行过的描述和一些步骤的描写。这个和开发企业付款到银行卡的开发步骤基本一致,不过这个有开通微信企业付款到零钱有点要求:1、商户号(或同主体...
  • 微信企业付款到零钱功能介绍

    千次阅读 2020-08-18 16:59:40
    微信企业付款到零钱功能介绍 一、企业付款至零钱业务介绍 企业付款业务是为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,通过API或网页操作,付款至目标用户(企业可根据APPID+OpenID锁定目标...
  • 微信有一个API是企业付款,可以从企业账户付款到个人微信的零钱,另外还支持付款到银行卡,其实这个功能可以用于普通用户在商户端提现功能的开发。...课程大纲课时1:微信企业付款到零钱接口分析与实现课时...
  • 微信支付、微信企业付款到零钱工具类 主要依赖:apache httpclient 4.5 工具类主要功能: xml参数拼接 签名算法实现 post加密请求 import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpEntity; import...
  • 微信企业付款到零钱DEMO PHP 单文件本地下载即可执行版本 完美无错
  • 微信企业付款到零钱 先检查微信商户号的资质是T+1还是T+N,两种账户的要求标准不同,T+1需要90天的流水,T +N不需要 签名方面需要用MD5 微信提现金额最小值为一元 请求得失后需要验证证书,证书在商户平台下载,路径使用...
  • JAVA微信企业付款到零钱(十分钟搞定),最近帮朋友做了一个简单的微分销系统,实现从企业付款到零钱分润的功能,简单记录一下微信企业付款到零钱的开发过程,主要就是按规则封装好请求参数调用微信接口,涉及一些签名...
  • 最近帮朋友做了一个简单的微分销系统,实现从企业付款到零钱分润的功能,记录一下微信企业付款到零钱的开发过程; A.前置条件 已开通微信应用(服务号或者小程序),主要用到APPID+OPENID 已开通微信商户,并且开通...
  • java 微信企业转账给个人继承微信sdk 非常Good 不会的可以加我可远程 比网上的那些直接给项目的好很多 新手易懂
  • 最近帮朋友做了一个简单的微分销系统,实现从企业付款到零钱分润的功能,简单记录一下微信企业付款到零钱的开发过程,主要就是按规则封装好请求参数调用微信接口,涉及一些签名校验;A.接口流程1. 获取用户OPENID ,...
  • 企业付款为企业提供付款至用户零钱的能力,支持通过API接口付款,或通过微信支付商户平台(pay.weixin.qq.com)网页操作付款。 使用条件 1、商户号(或同主体其他非服务商商户号)已入驻90日 ...企业付款到零钱资...
  • <?... use think\Controller;...//微信企业付款接口sdk class WxpayTransfer extends Controller { const API_URL = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'; private $_appid; ...
  • 关键参数如图: 证书如图: 证书路径要与代码里的路径对应,放在根目录下,最好用cert或其它命名文件夹存起来(本人实践时发现放在文件夹里有效),如图 基本流程 1、拼凑所需要传递的参数 ...5、发送请求到企业
  • 最近在做微信用户提现功能用到了微信企业付款到零钱,做简单记录 微信开发者文档->企业付款 开发之前需要获得的重要信息 商户号mchid:微信支付分配的商户号 商户账号appid 在有效期内的API证书:微信商户平台...
  • Thinkphp5.0 微信企业付款到零钱

    千次阅读 2018-03-06 16:31:00
    转载请添加原出处【微信支付】企业付款到零钱:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1注意:1,证书路径一定要写绝对路径,且使用函数getcwd()。function transfer($data){ //...

空空如也

空空如也

1 2 3 4 5 ... 18
收藏数 348
精华内容 139
关键字:

微信企业付款到零钱