第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.商戶確認訂單已支付後給用戶發貨。