企业微信号红包调用流程 后端

前期准备条件

1.企业号 https://work.weixin.qq.com/

2.已开通支付功能的微信商户号 https://pay.weixin.qq.com/

 

 

一、获取支付证书apiclient_cert.p12下载

微信商户平台(pay.weixin.qq.com)-->账户中心-->账户设置-->API安全

(放置到web访问无法下载的地方,防止证书下载泄露)

 

二、企业台开通微信支付

企业管理后台-->应用管理-->企业支付-->绑定商户平台商户号

 

三、发放企业红包

官方文档地址:https://work.weixin.qq.com/api/doc/90000/90135/90274

发送红包接口

请求方式:POST(HTTPS)
请求地址:https://api.mch.weixin.qq.com/mmpaymkttransfers/sendworkwxredpack
是否需要证书:是
数据格式:xml
部分容易混淆参数说明:
商户号  微信商户平台-->账户中心-->商户信息-->商户号
公众账号appid   企业微信后台-->我的企业-->企业信息-->企业ID
用户openid   使用企业用户的userId转为openId  官方文档:http://work.weixin.qq.com/api/doc#11279
 
微信支付签名算法
第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特别注意以下重要规则:
参数名ASCII码从小到大排序(字典序);如果参数的值为空不参与签名;参数名区分大小写;验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。微信接口可能增加字段,验证签名时必须支持增加的扩展字段
第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
附:key为商户平台API密钥里面设置的key,key设置之后不能查看,建议设置后另外保存一份,以免遗忘。另外,再建议将key顺便保存到 商户平台->产品中心->企业微信收款->API密钥管理 里面,这样后续企业微信收款才能正常使用。
签名字段:
除sign字段外所有字段都参与签名(包括企业微信签名字段workwx_sign一起参与签名).
 
 
企业微信签名算法
第一步: 设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
注意:
参数名ASCII码从小到大排序(字典序)如果参数的值为空不参与签名参数名区分大小写传送的sign参数不参与签名,将生成的签名与该sign值作校验
第二步: 在stringA最后拼接上企业微信支付应用secret(参见企业微信管理端支付应用页面的secret),得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
企业微信签名字段说明:
发红包api固定如下几个字段参与签名:
act_name
mch_billno
mch_id
nonce_str
re_openid
total_amount
wxappid
第一步: 对参数按照key=value的格式,并按照参数名ASCII字典序排序如下
stringA=”act_name=XXX&mch_billno=11111234567890&mch_id=10000098&nonce_str=qFKEgfig76DF9912fewmkp&re_openid=oxTWIuGaIt6gTKsQRLau2M0yL16E&total_amount=100&wxappid=wx12345678
第二步:拼接企业微信支付应用secret(参见企业微信管理端支付应用页面)
stringSignTemp=”stringA&secret=192006250b4c09247ec02edce69f6a2d”
sign=MD5(stringSignTemp).toUpperCase()
 
/** * 发送红包请求 
* @param openId 用户openid
* @param mchBillNo 订单号 
* @param totalAmount 发送金额(单位:分) 
* @param wishing 祝福语 
* @param actName 项目名称(在微信端不显示)
* @param senderName 发送人姓名
* @return
*/
public Boolean sendWorkWxRedPack(String openId,String mchBillNo,int totalAmount,String wishing,String actName,String senderName) throws Exception 
    Map<String,String> paramMap = new TreeMap<>();    
    paramMap.put("act_name",actName);//项目名称    
    paramMap.put("mch_billno",mchBillNo);    
    paramMap.put("mch_id",mchId);    
    paramMap.put("nonce_str",WXPayUtil.generateNonceStr());    
    paramMap.put("re_openid",openId);//openId    
    paramMap.put("total_amount",String.valueOf(totalAmount));//金额,单位分    
    paramMap.put("wxappid",corpId);    
    String workWxSign = gerCompanySign(paramMap);//生成企业签名   
    paramMap.put("workwx_sign",workWxSign);    
    paramMap.put("wishing",wishing);//红包祝福语    
    paramMap.put("remark","星宏");    
    paramMap.put("sender_name",senderName);    
    paramMap.put("sender_header_media_id","1G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K0");   
    paramMap.put("scene_id","PRODUCT_4");    
    String paySign = gerPaySign(paramMap);//生成微信支付签名   
    paramMap.put("sign",paySign);    
    String xmlBody = WXPayUtil.mapToXml(paramMap);    
    String request = requestOnce(CP_SEND_WORK_WX_REDPACK,xmlBody,8*1000,8*1000,true);   
    Map<String,String> retMap = WXPayUtil.xmlToMap(request);    
    if(retMap.containsKey("result_code")&&"SUCCESS".equals(retMap.get("result_code")))
      log.debug("微信发送参数"+xmlBody);        
      log.debug("##############发送红包成功:"+request);       
      return true;    
    }else{
      log.error("微信发送参数"+xmlBody);       
      log.error("###############发送红包失败,返回原因:"+request);   
      return false;   
    }
}
 
/** 
   * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
   * @param data 待签名数据 
   * @param key API密钥
   * @return 签名
 */
private static String generateSignature(final Map<String, String> data, String key,String type) throws Exception {
    Set<String> keySet = data.keySet();    
    String[] keyArray = keySet.toArray(new String[keySet.size()]);    
    Arrays.sort(keyArray);    
    StringBuffer sb = new StringBuffer();    
    for (String k : keyArray) {
        if (k.equals(WXPayConstants.FIELD_SIGN)) {
            continue;        
        }
    // 参数值为空,则不参与签名
    if (data.get(k).trim().length() > 0)  
       sb.append(k).append("=").append(data.get(k).trim()).append("&");    
    }
    if("companyPaySecret".equals(type)){
        sb.append("secret=").append(key);        
        log.debug("企业拼接结果"+sb.toString());    
    }
    if("paySecret".equals(type)){
        sb.append("key=").append(key);        
        log.debug("微信支付拼接结果"+sb.toString());   
    }
    String sign = SecureUtil.md5(sb.toString()).toUpperCase();
    log.debug("生成:"+sign);    
    return sign;
}

   
/**
* 发送https请求
* @param url 请求地址
* @param data 请求体
* @param connectTimeoutMs 连接超时时间
* @param readTimeoutMs 读取超时时间
* @param useCert 是否使用证书,针对退款、撤销等操作
*/
private String requestOnce(String url, String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert) throws Exception {
    try( InputStream certStream = this.getClass().getClassLoader().getResourceAsStream("apiclient_cert.p12")){
        BasicHttpClientConnectionManager connManager;        
        if (useCert) {
            // 证书            
            char[] password = mchId.toCharArray();            
            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(), nullnew SecureRandom());           
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,new String[]{"TLSv1"},null,new 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);
                            }
 
        HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connManager).build();
        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();
        httpPost.setConfig(requestConfig);
        StringEntity postEntity = new StringEntity(data, "UTF-8")
        httpPost.setEntity(postEntity);
        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        return EntityUtils.toString(httpEntity, "UTF-8");
}

posted on 2019-12-18 16:53  贾广祥  阅读(952)  评论(0)    收藏  举报

导航