springboot篇】二十一. 基于springboot电商项目 十四 支付功能

中国加油,武汉加油!

篇幅较长,配合目录观看

案例准备

  1. 本案例基于springboot篇】二十一. 基于springboot电商项目 十三 分库分表应用项目中
  2. 开发文档 https://opendocs.alipay.com/open/270/105899
  3. 服务端SDK https://github.com/alipay/alipay-easysdk
  4. 沙箱测试 https://opendocs.alipay.com/open/200/105311
  5. 阿里app公私钥生成器 https://opendocs.alipay.com/open/291/106097/

1. 支付

1.1 shop-web新建shop-pay(module-springboot)

  1. Spring Web

1.2 导包

<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>3.7.110.ALL</version>
</dependency>
<dependency>
    <groupId>com.wpj</groupId>
    <artifactId>shop-service-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>com.wpj</groupId>
    <artifactId>shop-common</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>com.alibaba.boot</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>0.2.0</version>
</dependency>

1.3 沙箱应用设置公钥,公钥用keytool生成

1.4 编写yml

server:
  port: 8088
spring:
  redis:
    host: 192.168.59.100
    password: admin
dubbo:
  application:
    name: shop-web
  registry:
    address: zookeeper://192.168.59.00:2181
  consumer:
    check:  false
    retries: 3

1.5 程序入口开启包扫描

package com.wpj;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(scanBasePackages = "com.wpj",exclude = DataSourceAutoConfiguration.class)
public class ShopPayApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShopPayApplication.class, args);
    }
}

1.6 编写Controller

package com.wpj.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.wpj.entity.Order;
import com.wpj.service.IOrderService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;

@Controller
public class PayController {
    @Reference
    private IOrderService orderService;

    @RequestMapping(value = "/pay")
    public void pay(HttpServletResponse httpResponse, String oid) throws Exception {

        // 获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(
                "https://openapi.alipaydev.com/gateway.do",// 支付接口url
                "appId",// appId
                // 商家的私钥
                "私钥",
                "JSON",      // 格式化编码
                "utf-8",    // 编码格式
                // 支付宝的公钥(在沙箱环境中可以获取)
                "应用公钥",
                "RSA2"  // 签名的算法
        );

        // 创建API对应的request
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl("http://domain.com/CallBack/return_url.jsp"); // 用户支付完比后跳转到页面,同步
        // 用户支付成功异步通知的请求
        alipayRequest.setNotifyUrl("http://domain.com/CallBack/return_url.jsp");//在公共参数中设置回跳和通知地址
     	Order order = new Order();
        order.setTotalPrice(BigDecimal.valueOf(34409.2));

        // 订单的信息都是封装到下面的
        alipayRequest.setBizContent("{" +
                "    \"out_trade_no\":\" 111111 \"," +
                "    \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
                "    \"total_amount\":" + order.getTotalPrice() + "," +
                "    \"subject\":\"Iphone6 16G\"," +
                "    \"body\":\"Iphone6 16G\"," +
                "    \"passback_params\":\"merchantBizType%3d3C%26merchantBizNo%3d2016010101111\"," +
                "    \"extend_params\":{" +
                "    \"sys_service_provider_id\":\"2088511833207846\"" +
                "    }" +
                "  }");//填充业务参数


        String form = "";
        try {
            form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        httpResponse.setContentType("text/html;charset=" + "utf-8");
        httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
    }
}

1.7 启动程序入口访问

在这里插入图片描述

2. 支付功能完善

2.1 shop-service-api的Service接口添加方法

package com.wpj.service;

import com.wpj.entity.Order;
import com.wpj.entity.User;

import java.util.List;
import java.util.Map;

public interface IOrderService {

    public int addOrder(Integer addressId, User user);
    void updateOrderState(Map<String, String> map);
    Order getOrderById(String oid);
    List<Order> getOrderListByUid(User user);
}

2.2 shop-mapper修改xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wpj.mapper.IOrderMapper">

	<resultMap id="orderResultMap" type="order">
		<id column="id" property="id"/>
		<result column="total_price" property="totalPrice"/>
		<result column="ocreate_time" property="createTime"/>
		<result column="u_id" property="uid"/>
		<result column="person" property="person"/>
		<result column="phone" property="phone"/>
		<result column="address" property="address"/>
	</resultMap>
	
    <insert id="addOrder">
		INSERT INTO t_order${tabIndex} (
			id,
			total_price,
			ocreate_time,
			ostatus,
			u_id,
			person,
			phone,
			address
		)
		VALUES
			(
			  #{order.id},
			  #{order.totalPrice},
			  #{order.createTime},
			  #{order.ostatus},
			  #{order.uid},
			  #{order.person},
			  #{order.phone},
			  #{order.address}
			)
	</insert>
	<update id="updateOrderState">
		update t_order${tabIndex} set ostatus = #{map.state} where id = #{map.oid}
	</update>
	
	<select id="selectById" resultMap="orderResultMap">
		select * from t_order${tabIndex} where id = #{oid}
	</select>
</mapper>

2.3 order-service的ServiceImpl实现方法

package com.wpj.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.wpj.common.constant.Constants;
import com.wpj.common.utils.OrderUtils;
import com.wpj.config.DynamicDataSource;
import com.wpj.entity.*;
import com.wpj.mapper.IOrderDetailMapper;
import com.wpj.mapper.IOrderMapper;
import com.wpj.service.IAddressService;
import com.wpj.service.ICartService;
import com.wpj.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class OrderServiceImpl implements IOrderService {
    @Autowired
    private IOrderMapper orderMapper;
    @Reference
    private IAddressService addressService;
    @Reference
    private ICartService cartService;
    @Autowired
    private IOrderDetailMapper orderDetailMapper;
    @Autowired
    private OrderUtils orderUtils;

    @Override
    public int addOrder(Integer addressId, User user) {
        // 根据地址id查询地址的对象
        Address address = addressService.selectById(addressId);
        List<Cart> cartList = cartService.getUserCartList(user,"");
        // 插入订单
        Order order = new Order();
        String orderId = orderUtils.createOrderId(user.getId());
        order.setId(orderId);
        order.setUid(user.getId());
        order.setPerson(address.getPhone());
        order.setAddress(address.getAddress());
        order.setCreateTime(new Date());
        order.setOstatus(0); // 0 未支付 1 已支付 2 超时 3 取消
        order.setPerson(address.getPerson());
        order.setTotalPrice(cartService.getTotalPrice(cartList));
        // 清空购物车
        cartService.deleteCartByUid(user.getId());
        return 1;
    }

    @Override
    public void updateOrderState(Map<String, String> map) {
        Integer tabIndex = setOrderDataSourceByOid(map.get("oid"));
        orderMapper.updateOrderState(map,tabIndex);
    }

    public Integer setOrderDataSourceByOid(String oid){
        // yyyyMMddxxxx000000000
        // 1.根据订单id获取userId
        Integer userId = parseOrderId(oid);
        // 2.设置数据源
        Integer tabIndex = setOrderDataSource(userId);
        return tabIndex;
    }

    @Override
    public Order getOrderById(String oid) {
        Integer tabIndex = setOrderDataSourceByOid(oid);
        // 查询
        Order order = orderMapper.selectById(oid,tabIndex);
        return order;
    }

    @Override
    public List<Order> getOrderListByUid(User user) {
        Integer tabIndex = setOrderDataSource(user.getId());
        List<Order> orderList = orderMapper.getOrderListByUid(user.getId(),tabIndex);
        return orderList;
    }

    private static Integer parseOrderId(String oid) {
        return Integer.parseInt(oid.substring(8,8+4));
    }

    /**
     * 设置order的数据源
     * @param userId
     * @return 表的索引
     */
    public Integer setOrderDataSource(Integer userId) {
        // 获取用户id后四位
        Integer userIdEnd = Integer.parseInt(orderUtils.getUserIdEnd(userId));
        // 根据用户id后四位获取数据源编号
        Integer dbIndex = (userIdEnd % Constants.ORDER_DB_NUM)+1;
        // 设置数据源
        DynamicDataSource.setDbName("db"+dbIndex);
        // 算出表的索引
        Integer tabIndex = (userId/Constants.ORDER_TAB_NUM %Constants.ORDER_TAB_NUM )+1;
        return tabIndex;
    }
}

2.4 shop-order修改OrderController

@RequestMapping("/addOrder")
@IsLogin(mustUser = true)
@ResponseBody
public String addOrder(Integer addressId,User user){
    int oid = orderService.addOrder(addressId, user);
    // 跳转到支付页面
    return "redirect:http://localhost:8088/pay?oid="+oid;
}
@RequestMapping(value = "/getOrderListByUid")
@IsLogin(mustUser = true)
public String getOrderListByUid(User user,ModelMap map){
    return "orderList";
}

2.5 完善shop-pay的Controller

package com.wpj.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.wpj.entity.Order;
import com.wpj.service.IOrderService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

@Controller
public class PayController {
    @Reference
    private IOrderService orderService;

    @RequestMapping(value = "/pay")
    public void pay(HttpServletResponse httpResponse, String oid) throws Exception {
        // 获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(
                "https://openapi.alipaydev.com/gateway.do",// 支付接口url
                "2016102300747192",// appId
                // 商家的私钥
                "私钥",
                "JSON",      // 格式化编码
                "utf-8",    // 编码格式
                // 支付宝的公钥(在沙箱环境中可以获取)
                "公钥",
                "RSA2"  // 签名的算法
        );

        // 创建API对应的request
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl("http://localhost:8081/"); // 用户支付完比后跳转到页面,同步
        // 用户支付成功异步通知的请求
        alipayRequest.setNotifyUrl("http://7wfk8t.natappfree.cc/updateOrder");//在公共参数中设置回跳和通知地址

//        Order order = orderService.getOrderById(oid);
        Order order = new Order();
        order.setTotalPrice(BigDecimal.valueOf(34409.2));

        // 订单的信息都是封装到下面的
        alipayRequest.setBizContent("{" +
                "    \"out_trade_no\":" + oid + "," +
                "    \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
                "    \"total_amount\":" + order.getTotalPrice() + "," +
                "    \"subject\":\"Iphone6 16G\"," +
                "    \"body\":\"Iphone6 16G\"," +
                "    \"passback_params\":\"merchantBizType%3d3C%26merchantBizNo%3d2016010101111\"," +
                "    \"extend_params\":{" +
                "    \"sys_service_provider_id\":\"2088511833207846\"" +
                "    }" +
                "  }");//填充业务参数
        String form = "";
        try {
            form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        httpResponse.setContentType("text/html;charset=" + "utf-8");
        httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
    }
    @RequestMapping(value = "/updateOrder", method = RequestMethod.POST)
    @ResponseBody
    public String updateOrder(String out_trade_no, String trade_status) {
        if ("TRADE_SUCCESS".equals(trade_status)) {
            // 支付成功,修改订单的姿态
            Map<String, String> map = new HashMap<>();
            map.put("oid", out_trade_no);
            map.put("state", "1");
            orderService.updateOrderState(map);
        }
        return "ok";
    }
}

2.6 编写orderList.html

2.7 启动程序入口全程跑一编测试

发布了126 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/TheNew_One/article/details/105391450