接上一章,完成服务商模式下的微信支付之后,进行服务商分账。微信单次分账文档地址
首先在进行单次分账之前,需要设置一个分账比例,步骤如下:
登录特约商户号–产品中心–我授权的产品–服务商分账–产品配置
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190822105110224.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTQxNjEwMQ==,size_16,color_FFFFFF,t_70
这里分账比例需要解释一下:
一般情况下,只能采用低比例分账,最大设置30%,顾客付款100元,其中最多30元进行分账,剩余70元分账之后解冻资金后进入子商户中(特约商户);如需使用高比例分账,只能想办法联系到微信支付运营人员(BD)开通。
单次分账成功后,剩余资金自动解冻,不能继续进行分账操作,如需多次分账请调用多次分账接口。
接下来就是需要拿到服务商商户号的证书和api密钥,登录到服务商商户号–账户中心–API安全–申请证书和设置密钥
接下来就是上代码时间了
老规矩,先在小程序中写个按钮
然后js代码如下:
profitSharing:function(){//进行分账
var that = this;
this.req('/interfaceController/profitSharing', {
openId: this.data.openid
}, function (res) {
});
},
然后是后台代码:
/**请求单次分账接口*/
public static final String profitSharingUrl="https://api.mch.weixin.qq.com/secapi/pay/profitsharing";
/**
* 请求单次分账
* @return
*/
@RequestMapping("/profitSharing")
public R profitSharing(HttpServletRequest request,String openId){
try {
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject();
jsonObject.put("type", "PERSONAL_WECHATID");
jsonObject.put("account", "");//个人的微信号,需要事先添加分账接收人
jsonObject.put("amount", 29);//分账金额单位是分,注意不要超过最大分账比例
jsonObject.put("description", "分给个人");
jsonArray.put(jsonObject);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
// 调用请求单次分账接口必需传的参数
nvps.add(new NameValuePair("appid",""));//服务商对应公众号appid
nvps.add(new NameValuePair("mch_id",""));//服务商商户号
nvps.add(new NameValuePair("nonce_str","ibuaiVcKdpRxkhJA"));
nvps.add(new NameValuePair("out_order_no",CommonUtil.getUID()));//商户分账单号
nvps.add(new NameValuePair("receivers",jsonArray.toString()));
nvps.add(new NameValuePair("sub_mch_id",""));//特约商户号
nvps.add(new NameValuePair("transaction_id",""));//微信支付订单号(注意是微信的不是商户的)
StringBuffer sb = new StringBuffer();
for (NameValuePair nvp : nvps) {
sb.append(nvp.getName() + "=" + nvp.getValue() + "&");
}
String signA = sb.toString(); // 根据签名格式组装数据,详见微信支付api
String stringSignTemp = signA + "key=asjdkkashdkjashkd"; // 根据签名格式组装数据,key是服务商商户号中的api密钥
String sign = HMACSHA256(stringSignTemp, "asjdkkashdkjashkd");//第二个参数是服务商商户号中的api密钥
nvps.add(new NameValuePair("sign", sign)); // 把签名后的数据组装成参数
String xml = toXml(nvps);
String result = HttpClientUtils.executeBySslPost(profitSharingUrl,xml,"","");//发送http请求 参数一:请求地址 参数二:请求参数 参数三:证书地址 参数四:服务商商户号
String return_code = "";
String return_msg = "";
String result_code = "";
String err_code = "OK";
JSONObject xmlJSONObj = XML.toJSONObject(result);
JSONArray childNodes = JSONML.toJSONObject(result.toString()).getJSONArray("childNodes");
int len = childNodes.length() - 1;
for (int i = len; i > -1; i--) {
JSONObject js = childNodes.getJSONObject(i);
if(!"".equals(return_code) && !"".equals(return_msg)){
break;
}
if (js.get("tagName").equals("return_code")) {
return_code = js.getJSONArray("childNodes").getString(0);
}
if (js.get("tagName").equals("result_code")) {
result_code = js.getJSONArray("childNodes").getString(0);
}
if (js.get("tagName").equals("return_msg")) {
return_msg = js.getJSONArray("childNodes").getString(0);
}
if (js.get("tagName").equals("err_code")) {
err_code = js.getJSONArray("childNodes").getString(0);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return R.ok();
}
httpclient代码:
public class HttpClientUtils {
public static String executeBySslPost(String url, String body,String certificatePath,String password) throws Exception {
String result = "";
//商户id
//指定读取证书格式为PKCS12
KeyStore keyStore = KeyStore.getInstance("PKCS12");
//读取本机存放的PKCS12证书文件
FileInputStream instream = new FileInputStream(new File(certificatePath));
try {
//指定PKCS12的密码(商户ID)
keyStore.load(instream, password.toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, password.toCharArray()).build();
//指定TLS版本
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
//设置httpclient的SSLSocketFactory
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
try {
HttpPost httppost = new HttpPost(url);
StringEntity reqEntity = new StringEntity(body, "UTF-8");
httppost.setEntity(reqEntity);
System.out.println("Executing request: " + httppost.getRequestLine());
CloseableHttpResponse response = null;
try {
response = httpclient.execute(httppost);
result = EntityUtils.toString(response.getEntity(),"UTF-8");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
}
其他用到的工具类代码
// 转换成xml格式
private String toXml(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
sb.append("<xml>");
for (int i = 0; i < params.size(); i++) {
sb.append("<" + params.get(i).getName() + ">");
sb.append((params.get(i)).getValue());
sb.append("</" + params.get(i).getName() + ">");
}
sb.append("</xml>");
//System.out.println("xml数据=" + sb.toString());
return sb.toString();
}
/**
* 生成 HMACSHA256
* @param data 待处理数据
* @param key 密钥
* @return 加密结果
* @throws Exception
*/
public static String HMACSHA256(String data, String key) throws Exception {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secret_key);
byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}
以上就是全部内容,大家如果有不懂的地方评论。