微信开发之普通直连分账(境内普通商户)

简介: 单次分账请求按照传入的分账接收方账号和资金进行分账,同时会将订单剩余的待分账金额解冻给本商户。故操作成功后,订单不能再进行分账,也不能进行分账完结。

1、应用场景

直连商户分账主要用于商户将交易成功的资金,按照一定的周期,分账给其他方,可以是合作伙伴、员工、用户或者其他分润方。

单次分账请求按照传入的分账接收方账号和资金进行分账,同时会将订单剩余的待分账金额解冻给本商户。故操作成功后,订单不能再进行分账,也不能进行分账完结。

2、接口说明

image.png

微信开发文档地址:

https://pay.weixin.qq.com/wiki/doc/api/allocation.php?chapter=27_1&index=1

3、实现代码

PayCommonUtil

public class PayCommonUtil {

private static Logger log = LoggerFactory.getLogger(PayCommonUtil.class);

public static String hashHmac(SortedMap<Object,Object> parameters,String apiKey){
    StringBuffer sb = new StringBuffer();
    Set es = parameters.entrySet();
    Iterator it = es.iterator();
    while(it.hasNext()) {
      Map.Entry entry = (Map.Entry)it.next();
      String k = (String)entry.getKey();
      Object v = entry.getValue();
      if(null != v && !"".equals(v)
          && !"sign".equals(k) && !"key".equals(k)) {
        sb.append(k + "=" + v + "&");
      }
    }
    sb.append("key=" + apiKey);
    String sign = sha256_HMAC(sb.toString(),apiKey).toUpperCase();
    log.info("createSign方法sign签名=====:"+sign);
    return sign;
  }
  
  /**
     * sha256_HMAC加密
     * @param message 消息
     * @param secret  秘钥
     * @return 加密后字符串
     */
    public static String sha256_HMAC(String message, String secret) {
        String hash = "";
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] bytes = sha256_HMAC.doFinal(message.getBytes());
            hash = byteArrayToHexString(bytes);
        } catch (Exception e) {
            System.out.println("Error HmacSHA256 ===========" + e.getMessage());
        }
        return hash;
    }
    
   /**
   * 
   * @Title: getRequestXml
   * @Description:将请求参数转换为xml格式的string
   * @param parameters 请求参数
   * @return String 返回类型
   * @throws
   */
  public static String getRequestXml(SortedMap<Object,Object> parameters){
    StringBuffer sb = new StringBuffer();
    sb.append("<xml>");
    Set es = parameters.entrySet();
    Iterator it = es.iterator();
    while(it.hasNext()) {
      Map.Entry entry = (Map.Entry)it.next();
      String k = (String)entry.getKey();
      String v = (String)entry.getValue();
      if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) {
        sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
      }else {
        sb.append("<"+k+">"+v+"</"+k+">");
      }
    }
    sb.append("</xml>");
    return sb.toString();
  }
}

SubAccount

public static Logger logger = LoggerFactory.getLogger(SubAccount.class);
/**
     * 请求单次分账
     * https://pay.weixin.qq.com/wiki/doc/api/allocation.php?chapter=27_1&index=1
     * @return
     */
    public static SortedMap<Object, Object> profitSharing() throws Exception {
        SortedMap<Object, Object> params = new TreeMap<>();
        //微信支付分配的商户号
        String mchId = "商户号";
        try {
            // 我们发送给微信服务器的参数是xml格式的string,微信返回来的信息也是xml格式的string
            // 获取package包
            SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
            //微信分配的公众账号ID
            parameters.put("appid", "appid");
            //微信支付分配的商户号
            parameters.put("mch_id", "商户号");
            //随机字符串,不长于32位
            parameters.put("nonce_str", "随机字符串");
            //微信支付订单号
            parameters.put("transaction_id", "4200000418201910287201948196");//     4200000418201910296095353357
            //商户系统内部的分账单号,在商户系统内部唯一(单次分账、多次分账、完结分账应使用不同的商户分账单号),同一分账单号多次请求等同一次。只能是数字、大小写字母_-|*@ 
            parameters.put("out_order_no", System.currentTimeMillis() + "");
            //分账接收方列表,不超过50个json对象,不能设置分账方作为分账接受方
            List<Map<String, Object>> receivers = new ArrayList<>();
            
            Map<String, Object> receiver1 = new HashMap<>();
            //MERCHANT_ID:商户ID,PERSONAL_WECHATID:个人微信,号PERSONAL_OPENID:个人openid
            receiver1.put("type", "MERCHANT_ID");
            //类型是MERCHANT_ID时,是商户ID,类型是PERSONAL_WECHATID时,是个人微信号,类型是PERSONAL_OPENID时,是个人openid
            receiver1.put("account", "商户号");
            //分账金额,单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额
            receiver1.put("amount", 10);
            //分账的原因描述,分账账单中需要体现
            receiver1.put("description", "分账给商户");
            receivers.add(receiver1);
            
            Map<String, Object> receiver2 = new HashMap<>();
            receiver2.put("type", "PERSONAL_WECHATID");
            receiver2.put("account", "微信号");
            receiver2.put("amount", 10);
            receiver2.put("description", "分账给个人");
            receivers.add(receiver2);

            Map<String, Object> receiver3 = new HashMap<>();
            receiver3.put("type", "PERSONAL_WECHATID");
            receiver3.put("account", "微信号");
            receiver3.put("amount", 1);
            receiver3.put("description", "分账给个人");
            receivers.add(receiver3);

            String receiversJson = JSONObject.toJSONString(receivers);

            parameters.put("receivers", receiversJson);
            System.out.println(receiversJson);
            parameters.put("sign_type", "HMAC-SHA256");
            String sign = PayCommonUtil.hashHmac(parameters, "支付签名密钥(api_key)");// 进行签名
            parameters.put("sign", sign);
            // 将请求的参数转为字符串
            String requestXML = PayCommonUtil.getRequestXml(parameters);
            logger.info("post请求微信支付参数============:" + requestXML);

            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            //安全证书P12文件目录
            FileInputStream instream = new FileInputStream(new File("/Users/mac/Desktop/mchid.p12"));
            try {
                keyStore.load(instream, mchId.toCharArray());
            } finally {
                instream.close();
            }
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build();
            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(WxUrl.SHARING);
                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(requestXML, "UTF-8"));
                CloseableHttpResponse response = httpclient.execute(httpost);
                try {
                    HttpEntity entity = response.getEntity();
                    String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                    EntityUtils.consume(entity);
                    Map<String, String> result = XMLUtil.doXMLParse(jsonStr);
                    net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(result);
                    logger.info("请求单次分账返回结果==={}", jsonObject);
                } finally {
                    response.close();
                }
            } finally {
                httpclient.close();
            }
            return params;
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //============结束==================
        return params;
    }
}

山水有相逢,来日皆可期,谢谢阅读,我们再会

我手中的金箍棒,上能通天,下能探海

上一篇:微信公众号关注或取关后再处理我们自己的业务逻辑

相关文章
|
4月前
|
API
支付系统----微信支付24--APlv3介绍,首先我们要引入支付参数,包含商户号,APPID、API秘钥,数字证书,用代码加载到应用程序当中,之后加载商户私钥,商户需要用私钥进行验签,微信平台接收商
支付系统----微信支付24--APlv3介绍,首先我们要引入支付参数,包含商户号,APPID、API秘钥,数字证书,用代码加载到应用程序当中,之后加载商户私钥,商户需要用私钥进行验签,微信平台接收商
|
移动开发 Android开发
实战:第七章:微信H5支付时用户有微信分身停留5秒后未选择哪个微信分身,也未支付就被动回调到商户支付是否完成的页面...
实战:第七章:微信H5支付时用户有微信分身停留5秒后未选择哪个微信分身,也未支付就被动回调到商户支付是否完成的页面...
147 0
|
消息中间件 缓存 算法
Springboot----项目整合微信支付(引入延迟队列实现订单过期取消以及商户主动查单)
介绍了如何使用RabbitMQ实现订单过期自动取消以及如何采用RabbitMQ实现商户主动向微信支付后台查询订单状态,一石二鸟。
521 0
Springboot----项目整合微信支付(引入延迟队列实现订单过期取消以及商户主动查单)
|
数据可视化
微信支付服务商,可视化进件特约商户
微信支付面向服务商开放“特约商户进件接口”,协助个体工商户、企业等各类型商户发起接入申请,提高商户进件效率,节省人力成本。
447 0
微信支付服务商,可视化进件特约商户
微信支付服务商下特约商户申请流程详解
微信支付服务商下特约商户申请流程详解
2856 0
|
索引
微信公众平台上线小程序二维码,便于商户线下推广
  12月30日,微信公众平台上线小程序二维码,便于商户线下推广。开发者首先可在“设置”中查看小程序的正式二维码,该二维码只用于访问小程序的线上正式版本。然后,通过接口获得带参数二维码,最多可生成带参数二维码10000个。
1082 0
微信说中国人的国庆长假 境内游西湖外滩上榜
  国庆长假过完了,2016年所有的法定节日也就清零了。大伙都去哪玩了?有的朋友说“第一天睡觉,第二天休息,第三天睡觉,第四天休息,第五天睡觉,第六天睡觉,第七天睡觉”,原来休息和睡觉是可以分开的~~   很多朋友说在朋友圈环球旅行。
1051 0
微信支付携手18家商户首创“早7晚5”优惠新玩法
  这个八月,微信支付携手18家商户首创“早7晚5”优惠新玩法,8月15日至8月21日期间,只要通过微信支付刷卡消费任意金额可享受随机立减优惠,最高立减100元!  在早上7:00-10:00时间段到去美宜佳,华南7-Eleven,华东罗森,好德,可的,华南喜市多,华东喜士多,联华快客,十足,太原唐...
967 0
|
新零售 API
微信卡券功能商户后台卡券货架、最新页面导航等五项优化
  微信卡券最近又更新了,汲取苹果产品的精髓,势必将简单化进行到底。微信卡券商户后台近日发布卡券货架、最新页面导航等五项新优化。具体调整如下:   一、 类目及资质调整:   1. 取消【其它】类目   申请时,若无对应类目可选,即你所属的行业暂未开放,请留意平台后续通知。
1343 0
|
新零售 UED
卡券核销助手微信公众服务号全面升级 并更名为“卡券商户助手”
  微信公众平台最近可谓动作频频,自动回复支持插入微信卡券 多图文消息可嵌入卡券,微信公众号支付测试功能策略调整 加快商户申请速度,新增"微信连Wi-Fi"功能,势为不太理想的双十一战绩扭转局势,微信卡券是微信支付(微信电商)重要一环,不断升级更新中,作为公众平台官方为卡券商户提供的服务号“卡券核销助手”昨天发布升级公告,更好地帮助商户在手机端进行卡券核销。
2349 0