微信支付(小程序)-java实现与小程序实现

本文档展示了如何在Java中配置微信支付接口,包括获取本地IP的工具类、订单状态和支付方式的Enum枚举、微信支付的表单数据及返回数据。此外,还详细介绍了支付Service和Controller的实现,包括支付回调处理逻辑。小程序调用支付接口的流程也在文中提及。
摘要由CSDN通过智能技术生成

一:java配置

微信支付(小程序)-java配置

二:工具类:获取本地IP与Enum类 与订单支付返回数据

1: 获取本地IP工具类
2:订单 Enum类

package com.io.common.enums;

public enum OrderStatusEnum {
    CANCEL(0,"已取消"),
    NOT_YET_SHIPPED(1,"待支付"),
    PART_OF_THE_SHIPMENT(2,"待发货"),
    WAIT_RECEIVING(3,"待收货"),
    ACHIEVE(4,"已完成"),
    ;
    private Integer key;
    private String desc;

    OrderStatusEnum(Integer key, String desc){
        this.key = key;
        this.desc = desc;
    }

    public Integer getKey() {
        return key;
    }

    public String getDesc() {
        return desc;
    }
}

3:支付方式Enum类

package com.io.common.enums;

public enum PayTypeEnum {

    WX_PAY(1, "微信支付"),

    ;

    private Integer key;
    private String desc;

    PayTypeEnum(Integer key, String desc) {
        this.key = key;
        this.desc = desc;
    }

    public Integer getKey() {
        return key;
    }

    public String getDesc() {
        return desc;
    }

    public static String getDesc(Integer key) {
        for (PayTypeEnum c : PayTypeEnum.values()) {
            if (c.key.equals(key)) {
                return c.getDesc();
            }
        }
        return null;
    }
}

4:微信支付form提交数据

package com.io.order.form;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.math.BigDecimal;

/**
 * @author ts
 * @version 1.0
 * @date 2022/08/05
 */
@Data
public class WxPayForm {

    private Integer orderId;

    @ApiModelProperty("订单号")
    private String orderNo;

    @ApiModelProperty("支付订单号")
    private String orderPayNo;

    @ApiModelProperty("实际支付金额")
    private BigDecimal payAmount;


}

5:微信支付订单返回数据

package com.io.order.vo;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;


@Data
public class AfterPayVO {

    @ApiModelProperty("timeStamp")
    private String timeStamp;

    @ApiModelProperty("nonceStr")
    private String nonceStr;

    @ApiModelProperty("packageValue")
    private String packageValue;

    @ApiModelProperty("signType")
    private String signType;

    @ApiModelProperty("paySign")
    private String paySign;
}

三:service与controller

1:支付 service类

package com.io.order.service;

import com.github.binarywang.wxpay.exception.WxPayException;
import com.io.order.form.WxPayForm;
import com.io.order.vo.AfterPayVO;

import javax.servlet.http.HttpServletResponse;

public interface PayService {

    /**
     * 微信支付
     * @param form 订单数据
     * @param userId // 用户id
     * @param wxId // 微信用户id
     * @return
     * @throws
     */
    AfterPayVO pay(WxPayForm form, String userId,Integer wxId) throws WxPayException;

    /**
     * 微信支付回调
     * @param appid
     * @param xmlData
     * @param response
     * @throws Exception
     */
    void payNotify(String appid, String xmlData, HttpServletResponse response) throws Exception;
}

2:支付 service类实现

package com.io.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.io.common.enums.OrderStatusEnum;
import com.io.common.enums.PayTypeEnum;
import com.io.entity.WxUserEntity;
import com.io.exception.RRException;
import com.io.order.config.WxPayProperties;
import com.io.order.dao.OrderDao;
import com.io.order.entity.OrderEntity;
import com.io.order.form.WxPayForm;
import com.io.order.service.PayService;
import com.io.order.vo.AfterPayVO;
import com.io.order.vo.RefundVO;
import com.io.service.WxUserService;
import com.io.util.ConvertUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.time.LocalDateTime;
import java.util.Objects;

@Service
@Slf4j
public class PayServiceImpl implements PayService {

    @Autowired
    private WxUserService wxUserService;

    @Value("${he.wx.appid}")
    private String wxAppid;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public AfterPayVO pay(WxPayForm form, String userId, Integer wxId) throws WxPayException {
        // 查询根据微信id(存微信用户表的id)查询MySQL数据库获取当前用户的微信数据
        WxUserEntity byId = wxUserService.getById(wxId);
        if (Objects.isNull(byId)){
            log.info("微信支付用户wxId:" + wxId);
            throw new RRException("无该微信用户");
        }
        WxPayService wxPayService = this.getWxPayService(wxAppid);

        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setBody("商品付款");
        orderRequest.setOutTradeNo(form.getOrderPayNo());
        orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(form.getPayAmount().toString()));//元转成分
        orderRequest.setOpenid(byId.getXwOpenId()); // 支付微信用户 微信openId
        orderRequest.setSpbillCreateIp(IpUtils.getAddrIp()); // 本地ip设置
        orderRequest.setSpbillCreateIp("114.55.114.66");
        orderRequest.setNotifyUrl(String.format(properties.getNotifyUrl(), "payNotify", byId.getXwOpenId())); // 支付回调路径与参数拼接设置
        // 支付方式
        orderRequest.setTradeType("JSAPI");

        orderRequest.setAppid(wxAppid);

        Object result = wxPayService.createOrder(orderRequest);
        AfterPayVO afterPayVO = ConvertUtils.sourceToTarget(result, AfterPayVO.class);
        return afterPayVO;
    }

    @Override
    public void payNotify(String appid, String xmlData, HttpServletResponse response) throws Exception {

        WxPayService wxPayService = this.getWxPayService(appid);
        final WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
        log.info("支付订单号:" + notifyResult.getOutTradeNo());

        // 小程序支付成功后回调这个接口 后的订单业务逻辑 (请根据项目来编写)
        LambdaQueryWrapper<OrderEntity> lambdaQueryWrapper =new LambdaQueryWrapper<OrderEntity>();
        lambdaQueryWrapper.eq(OrderEntity::getOrderPayNo,notifyResult.getOutTradeNo());
        OrderEntity orderEntity = orderDao.selectOne(lambdaQueryWrapper);
        //订单状态
        if (OrderStatusEnum.NOT_YET_SHIPPED.getKey().equals(orderEntity.getOrderStatus())){
            orderEntity.setOrderStatus(OrderStatusEnum.PART_OF_THE_SHIPMENT.getKey());
            orderEntity.setPaymentType(PayTypeEnum.WX_PAY.getKey());
            orderEntity.setPaymentTime(LocalDateTime.now());
            orderDao.updateById(orderEntity);
        }

        //回复微信防止重复回调
        StringBuilder resXml = new StringBuilder();
        resXml.append("<xml>");
        resXml.append("<return_code><![CDATA[SUCCESS]]></return_code>");
        resXml.append("<return_msg><![CDATA[OK]]></return_msg>");
        resXml.append("</xml>");
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        out.write(resXml.toString().getBytes());
        out.flush();
        out.close();
    }
    
    /** 获取商户号配置并生成 WxPayService 
     * getWxPayService
     * @param appid
     * @return
     */
    private WxPayService getWxPayService(String appid){
        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(appid);
        payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
        payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
        payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
        // 可以指定是否使用沙箱环境
        payConfig.setUseSandboxEnv(false);

        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        return wxPayService;
    }
}

3: Controller类

package com.io.order.controller;

import com.io.base.BaseController;
import com.io.order.service.PayService;
import com.io.util.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;

@RestController
@RequestMapping("/pay")
@Api(tags = "支付接口")
@Slf4j
public class PayController{

    @Autowired
    private PayService payService;

    @PostMapping("/payNotify/{appid}")
    @ApiOperation("支付回调")
    public R payNotify(@PathVariable String appid, @RequestBody String xmlData, HttpServletResponse response) throws Exception {
        payService.payNotify(appid, xmlData, response);
        return R.ok();
    }

三:小程序调用 支付接口

官方文档:wx.requestPayment

注:res.data.purchase  是先走下单逻辑(去后台下单并且调用了 支付接口)
返回参数: AfterPayVO;
小程序前端所用到的参数是 订单支付返回的参数
wx.requestPayment({
  timeStamp: res.data.purchase.timeStamp,
  nonceStr: res.data.purchase.nonceStr,
  package: res.data.purchase.packageValue,
  signType: 'MD5',
  paySign: res.data.purchase.paySign,
  success (res) {
    支付成功
  },
  fail (res) {
    支付取消或失败
  }
})

2: 开发工具中测试支付接口 所展示的样子
在这里插入图片描述
3:正式环境样式

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值