微信小程序商家转账到零钱【java】

这篇具有很好参考价值的文章主要介绍了微信小程序商家转账到零钱【java】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

微信支付平台 开通权限

商家转账到零钱官方简介
登录微信支付平台 点击产品中心
java对接微信小程序商家转账到零钱,小程序,微信小程序,java,小程序
产品大全 -> 我的 -> 运营工具
java对接微信小程序商家转账到零钱,小程序,微信小程序,java,小程序

然后根据要求 上传资料 提交开通申请 他说得是7-15天但是快一点也就两三天之内就有结果了
开通之后需要设置一些东西
java对接微信小程序商家转账到零钱,小程序,微信小程序,java,小程序
点击前往功能

  • 设置转账账户
  • 设置转账发起方式 有两种 页面发起 && API发起
  • 设置转账配置 转账额度啥的
  • 重要: 设置访问IP 就是白名单的意思 如果本地的话查看外网IP(http://ifconfig.me ),服务器的自己找,hhhc(公司应该有记录)

开发文档

ps:很好找的其实,我刚开始还找了半天,哎
微信支付文档中心
进入之后点击 API文档
java对接微信小程序商家转账到零钱,小程序,微信小程序,java,小程序
到下面这个页面(把目录都收起来就好找了)
java对接微信小程序商家转账到零钱,小程序,微信小程序,java,小程序
然后点击运营工具就看见了
java对接微信小程序商家转账到零钱,小程序,微信小程序,java,小程序

  • emmm 再多写点吧 转账API 地址 和 查询API 地址也给你吧
    都在这了,自己拿吧hhh
    java对接微信小程序商家转账到零钱,小程序,微信小程序,java,小程序
    商家转账到零钱API传送门
    通过商家批次单号查询转账结果传送门
    ps :okok 好人做到底了

代码

pom 文件

<dependency>
  	<groupId>com.github.wechatpay-apiv3</groupId>
   	<artifactId>wechatpay-apache-httpclient</artifactId>
   	<version>0.4.7</version>
</dependency>

HttpUtil

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.Arrays;

import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.WECHAT_PAY_SERIAL;
import static org.apache.http.HttpHeaders.ACCEPT;
import static org.apache.http.HttpHeaders.CONTENT_TYPE;
import static org.apache.http.entity.ContentType.APPLICATION_JSON;


/**
 * @Author: 小新
 * @Date: 2023/12/29 10:01
 * 微信支付专用类 请求操作方法
 */
@Slf4j
public class HttpUtil {
    /**
     * 发起批量转账API 批量转账到零钱
     *
     * @param requestUrl
     * @param requestJson 组合参数
     * @param wechatPayserialNo 商户证书序列号
     * @param mchID  商户号
     * @param privatekeypath  商户私钥证书路径
     * @return
     */
    public static String postTransBatRequest(
            String requestUrl,
            String requestJson,
            String wechatPayserialNo,
            String mchID4M,
            String privatekeypath) {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        try {
            HttpPost httpPost = new HttpPost(requestUrl);
            // NOTE: 建议指定charset=utf-8。低于4.4.6版本的HttpCore,不能正确的设置字符集,可能导致签名错误
            httpPost.addHeader("Content-Type", "application/json");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Wechatpay-Serial", wechatPayserialNo);

            /*****************核心认证 start*****************/
            String strToken = WechatPayV3Util.getToken("POST",
                    "/v3/transfer/batches",
                    requestJson,mchID4M,wechatPayserialNo, privatekeypath);

            log.error("微信转账token "+strToken);
            // 添加认证信息
            httpPost.addHeader("Authorization",
                    "WECHATPAY2-SHA256-RSA2048" + " "
                            + strToken);
            /*****************核心认证 end*****************/
            
            httpPost.setEntity(new StringEntity(requestJson, "UTF-8"));
            //发起转账请求
            response = httpclient.execute(httpPost);
            entity = response.getEntity();//获取返回的数据
            log.info("返回请求ID :{} ", Arrays.toString(response.getHeaders("Request-ID")));
            return EntityUtils.toString(entity);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            try {
                if (httpclient != null) {
                    httpclient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    /**
     * 查询账单
     * @param requestUrl        请求地址
     * @param wechatPayserialNo 商户证书序列号
     * @param privatekeypath    商户私钥证书路径
     * @return
     */
    public static String getTransBatRequest(
            String requestUrl,
            String wechatPayserialNo,
            String mchId,
            String privatekeypath,
            String servletPath){
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            HttpGet httpGet = new HttpGet(requestUrl);
            // NOTE: 建议指定charset=utf-8。低于4.4.6版本的HttpCore,不能正确的设置字符集,可能导致签名错误
            httpGet.addHeader("Content-Type", "application/json");
            httpGet.addHeader("Accept", "application/json");
            httpGet.addHeader("Wechatpay-Serial", wechatPayserialNo);
            
            /*****************核心认证 start*****************/
            String strToken = null;
            try {
                strToken = WechatPayV3Util.getToken("GET", servletPath, "", mchId, wechatPayserialNo, privatekeypath);
            } catch (Exception e) {
                log.error("请求异常:{}", e.getMessage());
                e.printStackTrace();
            }

            log.info("token " + strToken);
            // 添加认证信息
            httpGet.addHeader("Authorization",
                    "WECHATPAY2-SHA256-RSA2048" + " "
                            + strToken);
            /*****************核心认证 end*****************/

            //发起查询请求
            response = httpClient.execute(httpGet);
            log.info("响应:  {}", response);
            entity = response.getEntity();//获取返回的数据
            return EntityUtils.toString(entity);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            try {
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

WechatPayV3Util


import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Random;

/**
 * @Author: 小新
 * @Date: 2023/12/29 9:58
 */
@Slf4j
public class VechatPayV3Util {


    /**
     * @param method       请求方法 post
     * @param canonicalUrl 请求地址
     * @param body         请求参数 
     * @param merchantId   商户号
     * @param certSerialNo 商户证书序列号
     * @param keyPath      私钥商户证书地址
     * @return
     * @throws Exception
     */
    public static String getToken(
            String method,
            String canonicalUrl,
            String body,
            String merchantId,
            String certSerialNo,
            String keyPath) throws Exception {
        String signStr = "";
        //获取32位随机字符串
        String nonceStr = getRandomString(32);
        //当前系统运行时间
        long timestamp = System.currentTimeMillis() / 1000;
        if (StringUtils.isEmpty(body)) {
            body = "";
        }
        String message = buildMessage(method, canonicalUrl, timestamp, nonceStr, body);
        //签名操作
        //签名操作
        String signature = sign(message.getBytes(StandardCharsets.UTF_8), keyPath);
        //组装参数
        signStr = "mchid=\"" + merchantId + "\",timestamp=\"" +  timestamp+ "\",nonce_str=\"" + nonceStr
                + "\",serial_no=\"" + certSerialNo + "\",signature=\"" + signature + "\"";

        return signStr;
    }

    public static String buildMessage(String method, String canonicalUrl, long timestamp, String nonceStr, String body) {
        return method + "\n" + canonicalUrl + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
    }

    public static String sign(byte[] message, String keyPath) throws Exception {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(getPrivateKey(keyPath));
        sign.update(message);
        return Base64.encodeBase64String(sign.sign());
    }

    /**
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey(String filename) throws IOException {

        //todo 我放在项目里的  也可以放在服务器上 都可以 看自己需求了
        String content = new String(Files.readAllBytes(Paths.get("src/main/resources" + filename)), "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("不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }

    /**
     * 获取随机位数的字符串
     * @param length  随机数长度
     * @return
     */
    public static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    /**
     * 微信敏感数据加密-公钥
     * @return
     */
    public static X509Certificate getSaveCertificates(String platformCertPath) throws IOException {
        InputStream inputStream = new FileInputStream(new File(platformCertPath));
        BufferedInputStream bis = new BufferedInputStream(inputStream);
        return PemUtil.loadCertificate(bis);
    }
}

ApiUrl

/**
 * 第三方api地址
 */
public class ApiUrl {
//ps: 当时申请商家转账还没通过的时候 想着先写代码,结果写错了,写成了企业转账到零钱,吐血
    /**
     * 企业转账到零钱 
     */
    //public static String WECHAT_TRANSFERS_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
    /**
     * 商家转账到零钱
     */
    public static String WECHAT_TRANSFERS_URL = "https://api.mch.weixin.qq.com/v3/transfer/batches";
    /**
     * 商户批次号查询
     */
    public static String SELECT_ORDER_URL = "https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no";
}

好像就没有了 对了 那个提现记录表也给你们吧 mysql的,看不上的你们就自己设计一个hhh

提现记录表

CREATE TABLE `tb_weixin_entpay_form` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `total_amount` decimal(19,2) DEFAULT NULL COMMENT '提现金额',
  `user_name` varchar(255) DEFAULT NULL COMMENT '用户名',
  `open_id` varchar(255) DEFAULT NULL COMMENT 'openid',
  `partner_trade_no` varchar(255) DEFAULT NULL COMMENT '提现单号',
  `progress` varchar(255) DEFAULT NULL COMMENT '提现进度 SUCCESS  INPROGRESS  FAIL',
  `wx_type` varchar(255) DEFAULT NULL COMMENT '类型',
  `user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
  `start_time` datetime DEFAULT NULL COMMENT '开始时间',
  `end_time` datetime DEFAULT NULL COMMENT '结束时间',
  `batch_id` varchar(255) DEFAULT NULL COMMENT '微信明细单号',
  PRIMARY KEY (`id`)
)comment '提现记录表';

下面的就是根据自己的业务来写了

controller 商家转账到零钱

@PostMapping("/transfer")
    public Result transfer(@RequestParam(name = "amount", required = true) String amount, HttpServletRequest request) {
        Long userId = (Long) request.getAttribute("userId"); 
        return wxPayService.transfer(amount, userId, request);
    }

ServiceImpl

	@Value("${wx.WeChat.AppID}")
    private String AppId;
    @Value("${wx.WeChat.SerialNo}")
    private String SerialNo;   // 支付证书序列号
    @Value("${wx.WeChat.Privatekeypath}")
    private String Privatekeypath;  // 我的是本地项目resource下的  /cert/apiclient_key.pem  这个 (别弄错了)
    
// todo  当时因为这个项目 证书给我了但是我不知道是哪个序列号 因为有好多个 ,所以又找了个根据商户私钥来找序列号
// 在哪找到的呢 emm  还是告诉你们吧,藏在代码里 应该看的人不多嘿嘿嘿
//https://pay.weixin.qq.com/docs/merchant/development/interface-rules/signature-faqs.html
/** 有需要的可以试试  1900009191_20180326_cert.pem 这个就是你本地存放地址了  window + R 就行
*   openssl x509 -noout -modulus -in 1900009191_20180326_cert.pem
	Modulus=C6D43C87B991...
	openssl rsa -noout -modulus -in 1900009191_20180326_key.pem
	Modulus=C6D43C87B991...
*/
/**
     * 商家转账到零钱
     * @param amount
     * @param userId
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result transfer(String amount, Long userId, HttpServletRequest request) {
        // 查询当前用户
        LbUser lbUser = lbUserMapper.selectById(userId);
        if (lbUser == null) {
            return new Result("400", "当前用户未注册");
        }
        // 查询是否绑定微信
        List<LbUserWx> userWxList = lbUserWxMapper.findByUserIdAndAppid(userId,AppId);
        if (userWxList.isEmpty()){
            return new Result("400", "请先绑定微信");
        }
        // 查询余额
        List<TbUserAccount> accountList = tbUserAccountMapper.selectList(new QueryWrapper<TbUserAccount>().lambda().eq(TbUserAccount::getUserId, userId).orderByDesc(TbUserAccount::getId));
        if (accountList.isEmpty()) {
            return new Result("400", "当前用户未登录");
        }
        // 是否可以提现
        TbUserAccount tbUserAccount = accountList.get(0);
        BigDecimal availableBalance = tbUserAccount.getAvailableBalance();
        if (availableBalance.compareTo(new BigDecimal(amount)) < 0){
            return new Result("400","余额不足");
        }
        // 提现记录
        WeixinEntPayForm weixinEntPayForm = new WeixinEntPayForm();
        // 用户id
        weixinEntPayForm.setUserId(userId);
        // openid
        weixinEntPayForm.setOpenId(userWxList.get(0).getOpenid());
        // 用户名
        weixinEntPayForm.setUserName(lbUser.getNickname());
        // 提现类型
        weixinEntPayForm.setWxType("MINIAPP");
        // 提现单号
        weixinEntPayForm.setPartnerTradeNo(IDUtil.getUUIDStr(32));
        // 提现金额
        weixinEntPayForm.setTotalAmount(new BigDecimal(amount));
        // 提现进度 进行中
        weixinEntPayForm.setProgress("INPROGRESS");
        // 开始时间
        weixinEntPayForm.setStartTime(new Date());
        // 保存提现记录
        weixinEntPayFormMapper.insert(weixinEntPayForm);
        // 提现
        Map<String, String> map = entPay(weixinEntPayForm, request,tbUserAccount);
        return new Result(map.get("code"),map.get("message"));
    }

	private Map<String, String> entPay(WeixinEntPayForm weixinEntPayForm, HttpServletRequest request,TbUserAccount tbUserAccount){
        // 返回
        Map<String, Object> postMap = new HashMap<String, Object>();

        //小程序 id
        postMap.put("appid", AppId); // 需要跟商户ID 绑定的奥
        postMap.put("out_batch_no", weixinEntPayForm.getPartnerTradeNo());
        //该笔批量转账的名称
        postMap.put("batch_name", "提现");
        //转账说明
        postMap.put("batch_remark", "提现");
        //转账金额单位为“分”。 总金额
        postMap.put("total_amount",weixinEntPayForm.getTotalAmount().multiply(new BigDecimal(100)).intValue());
        //转账总笔数
        postMap.put("total_num", 1);

        // 转账批次集合
        List<Map> list = new ArrayList<>();
        Map<String, Object> subMap = new HashMap<>(4);
        //商家明细单号 (系统内唯一)
        subMap.put("out_detail_no", IDUtil.getUUIDStr(32));
        //转账金额
        subMap.put("transfer_amount", weixinEntPayForm.getTotalAmount().multiply(new BigDecimal(100)).intValue());
        //转账备注
        subMap.put("transfer_remark", "提现到账");
        //用户使用小程序时 记录了用户的微信opneId  必须是在Appid 下的openId  不然不会成功的奥
        subMap.put("openid", weixinEntPayForm.getOpenId());
        //大金额需要传入真实姓名 根据自己需求设置
        //subMap.put("user_name", RsaCryptoUtil.encryptOAEP(userName,WechatPayV3Util.getSaveCertificates(privatekeypath)));
        list.add(subMap);
        postMap.put("transfer_detail_list", list);

        log.info("请求参数:{}",JSONObject.toJSONString(postMap));
        Map<String, String> results = new HashMap<>();
        String result = HttpUtil.postTransBatRequest(
                ApiUrl.WECHAT_TRANSFERS_URL,// 请求地址
                JSONObject.toJSONString(postMap),// 请求参数
                SerialNo,// 支付证书序列号
                wxPayConfig.getMchId(),// 商户号
                Privatekeypath); //证书私钥地址
        JSONObject jsonObject = JSONObject.parseObject(result);

        log.info("返回结果:{}",jsonObject);
        /*正常返回
        *{
			 "out_batch_no" : "plfk2020042013",
			  "batch_id" : "1030000071100999991182020050700019480001",
			  "create_time" : "2015-05-20T13:29:35.120+08:00",
			  "batch_status" : "ACCEPTED"
		}
        */

        if ("ACCEPTED".equals(jsonObject.getString("batch_status"))){
            //受理成功
            // 记录
            weixinEntPayForm.setBatchId(jsonObject.getString("batch_id"));
            results.put("code", "200");
            results.put("message", "提现申请成功");
        }else{
            //失败
            weixinEntPayForm.setProgress("FAIL");
            results.put("code", "400");
            results.put("message", "提现申请失败");
        }
        try {
            weixinEntPayFormMapper.updateById(weixinEntPayForm);
        } catch (Exception e) {
            log.info("异常原因:{}",e.getMessage());
            results.put("code", "400");
            results.put("message", "提现申请出现异常");
            return results;
        }
        return results;
    }

controller 通过商家明细单号查询明细单

@GetMapping("/getTransBat")
    public Result getTransBat(@RequestParam(name = "outBatchNo", required = true) String outBatchNo) {
        return wxPayService.getTransBat(outBatchNo);
    }

ServiceImpl

@Override
public Result getTransBat(String outBatchNo) {
     String result  =  HttpUtil.getTransBatRequest(
             ApiUrl.SELECT_ORDER_URL+"/"+outBatchNo+"?need_query_detail=True&detail_status=ALL",
             SerialNo,
             wxPayConfig.getMchId(),
             Privatekeypath,"/v3/transfer/batches/out-batch-no"+"/"+outBatchNo+"?need_query_detail=True&detail_status=ALL");
     JSONObject  results  =  JSONObject.parseObject(result);
     return new Result("200",results);
 }




/*
*{
  "code": "200",
  "data": {
    "offset": 0,
    "transfer_detail_list": [
      {
        "detail_status": "SUCCESS",  // 这个就是返回的结果了 还有失败和进行中什么的 文档里都有,自己看吧
        "out_detail_no": "不给看",
        "detail_id": "不给看"
      }
    ],
    "limit": 20,
    "transfer_batch": {
      "mchid": "不给看",
      "create_time": "也不给看",
      "success_amount": 不给看,
      "batch_id": "不给看",
      "success_num": 1,
      "batch_status": "FINISHED",
      "out_batch_no": "不给看",
      "batch_name": "提现",
      "update_time": "也不给看",
      "fail_amount": 0,
      "total_amount": 100,//分
      "appid": "不给看",
      "total_num": 1,
      "batch_remark": "提现",
      "batch_type": "API",
      "fail_num": 0,
      "transfer_scene_id": "不给看" // 这是场景ID
    }
  },
  "message": "操作成功"
}
*/

跟转账的参数也大差不差 返回没处理 直接返回了 懒狗hhhhc文章来源地址https://www.toymoban.com/news/detail-777511.html

  • okok 到这应该就没有了 ,对了,我还写了个定时器来查询结果更新一些数据的,但是我给公司留了不少坑hhhc,反正能用,你们看看乐子就行。
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @Author: 小新
 * @Date: 2023/12/29 16:05
 */
@Slf4j
@Configuration
public class WexinEntPayTask {

    @Resource
    private WxPayConfig wxPayConfig;

    @Value("${wx.WeChat.SerialNo}")
    private String SerialNo;

    @Value("${wx.WeChat.Privatekeypath}")
    private String Privatekeypath;

    @Resource
    private WeixinEntPayFormMapper weixinEntPayFormMapper;

    @Resource
    private LbUserMapper lbUserMapper;

    @Resource
    private TbUserAccountMapper tbUserAccountMapper;

    @Resource
    private LbUserLawyerMessageLogMapper lbUserLawyerMessageLogMapper;

    @Resource
    private UrlLinkUtil urlLinkUtil;

    @Resource
    private ShlianLuUtil shlianLuUtil;

    private static final String SUCCESS = "SUCCESS";
    private static final String FAIL = "FAIL";

    @Scheduled(cron = "0 */3 * * * ?")
    @Transactional
    void selectWexinEnPay() {
        log.info("==========开始查询转账记录================");
        // 查询所有进行中的转账记录
        List<WeixinEntPayForm> list = weixinEntPayFormMapper.selectList(new QueryWrapper<WeixinEntPayForm>().lambda().eq(WeixinEntPayForm::getProgress, "INPROGRESS"));

        if (list.isEmpty()) {
            log.info("没有转账记录");
            return;
        }

        for (WeixinEntPayForm weixinEntPayForm : list) {
            LbUser user = lbUserMapper.selectById(weixinEntPayForm.getUserId());

            if (user == null) {
                log.info("用户不存在");
                continue;
            }

            try {
                String result = HttpUtil.getTransBatRequest(buildUrl(weixinEntPayForm), SerialNo, wxPayConfig.getMchId(), Privatekeypath, buildOutBatchNoUrl(weixinEntPayForm));
                JSONObject results = JSONObject.parseObject(result);

                processTransferResult(weixinEntPayForm, user, results);
                log.info("=========={} 转账记录查询及后续操作完成================",weixinEntPayForm.getId());

            } catch (Exception e) {
                log.error("查询转账记录出现错误:{}, 商户批次单号:{}", e.getMessage(), weixinEntPayForm.getPartnerTradeNo());
                continue;
            }
        }
    }

    /**
     * 查询请求地址
     * @param weixinEntPayForm
     * @return
     */
    private String buildUrl(WeixinEntPayForm weixinEntPayForm) {
        return ApiUrl.SELECT_ORDER_URL + "/" + weixinEntPayForm.getPartnerTradeNo() + "?need_query_detail=True&detail_status=ALL";
    }

    /**
     * 相对路径
     * @param weixinEntPayForm
     * @return
     */
    private String buildOutBatchNoUrl(WeixinEntPayForm weixinEntPayForm) {
        return "/v3/transfer/batches/out-batch-no" + "/" + weixinEntPayForm.getPartnerTradeNo() + "?need_query_detail=True&detail_status=ALL";
    }

    /**
     * 根据请求结果 进行处理
     * @param weixinEntPayForm 转账记录
     * @param user 用户
     * @param results 转账结果返回
     * @throws ParseException
     */
    private void processTransferResult(WeixinEntPayForm weixinEntPayForm, LbUser user, JSONObject results) throws ParseException {
        int updateAccount = 0;
        boolean flag = true;
        JSONArray transferDetailList = results.getJSONArray("transfer_detail_list");
        String detailStatus = transferDetailList.getJSONObject(0).getString("detail_status");

        if (SUCCESS.equals(detailStatus)) {
            // 转账成功
            updateAccount = updateAccount(weixinEntPayForm);
            weixinEntPayForm.setProgress(SUCCESS);
        } else if (FAIL.equals(detailStatus)) {
            // 转账失败
            weixinEntPayForm.setProgress(FAIL);
        }

        flag = flag && (updateAccount == 1);

        if (flag) {
            updateOrderAndSendMessage(weixinEntPayForm, user, results);
        }
    }

    /**
     * 更新余额
     * @param weixinEntPayForm
     * @return
     */
    private int updateAccount(WeixinEntPayForm weixinEntPayForm) {
        List<TbUserAccount> accountList = tbUserAccountMapper.selectList(new QueryWrapper<TbUserAccount>().lambda().eq(TbUserAccount::getUserId, weixinEntPayForm.getUserId()).orderByDesc(TbUserAccount::getId));
        if (!accountList.isEmpty()) {
            TbUserAccount tbUserAccount = accountList.get(0);
            // 更新余额
            BigDecimal subtract = tbUserAccount.getAvailableBalance().subtract(weixinEntPayForm.getTotalAmount());
            tbUserAccount.setAvailableBalance(subtract);
            tbUserAccount.setBalance(subtract);
            return tbUserAccountMapper.updateById(tbUserAccount);
        }
        return 0;
    }

    /**
     * 更新 转账记录  和  发送消息
     * @param weixinEntPayForm
     * @param user
     * @param results
     * @throws ParseException
     */
    private void updateOrderAndSendMessage(WeixinEntPayForm weixinEntPayForm, LbUser user, JSONObject results) throws ParseException {
        // 处理时间
        Date updateTime = parseUpdateTime(results);
        weixinEntPayForm.setEndTime(updateTime == null ? new Date() : updateTime);
        boolean flag = weixinEntPayFormMapper.updateById(weixinEntPayForm) == 1;

        try {
            LbUserLawyerMessageLog lbUserLawyerMessageLog = buildMessageLog(weixinEntPayForm, user);
            flag = flag && (lbUserLawyerMessageLogMapper.insert(lbUserLawyerMessageLog) == 1);
        } catch (Exception e) {
            log.info("存储消息失败 原因:{}", e.getMessage());
        }

        if (flag) {
            if (SUCCESS.equals(weixinEntPayForm.getProgress())) {
                sendTransferSMS(user,SUCCESS);
            } else {
                sendTransferSMS(user,FAIL);
            }

        } else {
            log.info("转账短信发送失败");
        }
    }

    /**
     * 处理时间
     * @param results
     * @return
     * @throws ParseException
     */
    private Date parseUpdateTime(JSONObject results) throws ParseException {
        String timeWithTimeZone = results.getJSONObject("transfer_batch").getString("update_time");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

        try {
           return dateFormat.parse(timeWithTimeZone);
        } catch (ParseException e) {
            log.info("日期处理失败");
            return null;
        }
    }

    /**
     * 构建短信记录
     * @param weixinEntPayForm
     * @param user
     * @return
     */
    private LbUserLawyerMessageLog buildMessageLog(WeixinEntPayForm weixinEntPayForm, LbUser user) {
        LbUserLawyerMessageLog lbUserLawyerMessageLog = new LbUserLawyerMessageLog();
        lbUserLawyerMessageLog.setUserId(weixinEntPayForm.getUserId());
        lbUserLawyerMessageLog.setCreatedTime(new Date());
        lbUserLawyerMessageLog.setTopicLawyerId(0L);
        lbUserLawyerMessageLog.setIdentityType(user.getIsAuth());
        lbUserLawyerMessageLog.setReadIsNot(1);
        lbUserLawyerMessageLog.setMessageType(SUCCESS.equals(weixinEntPayForm.getProgress()) ? UserMessageType.TRANSFERSUCCESS : UserMessageType.TRANSFERFAIL);
        return lbUserLawyerMessageLog;
    }

    /**
     * 发送短信
     * @param user
     * @param successOrFail
     */
    private void sendTransferSMS(LbUser user,String successOrFail) {
        // 发送短信
        String smsResult2 = shlianLuUtil.sendSMSTemplate(new String[]{user.getPhone()}, SUCCESS.equals(successOrFail) ? SmsTemplateIdUtil.transferSuccess : SmsTemplateIdUtil.transferFail,
                new String[]{
                        user.getNickname(),
                        urlLinkUtil.jumpAppletShortUrl("")});
        log.info("转账短信发送返回 smsResult2:{}", smsResult2);
    }
}
  • 老板应该看不见吧 hhhc 这次就到这吧,家人们看看乐子。

到了这里,关于微信小程序商家转账到零钱【java】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序支付-java对接微信

     一共是两个方法: 一个方法后台生成预支付订单,得到预支付交易会话标识prepay_id,传给前端,让前端调起小程序支付; 一个是支付回调 目录 一、生成预支付订单  注意: 二、 支付回调         封装参数向微信发送生成预支付交易单请求,微信会返回一个prepay_id,再将

    2024年02月12日
    浏览(47)
  • Java 微信小程序-发货信息录入接口 对接代码

    微信小程序-发货信息录入接口开发文档 POST https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token=ACCESS_TOKEN 参见「查询物流公司编码列表」对接代码

    2024年02月03日
    浏览(69)
  • java对接微信小程序(登录&获取用户信息)

    用户通过小程序登录,进入到平台系统,进行各功能操作; 解决方案: 首先通过对接小程序,用户通过小程序登录及授权获取用户信息,后端调用接口获取微信用户信息,进行保存到数据库,然后返回token给前端(实际在这里相当于用户的一个注册及登录),前端使用该to

    2024年02月15日
    浏览(44)
  • 微信小程序数字键盘(仿微信转账键盘)

    微信小程序 input 自带数字输入键盘,不过是直接调用的系统键盘,无法个性化。 代码中使用使用了 Vant Weapp Vant UI小程序版,这里就不介绍相关安装说明了,大家自行安装Vant Weapp。 json 用到的组件 wxml 结构 js 内容 wxss 样式

    2024年02月15日
    浏览(40)
  • 怎么做微信小程序商家店铺_分享商家店铺小程序制作

    1、实体店铺的老板们可以使用营业执照和法人绑定的微信免费开通一个微信商家店铺小程序。 2、使用微信小商店助手开通一个也是免费的小商店助手小程序。 3、购买成熟商城小程序系统,一般年2000元左右。商城小程序系统要比微信自家推出的小程序功能强大很多。 4、找

    2024年02月12日
    浏览(49)
  • 今日餐饮美食推荐系统多商家 uniapp+vue微信小程序

    此今日美食推荐小程序信息的设计主要有两个用户,会员客户端和管理员服务端两个部分:会员客户主要功能; (1)会员信息:包括:会员注册、会员登录,包括对个人信息进行修改。 (2)大吃大喝:通过大吃大喝页面查看美食名称、菜系分类、图片、特色、商家名称、商

    2024年02月11日
    浏览(40)
  • 微信小程序对接百度地图

    微信小程序如何接入百度地图导航功能?下面带来接入百度地图的操作教程。 1、登录百度地图开放平台:lbsyun.baidu.com,注册为开发者;需要填写使用场景,至少100字。 2、依次点击顶部开发文档—Web开发下方的微信小程序 Javascript API—开发指南—配置环境—下载百度地图微

    2024年02月10日
    浏览(41)
  • 微信小程序对接微信支付详细教程

    小程序 微信支付官方文档 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_11index=2 https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_0.shtml 前提 在进行对接微信支付之前,我们首先需要将以下几点准备好: 申请APPID 申请商户号 小程序开通微信支付,绑定已经申请好的商户号。

    2024年02月09日
    浏览(47)
  • springboot+uniapp微信小程序基于Android+hbuiderx的商家团购系统z549a

    作为一款团购系统,面向的是大多数学者,软件的界面设计简洁清晰,用户可轻松掌握使用技巧。在调查之后,获得用户以下需求: (1)用户注册登录后,可进入系统解锁更多功能,用户将信息加入到后台数据库。 (2)用户不仅可以查看商品信息,而且还可以自行搜索商品

    2024年02月19日
    浏览(34)
  • 微信小程序对接SSE接口记录

    微信小程序对接SSE接口记录 需求 :公司项目对接gpt,gpt产生的结果是分段返回,所以要求在产生结果时,有打字机的效果。原本是由定时器调用,后来优化改为服务端使用SSE接口。 小程序使用起来比较方便,但是要求小程序 基本库 的版本需要在 2.20.2 以上。文档地址移步这

    2024年02月15日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包