dcs 4 settimane fa
parent
commit
d4ba7b9563

+ 25 - 0
virgo.api/src/main/java/com/bosshand/virgo/api/workark/controller/WxPayController.java

@@ -3,6 +3,7 @@ package com.bosshand.virgo.api.workark.controller;
 
 import com.bosshand.virgo.api.workark.service.WxPayJsApiService;
 import com.bosshand.virgo.api.workark.service.WxPayService;
+import com.bosshand.virgo.api.workark.service.WxTransferService;
 import com.bosshand.virgo.api.workark.util.HttpUtils;
 import com.bosshand.virgo.core.response.Response;
 import com.google.gson.Gson;
@@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
@@ -32,6 +34,9 @@ public class WxPayController {
     @Autowired
     WxPayJsApiService wxPayJsApiService;
 
+    @Autowired
+    WxTransferService wxTransferService;
+
     /**
      * Native下单
      * @param orderNo
@@ -62,6 +67,26 @@ public class WxPayController {
         return Response.ok(wxPayJsApiService.jsapiPay(orderNo, openid));
     }
 
+    /**
+     * 用户提现,商户转账
+     */
+    @ApiOperation("用户提现,商户转账")
+    @PostMapping("/transfer/{openid}/{money}")
+    public Response transfer(@PathVariable String openid, @PathVariable BigDecimal money){
+
+        log.info("发起提现请求");
+        return Response.ok(wxTransferService.transfer(openid, money));
+    }
+
+    /**
+     * 用户提现,商户单号查询转账单
+     */
+    @ApiOperation("用户提现,商户单号查询转账单")
+    @PostMapping("/transferOutBillNo/{outBillNo}")
+    public Response transfer(@PathVariable String outBillNo){
+        return Response.ok(wxTransferService.transferOutBillNo(outBillNo));
+    }
+
     /**
      * 支付通知
      * 微信支付通过支付通知接口将用户支付成功消息通知给商户

+ 19 - 0
virgo.api/src/main/java/com/bosshand/virgo/api/workark/dao/TransferInfoDao.java

@@ -0,0 +1,19 @@
+package com.bosshand.virgo.api.workark.dao;
+
+import com.bosshand.virgo.api.workark.model.TransferInfo;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface TransferInfoDao {
+
+    List<TransferInfo> getUserId(long userId);
+
+    TransferInfo getOutBillNo(String outBillNo);
+
+    void save(TransferInfo transferInfo);
+
+    void update(TransferInfo transferInfo);
+
+}

+ 141 - 0
virgo.api/src/main/java/com/bosshand/virgo/api/workark/model/TransferInfo.java

@@ -0,0 +1,141 @@
+package com.bosshand.virgo.api.workark.model;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 转账信息
+ */
+public class TransferInfo {
+
+    private Long id;
+
+    /**
+     * 微信用户的openId
+     */
+    private  String openId;
+
+    /**
+     * 用户
+     */
+    private long userId;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+
+    /**
+     * 商户单号
+     */
+    private String outBillNo;
+
+    /**
+     * 微信转账单号
+     */
+    private String transferBillNo;
+
+    /**
+     * 跳转微信支付收款页的package信息,APP调起用户确认收款或者JSAPI调起用户确认收款 时需要使用的参数。
+     */
+    private String packageInfo;
+
+    /**
+     * 金额
+     */
+    private BigDecimal money;
+
+    /**
+     * 状态
+     */
+    private String state;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getOpenId() {
+        return openId;
+    }
+
+    public void setOpenId(String openId) {
+        this.openId = openId;
+    }
+
+    public long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(long userId) {
+        this.userId = userId;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getOutBillNo() {
+        return outBillNo;
+    }
+
+    public void setOutBillNo(String outBillNo) {
+        this.outBillNo = outBillNo;
+    }
+
+    public String getTransferBillNo() {
+        return transferBillNo;
+    }
+
+    public void setTransferBillNo(String transferBillNo) {
+        this.transferBillNo = transferBillNo;
+    }
+
+    public String getPackageInfo() {
+        return packageInfo;
+    }
+
+    public void setPackageInfo(String packageInfo) {
+        this.packageInfo = packageInfo;
+    }
+
+    public BigDecimal getMoney() {
+        return money;
+    }
+
+    public void setMoney(BigDecimal money) {
+        this.money = money;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+}

+ 165 - 0
virgo.api/src/main/java/com/bosshand/virgo/api/workark/service/WxTransferService.java

@@ -0,0 +1,165 @@
+package com.bosshand.virgo.api.workark.service;
+
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.bosshand.virgo.api.workark.config.WxPayConfig;
+import com.bosshand.virgo.api.workark.dao.ProceDao;
+import com.bosshand.virgo.api.workark.dao.TransferInfoDao;
+import com.bosshand.virgo.api.workark.model.TransferInfo;
+import com.bosshand.virgo.api.workark.util.OrderNoUtils;
+import com.bosshand.virgo.core.utils.ContextUtils;
+import com.bosshand.virgo.exception.ServiceException;
+import com.wechat.pay.java.core.RSAAutoCertificateConfig;
+import com.wechat.pay.java.core.http.*;
+import okhttp3.OkHttpClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.HashMap;
+
+@Service
+public class WxTransferService {
+
+    @Resource
+    private WxPayConfig wxPayConfig;
+
+    @Autowired
+    ProceDao proceDao;
+
+    @Autowired
+    TransferInfoDao transferInfoDao;
+
+    public String transfer(String openId, BigDecimal money) {
+
+        long userId = ContextUtils.getUserContext().getUserId();
+
+        TransferInfo transferInfo = new TransferInfo();
+        transferInfo.setOpenId(openId);
+        transferInfo.setUserId(userId);
+        transferInfo.setMoney(money);
+
+        OkHttpClient okHttpClient = new OkHttpClient();
+        HttpClient httpClient = new DefaultHttpClientBuilder()
+                .config(rsaAutoCertificateConfig())
+                .okHttpClient(okHttpClient)
+                .build();
+        HttpHeaders headers = new HttpHeaders();
+        headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
+        headers.addHeader("Content-Type", MediaType.APPLICATION_JSON.getValue());
+        headers.addHeader("Wechatpay-Serial", wxPayConfig.getMchSerialNo());
+
+        HashMap<Object, Object> map = new HashMap<>();
+        //小程序 appId
+        map.put("appid", wxPayConfig.getAppid());
+        String orderNo = OrderNoUtils.getTransferNo();
+
+        transferInfo.setTransferBillNo(orderNo);
+
+        // 订单编号
+        map.put("out_bill_no", orderNo);
+        // 转账场景ID
+        map.put("transfer_scene_id", "1000");
+        // openid
+        map.put("openid", openId);
+
+        // 元 转换 分
+        BigDecimal multiplier = new BigDecimal("100");
+        // 使用multiply方法乘以100
+        BigDecimal result = money.multiply(multiplier);
+
+        // 金额(分)
+        map.put("transfer_amount", result.intValue());
+        // 转账备注
+        map.put("transfer_remark", "佣金提现: " + orderNo);
+        //回调地址: 商家转账回调地址
+        map.put("notify_url", "");
+        // 用户收款感知
+        map.put("user_recv_perception", "佣金奖励");
+        // 转账场景报备信息
+        JSONArray jsonArray = new JSONArray();
+        jsonArray.add(new JSONObject().fluentPut("info_type", "活动名称").fluentPut("info_content", "邀请新用户"));
+        jsonArray.add(new JSONObject().fluentPut("info_type", "奖励说明").fluentPut("info_content", "佣金提现"));
+        map.put("transfer_scene_report_infos", jsonArray);
+
+        JsonRequestBody build = new JsonRequestBody.Builder()
+                .body(JSONUtil.toJsonStr(map))
+                .build();
+        HttpRequest executeSendGetHttpRequest = new HttpRequest.Builder()
+                .httpMethod(HttpMethod.POST)
+                .url("https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills")
+                .headers(headers)
+                .body(build)
+                .build();
+        try {
+            HttpResponse<JSONObject> execute = httpClient.execute(executeSendGetHttpRequest, JSONObject.class);
+            JSONObject responseBody = execute.getServiceResponse();
+
+            String packageInfo = responseBody.getString("package_info");
+            String transferBillNo = responseBody.getString("transfer_bill_no");
+
+            transferInfo.setTransferBillNo(transferBillNo);
+            transferInfo.setPackageInfo(packageInfo);
+            transferInfoDao.save(transferInfo);
+
+            return packageInfo;
+        } catch (ServiceException e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private RSAAutoCertificateConfig rsaAutoCertificateConfig() {
+        return new RSAAutoCertificateConfig.Builder()
+                .merchantId(wxPayConfig.getMchId())
+                .privateKey(wxPayConfig.getFileContent(wxPayConfig.getPrivateKeyPath()))
+                .merchantSerialNumber(wxPayConfig.getMchSerialNo())
+                .apiV3Key(wxPayConfig.getApiV3Key())
+                .build();
+    }
+
+    public String transferOutBillNo(String outBillNo) {
+        OkHttpClient okHttpClient = new OkHttpClient();
+        HttpClient httpClient = new DefaultHttpClientBuilder()
+                .config(rsaAutoCertificateConfig())
+                .okHttpClient(okHttpClient)
+                .build();
+        HttpHeaders headers = new HttpHeaders();
+        headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
+        headers.addHeader("Content-Type", MediaType.APPLICATION_JSON.getValue());
+        headers.addHeader("Wechatpay-Serial", wxPayConfig.getMchSerialNo());
+
+        HttpRequest executeSendGetHttpRequest = new HttpRequest.Builder()
+                .httpMethod(HttpMethod.GET)
+                .url("https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/" + outBillNo)
+                .headers(headers)
+                .build();
+        try {
+            HttpResponse<JSONObject> execute = httpClient.execute(executeSendGetHttpRequest, JSONObject.class);
+            JSONObject responseBody = execute.getServiceResponse();
+
+            String state = responseBody.getString("state");
+
+            if("SUCCESS".equals(state)){
+                TransferInfo outBillNo1 = transferInfoDao.getOutBillNo(outBillNo);
+                outBillNo1.setState(state);
+                transferInfoDao.update(outBillNo1);
+            }
+            return state;
+        } catch (ServiceException e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public void update(TransferInfo transferInfo) {
+        transferInfoDao.update(transferInfo);
+    }
+
+}

+ 8 - 0
virgo.api/src/main/java/com/bosshand/virgo/api/workark/util/OrderNoUtils.java

@@ -28,6 +28,14 @@ public class OrderNoUtils {
         return "REFUND_" + getNo();
     }
 
+    /**
+     * 获取转账单编号
+     * @return
+     */
+    public static String getTransferNo() {
+        return "TRANSFER_" + getNo();
+    }
+
     /**
      * 获取编号
      * @return

+ 42 - 0
virgo.api/src/main/resources/mapper/TransferInfoMapper.xml

@@ -0,0 +1,42 @@
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.bosshand.virgo.api.workark.dao.TransferInfoDao">
+
+    <resultMap type="com.bosshand.virgo.api.workark.model.TransferInfo" id="result">
+        <id column="id" property="id"/>
+        <result column="openId" property="openId"/>
+        <result column="userId" property="userId"/>
+        <result column="createTime" property="createTime"/>
+        <result column="updateTime" property="updateTime"/>
+        <result column="outBillNo" property="outBillNo"/>
+        <result column="transferBillNo" property="transferBillNo"/>
+        <result column="packageInfo" property="packageInfo"/>
+        <result column="money" property="money"/>
+        <result column="state" property="state"/>
+    </resultMap>
+
+    <select id="getOutBillNo" resultMap="result">
+        select * from workark_transferInfo where outBillNo = #{outBillNo}
+    </select>
+
+    <select id="getUserId" resultMap="result">
+        select * from workark_transferInfo where userId = #{userId}
+    </select>
+
+    <insert id="save" useGeneratedKeys="true" keyProperty="id">
+        INSERT INTO workark_transferInfo (createTime, openId, userId, outBillNo, transferBillNo, packageInfo, money, state) VALUES
+            (now(), #{openId}, #{userId}, #{outBillNo}, #{transferBillNo}, #{packageInfo}, #{money}, #{state})
+    </insert>
+
+    <update id="update" parameterType="com.bosshand.virgo.api.workark.model.TransferInfo">
+        UPDATE workark_transferInfo
+        <trim prefix="set" suffixOverrides=",">
+            <if test="state!=null">state=#{state},</if>
+            <if test="updateTime==null">updateTime=now(),</if>
+        </trim>
+        WHERE id=#{id}
+    </update>
+
+</mapper>