您当前的位置: 首页 > 

杨林伟

暂无认证

  • 0浏览

    0关注

    3337博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

淘东电商项目(57) -聚合支付(支付令牌接口)

杨林伟 发布时间:2020-05-13 16:02:13 ,浏览量:0

引言

本文代码已提交至Github(版本号:99a5a21d8139a9d05eb91f1298aa5565f7d513d5),有兴趣的同学可以下载来看看:https://github.com/ylw-github/taodong-shop

前面讲解了聚合支付的介绍、银联支付相关的源码分析、支付系统的表设计以及分布式系统的解决方案,有兴趣的同学可以参阅:

  • 《淘东电商项目(52) -聚合支付开篇》
  • 《淘东电商项目(53) -银联支付案例源码分析》
  • 《淘东电商项目(54) -银联支付案例(同步与异步)》
  • 《淘东电商项目(55) -支付系统核心表设计》
  • 《淘东电商项目(56) -支付系统分布式事务的解决方案》

现在开始进入代码讲解,后续会逐步根据如下流程图,实现每一步骤的代码。本文主要讲解如下流程图的第1到第4个步骤: 在这里插入图片描述

本文目录结构: l____引言 l____ 1. 提交订单功能实现(第1、2个步骤)) l____ 2. token获取支付内容功能实现(第3、4个步骤) l____ 3. 测试

1. 提交订单功能实现(第1、2个步骤)

提交订单,请求的url为:http://localhost:8600/cratePayToken?payAmount=9999&orderId=20200513141452&userId=27&productName=江西脐橙,这个url是在我们选好了要购买的商品后提交。测试效果图如下: 在这里插入图片描述

①来看看Controller的代码,它的作用是用来创建token令牌,并把订单与预插入到数据库,生成待支付订单,下面使用Redis来生成token,Redis的key值为token,对应的value为数据库中订单的唯一主键:

@RestController
public class PayMentTransacTokenServiceImpl extends BaseApiService implements PayMentTransacTokenService {
	@Autowired
	private PaymentTransactionMapper paymentTransactionMapper;

	@Autowired
	private GenerateToken generateToken;

	@Override
	public BaseResponse cratePayToken(PayCratePayTokenDto payCratePayTokenDto) {
		String orderId = payCratePayTokenDto.getOrderId();
		if (StringUtils.isEmpty(orderId)) {
			return setResultError("订单号码不能为空!");
		}
		Long payAmount = payCratePayTokenDto.getPayAmount();
		if (payAmount == null) {
			return setResultError("金额不能为空!");
		}
		Long userId = payCratePayTokenDto.getUserId();
		if (userId == null) {
			return setResultError("userId不能为空!");
		}
		String productName = payCratePayTokenDto.getProductName();
		if (productName == null) {
			return setResultError("商品名称不能为空!");
		}
		// 2.将输入插入数据库中 待支付记录
		PaymentTransactionEntity paymentTransactionEntity = new PaymentTransactionEntity();
		paymentTransactionEntity.setOrderId(orderId);
		paymentTransactionEntity.setPayAmount(payAmount);
		paymentTransactionEntity.setUserId(userId);
		// 使用雪花算法 生成全局id
		paymentTransactionEntity.setPaymentId(SnowflakeIdUtils.nextId());
		paymentTransactionEntity.setProductName(productName);
		int result = paymentTransactionMapper.insertPaymentTransaction(paymentTransactionEntity);
		if (!toDaoResult(result)) {
			return setResultError("系统错误!");
		}
		// 获取主键id
		Long payId = paymentTransactionEntity.getId();
		if (payId == null) {
			return setResultError("系统错误!");
		}

		// 3.生成对应支付令牌
		String keyPrefix = "pay_";
		String token = generateToken.createToken(keyPrefix, payId + "");
		JSONObject dataResult = new JSONObject();
		dataResult.put("token", token);

		return setResultSuccess(dataResult);
	}
}

②这里的订单id使用雪花算法生成,附录上雪花算法工具类:

package com.ylw.common.web.core.util.twitter;

/**
 * Twitter_Snowflake
 * SnowFlake的结构如下(每部分用-分开):
 * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 -
 * 000000000000 
 * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
 * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
 * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。
 * 41位的时间截,可以使用69年,年T = (1L 
            支付金额: 
						¥${(data.payAmount/100)?string('0.00')}
        
        
            订单详情:
            
            
                商品名称:${data.productName}
            
            
                支付订单:${data.paymentId}
            
            
                应付金额: ¥${(data.payAmount/100)?string('0.00')} 
            
            
                购买时间:${currentTime}
            
        
    

②首先请求获取订单详情,携带token参数,url为:http://localhost:8079/pay?payToken=第1、2步骤返回的token,看看Controller代码,它的流程主要是根据token获取订单详情,然后显示到index页面。

/**
 * description: 支付
 * create by: YangLinWei
 * create time: 2020/5/13 1:35 下午
 */
@Controller
public class PayController extends BaseWebController {
    @Autowired
    private PayMentTransacInfoFeign payMentTransacInfoFeign;

    @Autowired
    private PaymentChannelFeign paymentChannelFeign;

	/**
	 * 跳转到index页面
	 */
	private static final String INDEX_FTL = "index";

    @RequestMapping("/pay")
    public String pay(HttpServletRequest request, String payToken, Model model) {
        // 1.验证payToken参数
        if (StringUtils.isEmpty(payToken)) {
            setErrorMsg(model, "支付令牌不能为空!");
            return ERROR_500_FTL;
        }
        // 2.使用payToken查询支付信息
        BaseResponse tokenByPayMentTransac = payMentTransacInfoFeign.tokenByPayMentTransac(payToken);
        if (!isSuccess(tokenByPayMentTransac)) {
            setErrorMsg(model, tokenByPayMentTransac.getMsg());
            return ERROR_500_FTL;
        }
        // 3.查询支付信息
        PayMentTransacDTO data = tokenByPayMentTransac.getData();
        model.addAttribute("data", data);
        // 4.查询渠道信息
        List paymentChanneList = paymentChannelFeign.selectAll();
        model.addAttribute("paymentChanneList", paymentChanneList);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        model.addAttribute("currentTime",sdf.format(new Date()));
        return INDEX_FTL;
    }

}
3. 测试

测试前须知:因为之前聚合支付模块已经实现了单点登录,所以测试前,需要启动的模块有:Eureka注册中心、xxlsso单点登录系统、member会员服务(如下图),下面开始来测试。 在这里插入图片描述

1.启动支付服务AppPay和聚合支付门户服务AppPortalPayWeb在这里插入图片描述

2.首先验证获取token令牌,浏览器请求:http://localhost:8600/cratePayToken?payAmount=9999&orderId=20200513141452&userId=27&productName=广东米酒 在这里插入图片描述 3.根据返回的token请求支付申请:http://localhost:8079/pay?payToken=pay_c013d23b039446c68f522517929cfa57 在这里插入图片描述 好了,到此为止,支付流程图的第1到第4个步骤已经完成,下一篇博客继续讲解使用设计模式(策略、工厂等)根据支付方式来进行支付。

关注
打赏
1662376985
查看更多评论
立即登录/注册

微信扫码登录

0.2367s