【SpringBoot学习】50、SpringBoot 集成 wxJava 微信公众号:订单支付

SpringBoot 集成 wxJava 微信公众号:订单支付

从上一篇文章的集成【SpringBoot 学习】49、SpringBoot 集成 wxJava 微信公众号:授权登录
, 已经整合好了基本配置,这里直接增加支付相关配置即可

1、SpringBoot 集成 wxjava 公众号支付

        <!-- 微信支付 -->
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-pay</artifactId>
            <version>4.4.0</version>
        </dependency>

配置文件

# 微信配置
wx:
  # 公众号配置
  mp:
    configs:
      - appid:
        secret:
        token: #微信小程序消息服务器配置的token
        aesKey: #微信小程序消息服务器配置的EncodingAESKey
        msgDataFormat: JSON
  # 支付配置
  pay:
    appId:
    mchId:
    mchKey:
    keyPath: cert/apiclient_cert.p12
    notifyUrl: ${business.serviceUrl}/au/orderInfo/notifyUrl

wxjava 属性配置

package com.ruoyi.business.appuser.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * wxpay pay properties.
 *
 * @author Binary Wang
 */
@Data
@ConfigurationProperties(prefix = "wx.pay")
public class WxPayProperties {
  /**
   * 设置微信公众号或者小程序等的appid
   */
  private String appId;

  /**
   * 微信支付商户号
   */
  private String mchId;

  /**
   * 微信支付商户密钥
   */
  private String mchKey;

  /**
   * 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除
   */
  private String subAppId;

  /**
   * 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除
   */
  private String subMchId;

  /**
   * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
   */
  private String keyPath;

  /**
   * 支付回调
   */
  private String notifyUrl;
}


wxjava 支付配置

package com.ruoyi.business.appuser.config;

import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Binary Wang
 */
@Configuration
@ConditionalOnClass(WxPayService.class)
@EnableConfigurationProperties(WxPayProperties.class)
@AllArgsConstructor
public class WxPayConfiguration {
  private WxPayProperties properties;

  @Bean
  @ConditionalOnMissingBean
  public WxPayService wxService() {
    WxPayConfig payConfig = new WxPayConfig();
    payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
    payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
    payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
    payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
    payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
    payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));

    // 可以指定是否使用沙箱环境
    payConfig.setUseSandboxEnv(false);

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

}


下单接口

    @ApiOperation("创建订单")
    @RepeatSubmit
    @PostMapping("createOrder")
    public AjaxResult createOrder(@Validated @RequestBody TOrderInfoVo entity) {
        return weiXinPayService.createOrder(entity);
    }

    @ApiOperation("支付回调")
    @RequestMapping("notifyUrl")
    public String notifyUrl() {
        return weiXinPayService.notifyUrl();
    }

service 接口

package com.ruoyi.business.appuser.service;

import com.ruoyi.business.vo.TOrderInfoVo;
import com.ruoyi.common.core.domain.AjaxResult;

/**
 * @author Tellsea
 * @date 2022/8/17
 */
public interface WeiXinPayService {

    /**
     * 统一下单
     *
     * @param entity
     * @return
     */
    AjaxResult createOrder(TOrderInfoVo entity);

    /**
     * 支付回调
     *
     * @return
     */
    String notifyUrl();

}

实现类

/**
 * @author Tellsea
 * @date 2022/8/17
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class WeiXinPayServiceImpl implements WeiXinPayService {

    private final WxMpService wxMpService;
    private final WxPayService wxPayService;
    private final WxPayProperties wxPayProperties;
    private final BusinessProperties businessProperties;

    @Override
    @Transactional
    public AjaxResult createOrder(TOrderInfoVo entity) {
        try {
            String openId = SecurityUtils.getLoginUser().getUser().getUserName();
            WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
            orderRequest.setSignType(WxPayConstants.SignType.MD5);
            orderRequest.setBody("请求支付订单");
            orderRequest.setOutTradeNo(entity.getOrderNumber());
            orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
            orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(String.valueOf(entity.getPayMoney())));
            orderRequest.setOpenid(openId);
            orderRequest.setSpbillCreateIp(ServletUtil.getClientIP(ServletUtils.getRequest()));
            orderRequest.setNotifyUrl(wxPayProperties.getNotifyUrl());
            Object order = wxPayService.createOrder(orderRequest);
            WxJsapiSignature jsapiSignature = wxMpService.createJsapiSignature(entity.getUrl());
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("order", order);
            jsonObject.put("jsapiSignature", jsapiSignature);
            jsonObject.put("orderId", entity.getId());
            log.info("下单成功:{}", JSONObject.toJSONString(jsonObject));
            return AjaxResult.success("下单成功", jsonObject);
        } catch (WxPayException e) {
            e.printStackTrace();
            log.error("下单失败:{}", e.toString());
            return AjaxResult.error(e.getMessage());
        } catch (WxErrorException e) {
            e.printStackTrace();
            log.error("下单失败:{}", e.toString());
            return AjaxResult.error(e.getMessage());
        }
    }

    @Override
    public String notifyUrl() {
        try {
            HttpServletRequest request = ServletUtils.getRequest();
            HttpServletResponse response = ServletUtils.getResponse();
            String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
            WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlResult);
            log.info("订单支付回调:{}", result);
            // 加入自己处理订单的业务逻辑,需要判断订单是否已经支付过,否则可能会重复调用
            String outTradeNo = result.getOutTradeNo();
            String transactionId = result.getTransactionId();
            String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
            return WxPayNotifyResponse.success("支付成功");
        } catch (Exception e) {
            log.error("微信回调结果异常,异常原因{}", e.getMessage());
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }
}

2、Uniapp 用户端

安装 jweixin,因为 wx.config 已经被 uniapp 底层占用了,所以这里需要自己引入一个其他名称

npm install jweixin-module --save

完整流程

<script>
const jweixin = require('jweixin-module');
let that;
export default {
  data() {
    return {
      baseUrl: this.$config.baseUrl,
      // 下单参数
      orderInfo: {
        payMoney: 0,
        storeId: 0,
        userAddressId: 0,
        orderDetailJson: '',
        orderRemark: '',
        url: window.location.href.split('#')[0],
      }
    }
  },
  methods: {
    // 创建订单
    submit() {
      uni.showLoading({
        title: '下单中...'
      });
      uni.$u.http.post('/au/orderInfo/createOrder', that.orderInfo).then(res => {
        let config = res.data.jsapiSignature;
        let data = res.data.order;
        let orderId = res.data.orderId;
        jweixin.config({
          debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
          appId: config.appId, // 必填,公众号的唯一标识
          nonceStr: config.nonceStr, // 必填,生成签名的随机串
          signature: config.signature, // 必填,签名
          timestamp: config.timestamp, // 必填,生成签名的时间戳
          jsApiList: ['checkJsApi', 'chooseWXPay'] // 必填,需要使用的JS接口列表
        });
        jweixin.ready(() => {
          jweixin.checkJsApi({
            jsApiList: ['chooseWXPay'],
            success(res) {
              uni.hideLoading();
              jweixin.chooseWXPay({
                appId: data.appId,
                nonceStr: data.nonceStr, // 必填,生成签名的随机串
                package: data.packageValue,
                paySign: data.paySign, // 必填,签名
                signType: data.signType,
                timestamp: data.timeStamp, // 必填,生成签名的时间戳
                success(res) {
                  that.$msg('支付成功');
                  console.log('支付成功: ' + JSON.stringify(res));
                  uni.removeStorageSync(that.$config.cachePrefix + 'cart-' + uni.getStorageSync(that.$config.cachePrefix + 'storeId'));
                  uni.$u.route({url: '/pages/order/detail', params: {id: orderId}});
                },
                cancel(res) {
                  that.$msg('取消支付');
                  console.log('取消支付' + JSON.stringify(res));
                  uni.$u.route({url: '/pages/order/detail', params: {id: orderId}});
                },
                fail(res) {
                  that.$msg('支付失败');
                  console.log('支付失败: ' + JSON.stringify(res));
                },
                // success:接口调用成功时执行的回调函数。
                // fail:接口调用失败时执行的回调函数。
                // complete:接口调用完成时执行的回调函数,无论成功或失败都会执行。
                // cancel:用户点击取消时的回调函数,仅部分有用户取消操作的api才会用到。
                // trigger: 监听Menu中的按钮点击时触发的方法,该方法仅支持Menu中的相关接口。
              })
            },
            fail(res) {
              that.$msg('检查API失败');
              console.log('检查API失败: ' + JSON.stringify(res));
            }
          });
        });
        jweixin.error(err => {
          // that.$msg('支付错误:' + JSON.stringify(err));
        });
      });
    },
    toCategory() {
      uni.$u.route({type: 'tab', url: '/pages/category/category'});
    },
    toAddress() {
      uni.$u.route({url: '/pages/my/address/list'});
    },
  }
}
</script>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tellsea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值