【电商支付项目(三)】(微信vs支付宝)支付系统开发

一、理论(重要)

如何学好支付:
1、熟悉理论
2、官方文档(微信支付支付宝

1、支付场景

在这里插入图片描述
在这里插入图片描述

2、支付理论

在这里插入图片描述
在这里插入图片描述

同步vs异步

同步:打电话给女神,约吃饭
异步:发微信给女神,约吃饭 -> 不会立即响应 (MQ来实现)

支付结果以异步为准

支付 -> 独立系统 -> 新建java项目、专用数据库/表

核心是数据,只有支付系统才可以操作支付的数据

支付系统和业务系统(仓库、mall、活动)解耦

在这里插入图片描述

区分get请求和跳转

get:获得源码 -> postman
跳转:跳转到浏览器呈现的页面

二、代码

1、新建项目

之前的配置同mall
在这里插入图片描述

postman 下载及使用
支付SDK:https://github.com/Pay-Group/best-pay-sdk
在这里插入图片描述

2、支付接口及实现

1、接口IPayService
在这里插入图片描述
2、接口实现类PayService -> @Service
支付SDK:https://github.com/Pay-Group/best-pay-sdk 参考文档
在这里插入图片描述
3、测试 -> 注意public
在这里插入图片描述
在这里插入图片描述

Postman测试
在这里插入图片描述
手动生成二维码
在这里插入图片描述


(前端代码)

4、自动生成二维码
选择用前端浏览器生成 -> 减轻服务器压力
com.imooc.pay 下新建 PayController

①引入渲染模板 (生成二维码)
加粗样式
新建.ftl文件 ->
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

②将参数改成“活”的
在这里插入图片描述

③请求时在url中输入参数(get方法)
暴露了amount会被修改怎么办? ->
没关系,我们定义支付成功(即用户真正付了多少钱)是根据微信异步回调判断
在这里插入图片描述


2.1 微信异步通知

NotifyUrl这个参数
在这里插入图片描述


问题①:notify_url要在微信后台设置吗?

Native支付有两个模式,模式一需要,我们用的是模式二,故不需要

问题②:notify_url一定要用域名吗?用IP地址是否可以?

不一定,用ip也可以


官方文档对于notify_url的规定:
在这里插入图片描述

2.1.1 签名校验
2.1.2 金额校验
2.1.3 修改订单支付状态
2.1.4 告诉微信不要重复通知

官方文档
在这里插入图片描述

2.2 写入数据库

1、利用Mybatis-generator生成pojo、dao、mapper

package com.imooc.pay.service.impl;

import com.imooc.pay.dao.PayInfoMapper;
import com.imooc.pay.enums.PayPlatformEnum;
import com.imooc.pay.pojo.PayInfo;
import com.imooc.pay.service.IPayService;
import com.lly835.bestpay.enums.BestPayPlatformEnum;
import com.lly835.bestpay.enums.BestPayTypeEnum;
import com.lly835.bestpay.enums.OrderStatusEnum;
import com.lly835.bestpay.model.PayRequest;
import com.lly835.bestpay.model.PayResponse;
import com.lly835.bestpay.service.BestPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * @description:   
 * @author: Dixinkk
 * @create: 2022-03-16 22:32
 */
@Slf4j
@Service
public class PayService implements IPayService {

    @Autowired
    private BestPayService bestPayService; //对应BestPayConfig里的bestPayService

    @Autowired
    private PayInfoMapper payInfoMapper;

    @Override
    public PayResponse create(String orderId, BigDecimal amount, BestPayTypeEnum bestPayTypeEnum) {

        //写入数据库
        PayInfo payInfo = new PayInfo(Long.parseLong(orderId),
                PayPlatformEnum.getByBestPayTypeEnum(bestPayTypeEnum).getCode(),
                OrderStatusEnum.NOTPAY.name(),
                amount);
        payInfoMapper.insertSelective(payInfo);

        PayRequest request = new PayRequest();
        request.setOrderId(orderId);
        request.setOrderName("微信公众账号支付订单(心海非海_)");
        request.setOrderAmount(amount.doubleValue());
        request.setPayTypeEnum(BestPayTypeEnum.WXPAY_NATIVE);

        PayResponse response = bestPayService.pay(request);
        log.info("发起支付 response={}", response);

        return response;
    }

    /**
     * 异步通知处理
     * @param notifyData
     */
    @Override
    public String asyncNotify(String notifyData) {

        //1.签名校验
        PayResponse payResponse = bestPayService.asyncNotify(notifyData);
        log.info("异步通知 payResponse={}", payResponse);

        //2、金额校验(从数据库查订单)
        //比较严重(正常情况下是不会发生的)发出告警:钉钉、短信
        PayInfo payInfo = payInfoMapper.selectByOrderNo(Long.parseLong(payResponse.getOrderId()));
        if (payInfo == null) {
            throw new RuntimeException("通过orderNo查询到的结果是null");
        }
        // 如果订单状态不是已支付
        if (!payInfo.getPlatformStatus().equals(OrderStatusEnum.SUCCESS.name())) {
            if (payInfo.getPayAmount().compareTo(BigDecimal.valueOf(payResponse.getOrderAmount())) != 0) {
                throw new RuntimeException("异步通知中的金额和数据库里的不一致,orderNo=" + payResponse.getOrderId());
            }

            //3、修改订单支付状态
            payInfo.setPlatformStatus(OrderStatusEnum.SUCCESS.name());
            payInfo.setPlatformStatus(payResponse.getOutTradeNo()); //支付流水号 -> 由支付平台产生,作为支付凭证
            payInfo.setUpdateTime(null);
            payInfoMapper.updateByPrimaryKeySelective(payInfo);
        }

        if (payResponse.getPayPlatformEnum() == BestPayPlatformEnum.WX) {
            //4、告诉微信不要重复通知
            return "<xml>\n" +
                    "  <return_code><![CDATA[SUCCESS]]></return_code>\n" +
                    "  <return_msg><![CDATA[OK]]></return_msg>\n" +
                    "</xml>";
        }

        throw new RuntimeException("异步通知中错误的支付平台");
    }
}

3、微信支付完成页面跳转

主要是通过前端完成页面跳转: Ajax 请求后端api(通过订单号查询支付状态) - > 已支付 -> 跳转
在这里插入图片描述

三、微信支付前端代码

注意①:配置单独写,方便管理

以下为反例,是在代码里写的配置;
在这里插入图片描述
部分改进:

/**
 * @description:
 * @author: Dixinkk
 * @create: 2022-03-19 17:13
 */
@Component
public class BestPayConfig {

    @Bean //Spring容器管理功能,此注解表示在项目启动时自动运行此代码
    public BestPayService bestPayService(WxPayConfig wxPayConfig) { // Spring特性 同一个类中可直接放参数中调用 -> WxPayConfig wxPayConfig

        BestPayServiceImpl bestPayService = new BestPayServiceImpl();
        bestPayService.setWxPayConfig(wxPayConfig);

        return bestPayService;
    }

    /**
     * 配置单独写,方便管理
     */
    @Bean
    public WxPayConfig wxPayConfig() {
        WxPayConfig wxPayConfig = new WxPayConfig();
        wxPayConfig.setAppId("***************");          //公众号Id -> Native支付
        //支付商户资料
        wxPayConfig.setMchId("**********");
        wxPayConfig.setMchKey("********************");
        wxPayConfig.setNotifyUrl("http://127.0.0.1"); //微信异步回调地址
        wxPayConfig.setReturnUrl("http://127.0.0.1");
        return wxPayConfig;
    }
}

正确写法:
1、配置yml (yml格式相对传统格式更加简介,但特别注意格式,尤其是空格)
在这里插入图片描述
2、新建WxAccountConfig配置文件

在这里插入图片描述

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Delphi是一种面向对象的编程语言,被广泛应用于软件开发行业。它是由Borland公司开发并于1995年发布的。Delphi允许开发人员使用图形化的用户界面设计器以及可视化编程环境,从而更加便捷地开发软件应用程序。Delphi具有许多强大的特性,如内存管理、异常处理、事件驱动等,使得软件开发过程更加高效和用户友好。 微信是中国最流行的社交媒体平台之一,它为用户提供聊天、分享照片和视频、发布朋友圈等功能。微信还提供了便捷的支付功能,用户可以通过微信支付进行线上和线下的各类交易。微信支付的特点是方便快捷、安全可靠,受到了广大用户的喜爱。 支付宝是中国著名的第支付平台,由阿里巴巴集团旗下的蚂蚁金服运营。支付宝为用户提供了电子钱包、在线支付、转账收款、生活缴费等多种便利的支付服务。支付宝拥有庞大的用户基数和广泛的应用场景,覆盖了不同行业和领域,成为了中国人们生活中必不可少的支付工具。 在中国,微信支付支付宝是两个主要的移动支付平台。无论是线上购物还是线下消费,用户可以通过扫描二维码或输入手机号进行付款。微信支付支付宝相互竞争,为用户提供了多种优惠活动和便利的支付方式。无论是在电商网站购买商品、在实体店铺结账,还是进行转账、缴纳水电费,微信支付支付宝都能够满足用户的需求。 总而言之,Delphi是一种编程语言,微信支付宝是中国的两个主要移动支付平台。它们各自在不同领域发挥着重要的作用,为用户提供了便利和安全的支付方式。无论是开发软件还是进行日常支付,Delphi、微信支付支付宝都在不同方面为我们的生活提供了便利。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

心海非海_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值