暢購商城第十一天

第11章 訂單

學習目標

  • 登錄頁的配置
  • 登錄成功跳轉實現
  • 結算頁查詢實現
  • 下單實現
  • 變更庫存
  • 增加積分
  • 支付流程介紹
  • 微信掃碼支付介紹

1 登錄頁面配置

前面使用的都是採用Postman實現登錄,接着我們實現一次oauth自定義登錄。

1.1 準備工作

(1)靜態資源導入

資料/頁面/前端登錄相關的靜態資源導入到changgou-user-oauth中,如下圖。

在這裏插入圖片描述

(2)引入thymeleaf

修改changgou-user-oauth,引入thymeleaf模板引擎

<!--thymeleaf-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

(3)登錄配置

修改changgou-user-oauth,編寫一個控制器com.changgou.oauth.controller.LoginRedirect,實現登錄頁跳轉,代碼如下:

@Controller
@RequestMapping(value = "/oauth")
public class LoginRedirect {

    /***
     * 跳轉到登錄頁面
     * @return
     */
    @GetMapping(value = "/login")
    public String login(){
        return "login";
    }
}

(4)登錄頁配置

針對靜態資源和登錄頁面,我們需要實現忽略安全配置,並且要指定登錄頁面。修改com.changgou.oauth.config.WebSecurityConfig的2個configure方法,代碼如下:

第1個configure配置:
在這裏插入圖片描述
第2個configure配置:

在這裏插入圖片描述

測試
在這裏插入圖片描述

1.2 登錄實現

點擊登錄按鈕,訪問之前的登錄方法實現登錄,我們需要對登錄頁做一下調整。

(1)引入thymeleaf命名空間

修改login.html,引入命名空間
在這裏插入圖片描述

(2)登錄腳本

點擊登錄按鈕,使用vue+axios實現登錄,我們需要定義腳本訪問後臺登錄方法。

先添加vue入口標籤:修改login.html,在73行左右的標籤上添加id=“app”,代碼如下:

在這裏插入圖片描述

引入js

<script src="/js/vue.js"></script>
<script src="/js/axios.js"></script>

登錄腳本實現:
在這裏插入圖片描述

(3)表單修改
在這裏插入圖片描述

(4)測試

在這裏插入圖片描述

1.3 登錄跳轉

用戶沒有登錄的時候,我們直接訪問購物車,效果如下:
在這裏插入圖片描述
我們可以發現,返回的只是個錯誤狀態碼,不方便測試,我們可以重定向到登錄頁面,讓用戶登錄,我們可以修改網關的頭文件,讓用戶每次沒登錄的時候,都跳轉到登錄頁面。

修改changgou-gateway-web的com.changgou.filter.AuthorizeFilter,代碼如下:
在這裏插入圖片描述
此時再測試,就可以跳轉到登錄頁面了。當然,在工作中,這裏不能直接跳轉到登錄頁,應該提示狀態給頁面,讓頁面根據判斷跳轉,這裏只是爲了方便測試。

1.4 成功登錄跳轉到原訪問頁

在這裏插入圖片描述
上面雖然實現了登錄跳轉,但登錄成功後卻並沒有返回到要訪問的購物車頁面,我們可以將用戶要訪問的頁面作爲參數傳遞給登錄控制器,登錄控制器記錄下來,每次登錄成功後,再跳轉記錄訪問路勁參數指定的頁面即可。

(1)修改網關攜帶當前URI

修改changgou-gateway-web的com.changgou.filter.AuthorizeFilter,在之前的URL後面添加FROM參數以及FROM參數的值爲request.getURI(),代碼如下:
在這裏插入圖片描述

(2)認證服務器獲取FROM參數

修改changgou-user-oauth的com.changgou.oauth.controller.LoginRedirect記錄訪問來源頁,代碼如下:
在這裏插入圖片描述
修改頁面,獲取來源頁信息,並存到from變量中,登錄成功後跳轉到該地址。
在這裏插入圖片描述
此時再測試,就可以識別未登錄用戶,跳轉到登錄頁,然後根據登錄狀態,如果登錄成功,則跳轉到來源頁。

2 訂單結頁

2.1 收件地址分析

用戶從購物車頁面點擊結算,跳轉到訂單結算頁,結算頁需要加載用戶對應的收件地址,如下圖:
在這裏插入圖片描述

表結構分析:

CREATE TABLE `tb_address` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) DEFAULT NULL COMMENT '用戶名',
  `provinceid` varchar(20) DEFAULT NULL COMMENT '省',
  `cityid` varchar(20) DEFAULT NULL COMMENT '市',
  `areaid` varchar(20) DEFAULT NULL COMMENT '縣/區',
  `phone` varchar(20) DEFAULT NULL COMMENT '電話',
  `address` varchar(200) DEFAULT NULL COMMENT '詳細地址',
  `contact` varchar(50) DEFAULT NULL COMMENT '聯繫人',
  `is_default` varchar(1) DEFAULT NULL COMMENT '是否是默認 1默認 0否',
  `alias` varchar(50) DEFAULT NULL COMMENT '別名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8;

我們可以根據用戶登錄名去tb_address表中查詢對應的數據。

2.2 實現用戶收件地址查詢

2.2.1 代碼實現

(1)業務層

業務層接口

修改changgou-service-user微服務,需改com.changgou.user.service.AddressService接口,添加根據用戶名字查詢用戶收件地址信息,代碼如下:

/***
 * 收件地址查詢
 * @param username
 * @return
 */
List<Address> list(String username);

業務層接口實現類

修改changgou-service-user微服務,修改com.changgou.user.service.impl.AddressServiceImpl類,添加根據用戶查詢用戶收件地址信息實現方法,如下代碼:

/***
 * 收件地址查詢
 * @param username
 * @return
 */
@Override
public List<Address> list(String username) {
    Address address = new Address();
    address.setUsername(username);
    return addressMapper.select(address);
}

(2)控制層

修改changgou-service-user微服務,修改com.changgou.user.controller.AddressController,添加根據用戶名查詢用戶收件信息方法,代碼如下:

/****
 * 用戶收件地址
 */
@GetMapping(value = "/user/list")
public Result<List<Address>> list(){
    //獲取用戶登錄信息
    Map<String, String> userMap = TokenDecode.getUserInfo();
    String username = userMap.get("username");
    //查詢用戶收件地址
    List<Address> addressList = addressService.list(username);
    return new Result(true, StatusCode.OK,"查詢成功!",addressList);
}

2.2.2 測試

訪問 http://localhost:8001/api/address/user/list
在這裏插入圖片描述

2.2.3 運送清單

在這裏插入圖片描述
運送清單其實就是購物車列表,直接查詢之前的購物車列表即可,這裏不做說明了。

3 下單

3.1 業務分析

點擊結算頁的時候,會立即創建訂單數據,創建訂單數據會將數據存入到2張表中,分別是訂單表和訂單明細表,此處還需要修改商品對應的庫存數量。在這裏插入圖片描述
訂單表結構如下:

CREATE TABLE `tb_order` (
  `id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT '訂單id',
  `total_num` int(11) DEFAULT NULL COMMENT '數量合計',
  `total_money` int(11) DEFAULT NULL COMMENT '金額合計',
  `pre_money` int(11) DEFAULT NULL COMMENT '優惠金額',
  `post_fee` int(11) DEFAULT NULL COMMENT '郵費',
  `pay_money` int(11) DEFAULT NULL COMMENT '實付金額',
  `pay_type` varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT '支付類型,1、在線支付、0 貨到付款',
  `create_time` datetime DEFAULT NULL COMMENT '訂單創建時間',
  `update_time` datetime DEFAULT NULL COMMENT '訂單更新時間',
  `pay_time` datetime DEFAULT NULL COMMENT '付款時間',
  `consign_time` datetime DEFAULT NULL COMMENT '發貨時間',
  `end_time` datetime DEFAULT NULL COMMENT '交易完成時間',
  `close_time` datetime DEFAULT NULL COMMENT '交易關閉時間',
  `shipping_name` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流名稱',
  `shipping_code` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流單號',
  `username` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '用戶名稱',
  `buyer_message` varchar(1000) COLLATE utf8_bin DEFAULT NULL COMMENT '買家留言',
  `buyer_rate` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '是否評價',
  `receiver_contact` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '收貨人',
  `receiver_mobile` varchar(12) COLLATE utf8_bin DEFAULT NULL COMMENT '收貨人手機',
  `receiver_address` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '收貨人地址',
  `source_type` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '訂單來源:1:web,2:app,3:微信公衆號,4:微信小程序  5 H5手機頁面',
  `transaction_id` varchar(30) COLLATE utf8_bin DEFAULT NULL COMMENT '交易流水號',
  `order_status` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '訂單狀態,0:未完成,1:已完成,2:已退貨',
  `pay_status` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '支付狀態,0:未支付,1:已支付,2:支付失敗',
  `consign_status` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '發貨狀態,0:未發貨,1:已發貨,2:已收貨',
  `is_delete` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '是否刪除',
  PRIMARY KEY (`id`),
  KEY `create_time` (`create_time`),
  KEY `status` (`order_status`),
  KEY `payment_type` (`pay_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

訂單明細表結構如下:

CREATE TABLE `tb_order_item` (
  `id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT 'ID',
  `category_id1` int(11) DEFAULT NULL COMMENT '1級分類',
  `category_id2` int(11) DEFAULT NULL COMMENT '2級分類',
  `category_id3` int(11) DEFAULT NULL COMMENT '3級分類',
  `spu_id` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT 'SPU_ID',
  `sku_id` bigint(20) NOT NULL COMMENT 'SKU_ID',
  `order_id` bigint(20) NOT NULL COMMENT '訂單ID',
  `name` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '商品名稱',
  `price` int(20) DEFAULT NULL COMMENT '單價',
  `num` int(10) DEFAULT NULL COMMENT '數量',
  `money` int(20) DEFAULT NULL COMMENT '總金額',
  `pay_money` int(11) DEFAULT NULL COMMENT '實付金額',
  `image` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '圖片地址',
  `weight` int(11) DEFAULT NULL COMMENT '重量',
  `post_fee` int(11) DEFAULT NULL COMMENT '運費',
  `is_return` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '是否退貨,0:未退貨,1:已退貨',
  PRIMARY KEY (`id`),
  KEY `item_id` (`sku_id`),
  KEY `order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

3.2 下單實現

下單的時候,先添加訂單往tb_order表中增加數據,再添加訂單明細,往tb_order_item表中增加數據。

3.2.1 代碼實現

這裏先修改changgou-service-order微服務,實現下單操作,這裏會生成訂單號,我們首先需要在啓動類中創建一個IdWorker對象。

com.changgou.OrderApplication中創建IdWorker,代碼如下:

@Bean
public IdWorker idWorker(){
    return new IdWorker(1,1);
}

(1)業務層

修改changgou-service-order微服務,修改com.changgou.order.service.impl.OrderServiceImpl,代碼如下:

修改訂單微服務添加com.changgou.order.service.impl.OrderServiceImpl,代碼如下:

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private CartService cartService;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RedisTemplate redisTemplate;

    /***
     * 添加訂單
     * @param order
     * @return
     */
    @Override
    public int add(Order order) {
        //查詢出用戶的所有購物車
        List<OrderItem> orderItems = cartService.list(order.getUsername());

        //統計計算
        int totalMoney = 0;
        int totalPayMoney=0;
        int num = 0;
        for (OrderItem orderItem : orderItems) {
            //總金額
            totalMoney+=orderItem.getMoney();

            //實際支付金額
            totalPayMoney+=orderItem.getPayMoney();
            //總數量
            num+=orderItem.getNum();
        }
        order.setTotalNum(num);
        order.setTotalMoney(totalMoney);
        order.setPayMoney(totalPayMoney);
        order.setPreMoney(totalMoney-totalPayMoney);

        //其他數據完善
        order.setCreateTime(new Date());
        order.setUpdateTime(order.getCreateTime());
        order.setBuyerRate("0");        //0:未評價,1:已評價
        order.setSourceType("1");       //來源,1:WEB
        order.setOrderStatus("0");      //0:未完成,1:已完成,2:已退貨
        order.setPayStatus("0");        //0:未支付,1:已支付,2:支付失敗
        order.setConsignStatus("0");    //0:未發貨,1:已發貨,2:已收貨
        order.setId("NO."+idWorker.nextId());
        int count = orderMapper.insertSelective(order);

        //添加訂單明細
        for (OrderItem orderItem : orderItems) {
            orderItem.setId("NO."+idWorker.nextId());
            orderItem.setIsReturn("0");
            orderItem.setOrderId(order.getId());
            orderItemMapper.insertSelective(orderItem);
        }

        //清除Redis緩存購物車數據
        redisTemplate.delete("Cart_"+order.getUsername());
        return count;
    }
}

(2)控制層

修改changgou-service-order微服務,修改com.changgou.order.controller.OrderController類,代碼如下:

@Autowired
private TokenDecode tokenDecode;

/***
 * 新增Order數據
 * @param order
 * @return
 */
@PostMapping
public Result add(@RequestBody Order order){
    //獲取用戶名
    Map<String, String> userMap = tokenDecode.getUserInfo();
    String username = userMap.get("username");
    //設置購買用戶
    order.setUsername(username);
    orderService.add(order);
    return new Result(true,StatusCode.OK,"添加成功");
}

3.2.2 測試

保存訂單測試,表數據變化如下:

tb_order表數據:
在這裏插入圖片描述
tb_order_item表數據:
在這裏插入圖片描述

3.3 庫存變更

3.3.1 業務分析

上面操作只實現了下單操作,但對應的庫存還沒跟着一起減少,我們在下單之後,應該調用商品微服務,將下單的商品庫存減少,銷量增加。每次訂單微服務只需要將用戶名傳到商品微服務,商品微服務通過用戶名到Redis中查詢對應的購物車數據,然後執行庫存減少,庫存減少需要控制當前商品庫存>=銷售數量。
在這裏插入圖片描述
如何控制庫存數量>=銷售數量呢?其實可以通過SQL語句實現,每次減少數量的時候,加個條件判斷。

where num>=#{num}即可。

該工程中一會兒需要查詢購物車數據,所以需要引入訂單的api,在pom.xml中添加如下依賴:

<!--order api 依賴-->
<dependency>
    <groupId>com.changgou</groupId>
    <artifactId>changgou-service-order-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

3.3.2 代碼實現

要調用其他微服務,需要將頭文件中的令牌數據攜帶到其他微服務中取,所以我們不能使用hystrix的多線程模式,修改changgou-service-goods的applicatin.yml配置,代碼如下:

#hystrix 配置
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000
          strategy: SEMAPHORE

每次還需要使用攔截器添加頭文件信息,修改配置類com.changgou.GoodsApplication添加攔截器,代碼如下:

@Bean
public FeignInterceptor feignInterceptor(){
    return new FeignInterceptor();
}

(1)Dao層

修改changgou-service-goods微服務的com.changgou.goods.dao.SkuMapper接口,增加庫存遞減方法,代碼如下:

/**
 * 遞減庫存
 * @param orderItem
 * @return
 */
@Update("UPDATE tb_sku SET num=num-#{num},sale_num=sale_num+#{num} WHERE id=#{skuId} AND num>=#{num}")
int decrCount(OrderItem orderItem);

(2)業務層

修改changgou-service-goods微服務的com.changgou.goods.service.SkuService接口,添加如下方法:

/***
 * 庫存遞減
 * @param username
 */
void decrCount(String username);

修改changgou-service-goods微服務的com.changgou.goods.service.impl.SkuServiceImpl實現類,添加一個實現方法,代碼如下:

@Autowired
private RedisTemplate redisTemplate;

/***
 * 庫存遞減
 * @param username
 */
@Override
public void decrCount(String username) {
    //獲取購物車數據
    List<OrderItem> orderItems = redisTemplate.boundHashOps("Cart_" + username).values();

    //循環遞減
    for (OrderItem orderItem : orderItems) {
        //遞減庫存
        int count = skuMapper.decrCount(orderItem);
        if(count<=0){
            throw new RuntimeException("庫存不足,遞減失敗!");
        }
    }
}

(3)控制層

修改changgou-service-goods的com.changgou.goods.controller.SkuController類,添加庫存遞減方法,代碼如下:

/***
 * 庫存遞減
 * @param username
 * @return
 */
@PostMapping(value = "/decr/count")
public Result decrCount(String username){
    //庫存遞減
    skuService.decrCount(username);
    return new Result(true,StatusCode.OK,"庫存遞減成功!");
}

(4)創建feign

同時在changgou-service-goods-api工程添加com.changgou.goods.feign.SkuFeign的實現,代碼如下:

/***
 * 庫存遞減
 * @param username
 * @return
 */
@PostMapping(value = "/decr/count")
Result decrCount(@RequestParam(value = "username") String username);

3.3.3 調用庫存遞減

修改changgou-service-order微服務的com.changgou.order.service.impl.OrderServiceImpl類的add方法,增加庫存遞減的調用。

先注入SkuFeign

@Autowired
private SkuFeign skuFeign;

再調用庫存遞減方法

//庫存減庫存
skuFeign.decrCount(order.getUsername());

完整代碼如下:
在這裏插入圖片描述

3.3.4 測試

庫存減少前,查詢數據庫Sku數據如下:個數98,銷量0
在這裏插入圖片描述
使用Postman執行 http://localhost:18081/api/order/add

在這裏插入圖片描述
執行測試後,剩餘庫存97,銷量1
在這裏插入圖片描述

3.4 增加積分

比如每次下單完成之後,給用戶增加10個積分,支付完成後贈送優惠券,優惠券可用於支付時再次抵扣。我們先完成增加積分功能。如下表:points表示用戶積分

CREATE TABLE `tb_user` (
  `username` varchar(50) NOT NULL COMMENT '用戶名',
  `password` varchar(100) NOT NULL COMMENT '密碼,加密存儲',
  `phone` varchar(20) DEFAULT NULL COMMENT '註冊手機號',
  `email` varchar(50) DEFAULT NULL COMMENT '註冊郵箱',
  `created` datetime NOT NULL COMMENT '創建時間',
  `updated` datetime NOT NULL COMMENT '修改時間',
  `source_type` varchar(1) DEFAULT NULL COMMENT '會員來源:1:PC,2:H5,3:Android,4:IOS',
  `nick_name` varchar(50) DEFAULT NULL COMMENT '暱稱',
  `name` varchar(50) DEFAULT NULL COMMENT '真實姓名',
  `status` varchar(1) DEFAULT NULL COMMENT '使用狀態(1正常 0非正常)',
  `head_pic` varchar(150) DEFAULT NULL COMMENT '頭像地址',
  `qq` varchar(20) DEFAULT NULL COMMENT 'QQ號碼',
  `is_mobile_check` varchar(1) DEFAULT '0' COMMENT '手機是否驗證 (0否  1是)',
  `is_email_check` varchar(1) DEFAULT '0' COMMENT '郵箱是否檢測(0否  1是)',
  `sex` varchar(1) DEFAULT '1' COMMENT '性別,1男,0女',
  `user_level` int(11) DEFAULT NULL COMMENT '會員等級',
  `points` int(11) DEFAULT NULL COMMENT '積分',
  `experience_value` int(11) DEFAULT NULL COMMENT '經驗值',
  `birthday` datetime DEFAULT NULL COMMENT '出生年月日',
  `last_login_time` datetime DEFAULT NULL COMMENT '最後登錄時間',
  PRIMARY KEY (`username`),
  UNIQUE KEY `username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶表';

3.4.1 代碼實現

(1)dao層

修改changgou-service-user微服務的com.changgou.user.dao.UserMapper接口,增加用戶積分方法,代碼如下:

/***
 * 增加用戶積分
 * @param username
 * @param pint
 * @return
 */
@Update("UPDATE tb_user SET points=points+#{point} WHERE  username=#{username}")
int addUserPoints(@Param("username") String username, @Param("point") Integer pint);

(2)業務層

修改changgou-service-user微服務的com.changgou.user.service.UserService接口,代碼如下:

/***
 * 添加用戶積分
 * @param username
 * @param pint
 * @return
 */
int addUserPoints(String username,Integer pint);

修改changgou-service-user微服務的com.changgou.user.service.impl.UserServiceImpl,增加添加積分方法實現,代碼如下:

/***
 * 修改用戶積分
 * @param username
 * @param pint
 * @return
 */
@Override
public int addUserPoints(String username, Integer pint) {
    return userMapper.addUserPoints(username,pint);
}

(3)控制層

修改changgou-service-user微服務的com.changgou.user.controller.UserController,添加增加用戶積分方法,代碼如下:

@Autowired
private TokenDecode tokenDecode;

/***
 * 增加用戶積分
 * @param points:要添加的積分
 */
@GetMapping(value = "/points/add")
public Result addPoints(Integer points){
    //獲取用戶名
    Map<String, String> userMap = tokenDecode.getUserInfo();
    String username = userMap.get("username");

    //添加積分
    userService.addUserPoints(username,points);
    return new Result(true,StatusCode.OK,"添加積分成功!");
}

(4)Feign添加

修改changgou-service-user-api工程,修改com.changgou.user.feign.UserFeign,添加增加用戶積分方法,代碼如下:

/***
 * 添加用戶積分
 * @param points
 * @return
 */
@GetMapping(value = "/points/add")
Result addPoints(@RequestParam(value = "points")Integer points);

3.4.2 增加積分調用

修改changgou-service-order,添加changgou-service-user-api的依賴,修改pom.xml,添加如下依賴:

<!--user api 依賴-->
<dependency>
    <groupId>com.changgou</groupId>
    <artifactId>changgou-service-user-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

在增加訂單的時候,同時添加用戶積分,修改changgou-service-order微服務的com.changgou.order.service.impl.OrderServiceImpl下單方法,增加調用添加積分方法,代碼如下:
在這裏插入圖片描述

修改changgou-service-order的啓動類com.changgou.OrderApplication,添加feign的包路徑:在這裏插入圖片描述

4 支付流程分析

4.1 訂單支付分析

在這裏插入圖片描述
如上圖,步驟分析如下:

1.用戶下單之後,訂單數據會存入到MySQL中,同時會將訂單對應的支付日誌存入到Redis,以隊列的方式存儲。
2.用戶下單後,進入支付頁面,支付頁面調用支付系統,從微信支付獲取二維碼數據,並在頁面生成支付二維碼。
3.用戶掃碼支付後,微信支付服務器會通調用前預留的回調地址,並攜帶支付狀態信息。
4.支付系統接到支付狀態信息後,將支付狀態信息發送給RabbitMQ
5.訂單系統監聽RabbitMQ中的消息獲取支付狀態,並根據支付狀態修改訂單狀態
6.爲了防止網絡問題導致notifyurl沒有接到對應數據,定時任務定時獲取Redis中隊列數據去微信支付接口查詢狀態,並定時更新對應狀態。

4.2 二維碼創建(瞭解)

今天主要講微信支付,後面爲了看到效果,我們簡單說下利用qrious製作二維碼插件。

qrious是一款基於HTML5 Canvas的純JS二維碼生成插件。通過qrious.js可以快速生成各種二維碼,你可以控制二維碼的尺寸顏色,還可以將生成的二維碼進行Base64編碼。

qrious.js二維碼插件的可用配置參數如下:

參數 類型 默認值 描述
background String “white” 二維碼的背景顏色。
foreground String “black” 二維碼的前景顏色。
level String “L” 二維碼的誤差校正級別(L, M, Q, H)。
mime String “image/png” 二維碼輸出爲圖片時的MIME類型。
size Number 100 二維碼的尺寸,單位像素。
value String “” 需要編碼爲二維碼的值

下面的代碼即可生成一張二維碼

<html>
<head>
<title>二維碼入門小demo</title>
</head>
<body>
<img id="qrious">
<script src="qrious.js"></script>
<script>
 var qr = new QRious({
	    element:document.getElementById('qrious'),
	    size:250, 	   
     	level:'H',	   
     	value:'http://www.itheima.com'
	});
</script>
</body>
</html>

運行效果:
在這裏插入圖片描述
大家掏出手機,掃一下看看是否會看到黑馬的官網呢?

5 微信掃碼支付簡介

5.1微信掃碼支付申請

微信掃碼支付是商戶系統按微信支付協議生成支付二維碼,用戶再用微信“掃一掃”完成支付的模式。該模式適用於PC網站支付、實體店單品或訂單支付、媒體廣告支付等場景。

申請步驟:(瞭解)

第一步:註冊公衆號(類型須爲:服務號)

請根據營業執照類型選擇以下主體註冊:個體工商戶| 企業/公司| 政府| 媒體| 其他類型

第二步:認證公衆號

公衆號認證後纔可申請微信支付,認證費:300元/次。

第三步:提交資料申請微信支付

登錄公衆平臺,點擊左側菜單【微信支付】,開始填寫資料等待審覈,審覈時間爲1-5個工作日內。

第四步:開戶成功,登錄商戶平臺進行驗證

資料審覈通過後,請登錄聯繫人郵箱查收商戶號和密碼,並登錄商戶平臺填寫財付通備付金打的小額資金數額,完成賬戶驗證。

第五步:在線簽署協議

本協議爲線上電子協議,簽署後方可進行交易及資金結算,簽署完立即生效。

本課程已經提供好“傳智播客”的微信支付賬號,學員無需申請。

5.2 開發文檔

微信支付接口調用的整體思路:

按API要求組裝參數,以XML方式發送(POST)給微信支付接口(URL),微信支付接口也是以XML方式給予響應。程序根據返回的結果(其中包括支付URL)生成二維碼或判斷訂單狀態。

在線微信支付開發文檔:

https://pay.weixin.qq.com/wiki/doc/api/index.html

如果你不能聯網,請查閱講義配套資源 (資源\配套軟件\微信掃碼支付\開發文檔)

我們在本章課程中會用到”統一下單”和”查詢訂單”兩組API

1. appid:微信公衆賬號或開放平臺APP的唯一標識
2. mch_id:商戶號  (配置文件中的partner)
3. partnerkey:商戶密鑰
4. sign:數字簽名, 根據微信官方提供的密鑰和一套算法生成的一個加密信息, 就是爲了保證交易的安全性

5.3 微信支付模式介紹

5.3.1 模式一

在這裏插入圖片描述
業務流程說明:

1.商戶後臺系統根據微信支付規定格式生成二維碼(規則見下文),展示給用戶掃碼。
2.用戶打開微信“掃一掃”掃描二維碼,微信客戶端將掃碼內容發送到微信支付系統。
3.微信支付系統收到客戶端請求,發起對商戶後臺系統支付回調URL的調用。調用請求將帶productid和用戶的openid等參數,並要求商戶系統返回交數據包,詳細請見"本節3.1回調數據輸入參數"
4.商戶後臺系統收到微信支付系統的回調請求,根據productid生成商戶系統的訂單。
5.商戶系統調用微信支付【統一下單API】請求下單,獲取交易會話標識(prepay_id)
6.微信支付系統根據商戶系統的請求生成預支付交易,並返回交易會話標識(prepay_id)。
7.商戶後臺系統得到交易會話標識prepay_id(2小時內有效)。
8.商戶後臺系統將prepay_id返回給微信支付系統。返回數據見"本節3.2回調數據輸出參數"
9.微信支付系統根據交易會話標識,發起用戶端授權支付流程。
10.用戶在微信客戶端輸入密碼,確認支付後,微信客戶端提交支付授權。
11.微信支付系統驗證後扣款,完成支付交易。
12.微信支付系統完成支付交易後給微信客戶端返回交易結果,並將交易結果通過短信、微信消息提示用戶。微信客戶端展示支付交易結果頁面。
13.微信支付系統通過發送異步消息通知商戶後臺系統支付結果。商戶後臺系統需回覆接收情況,通知微信後臺系統不再發送該單的支付通知。
14.未收到支付通知的情況,商戶後臺系統調用【查詢訂單API】。
15.商戶確認訂單已支付後給用戶發貨。

5.3.2 模式二

在這裏插入圖片描述
業務流程說明:

1.商戶後臺系統根據用戶選購的商品生成訂單。
2.用戶確認支付後調用微信支付【統一下單API】生成預支付交易;
3.微信支付系統收到請求後生成預支付交易單,並返回交易會話的二維碼鏈接code_url。
4.商戶後臺系統根據返回的code_url生成二維碼。
5.用戶打開微信“掃一掃”掃描二維碼,微信客戶端將掃碼內容發送到微信支付系統。
6.微信支付系統收到客戶端請求,驗證鏈接有效性後發起用戶支付,要求用戶授權。
7.用戶在微信客戶端輸入密碼,確認支付後,微信客戶端提交授權。
8.微信支付系統根據用戶授權完成支付交易。
9.微信支付系統完成支付交易後給微信客戶端返回交易結果,並將交易結果通過短信、微信消息提示用戶。微信客戶端展示支付交易結果頁面。
10.微信支付系統通過發送異步消息通知商戶後臺系統支付結果。商戶後臺系統需回覆接收情況,通知微信後臺系統不再發送該單的支付通知。
11.未收到支付通知的情況,商戶後臺系統調用【查詢訂單API】。
12.商戶確認訂單已支付後給用戶發貨。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章