主要记录微信企业付款开发的过程

开发前准备:1.申请微信appid,2.微信secret,3.微信mchid商户名,4.微信key,5.下载证书,

6.商户平台设置扫码回调接口,即项目的外网可访问地址

微信企业付款官方文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2

商户签名以及证书相关官方文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=4_3

一、业务单生成,推送消息至虚拟充值服务,采用队列,这一步可以省略,只是项目中需要

/*** 消费业务单传递过来的消息* 充值类,快充订单,回传状态至虚拟商品,然后生成转账二维码** @param message* @author scott*/@RabbitListener(queues = VirtualProductQueueConstants.VIRTUAL_RECHARGE_ORDER_QUEUE, containerFactory = "rabbitListenerContainerFactory")@RabbitHandlerpublic void getWeChatQrCodeMessage(MessageDto<WeChatQrCodeMessage> message) {logger.info("RechargeOrderReceiver==>getWeChatQrCodeMessage(), message:{}", JSON.toJSONString(message));try {orderRechargeService.addOrderRecharge(message.getMessage().getOrderRecharge());createOrderRecharge(message.getMessage());} catch (Exception e) {logger.error("RechargeOrderReceiver==>getWeChatQrCodeMessage,消费失败", e);}}

二、请求生成对应的二维码

/*** 调用微信接口生成二维码,并添加二维码记录** @param weChatQrCodeMessage* @author scott*/private void createOrderRecharge(WeChatQrCodeMessage weChatQrCodeMessage) {OrderRecharge orderRecharge = weChatQrCodeMessage.getOrderRecharge();RechargeOrderQrCode qrCode = new RechargeOrderQrCode();qrCode.setOrderNo(orderRecharge.getOrderNo());qrCode.setItemNo(orderRecharge.getItemNo());qrCode.setBuyerId(orderRecharge.getBuyerId());qrCode.setOrderTime(orderRecharge.getOrderTime());int count = rechargeOrderQrCodeService.addRechargeOrderQrCode(qrCode);if (count == 0) {//当二维码失败且重试次数小于3次时,进行重试,这里用另外一个队列做重试队列并规定重试次数int retryCount = weChatQrCodeMessage.getRetryCount() != null ? weChatQrCodeMessage.getRetryCount() : 0;if (retryCount < Constants.WECHAT_RETRY_COUNT) {//重试次数+1weChatQrCodeMessage.setRetryCount(weChatQrCodeMessage.getRetryCount() + 1);mqDao.pushRetryCreateWeChatQrCode(weChatQrCodeMessage);}}}

获取微信token官方文档: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183

生成二维码官方文档链接:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443433542

/*** 添加充值类订单二维码生成** @param orderQrCode* @return* @author scott*/@Overridepublic int addRechargeOrderQrCode(RechargeOrderQrCode orderQrCode) {int count = 0;try {//将token写到缓存中,每次请求的token最长时间为7200秒,缓存的最长时间比过期时间稍短即可String accessToken = valueOperations.get(Constants.WECHAT_ACCESS_TOKEN_REDIS_KEY);if (StringUtils.isBlank(accessToken)) {String accessTokenResultMsg = rfRechargeOrderService.getWeChatAccessToken();if (StringUtils.isNotBlank(accessTokenResultMsg)) {String errorCode = JsonUtil.getNodeValueRemoveQuotes(accessTokenResultMsg, "errcode");if (StringUtils.isNotBlank(errorCode) && !"0".equals(errorCode)) {logger.error("OrderRechargeServiceImpl==>addOrderRechargeAndCreateQrCode,获取access_token出错, resultMsg:{}", accessTokenResultMsg);Monitor.add("获取微信token失败", 1);return count;}accessToken = JsonUtil.getNodeValueRemoveQuotes(accessTokenResultMsg, "access_token");String expiresIn = JsonUtil.getNodeValueRemoveQuotes(accessTokenResultMsg, "expires_in");logger.info("OrderRechargeServiceImpl==>addOrderRechargeAndCreateQrCode, accessToken:{}, expiresIn:{}", accessToken, expiresIn);valueOperations.set(Constants.WECHAT_ACCESS_TOKEN_REDIS_KEY, accessToken, Integer.parseInt(expiresIn) - 10, TimeUnit.SECONDS);} else {Monitor.add("获取微信token失败", 1);logger.error("OrderRechargeServiceImpl==>addOrderRechargeAndCreateQrCode, 未成功请求到access_token");}}//加密组合与方式暂时隐藏,此处只是用作一个扫码转账的密钥校验String orderSecret = "xxxxx";Map<String, Object> scene = new HashMap<>(4);scene.put("scene_str", Constants.WECHAT_SCENE_ID + "_" + orderQrCode.getBuyerId() + "_" + orderQrCode.getOrderNo() + "_" + orderSecret);//生成带参数的二维码String qrCodeResultMsg = rfRechargeOrderService.createWeChatQrCode(accessToken, scene);if (StringUtils.isNotBlank(qrCodeResultMsg)) {String qrCodeErrCode = JsonUtil.getNodeValueRemoveQuotes(qrCodeResultMsg, "errcode");if (StringUtils.isBlank(qrCodeErrCode) || 0 == (Integer.parseInt(qrCodeErrCode))) {String ticket = JsonUtil.getNodeValueRemoveQuotes(qrCodeResultMsg, "ticket");String expireSeconds = JsonUtil.getNodeValueRemoveQuotes(qrCodeResultMsg, "expire_seconds");String qrUrl = JsonUtil.getNodeValueRemoveQuotes(qrCodeResultMsg, "url");orderQrCode.setOrderSecret(orderSecret);orderQrCode.setQrTicket(ticket);orderQrCode.setQrExpireSeconds(Integer.parseInt(expireSeconds));orderQrCode.setQrUrl(qrUrl);count = rechargeOrderQrCodeDao.addRechargeOrderQrCode(orderQrCode);if (count == 1) {orderRechargeService.updateStatusByOrderNo(orderQrCode.getOrderNo(), OrderConstant.ORDER_STATUS_DISPATCH);try {rpcOrderItemService.setOrderItemStatus4RechargeOrder(orderQrCode.getOrderNo(), orderQrCode.getItemNo(), OrderConstant.ORDER_STATUS_DISPATCH);} catch (TException e) {logger.error("OrderRechargeServiceImpl==>addOrderRechargeAndCreateQrCode, 已发货状态回传至业务单出错, orderNo:{}", orderQrCode.getOrderNo(), e);}}logger.info("OrderRechargeServiceImpl==>addOrderRechargeAndCreateQrCode,二维码创建成功,count:{}", count);} else {Monitor.add("获取微信二维码失败", 1);logger.info("OrderRechargeServiceImpl==>addOrderRechargeAndCreateQrCode, 未成功请求到二维码, qrCodeResultMsg: {}", qrCodeResultMsg);return count;}} else {Monitor.add("获取微信二维码失败", 1);logger.info("OrderRechargeServiceImpl==>addOrderRechargeAndCreateQrCode, 未成功请求到二维码");return count;}} catch (IOException e) {logger.error("OrderRechargeServiceImpl==>addOrderRechargeAndCreateQrCode,", e);}return count;}

用户查看订单时,返回刚刚已生成的订单二维码(微信二维码)

/*** 通过商品项获取二维码** @param itemNo* @return* @author scott*/@RequestMapping(value = "/getQrCodeByItemNo/{itemNo}", method = RequestMethod.GET)@ResponseBodypublic ResultMsg getQrCodeByItemNo(@PathVariable String itemNo) {ResultMsg resultMsg = new ResultMsg();try{RechargeOrderQrCode qrCode = rechargeOrderQrCodeService.getQrCodeByItemNo(itemNo);resultMsg.setData(qrCode);resultMsg.setState(Constants.SUCCESS_STATE);resultMsg.setMsg(Constants.SUCCESS_MESSAGE);}catch (Exception e){logger.error("==>getQrCodeByItemNo,", e);resultMsg.setState(Constants.ERROR_STATE);resultMsg.setMsg(Constants.ERROR_MESSAGE);}return resultMsg;}

三、扫描二维码进行微信转账充值

/*** 接受微信扫描后的信息回调,并进行微信转账** @param infoDto* @author scott*/@RequestMapping(value = "/receiveWeChatInfo", method = RequestMethod.POST)public void receiveWeChatInfo(@RequestBody WeChatCallBackInfoDto infoDto) {logger.info("RechargeOrderController==>receiveWeChatInfo, request params infoDto:{}", infoDto);WeChatPaymentResult result = orderRechargeService.weChatRecharge(infoDto);if (Constants.WECHAT_RETURN_FAIL.equals(result.getReturnCode()) || Constants.WECHAT_RETURN_SYSTEM_ERROR.equals(result.getErrCode())) {logger.error("OrderRechargeServiceImpl==>parseWeChatPaymentResult, 转账业务失败, result:{}", result);WeChatRechargeMessage message = new WeChatRechargeMessage();message.setWeChatCallBackInfo(infoDto);message.setRetryCount(1);mqDao.pushRetryWeChatRecharge(message);}}

微信充值官方文档:

/*** 微信充值** @param infoDto* @return* @author scott*/@Overridepublic WeChatPaymentResult weChatRecharge(WeChatCallBackInfoDto infoDto) {WeChatPaymentResult result = new WeChatPaymentResult();String ticket = infoDto.getTicket();String eventKey = infoDto.getEventKey();String openid = infoDto.getFromUserName();if (StringUtils.isNotBlank(ticket) && StringUtils.isNotBlank(eventKey)) {//eventKey由,sceneId + buyerId + orderNo + orderSecret组成String[] orderInfoArr = eventKey.split("_");String buyerId = "";String orderNo = "";String orderSecret = "";//判断传递过来的参数是否为二维码充值类的扫描,已关注扫描情况//未关注情况扫描二维码情况这里涉及具体的业务逻辑,就删除这块判断逻辑了//redis锁,锁订单,同一个订单,只允许一个用户进行扫描充值if (RedisLockUtil.tryLock(Constants.WECHAT_LOCK_PREFIX + orderNo, Constants.REDIS_LOCK_TIME_OUT, TimeUnit.SECONDS)) {try {RechargeOrderQrCode qrCode = rechargeOrderQrCodeService.getQrCodeByOrderNoAndTicket(orderNo, infoDto.getTicket());OrderRecharge orderRecharge = getByOrderNo(Long.parseLong(buyerId), orderNo);String secret = "xxxx";//这块是业务自己的加密算法,可以不用理会去除就好if (qrCode != null && orderSecret.equals(secret)) {RpcOrderItem rpcOrderItem = rpcOrderItemService.getOrderItemByItemBarcode(orderRecharge.getItemNo()).getOrderItem();//验证通过,调用转账接口if (orderRecharge != null && OrderConstant.ORDER_STATUS_DISPATCH == orderRecharge.getOrderStatus() && rpcOrderItem != null && OrderConstant.ORDER_STATUS_DISPATCH == rpcOrderItem.getItemStatus()) {WeChatPaymentTransfer transfer = fillWeChatRequestBody(openid, orderRecharge.getFaceValue() * orderRecharge.getGoodsNum(), orderNo);try {String url = rfRechargeOrderService.getWeChatPayUrl();String requestXml = XmlUtil.convertObjectToXml(transfer, WeChatPaymentTransfer.class);String responseDate = HttpsClientP12Util.httpPostSsl(url, requestXml, "UTF-8", "cert/apiclient_cert.p12", Constants.WECHAT_MCHID);logger.info("RechargeOrderController==>receiveWeChatInfo, responseData:{}", responseDate);if (StringUtils.isNotBlank(responseDate)) {result = XmlUtil.convertXmlStrToObject(responseDate, WeChatPaymentResult.class);//解析转账结果,成功则发送消息给用户,失败则做对应的处理parseWeChatPaymentResult(result, orderRecharge, infoDto.getFromUserName(), rpcOrderItem.getItemId());RedisLockUtil.unLock(Constants.WECHAT_LOCK_PREFIX + orderNo);}} catch (JAXBException e) {logger.error("RechargeOrderController==>receiveWeChatInfo, 对象转换成xml错误,transfer:{}", transfer, e);RedisLockUtil.unLock(Constants.WECHAT_LOCK_PREFIX + orderNo);}} else {//订单状态不对,已取消,或已完成RedisLockUtil.unLock(Constants.WECHAT_LOCK_PREFIX + orderNo);logger.error("RechargeOrderController==>receiveWeChatInfo, 订单状态不正确, infoDto:{}", infoDto);}} else {RedisLockUtil.unLock(Constants.WECHAT_LOCK_PREFIX + orderNo);logger.error("RechargeOrderController==>receiveWeChatInfo,扫码回传过来的信息校验不通过,infoDto:{}", infoDto);Monitor.add("微信二维码扫描回传信息校验失败", 1);}} catch (Exception e) {logger.error("RechargeOrderController==>receiveWeChatInfo, 微信转账异常, infoDto:{}", infoDto, e);RedisLockUtil.unLock(Constants.WECHAT_LOCK_PREFIX + orderNo);Monitor.add("微信快充异常", 1);}}}return result;}
/*** 组建微信请求体信息** @param openId* @param amount* @param orderNo* @return* @author scott*/private WeChatPaymentTransfer fillWeChatRequestBody(String openId, double amount, String orderNo) {WeChatPaymentTransfer transfer = new WeChatPaymentTransfer();String nonce = UUID.randomUUID().toString().substring(0, 30);transfer.setMchAppId(Constants.WECHAT_APPID);transfer.setMchid(Constants.WECHAT_MCHID);transfer.setNonceStr(nonce);transfer.setOpenId(openId);transfer.setCheckName(Constants.WECHAT_CHECK_NAME_NO_CHECK);transfer.setAmount(new Double(amount * 100).intValue());transfer.setDesc(Constants.WECHAT_DESC);//ipString ipAddress = "xx.xx.xx.xx";try {ipAddress = InetAddress.getLocalHost().getHostAddress();} catch (UnknownHostException e) {e.printStackTrace();}transfer.setSpbillCreateIp(ipAddress);transfer.setPartnerTradeNo(orderNo);String sign = createSendRedPackOrderSign(transfer);transfer.setSign(sign);return transfer;}
/*** 生成签名** @param transfer* @return* @author scott*/private String createSendRedPackOrderSign(WeChatPaymentTransfer transfer) {StringBuffer sign = new StringBuffer();sign.append("amount=").append(transfer.getAmount());sign.append("&check_name=").append(transfer.getCheckName());sign.append("&desc=").append(transfer.getDesc());sign.append("&mch_appid=").append(transfer.getMchAppId());sign.append("&mchid=").append(transfer.getMchid());sign.append("&nonce_str=").append(transfer.getNonceStr());sign.append("&openid=").append(transfer.getOpenId());sign.append("&partner_trade_no=").append(transfer.getPartnerTradeNo());sign.append("&spbill_create_ip=").append(transfer.getSpbillCreateIp());sign.append("&key=").append(Constants.WECHAT_KEY);return DigestUtils.md5Hex(sign.toString()).toUpperCase();}
public class HttpsClientP12Util {private final static Logger logger = LoggerFactory.getLogger(HttpsClientP12Util.class);/*** 发送微信转账的ssl请求** @param url      请求URL* @param data     请求内容* @param charset  编码格式* @param certPath 证书地址* @param mchId    证书密码* @return* @author scott*/public static String httpPostSsl(String url, String data, String charset, String certPath, String mchId) {String responseData = null;try {KeyStore keyStore = KeyStore.getInstance("PKCS12");//P12文件目录InputStream inputStream = HttpsClientP12Util.class.getClassLoader().getResourceAsStream(certPath);try {//密码,默认是MCHIDkeyStore.load(inputStream, mchId.toCharArray());} catch (Exception e) {logger.error("Error:", e);} finally {if (inputStream != null) {inputStream.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 httpPost = new HttpPost(url);httpPost.addHeader("Content-Type", "application/xml");httpPost.addHeader("Host", "api.mch.weixin.qq.com");httpPost.addHeader("Cache-Control", "max-age=0");httpPost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");httpPost.addHeader("Connection", "keep-alive");httpPost.addHeader("Accept", "*/*");httpPost.setEntity(new StringEntity(data, "UTF-8"));logger.info("request url: {}, charset:{}, data:{}", httpPost.getURI(), charset, data);CloseableHttpResponse response = httpclient.execute(httpPost);try {HttpEntity entity = response.getEntity();responseData = EntityUtils.toString(entity, charset);EntityUtils.consume(entity);logger.info("Response content:{} ", responseData);} finally {if (response != null) {response.close();}}} finally {// 关闭连接,释放资源try {if (httpclient != null) {httpclient.close();}} catch (IOException e) {logger.error("Error:{}", e);}}} catch (Exception e) {logger.error("Error:{}", e);}return responseData;}
}

四、结果处理,微信转账充值会返回两个结果, return_code和result_code,分别代表请求结果与业务结果

java微信支付,企业微信号转账给个人相关推荐

  1. php 工商银行公众号支付代码_php开发微信支付企业付款实例代码

    企业付款的应用场景: 公众号向已关注用户付款,比如处理退款.财务结算等,本文主要和大家分享php开发微信支付企业付款实例代码,希望能帮助到大家. 说明 1.证书需要用自己的商户里面的证书(注意:证书路 ...

  2. java微信支付代码_Java微信支付之服务号支付代码示例

    Java微信支付之服务号支付实现,网上的java微信支付sdk和Demo基本上是水的,看着头疼所以我决心自己开始写Java微信支付之公众号支付,多的不说见下面源码,为了方便使用我分别用了两个Servl ...

  3. 微信、企业微信、支付窗、微博SDK 四合一,JeeWx-api 1.2.2 版本发布!

    JeeWx-API 1.2.2 版本发布,微信.企业微信.支付窗.微博SDK四合一 JEEWX-API 是第一款JAVA版微信极速SDK,同时集成企业微信SDK,支付窗SDK,微博SDK,可以快速的基 ...

  4. 微信、企业微信和支付窗 SDK 三合一,JeeWx-api 1.2.0 版本发布

    JeeWx-API 1.2.0 版本发布,微信.企业微信和支付窗SDK三合一 摘要: JEEWX-API 是第一款JAVA版微信极速SDK,同时集成企业微信SDK,支付窗SDK,可以快速的基于她进行微 ...

  5. 微信支付、微信企业付款到零钱工具类

    微信支付.微信企业付款到零钱工具类 主要依赖:apache httpclient 4.5 jdk1.8 工具类主要功能: xml参数拼接 签名算法实现 post加密请求 import lombok.e ...

  6. php 微信支付企业付款

    1.所需参数 字段名 变量名 必填 示例值 类型 描述 公众账号appid mch_appid 是 wx8888888888888888 String 公众号的appId 商户号 mchid 是 19 ...

  7. 微信支付、微信公众号接口认证方案

    1 微信公众号接口认证方案 1.1 认证流程 安全API接口认证方案 流程图模板_ProcessOn思维导图.流程图​www.processon.com/view/link/636e05a21e085 ...

  8. 微信支付--企业支付到零钱

    最近由于开发需要,进行了微信支付--企业支付到零钱的功能开发,期间也参考了部分网上的开发思路,以及微信支付的开发问题,在这里做一下总结和源码分享. 腾讯的开发文档:https://pay.weixin ...

  9. 微信小程序-JAVA实现微信支付功能(微信支付2.0)

    微信小程序-JAVA实现微信支付功能(微信支付2.0) 一.前言 本博客主要介绍JAVA后台与微信小程序(UNI-APP或者原生微信小程序)的微信支付的实现,如果是APP或者H5的开发暂时不支持,具体 ...

  10. 微信分账功能与微信支付企业付款相关内容详解(payjs版)

    PAYJS开通微信分账功能以来,有很多同学咨询相关情况.很多同学关心有没有什么办法,可以让自己的商户号快速开通企业付款功能.这里就介绍下微信分账的具体相关内容,可以完美解决问题. 一.什么是微信分账? ...

最新文章

  1. CentOS全局配置JAVA环境变量,实现多个tomcat共用环境变量,不用再一个个tomcat配置
  2. 1280*720P和1920*1080P的视频在25帧30帧50帧60帧时的参数
  3. shell中使用echo命令改变输出显示样式
  4. Mongodb的游标,索引,聚合操作与MapReduce
  5. 老码农吐血建议:2020年,低于1w的程序员要注意了...
  6. Linux下BitNami Redmine的插件安装与更新
  7. 百度文本编辑器ueditor v1.2.3.0使用方法及配置(图片上传功能、目录更改)
  8. ASP.NET Gridview的简单的Bootstrap分页
  9. android onitemclicklistener 按钮代码,在listview Android的setOnItemClickListener上设置项目单击事件...
  10. 服务器测试文档格式,服务器测试文档格式
  11. 初始化请求例子_当一个http请求来临时,SpringMVC究竟偷偷帮你做了什么?
  12. 打出租辆来回机场好贵
  13. 管理感悟:对事又对人
  14. 7个步骤建立可用的机器学习模型
  15. ai怎么做盒子效果图_AI制作包装纸盒贴图教程
  16. 测试人员的绩效考核,看看你有哪些没做好
  17. 分享:快捷方便的函数命名网站
  18. java cap 反编译_应用 JD-Eclipse 插件实现 RFT 中 .class 文件的反向编译
  19. 使用excel进行数据挖掘(4)---- 突出显示异常值
  20. win7下安装配置theano详解

热门文章

  1. php 递归中的全局变量,PHP递归函数内的静态变量
  2. 【weblogic部署应用】
  3. 52 个有用的机器学习与预测接口盘点
  4. 2022:中国存储的生死时速
  5. 1252: [蓝桥杯2015初赛]奇妙的数字
  6. Computer Hardware ID(CHID)及驱动推送
  7. 设计模式-Adapter模式(适配器模式)
  8. 一个萌新关于电脑安装软件错误提示“1402”的应对方法
  9. webp格式图片如何简单快速转换成JPG、PNG格式
  10. 【web素材】02-10款大气的购物商城网站模板