微信转账到零钱2种实现方式,SDK和API对接 |
您所在的位置:网站首页 › 微信批量转账的正确方法 › 微信转账到零钱2种实现方式,SDK和API对接 |
微信官方文档地址 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_1.shtml#doc-main 第一种:SDK方式首先引入微信官方的sdk包 com.github.wechatpay-apiv3 wechatpay-java 0.2.11核心代码 import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import com.deliyun.transfer.util.UUIDUtil; import com.deliyun.transfer.util.WechatPayConstant; import com.wechat.pay.java.core.Config; import com.wechat.pay.java.core.RSAAutoCertificateConfig; import com.wechat.pay.java.service.transferbatch.TransferBatchService; import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferRequest; import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse; import com.wechat.pay.java.service.transferbatch.model.TransferDetailInput; import java.util.ArrayList; import java.util.List; public class BatchTransfer { /** * 商户号 */ public static String merchantId = "1********"; /** * 商户API私钥路径 */ public static String privateKeyPath = "F:apiclient_key.pem"; /** * 商户证书序列号 */ public static String merchantSerialNumber = "3860*********************E7447"; /** * 商户APIV3密钥 */ public static String apiV3Key = "V**********************************V"; public static TransferBatchService service; public static void main(String[] args) { Config config = new RSAAutoCertificateConfig.Builder() .merchantId(merchantId) .privateKeyFromPath(privateKeyPath) .merchantSerialNumber(merchantSerialNumber) .apiV3Key(apiV3Key) .build(); service = new TransferBatchService.Builder().config(config).build(); String out_batch_no = RandomUtil.randomNumbers(10); out_batch_no = StrUtil.concat(true, "sc", out_batch_no); InitiateBatchTransferRequest initiateBatchTransferRequest = new InitiateBatchTransferRequest(); initiateBatchTransferRequest.setAppid(WechatPayConstant.APP_ID); initiateBatchTransferRequest.setOutBatchNo(out_batch_no); initiateBatchTransferRequest.setBatchName("2019年1月深圳分部报销单"); initiateBatchTransferRequest.setBatchRemark("2019年1月深圳分部报销单"); initiateBatchTransferRequest.setTotalAmount(100l); initiateBatchTransferRequest.setTotalNum(1); List transferDetailListList = new ArrayList(); TransferDetailInput transferDetailInput = new TransferDetailInput(); transferDetailInput.setOutDetailNo(UUIDUtil.getUUID()); transferDetailInput.setTransferAmount(100l); transferDetailInput.setTransferRemark("2020年4月报销"); transferDetailInput.setOpenid("o_***************************"); // transferDetailInput.setUserName( // "757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45"); transferDetailListList.add(transferDetailInput); initiateBatchTransferRequest.setTransferDetailList( transferDetailListList); initiateBatchTransferRequest.setTransferSceneId("1000"); InitiateBatchTransferResponse response = service.initiateBatchTransfer(initiateBatchTransferRequest); System.out.println(response); } } 第二种:API方式协议对象 public class Transfer { private String appid; // 直连商户的appid private String out_batch_no; // 商家批次单号 private String batch_name = "分润红包"; // 该笔批量转账的名称: private String batch_remark = "分润红包"; // 转账说明,UTF8编码,最多允许32个字符 private int total_amount; // 转账总金额:分 private int total_num = 1; // 转账总笔数 private List transfer_detail_list; // 发起批量转账的明细列表,最多三千笔 public Transfer(String appid, String out_batch_no, int total_amount, List transfer_detail_list) { this.appid = appid; this.out_batch_no = out_batch_no; this.total_amount = total_amount; this.transfer_detail_list = transfer_detail_list; } public String getAppid() { return appid; } public void setAppid(String appid) { this.appid = appid; } public String getOut_batch_no() { return out_batch_no; } public void setOut_batch_no(String out_batch_no) { this.out_batch_no = out_batch_no; } public String getBatch_name() { return batch_name; } public void setBatch_name(String batch_name) { this.batch_name = batch_name; } public String getBatch_remark() { return batch_remark; } public void setBatch_remark(String batch_remark) { this.batch_remark = batch_remark; } public int getTotal_amount() { return total_amount; } public void setTotal_amount(int total_amount) { this.total_amount = total_amount; } public int getTotal_num() { return total_num; } public void setTotal_num(int total_num) { this.total_num = total_num; } public List getTransfer_detail_list() { return transfer_detail_list; } public void setTransfer_detail_list(List transfer_detail_list) { this.transfer_detail_list = transfer_detail_list; } public static class TransferDetailList { private String out_detail_no = UUIDUtil.getUUID(); // 商户系统内部区分转账批次单下不同转账明细单的唯一标识,要求此参数只能由数字、大小写字母组成 private int transfer_amount; // 转账金额单位为分 private String transfer_remark = "分润红包"; //转账备注 private String openid; // 用户在直连商户应用下的用户标示 public TransferDetailList( int transfer_amount, String openid) { this.transfer_amount = transfer_amount; this.openid = openid; } public String getOut_detail_no() { return out_detail_no; } public void setOut_detail_no(String out_detail_no) { this.out_detail_no = out_detail_no; } public int getTransfer_amount() { return transfer_amount; } public void setTransfer_amount(int transfer_amount) { this.transfer_amount = transfer_amount; } public String getTransfer_remark() { return transfer_remark; } public void setTransfer_remark(String transfer_remark) { this.transfer_remark = transfer_remark; } public String getOpenid() { return openid; } public void setOpenid(String openid) { this.openid = openid; } } }工具类 CertUtil.java public class CertUtil { public static String APICLIENT_KEY = "conf/cert/apiclient_key.pem"; public static String APICLIENT_CERT = "conf/cert/apiclient_cert.pem"; /** * 获取私钥。 * * @return 私钥对象 */ public static PrivateKey getPrivateKey() throws IOException { InputStream instream = CertUtil.class.getClassLoader().getResourceAsStream(APICLIENT_KEY); String content = new String(ByteStreams.toByteArray(instream), StandardCharsets.UTF_8); // String content = new String(Files.readAllBytes(Paths.get(APICLIENT_KEY)), StandardCharsets.UTF_8); try { String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", ""); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey))); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("当前Java环境不支持RSA", e); } catch (InvalidKeySpecException e) { throw new RuntimeException("无效的密钥格式"); } } /** * 获取商户证书。 * * @return X509证书 */ public static X509Certificate getCertificate() throws IOException { // InputStream fis = new FileInputStream(APICLIENT_CERT); InputStream fis = CertUtil.class.getClassLoader().getResourceAsStream(APICLIENT_CERT); ; try (BufferedInputStream bis = new BufferedInputStream(fis)) { CertificateFactory cf = CertificateFactory.getInstance("X509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(bis); cert.checkValidity(); return cert; } catch (CertificateExpiredException e) { throw new RuntimeException("证书已过期", e); } catch (CertificateNotYetValidException e) { throw new RuntimeException("证书尚未生效", e); } catch (CertificateException e) { throw new RuntimeException("无效的证书文件", e); } } /** * 获取商户证书序列号 * * @return * @throws IOException */ public static String getSerialNo() throws IOException { X509Certificate certificate = getCertificate(); return certificate.getSerialNumber().toString(16).toUpperCase(); } public static void main(String[] args) { try { System.out.println(CertUtil.getCertificate()); } catch (Exception e) { e.printStackTrace(); } } }HttpUrl工具类 public class HttpUrlUtil { public static String SCHEMA = "WECHATPAY2-SHA256-RSA2048"; public static String merchantId = WechatPayConstant.MCH_ID; // 服务商 public static String POST = "POST"; public static String GET = "GET"; public static String TRANSFER_URL = "https://api.mch.weixin.qq.com/v3/transfer/batches"; // 转账 public static String postTransfer(String body) { String authorization = getToken(POST, TRANSFER_URL, body); String returnMsg = HttpRequest.post(TRANSFER_URL) .header("Authorization", authorization) .header("Wechatpay-Serial", WechatPayConstant.merchantSerialNumber) .body(body) .execute().body(); JSONObject returnTransferInfo = JSON.parseObject(returnMsg); return returnTransferInfo.toJSONString(); } /** * 获取加密串 * * @param method * @param url * @param body * @return */ public static String getToken(String method, String url, String body) { String nonceStr = UUIDUtil.getUUID(); long timestamp = System.currentTimeMillis() / 1000; HttpUrl httpUrl = HttpUrl.parse(url); String message = buildMessage(method, httpUrl, timestamp, nonceStr, body); String signature = null; String certificateSerialNo = null; try { signature = sign(message.getBytes("utf-8")); certificateSerialNo = CertUtil.getSerialNo(); } catch (Exception e) { e.printStackTrace(); } return SCHEMA + " mchid=\"" + merchantId + "\"," + "nonce_str=\"" + nonceStr + "\"," + "timestamp=\"" + timestamp + "\"," + "serial_no=\"" + certificateSerialNo + "\"," + "signature=\"" + signature + "\""; } /** * 得到签名字符串 */ public static String sign(byte[] message) throws Exception { Signature sign = Signature.getInstance("SHA256withRSA"); PrivateKey privateKey = CertUtil.getPrivateKey(); sign.initSign(privateKey); sign.update(message); return Base64.getEncoder().encodeToString(sign.sign()); } public static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) { String canonicalUrl = url.encodedPath(); if (url.encodedQuery() != null) { canonicalUrl += "?" + url.encodedQuery(); } return method + "\n" + canonicalUrl + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n"; }UUID工具类 public class UUIDUtil { public static String getUUID () { return UUID.randomUUID().toString().replace("-", ""); } public static void main(String[] args) { System.out.println(UUIDUtil.getUUID()); } }常量类 WechatPayConstant.java public class WechatPayConstant { /** * appId */ public static String APP_ID = "wx64************"; /** * 商户号 */ public static String MCH_ID = "1***********"; /** * API_V3密钥 */ public static String API_V3KEY = "V*****************************"; /** * 证书序列号 */ public static String merchantSerialNumber = "************************************"; }转账业务类 public class TransferService { public static void exe(String openId) { String out_batch_no = RandomUtil.randomNumbers(10); out_batch_no = StrUtil.concat(true, "sc", out_batch_no); int transfer_amount = 100; Transfer.TransferDetailList transferDetailList = new Transfer.TransferDetailList(transfer_amount, openId); List list = new ArrayList(); list.add(transferDetailList); Transfer transfer = new Transfer(WechatPayConstant.APP_ID, out_batch_no, transfer_amount, list); String str = HttpUrlUtil.postTransfer(JSONObject.toJSONString(transfer)); System.out.println("转账结果返回:" + str); } public static void main(String[] args) { String openId = "o_F*******************************"; TransferService.exe(openId); } }执行结果: {"create_time":"2023-11-22T18:56:39+08:00","batch_id":"131000110008101808*********************3342","batch_status":"ACCEPTED","out_batch_no":"592147839212385514533287"} |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |