SpringBoot整合微信APP支付

如果你不相信努力和时光,那么成果就会是第一个选择辜负你的。不要去否定你自己的过去,也不要用你的过去牵扯你现在的努力和对未来的展望。不是因为拥有希望你才去努力,而是去努力了,你才有可能看到希望的光芒。SpringBoot整合微信APP支付,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

废话不多说,先上代码

  • application-dev.yml
#支付
pay:
  # 支付回调通知地址
  notifyUrl: 别想C 填自己的
  #  微信App支付
  weChat: 别想C 填自己的
    # 微信支付AppID
    applyAppId: 别想C 填自己的
    # 微信支付商户号
    mchId: 别想C 填自己的
    # 微信支付API密钥
    apiV3Key: 别想C 填自己的
    # 微信支付证书序列号
    mchSerialNo: 别想C 填自己的
    # 微信支付证书私钥路径 ssl
    privateKeyPath: C:\Users\dzx\Desktop\yiNong\ssl\apiclient_key.pem
    # 微信支付接口域名地址
    domain: https://api.mch.weixin.qq.com
  • QuickStart
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

/**
 * APP 支付
 */
@Configuration
@Data
public class QuickStart {
    /**
     * applyAppId
     */
    @Value("${pay.weChat.applyAppId}")
    private String appid;
    /**
     * 商户号
     */
    @Value("${pay.weChat.mchId}")
    private String merchantId;
    /**
     * 商户API私钥路径
     */
    @Value("${pay.weChat.privateKeyPath}")
    private String privateKeyPath;
    /**
     * 商户证书序列号
     */
    @Value("${pay.weChat.mchSerialNo}")
    private String merchantSerialNumber;
    /**
     * 商户APIV3密钥
     */
    @Value("${pay.weChat.apiV3Key}")
    private String apiV3Key;

    @Value("${pay.notifyUrl}")
    private String notifyUrl;
}
  • 接收数据的实体
    Resource
import lombok.Data;

@Data
public class Resource {
    private String algorithm;
    private String ciphertext;
    private String associated_data;
    private String original_type;
    private String nonce;
}

PayNotifyParams

import lombok.Data;

@Data
public class PayNotifyParams {
    private String id;
    private String create_time;
    private String event_type;
    private String resource_type;
    private Resource resource;
    private String summary;
}

上业务代码

  • WeChatService
import com.ynjs.common.pay.weChat.app.PayNotifyParams;

import java.util.Map;

public interface WeChatService {
    /**
     * 调用统一下单API
     *
     * @param orderId
     * @return
     * @throws Exception
     */
    String appPay(String orderId) throws Exception;

    /**
     * 支付成功通知
     *
     * @param payNotifyParams
     * @return
     */
    Map<String, String> payNotify(PayNotifyParams payNotifyParams);

}
  • WeChatServiceImpl
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.app.AppServiceExtension;
import com.wechat.pay.java.service.payments.app.model.Amount;
import com.wechat.pay.java.service.payments.app.model.PrepayRequest;
import com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse;
import com.ynjs.common.exception.CustomException;
import com.ynjs.common.pay.weChat.app.PayNotifyParams;
import com.ynjs.common.pay.weChat.app.QuickStart;
import com.ynjs.mapper.CrmUserOrderMapper;
import com.ynjs.mapper.DevIotClusterMapper;
import com.ynjs.pojo.CrmUserOrder;
import com.ynjs.pojo.DevIotCluster;
import com.ynjs.service.WeChatService;
import lombok.extern.log4j.Log4j2;
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.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.GeneralSecurityException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


@Log4j2
@Service
public class WeChatServiceImpl implements WeChatService {
    @Resource
    private CrmUserOrderMapper crmUserOrderMapper;
    @Resource
    private QuickStart quickStart;
    @Resource
    private CloseableHttpClient httpClient;
    @Resource
    private DevIotClusterMapper devIotClusterMapper;

    /**
     * 支付成功通知
     *
     * @param orderId
     * @return
     */
    public String appPay(String orderId) {
        if (StrUtil.isBlank(orderId)) {
            throw new CustomException("订单不能为空");
        }
        CrmUserOrder cuo = crmUserOrderMapper.getUsOrderInfo(orderId);
        if (Objects.isNull(cuo)) {
            throw new CustomException("找不到该订单!");
        }
        CrmUserOrder crmUserOrder = crmUserOrderMapper.finishOrder(orderId);
        Integer payState = crmUserOrder.getPAY_STATE();
        if (payState == 1) {
            throw new CustomException("该订单已支付,请勿重复支付");
        }
        // 使用自动更新平台证书的RSA配置
        // 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
        Config config = new RSAAutoCertificateConfig.Builder()
                .merchantId(quickStart.getMerchantId())
                .privateKeyFromPath(quickStart.getPrivateKeyPath())
                .merchantSerialNumber(quickStart.getMerchantSerialNumber())
                .apiV3Key(quickStart.getApiV3Key())
                .build();
        // 构建service
        AppServiceExtension service = new AppServiceExtension.Builder().config(config).build();
        // request.setXxx(val)设置所需参数,具体参数可见Request定义
        PrepayRequest request = new PrepayRequest();
        BigDecimal payAmount = cuo.getPAY_AMOUNT();
        BigDecimal multiply = payAmount.multiply(new BigDecimal("100")); //乘
        Amount amount = new Amount();
        amount.setTotal(multiply.intValue());    // 金额(以分为单位)
        amount.setCurrency("CNY");
        request.setAmount(amount);
        request.setAppid(quickStart.getAppid());
        request.setMchid(quickStart.getMerchantId());
        request.setDescription("渔浪浪平台充值");
        request.setAttach(crmUserOrder.getIOT_CODE() + "-" + cuo.getRECHARGE());
        request.setNotifyUrl(quickStart.getNotifyUrl() + "/api/appapi/WeChatAppNotify");
        request.setOutTradeNo(orderId);
        // 调用下单方法,得到应答
        PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
        response.getNonceStr();
        Gson gson = new Gson();
        return gson.toJson(response);
    }

    /**
     * 支付成功后回调通知
     *
     * @return
     */
    public Map<String, String> payNotify(PayNotifyParams payNotifyParams) {
        Map<String, String> res = new HashMap<>();
        try {
            String json = new AesUtil(quickStart.getApiV3Key().getBytes()).decryptToString(
                    payNotifyParams.getResource().getAssociated_data().getBytes(),
                    payNotifyParams.getResource().getNonce().getBytes(),
                    payNotifyParams.getResource().getCiphertext());
            String outTradeNo = JSON.parseObject(json, Map.class).get("out_trade_no").toString();
            String attach = JSON.parseObject(json, Map.class).get("attach").toString();
            String amount = JSON.parseObject(json, Map.class).get("amount").toString();
            String total = JSON.parseObject(amount, Map.class).get("total").toString();
            // 金额单位为分
            BigDecimal totalBig = new BigDecimal(total);
            LocalDateTime now = LocalDateTime.now();
            CrmUserOrder cuo = new CrmUserOrder();
            cuo.setOutTradeNo(outTradeNo);
            cuo.setTransactionId(JSON.parseObject(json, Map.class).get("transaction_id").toString());
            cuo.setCashFee(totalBig.divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP));
            cuo.setPAY_STATE(1);
            cuo.setORDER_ID(outTradeNo);
            cuo.setMEAL_EX(attach);
            cuo.setROW_DATE_UPDATE(now);
            int update = crmUserOrderMapper.UpdateOrder(cuo);
            if (update > 0) {
                CrmUserOrder order = crmUserOrderMapper.finishOrder(outTradeNo);
                Integer recharge = order.getRECHARGE();// 充值天数
                String iotCode = order.getIOT_CODE(); // 充值的SN设备
                DevIotCluster cluster = devIotClusterMapper.getCluster(iotCode);
                Duration duration = Duration.between(now, cluster.getDUE_DATE());
                long days = duration.toDays();
                if (days < 0) {
                    days = 0;
                }
                LocalDateTime timestamp = now.plusDays(recharge + days + 1);
                DevIotCluster dic = new DevIotCluster();
                dic.setDUE_DATE(timestamp);
                dic.setIOT_CODE(iotCode);
                dic.setROW_DATE_UPDATE(now);
                int 充值结果 = devIotClusterMapper.upByIotCode(dic);
                if (充值结果 > 0) {
                    res.put("code", JSON.parseObject(json, Map.class).get("trade_state").toString());
                    res.put("message", JSON.parseObject(json, Map.class).get("trade_state_desc").toString());
                }
            }
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
            res.put("code", "FAIL");
            res.put("message", "失败");
        }
        return res;
    }

    /**
     * 商户订单号查询订单
     *
     * @throws Exception
     */
    public void queryOrder(String orderId) throws Exception {
        //请求URL
        URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + orderId);
        uriBuilder.setParameter("mchid", quickStart.getMerchantId());
        //完成签名并执行请求
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        httpGet.addHeader("Accept", "application/json");
        CloseableHttpResponse response = httpClient.execute(httpGet);
        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
            } else if (statusCode == 204) {
                System.out.println("success");
            } else {
                System.out.println("failed,resp code = " + statusCode + ",return body = " + EntityUtils.toString(response.getEntity()));
                throw new IOException("request failed");
            }
        } finally {
            response.close();
        }
    }

    /**
     * 关闭订单
     *
     * @throws Exception
     */
    public void closeOrder(String orderId) throws Exception {
        //请求URL
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + orderId + "/close");
        //请求body参数
        String reqdata = "{\"mchid\": \"" + quickStart.getMerchantId() + "\"}";
        StringEntity entity = new StringEntity(reqdata, "utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");
        //完成签名并执行请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
            } else if (statusCode == 204) {
                System.out.println("success");
            } else {
                System.out.println("failed,resp code = " + statusCode + ",return body = " + EntityUtils.toString(response.getEntity()));
                throw new IOException("request failed");
            }
        } finally {
            response.close();
        }
    }
}

import com.ynjs.common.pay.weChat.app.PayNotifyParams;
import com.ynjs.common.result.Result;
import com.ynjs.service.WeChatService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@Log4j2
@RestController
@RequestMapping("/appapi")
@Api(tags = "WX APP支付")
public class WeChatPayController {
    @Resource
    private WeChatService weChatService;

    /**
     * 微信APP支付 /api/wechat_pay/app/GetAppParams
     *
     * @param orderId
     * @return
     * @throws Exception
     */
    @PostMapping("/GetAppParams")
    @ApiOperation("调用统一下单API")
    public Result AppPay(String orderId) throws Exception {
        //调用微信服务获取App支付参数
        return Result.success(weChatService.appPay(orderId));
    }


    @PostMapping("/WeChatAppNotify")
    @ApiOperation("支付成功通知")
    public Result weChatAppNotify(@RequestBody PayNotifyParams payNotifyParams) {
        return Result.success(weChatService.payNotify(payNotifyParams));
    }
}

建议自己也看看官方文档,光C解决不了小问题。懂的吧

代码随着微信支付的迭代可能会有啥问题,及时评论!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/205596.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!