企业微信号红包调用流程 后端
前期准备条件
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_namemch_billnomch_idnonce_strre_openidtotal_amountwxappid第一步: 对参数按照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(), null, new 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");}
浙公网安备 33010602011771号