Tài liệu này viết ra nhằm mục đích giúp cho
- Xác định các định dạng cơ bản của các API
- Lưu trữ lại các luồng dữ liệu của phần thanh toán
- Mô tả chi tiết từng API cho hệ thống Backend phần thanh toán
Tài liệu bao gồm các phần chính sau
-
Định dạng dữ liệu đầu vào của API
-
Định dạng dữ liệu trả về của API
-
Phương thức xác thực user
-
Các bảng mã lỗi
-
Các kiểu dữ liệu
-
Các API chi tiết
6.1. API module User
6.2. API module Order
Client muốn gọi API cần truyền vào
- phương thức của HTTP: cụ thể là các phương thức GET, POST, PUT, DELETE
- địa chỉ URI của API: ví dụ địa chỉ
/v1/users
- tham số truy vấn (query params) trên URI: ví dụ
/v1/users?access_token=abc
- dữ liệu trong POST:
API được phân chia version bằng cách đánh số version ngay trên URI
VD: API version 1, sẽ có tiền tố của URI là v1
Mọi API đều trả về với status code là 200, nội dung của dữ liệu trả về sẽ có định dang như sau
{
"data": <data>
"error": {
"code": <error_code>,
"message": <error_message>
}
}
Để phân biệt xem API đã được thực hiện thành công hay không.
Client kiểm tra xem dữ liệu trả về có trường error
không?
Nếu trường error
không được trả về, tức là API đã thực hiện thành công.
Client có thể lấy dữ liệu từ trường data
.
Tuy nhiên, nếu API không thể thực hiện được (vì nhiều nguyên nhân như (1) client gửi lên dữ liệu không chính xác (2) client chưa xác thực user (3) client không có quyền thực hiện API hoặc (4) có lỗi xảy ra nội tại bên trong server), thì trường error
sẽ được.
Dữ liệu của trường error
có định dạng như sau
{
"code": <error_code>
"message": <error_message>
}
Trong đó
error_code
: là chuỗi mô tả mã lỗierror_message
: là chuỗi mô tả lỗi
Mã lỗi và nội dung của lỗi sẽ được mô tả trong tài liệu [Các bảng mã lỗi]
Để xác thực xem user đang thực hiện API là user nào, client cần truyền vào một tham số truy vấn có tên là access_token
Phía server dựa vào access_token
sẽ xác định được user đang thực hiện request là user nào.
Đối với ứng dụng Impress, do chưa có hệ thống SignUp/Login, nên client sẽ tự cài đặt một phương thức xác thực đơn giản.
- Coi tất cả các user sử dụng chung một thiết bị là một user
- Khi ứng dụng bị xóa khỏi thiết bị, nếu ứng dụng được cài lại, sẽ coi như ứng dụng thuộc về một user mới
- (1) Khi lần đầu tiên user mở ứng dụng version mới lên, nếu ứng dụng chưa có access token, ứng dụng sẽ tự động tạo ra một UUID. UUID này sẽ được coi là access token lạc từ đây về sau của ứng dụng
- (2) Ứng dụng tự động lưu trữ lại access token vào một bộ nhớ trên thiết bị. Bộ nhớ này cần đảm bảo là khi ứng dụng bị xóa, thì bộ nhớ này cũng bị xóa theo.
- (3) Từ đây về sau, mỗi lần ứng dụng gọi API từ server, ứng dụng sẽ sử dụng access token tạo được từ bước 1 để gọi API.
Phương thức xác thực phía client có thể cải tiến cho các phiên bản mới. Cụ thể, ứng dụng có thể làm các chức năng để cho phép user đăng ký, đăng nhập và sửa profile.
code | message | description |
---|---|---|
D0001 | invalid data | dữ liệu truyền lên không đúng yêu cầu của server |
A0001 | invalid access token | access token truyền lên không hợp lệ |
O0001 | coupon does not exist | mã coupon không tồn tại |
O0002 | expired coupon | mã coupon đã quá hạn sử dụng |
O0003 | coupon usage limit exceed | mã coupon đã bị sử dụng vượt quá số lượng cho phép |
O0004 | payment gateway error | lỗi khi gọi API sang stripe |
O0005 | invalid sku | mã sku không tồn tại |
O0006 | invalid product type | product type không tồn tại |
field | description | type | requirement |
---|---|---|---|
id | id của user | string | |
last_recpipient | thông tin địa chỉ để ship hàng tới của lần order gần nhất | recipient | thông tin này có thể trả về null |
last_stripe_customer_id | id của strip_customer trong lần order gần đây nhất | string | nếu user chưa order thì trả về null |
last_stripe_ephemeral_key | stripe ephemeral key | string |
field | description | type | requirement |
---|---|---|---|
full_name | tên | string | không được để trống |
country | quốc gia | string | không được đế trống |
state | bang | string | không được để trống |
city | thành phố | string | không được để trống |
street_address | địa chỉ | string | không được để trống |
street_address_2 | địa chỉ 2 | string | không được để trống |
zip_code | mẫ zip | string | không được để trống |
phone | số điện thoại | string | không được để trống |
string | không được để trống |
field | description | type | requirement |
---|---|---|---|
raw_price | giá của sản phẩm | float | giá của sản phẩm được tính bằng cent |
shipping_price | phí ship sản phẩm | float | |
sale_tax_price | thuế của sản phẩm | float | |
shipping_tax | thuế của shipping | float | |
total_price | tổng tiền sau khi có cả thuế và tiền ship | float |
- User Module: các module liên quan tới việc tương tác với User
- Order Module: các module liên quan tới việc tạo order
GET /v4/me
Query params:
field | description | type | requirement |
---|---|---|---|
access_token |
access token được sinh ra dựa theo tài liệu mô tả ở phần Phương thức xác thực user | string | không được để trống |
Response
Trả về 1 user object
Các lỗi có thể xảy ra
mã lỗi | hoàn cảnh xảy ra |
---|---|
A0001 | access token truyền lên không tồn tại |
Các bước cần làm:
- Kiểm tra user đang thực hiện request
- Lấy ra order gần nhất của user
Ví dụ:
curl -H "Content-type: application/json" -XGET "http://localhost:8000/v4/me/?access_token=c9aa71a8-1ebc-4d8b-b54b-c88434607cda"
{
"data": {
"id": "c9aa71a8-1ebc-4d8b-b54b-c88434607cda",
"last_recipient": {
"id": 539,
"full_name": "Kien Nguyen",
"country": "Viet nam",
"state": "HCM",
"city": "HCM",
"email": "[email protected]",
"phone": "+111111111",
"street_address": "",
"street_address_2": "",
"zip_code": "10000"
},
"last_stripe_customer_id": "cus_CkxqMfmzeLPwa1",
"last_stripe_ephemeral_key": {
"id": "ephkey_1CLSbFLbKnetRaZ0FR0rbE1J",
"associated_objects": [
{
"id": "cus_CkxqMfmzeLPwa1",
"type": "customer"
}
],
"object": "ephemeral_key",
"created": 1524820241,
"expires": 1524823841,
"livemode": false,
"secret": "ek_test_YWNjdF8xN29NajFMYktuZXRSYVowLDNQdUZjT2JtR3dsQnpHa2k2TktkSTJFb25PNHJBcEw"
}
}
}
POST /v4/prices
Query params:
field | description | type | requirement |
---|---|---|---|
access_token |
access token được sinh ra dựa theo tài liệu mô tả ở phần Phương thức xác thực user | string | không được để trống |
Post data
field | description | type | requirement |
---|---|---|---|
recipient | địa chỉ nhận hàng | recipient | không được để trống |
sku | mã sku của sản phẩm | string | không được để trống |
coupon | mã giảm giá | string | mã giảm giá là một chuỗi dưới 100 ký tự, tất cả các ký tự đều được viết dưới dạng in thường |
Dữ liệu trả về một price object
Các lỗi có thể xảy ra
mã lỗi | hoàn cảnh xảy ra |
---|---|
A0001 | access token truyền lên không tồn tại |
O0001 | mã coupon không tồn tại |
O0002 | mã coupon đã quá hạn sử dụng |
O0003 | mã coupon đã bị sử dụng vượt quá số lượng cho phép |
O0004 | lỗi khi gọi API sang stripe |
O0005 | mã sku không tồn tại |
Các bước cần làm:
-
Kiểm tra user đang thực hiện request
-
Nếu user chưa có trong hệ thống, thì tạo mới user
-
Kiểm tra mã coupon xem có sử dụng đươc với user không
-
Tạo mới một Order trong Stripe cho Customer của stripe
4.1. Lấy giá của SKU từ Stripe (https://stripe.com/docs/api#retrieve_sku)
4.2. Tính discount price từ SKU và coupon (dựa vào công thức tính giá của coupon)
4.3. Tạo mới order dựa vào SKU và giá discount price (https://stripe.com/docs/api#create_order)
Các trường metadata cần thêm vào Order:
+ sku: sku
+ coupon: nếu có
+ user_id: id của user trong hệ thống backend
- Lưu lại price trong bộ nhớ RAM, xóa đi stripe Order.
- Trả về dữ liệu cho client
Ví dụ
curl -H "Content-type: application/json" -XPOST "http://localhost:8000/v4/prices/?access_token=c9aa71a8-1ebc-4d8b-b54b-c88434607cda" -d '
{
"product_type": 1,
"stripe_token": "tok_mastercard",
"sku": "sku_C5I3oDU0OIfKRk",
"recipient": {
"full_name": "Kien Nguyen",
"country": "Viet nam",
"city": "HCM",
"state": "HCM",
"street_address": "",
"street_address_2": "",
"email": "[email protected]",
"phone": "+111111111",
"zip_code": "10000"
},
"pdf_url": "a\nb",
"coupon": "ip1"
}
'
{
"data": {
"discount_price": 799,
"raw_price": 7999,
"sale_tax": 0,
"shipping_price": 550,
"shipping_tax": 0,
"total_price": 7750
}
}
POST /v4/orders
Query params:
field | description | type | requirement |
---|---|---|---|
access_token |
access token được sinh ra dựa theo tài liệu mô tả ở phần Phương thức xác thực user | string | không được để trống |
Post data
field | description | type | requirement |
---|---|---|---|
product_type | loại sản phẩm | integer | không được để trống |
meta | thông tin của từng sản phẩm | dictionary | không được để trống |
recipient | địa chỉ nhận hàng | recipient | không được để trống |
sku | mã sku của sản phẩm | string | không được để trống |
coupon | mã giảm giá | string | mã giảm giá là một chuỗi dưới 100 ký tự, tất cả các ký tự đều được viết dưới dạng in thường |
stripe_customer_id | mã khách hàng của stripe | string | |
stripe_token | token của credit card | string |
Dữ liệu trả về một Order object
Các lỗi có thể xảy ra
mã lỗi | hoàn cảnh xảy ra |
---|---|
A0001 | access token truyền lên không tồn tại |
O0001 | mã coupon không tồn tại |
O0002 | mã coupon đã quá hạn sử dụng |
O0003 | mã coupon đã bị sử dụng vượt quá số lượng cho phép |
O0004 | lỗi khi gọi API sang stripe |
O0005 | mã sku không tồn tại |
O0006 | product type không tồn tại |
Các bước cần làm:
-
Kiểm tra user đang thực hiện request
-
Nếu user chưa có trong hệ thống, thì tạo mới user
-
Kiểm tra mã coupon xem có sử dụng đươc với user không, nếu mã không hợp lệ trả về lỗi
-
Nếu user gửi lên stripe_token, tạo mới một Customer trong Stripe
-
Tạo mới một Order trong Stripe cho Customer của stripe
5.1. Lấy giá của SKU từ Stripe (https://stripe.com/docs/api#retrieve_sku)
5.2. Tính discount price từ SKU và coupon (dựa vào công thức tính giá của coupon)
5.3. Tạo mới order dựa vào SKU và giá discount price (https://stripe.com/docs/api#create_order)
Các trường metadata cần thêm vào Order:
+ sku: sku
+ coupon: nếu có
+ user_id: id của user trong hệ thống backend
- Charge tiền order (https://stripe.com/docs/api#pay_order)
- Tạo mới Order trong hệ thống backend
- Trả về dữ liệu cho client
Ví dụ
curl -H "Content-type: application/json" -XPOST "http://localhost:8000/v4/orders/?access_token=c9aa71a8-1ebc-4d8b-b54b-c88434607cda" -d '
{
"product_type": 1,
"stripe_token": "tok_mastercard",
"sku": "sku_C5I3oDU0OIfKRk",
"recipient": {
"full_name": "Kien Nguyen",
"country": "Viet nam",
"city": "HCM",
"state": "HCM",
"street_address": "",
"street_address_2": "",
"email": "[email protected]",
"phone": "+111111111",
"zip_code": "10000"
},
"pdf_url": "a\nb",
"coupon": "ip1"
}
'
{
"data": {
"coupon": "ip1",
"pdf_url": "a\nb",
"product_type": 1,
"recipient": {
"city": "HCM",
"country": "Viet nam",
"email": "[email protected]",
"full_name": "Kien Nguyen",
"phone": "+111111111",
"state": "HCM",
"street_address": "",
"street_address_2": "",
"zip_code": "10000"
},
"sku": "sku_C5I3oDU0OIfKRk",
"stripe_token": "tok_mastercard"
}
}
tên tham số | mô tả | giá trị |
---|---|---|
stripe_api_key | API key của stripe | pk_test_YZJjZfSnRTqoBmR0PIN8HOv3 |
stripe_api_secret | API secret của stripe | sk_test_AUSBqafUlNOVQkcNaSOprHBo |
sku | sku để test | sku_C5I3oDU0OIfKRk |
request_data | du lieu de request | { |
"sku": "sku_C5I3oDU0OIfKRk", | ||
"recipient": { |
"full_name": "Kien Nguyen Trung",
"country": "Vietnam",
"state": "HCM",
"city": "Ho Chi Minh",
"street_address": "hello there",
"street_address_2": "hello there2",
"zip_code": "12345",
} } |