自学内容网 自学内容网

微信小程序接入微信支付

微信小程序接入微信支付(代码部分)

准备

准备微信小程序

哈哈哈哈哈哈哈哈哈,这是废话,接着往下看

开通微信商户号,并和小程序绑定

具体可以看官方进行操作

微信支付->官方指引-接入前准备

最终会得到下面几个参数:

参数解释
mchId商户号:开通商户就有的参数
mchSerialNo证书序列号
apiKeyapiKey
keyPath存放证书的电脑位置地址

这里把参数都丢到实体类里面

@Data
@ToString
@Component
// 这里读取配置文件(application.yml)wx-app 前缀的参数
@ConfigurationProperties(prefix = "wx-app")
public class PayInfoConfig {
    //小程序appid
    private String appId;
    //小程序秘钥
    private String appSecret;
    //商户号
    private String mchId;
    //证书序列号
    private String mchSerialNo;
    // api秘钥
    private String apiKey;
    // 回调接口地址
    private String notifyUrl;
    // 证书地址
    private String keyPath;
    // 退款回调地址
    private String refundNotifyUrl;

}

支付流程

微信官方支付时序流程图
在这里插入图片描述

服务器端

建立商户系统相关 订单表

CREATE TABLE `order`  (
      `order_id` bigint(20) NOT NULL AUTO_INCREMENT,
      `order_number` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '订单编号',
      `user_id` bigint(20) NOT NULL COMMENT '用户ID',
      `order_status` tinyint(4) NOT NULL COMMENT '订单状态',
      `total_amount` decimal(12, 2) NOT NULL COMMENT '订单总金额',
      `discount_amount` decimal(12, 2) NULL DEFAULT 0.00 COMMENT '优惠金额',
      `payable_amount` decimal(12, 2) NOT NULL COMMENT '应付金额',
      `payment_method` tinyint(4) NULL DEFAULT NULL COMMENT '支付方式',
      `payment_status` tinyint(4) NULL DEFAULT NULL COMMENT '支付状态',
      `payment_time` datetime NULL DEFAULT NULL COMMENT '支付时间',
      `shipping_company` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '物流公司',
      `tracking_number` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '物流单号',
      `shipping_time` datetime NULL DEFAULT NULL COMMENT '发货时间',
      `delivery_time` datetime NULL DEFAULT NULL COMMENT '收货时间',
      `receiver_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '收货人姓名',
      `receiver_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '收货人电话',
      `receiver_address` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收货地址',
      `order_note` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '订单备注',
      `order_source` tinyint(4) NULL DEFAULT NULL COMMENT '订单来源',
      `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
      `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
      `is_deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除',
      PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '订单表' ROW_FORMAT = Dynamic;


CREATE TABLE `order_item`  (
   `order_item_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单明细ID',
   `order_id` bigint(20) NOT NULL COMMENT '订单ID',
   `product_id` bigint(20) NOT NULL COMMENT '商品ID',
   `product_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品名称',
   `product_image` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商品图片',
   `unit_price` decimal(12, 2) NOT NULL COMMENT '商品单价',
   `quantity` int(11) NOT NULL COMMENT '购买数量',
   `subtotal_amount` decimal(12, 2) NOT NULL COMMENT '小计金额',
   `after_sale_status` tinyint(4) NULL DEFAULT NULL COMMENT '售后状态',
   PRIMARY KEY (`order_item_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '订单明细表' ROW_FORMAT = Dynamic;

对应表的相关CRUD代码

自己使用代码生成器生成

引入支付相关Maven包

<!--    微信支付相关  -->
        <dependency>
            <groupId>com.github.wechatpay-apiv3</groupId>
            <artifactId>wechatpay-java</artifactId>
            <version>0.2.14</version>
        </dependency>

步骤三

生成商户系统平台订单,并请求微信下单接口,生成预付单

// Controller 下单接口
    @PostMapping("/payment")
    public AjaxResult payment(@RequestBody PaymentRequestVo vo) {
// ...          
// 创建订单
        SysOrder order = orderService.createOrder(vo,userId);
    
    String openId = user.getOpenId();
    
        // 发送请求下单接口
        Map<String, Object> result = service.payment(order.getPayableAmount().intValue(), order.getOrderNumber(), openId,vo.getProductName());
        return AjaxResult.success(result);
    }
    /**
     *
     * @author morris
     * @date 2024/10/16 9:47
     * 调起支付
     *
     */
    public static Map<String, Object> payment(Integer price, String orderId, String userId,String desc){
        JsapiService service = getService();  // 构建支付请求SERVICE
        PrepayRequest prepayRequest = buildParam(price, orderId, userId,desc); // 构建支付请求参数
        PrepayResponse response = service.prepay(prepayRequest); // 向微信请求下单并返回结果
        Map<String, Object> result = parsePay(response); // 解析支付结果
        result.put("orderId",orderId);
        return result;
    }

    /**
     *
     * @author morris
     * @date 2024/10/16 9:35
     * 构建支付请求SERVICE
     *
     */
    public static JsapiService getService(){
        PayInfoConfig payInfoConfig = getConfig();
        Config config = new RSAAutoCertificateConfig.Builder()
                .merchantId(payInfoConfig.getMchId())
                .privateKeyFromPath(payInfoConfig.getKeyPath())
                .merchantSerialNumber(payInfoConfig.getMchSerialNo())
                .apiV3Key(payInfoConfig.getApiKey())
                .build();
        JsapiService service = new JsapiService.Builder().config(config).build();
        return service;
    }

/**
     *
     * @author morris
     * @date 2024/10/16 9:35
     * 构建支付请求参数
     *
     */
    private static PrepayRequest buildParam(Integer price, String orderId, String openId ,String desc){
        PayInfoConfig payInfoConfig = getConfig();
        PrepayRequest prepayRequest = new PrepayRequest();
        Amount amount = new Amount();
        // 微信收款是以分位单位
        BigDecimal multiply = BigDecimal.valueOf(price);
        amount.setTotal(multiply.intValue());
        prepayRequest.setAmount(amount);
        prepayRequest.setAppid(payInfoConfig.getAppId());
        prepayRequest.setMchid(payInfoConfig.getMchId());
        prepayRequest.setNotifyUrl(payInfoConfig.getNotifyUrl());// 回调接口地址
        prepayRequest.setDescription(desc);
        prepayRequest.setOutTradeNo(orderId);       // 订单号
        prepayRequest.setAttach("activity");        // 订单类型(回调时可根据这个数据辨别订单类型或其他)

        //根据下单用户拿到openid,指定该预支付订单的支付者身份
        Payer payer = new Payer();
        payer.setOpenid(openId);
        prepayRequest.setPayer(payer);
        return prepayRequest;
    }

/**
     *
     * @author morris
     * @date 2024/10/16 9:53
     * 解析支付结果
     *
     */
    private static Map<String,Object> parsePay(PrepayResponse response){
        PayInfoConfig payInfoConfig = getConfig();
        Map<String, Object> params = new HashMap<>();
        Long timeStamp = System.currentTimeMillis() / 1000;
        String substring = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
        String signatureStr = Stream.of(
                payInfoConfig.getAppId(),
                String.valueOf(timeStamp),
                substring,
                "prepay_id=" + response.getPrepayId()
        ).collect(Collectors.joining("\n", "", "\n"));
        String sign = getSign(signatureStr, payInfoConfig.getKeyPath());
        params.put("timeStamp", String.valueOf(timeStamp));
        params.put("nonceStr", substring);
        params.put("paySign", sign);
        params.put("signType", "RSA");
        params.put("package", "prepay_id=" + response.getPrepayId());
        return params;
    }

小程序端

根据服务器返回的参数,拉起微信支付

const params = {...}
payment(params).then(res => {
if(res.code === 200){
// 加载弹窗隐藏
  uni.hideLoading();
   data.orderNum = res.data.orderId
   // 这里则是拉起微信支付,需要支付密码那个界面了
   wx.requestPayment({
  'timeStamp':  res.data.timeStamp,
  'nonceStr':  res.data.nonceStr,
  'package':  res.data.package,
  'signType': res.data.signType,
  'paySign': res.data.paySign,
  'success': function (res) {
// 支付成功的回调
console.log("支付成功:",res)
that.entryPxo(data)
  },
  'fail': function (res) {
console.log(JSON.stringify(res));
wx.showToast({title: '支付失败', icon: 'none',duration: 2000,mask: true})
  }
})
}
}).catch(res => {

}).finally(res => {
uni.hideLoading()
this.isSubmitting = false
})

支付完成后,微信会有回调商户系统,也就是提供的那个回调地址

回调处理

    /**
     *
     * @author morris
     * @date 2024/10/15 16:57
     * 微信支付回调
     *
     */
    @Anonymous
    @PostMapping("/payNotify")
    public void payNotify(HttpServletRequest request) throws Exception {
        service.payNotify(request);
    }

    /**
     * 退款回调通知
     * @param request
     * @throws Exception
     */
    @Anonymous
    @PostMapping("/refundNotify")
    public void refundNotify(HttpServletRequest request) throws Exception {
        service.refundNotify(request);
    }


 /**
     *
     * @author morris
     * @date 2024/10/16 11:03
     * 支付回调处理
     * 1.更新订单状态
     *
     */
    public Map<String,Object> updateAccountDetail(Transaction parse, boolean active) {
        String orderId = parse.getOutTradeNo();
        Transaction.TradeStateEnum tradeState = parse.getTradeState();
        if(tradeState==Transaction.TradeStateEnum.SUCCESS) {
            System.out.println("支付成功");
            String outTradeNo = parse.getOutTradeNo();

            SysOrder order = orderMapper.selectSysOrderByOrderNum(outTradeNo);
            order.setOrderStatus(1);
            order.setPaymentStatus(1);
            order.setPaymentTime(DateUtils.getNowDate());

            orderMapper.updateSysOrder(order);
        }
        if(active){
            return JSON.parseObject(buildParse(parse),Map.class);
        }else{
//            this.payNoticeMessage(parse,orderId);
        }
        return null;
    }

至此,完成微信支付开发


原文地址:https://blog.csdn.net/weixin_40864434/article/details/143052823

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!