App server gửi thông tin đơn hàng tới ZaloPay server để tạo đơn hàng.
Environment | Method | Endpoint |
---|---|---|
Sandbox | POST | https://sandbox.zalopay.com.vn/v001/tpe/createorder |
Real | POST | https://zalopay.com.vn/v001/tpe/createorder |
application/x-www-form-urlencoded
Đơn hàng gồm có các thông tin sau:
Tham số |
Kiểu dữ liệu | Kích thước | Bắt buộc | Ý nghĩa | Ví dụ |
---|---|---|---|---|---|
appid |
int | ✔ | Định danh cho ứng dụng đã được cấp bởi ZaloPay. | 1 |
|
appuser |
String | 50 | ✔ | Thông tin người dùng như: id/username/tên/số điện thoại/email của user. | user123 |
apptime |
long | ✔ | Thời gian tạo đơn hàng (unix timestamp in milisecond). Thời gian tính đến milisecond, lấy theo current time và không quá 15 phút so với thời điểm thanh toán | 1459823610957 |
|
amount |
long | ✔ | Thời gian hết hạn của đơn hàng. Thời gian tính bằng giây (giá trị nhỏ nhất: 300, giá trị lớn nhất: 2592000) | 50000 |
|
apptransid |
String | 40 | ✔ | Giá trị của đơn hàng VND | 180208_007242 |
embeddata |
String | 1024 | ✔ | Mã giao dịch của đơn hàng. Mã giao dịch phải bắt đầu theo format yymmdd của ngày hiện tại. Mã giao dịch nên theo format yymmdd_Mã đơn hàng thanh toán Lưu ý: yymmdd phải đúng TimeZone Vietnam (GMT+7) (Vì các giao dịch đối soát theo ngày giờ Việt Nam) |
{"promotioninfo":"","merchantinfo":"du lieu rieng cua ung dung"} |
item |
String | 2048 | ✔ | Dữ liệu riêng của đơn hàng. Dữ liệu này sẽ được callback lại cho AppServer khi thanh toán thành công (Nếu không có thì để chuỗi rỗng) | [{"itemid":"knb","itename":"kim nguyen bao","itemprice":198400,"itemquantity":1}] |
mac |
String | ✔ | Item của đơn hàng, do ứng dụng tự định nghĩa | c8f49d523336f0a182586a70b71c20da96 4d37954711de9273152b500df74c0d |
|
bankcode |
String | 20 | ✔ (*) | Thông tin chứng thực của đơn hàng, xem cách tạo thông tin chứng thực cho đơn hàng | VTB |
description |
String | 256 | Mã ngân hàng, xem cách lấy danh sách các ngân hàng được hỗ trợ | <Tên Merchant/Dịch vụ> - Thanh toán đơn hàng #<Mã đơn hàng> Ví dụ: Lazada - Thanh toán đơn hàng #180208_007242 |
|
phone |
String | 50 | Thông tin mô tả về dịch vụ đang được thanh toán dùng để hiển thị cho user trên app ZaloPay và trên tool quản lý Merchant | 0934568239 |
|
email |
String | 100 | Số điện thoại của người dùng | example@gmail.com |
|
address |
String | 1024 | Email của người dùng | TPHCM |
|
subappid |
String | 50 | Địa chỉ của người dùng | sub123 |
Tên |
Kiểu dữ liệu | Định dạng | Mô tả | Ví dụ |
---|---|---|---|---|
redirecturl |
String | URL | Redirect về url này sau khi thanh toán trên cổng ZaloPay (override redirect url lúc đăng ký app với ZaloPay) | {"redirecturl": "https://docs.zalopay.vn/result"} |
columninfo |
JSON String | {"column_name": "value"} |
Thêm thông tin hiển thị ở phần Quản lý giao dịch chi tiết trên Merchant site, nếu cột chưa tồn tại cần vào phần Cài đặt hiển thị dữ liệu để cấu hình Lưu ý: đối với thanh toán Offline cần thiết truyền các thông tin như branch_id, store_id, store_name, ... |
{"columninfo": "{\"branch_id\": \"HCM\",\"store_id\": \"CH123\",\"store_name\": \"Saigon Centre\",\"mc_campaign_id\": \"FREESHIP\"}"} |
promotioninfo |
JSON String | {"campaigncode":"code"} |
Dùng để triển khai chương trình khuyến mãi | {"promotioninfo": "{\"campaigncode\":\"blackfriday\"}"} |
zlppaymentid |
String | - Mã thông tin thanh toán. - Chỉ truyền khi đối tác cần nhận tiền đối soát về nhiều tài khoản khác nhau. - Hệ thống ZaloPay sẽ tạo ra một mã Thanh toán (tương ứng với mỗi Tài khoản ngân hàng đối tác cung cấp) và gởi lại cho đối tác thiết lập. |
{"zlppaymentid": "P4201372"} |
mac = HMAC(hmac_algorihtm, key1, hmac_input)
Trong đó:
HmacSHA256
appid +”|”+ apptransid +”|”+ appuser +”|”+ amount +"|"+ apptime +”|”+ embeddata +"|"+ item
Ví dụ:
appid=1&apptransid=160405095135-57032837085b5&appuser=pmqc&apptime=1459823610957&description=Mua kim nguyên bảo cho game VLTK&embeddata={"promotioninfo":"{\"campaigncode\":\"yeah\"}","merchantinfo":"embeddata123"}&item=[{"itemid":"knb","itemname":"kim nguyen bao","itemquantity":10,"itemprice":50000}]&amount=500000&&mac=28ecee91f4b32aa1306812f5d74c4ed1f7cbce7b4f2848cf06f23933ae8027e0
application/json
Tham số |
Kiểu dữ liệu | Ý nghĩa |
---|---|---|
returncode |
int |
|
returnmessage |
String | Mô tả chi tiết mã trạng thái |
orderurl |
String | Dùng để tạo QR code hoặc gọi chuyển tiếp sang trang cổng ZaloPay |
zptranstoken |
String | Kết hợp với appid để tạo QR code Deprecated Ví dụ: |
Ví dụ:
{
"zptranstoken": "190613000002244_order",
"orderurl": "https://qcgateway.zalopay.vn/openinapp?order=eyJ6cHRyYW5zdG9rZW4iOiIxOTA2MTMwMDAwMDIyNDRfb3JkZXIiLCJhcHBpZCI6NTUzfQ",
"returncode": 1,
"returnmessage": ""
}
/**
* .Net core 2.1.505
*/
using System;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
using ZaloPay.Helper; // HmacHelper, RSAHelper, HttpHelper, Utils (tải về ở mục DOWNLOADS)
using ZaloPay.Helper.Crypto;
using Newtonsoft.Json; // https://www.newtonsoft.com/json
namespace ZaloPayExample
{
class Program
{
static string appid = "553";
static string key1 = "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q";
static string createOrderUrl = "https://sandbox.zalopay.com.vn/v001/tpe/createorder";
static async Task Main(string[] args) {
var transid = Guid.NewGuid().ToString();
var embeddata = new { merchantinfo = "embeddata123" };
var items = new []{
new { itemid = "knb", itemname = "kim nguyen bao", itemprice = 198400, itemquantity = 1 }
};
var param = new Dictionary<string, string>();
param.Add("appid", appid);
param.Add("appuser", "demo");
param.Add("apptime", Utils.GetTimeStamp().ToString());
param.Add("amount", "50000");
param.Add("apptransid", DateTime.Now.ToString("yyMMdd") + "_" + transid); // mã giao dich có định dạng yyMMdd_xxxx
param.Add("embeddata", JsonConvert.SerializeObject(embeddata));
param.Add("item", JsonConvert.SerializeObject(items));
param.Add("description", "ZaloPay demo");
param.Add("bankcode", "zalopayapp");
var data = appid + "|" + param["apptransid"] + "|" + param["appuser"] + "|" + param["amount"] + "|"
+ param["apptime"] + "|" + param["embeddata"] + "|" + param["item"];
param.Add("mac", HmacHelper.Compute(ZaloPayHMAC.HMACSHA256, key1, data));
var result = await HttpHelper.PostFormAsync(createOrderUrl, param);
foreach(var entry in result) {
Console.WriteLine("{0} = {1}", entry.Key, entry.Value);
}
}
}
}
// Java version "1.8.0_201"
import org.apache.http.NameValuePair; // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject; // https://mvnrepository.com/artifact/org.json/json
import vn.zalopay.crypto.HMACUtil; // tải về ở mục DOWNLOADS
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.*;
public class CreateOrder {
private static Map<String, String> config = new HashMap<String, String>(){{
put("appid", "553");
put("key1", "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q");
put("key2", "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3");
put("endpoint", "https://sandbox.zalopay.com.vn/v001/tpe/createorder");
}};
public static String getCurrentTimeString(String format) {
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT+7"));
SimpleDateFormat fmt = new SimpleDateFormat(format);
fmt.setCalendar(cal);
return fmt.format(cal.getTimeInMillis());
}
public static void main( String[] args ) throws Exception
{
final Map embeddata = new HashMap(){{
put("merchantinfo", "embeddata123");
}};
final Map[] item = {
new HashMap(){{
put("itemid", "knb");
put("itemname", "kim nguyen bao");
put("itemprice", 198400);
put("itemquantity", 1);
}}
};
Map<String, Object> order = new HashMap<String, Object>(){{
put("appid", config.get("appid"));
put("apptransid", getCurrentTimeString("yyMMdd") +"_"+ UUID.randomUUID()); // mã giao dich có định dạng yyMMdd_xxxx
put("apptime", System.currentTimeMillis()); // miliseconds
put("appuser", "demo");
put("amount", 50000);
put("description", "ZaloPay Intergration Demo");
put("bankcode", "zalopayapp");
put("item", new JSONObject(item).toString());
put("embeddata", new JSONObject(embeddata).toString());
}};
// appid +”|”+ apptransid +”|”+ appuser +”|”+ amount +"|" + apptime +”|”+ embeddata +"|" +item
String data = order.get("appid") +"|"+ order.get("apptransid") +"|"+ order.get("appuser") +"|"+ order.get("amount")
+"|"+ order.get("apptime") +"|"+ order.get("embeddata") +"|"+ order.get("item");
order.put("mac", HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, config.get("key1"), data));
CloseableHttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost(config.get("endpoint"));
List<NameValuePair> params = new ArrayList<>();
for (Map.Entry<String, Object> e : order.entrySet()) {
params.add(new BasicNameValuePair(e.getKey(), e.getValue().toString()));
}
// Content-Type: application/x-www-form-urlencoded
post.setEntity(new UrlEncodedFormEntity(params));
CloseableHttpResponse res = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
StringBuilder resultJsonStr = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
resultJsonStr.append(line);
}
JSONObject result = new JSONObject(resultJsonStr.toString());
for (String key : result.keySet()) {
System.out.format("%s = %s\n", key, result.get(key));
}
}
}
// go version go1.11.1 linux/amd64
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"strconv"
"time"
"github.com/google/uuid" // go get github.com/google/uuid
"github.com/zpmep/hmacutil" // go get github.com/zpmep/hmacutil
)
type object map[string]interface{}
var (
appid = "553"
key1 = "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q"
key2 = "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3"
)
func main() {
embeddata, _ := json.Marshal(object{
"merchantinfo": "embeddata123",
})
items, _ := json.Marshal([]object{
object{"itemid": "knb", "itemname": "kim nguyen bao", "itemprice": 198400, "itemquantity": 1},
})
// request data
params := make(url.Values)
params.Add("appid", appid)
params.Add("amount", "1000")
params.Add("appuser", "demo")
params.Add("embeddata", string(embeddata))
params.Add("item", string(items))
params.Add("description", "ZaloPay QR Merchant Demo")
params.Add("bankcode", "zalopayapp")
now := time.Now()
params.Add("apptime", strconv.FormatInt(now.UnixNano()/int64(time.Millisecond), 10)) // miliseconds
transid := uuid.New().String() // unique id
params.Add("apptransid", fmt.Sprintf("%02d%02d%02d_%v", now.Year()%100, int(now.Month()), now.Day(), transid)) // mã giao dich có định dạng yyMMdd_xxxx
// appid|apptransid|appuser|amount|apptime|embeddata|item
data := fmt.Sprintf("%v|%v|%v|%v|%v|%v|%v", params.Get("appid"), params.Get("apptransid"), params.Get("appuser"),
params.Get("amount"), params.Get("apptime"), params.Get("embeddata"), params.Get("item"))
params.Add("mac", hmacutil.HexStringEncode(hmacutil.SHA256, key1, data))
// Content-Type: application/x-www-form-urlencoded
res, err := http.PostForm("https://sandbox.zalopay.com.vn/v001/tpe/createorder", params)
// parse response
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
var result map[string]interface{}
if err := json.Unmarshal(body, &result); err != nil {
log.Fatal(err)
}
for k, v := range result {
log.Printf("%s = %+v", k, v)
}
}
// Node v10.15.3
const axios = require('axios').default; // npm install axios
const CryptoJS = require('crypto-js'); // npm install crypto-js
const uuid = require('uuid/v1'); // npm install uuid
const moment = require('moment'); // npm install moment
// APP INFO
const config = {
appid: "553",
key1: "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
key2: "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
endpoint: "https://sandbox.zalopay.com.vn/v001/tpe/createorder"
};
const embeddata = {
merchantinfo: "embeddata123"
};
const items = [{
itemid: "knb",
itemname: "kim nguyen bao",
itemprice: 198400,
itemquantity: 1
}];
const order = {
appid: config.appid,
apptransid: `${moment().format('YYMMDD')}_${uuid()}`, // mã giao dich có định dạng yyMMdd_xxxx
appuser: "demo",
apptime: Date.now(), // miliseconds
item: JSON.stringify(items),
embeddata: JSON.stringify(embeddata),
amount: 50000,
description: "ZaloPay Integration Demo",
bankcode: "zalopayapp",
};
// appid|apptransid|appuser|amount|apptime|embeddata|item
const data = config.appid + "|" + order.apptransid + "|" + order.appuser + "|" + order.amount + "|" + order.apptime + "|" + order.embeddata + "|" + order.item;
order.mac = CryptoJS.HmacSHA256(data, config.key1).toString();
axios.post(config.endpoint, null, { params: order })
.then(res => {
console.log(res.data);
})
.catch(err => console.log(err));
<?php
// PHP Version 7.3.3
$config = [
"appid" => 553,
"key1" => "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
"key2" => "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
"endpoint" => "https://sandbox.zalopay.com.vn/v001/tpe/createorder"
];
$embeddata = [
"merchantinfo" => "embeddata123"
];
$items = [
[ "itemid" => "knb", "itemname" => "kim nguyen bao", "itemprice" => 198400, "itemquantity" => 1 ]
];
$order = [
"appid" => $config["appid"],
"apptime" => round(microtime(true) * 1000), // miliseconds
"apptransid" => date("ymd")."_".uniqid(), // mã giao dich có định dạng yyMMdd_xxxx
"appuser" => "demo",
"item" => json_encode($items, JSON_UNESCAPED_UNICODE),
"embeddata" => json_encode($embeddata, JSON_UNESCAPED_UNICODE),
"amount" => 50000,
"description" => "ZaloPay Intergration Demo",
"bankcode" => "zalopayapp"
];
// appid|apptransid|appuser|amount|apptime|embeddata|item
$data = $order["appid"]."|".$order["apptransid"]."|".$order["appuser"]."|".$order["amount"]
."|".$order["apptime"]."|".$order["embeddata"]."|".$order["item"];
$order["mac"] = hash_hmac("sha256", $data, $config["key1"]);
$context = stream_context_create([
"http" => [
"header" => "Content-type: application/x-www-form-urlencoded\r\n",
"method" => "POST",
"content" => http_build_query($order)
]
]);
$resp = file_get_contents($config["endpoint"], false, $context);
$result = json_decode($resp, true);
foreach ($result as $key => $value) {
echo "$key: $value<br>";
}
# ruby 2.5.1p57
require 'securerandom'
require 'json'
require 'openssl' # gem install openssl
require 'net/http'
config = {
appid: '553',
key1: '9phuAOYhan4urywHTh0ndEXiV3pKHr5Q',
key2: 'Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3',
endpoint: 'https://sandbox.zalopay.com.vn/v001/tpe/createorder'
}
apptime = (Time.now.to_f.round(3) * 1000).to_i # miliseconds
apptransid = Time.now.strftime('%y%m%d') + '_' + SecureRandom.uuid
embeddata = {
merchantinfo: 'embeddata123'
}
items = [{
itemid: 'knb',
itemname: 'kim nguyen bao',
itemprice: 198_400,
itemquantity: 1
}]
order = {
appid: config[:appid],
apptransid: apptransid, # mã giao dich có định dạng yyMMdd_xxxx
appuser: 'demo',
apptime: apptime, # miliseconds
item: items.to_json,
embeddata: embeddata.to_json,
amount: 50_000,
description: 'ZaloPay Integration Demo',
bankcode: 'zalopayapp'
}
# appid|apptransid|appuser|amount|apptime|embeddata|item
data = config[:appid] + '|' + apptransid + '|' + order[:appuser] + '|' + order[:amount].to_s + '|' +
order[:apptime].to_s + '|' + order[:embeddata].to_s + '|' + order[:item].to_s
order[:mac] = OpenSSL::HMAC.hexdigest('sha256', config[:key1], data)
res = Net::HTTP.post_form(URI.parse(config[:endpoint]), order)
result = JSON.parse(res.body)
result.each do |key, value|
puts "#{key}: #{value}"
end
# coding=utf-8
# Python 3.6
from time import time
from datetime import datetime
import uuid, json, hmac, hashlib, urllib.request, urllib.parse
config = {
"appid": 553,
"key1": "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
"key2": "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
"endpoint": "https://sandbox.zalopay.com.vn/v001/tpe/createorder"
}
order = {
"appid": config["appid"],
"apptransid": "{:%y%m%d}_{}".format(datetime.today(), uuid.uuid4()), # mã giao dich có định dạng yyMMdd_xxxx
"appuser": "demo",
"apptime": int(round(time() * 1000)), # miliseconds
"embeddata": json.dumps({
"merchantinfo": "embeddata123"
}),
"item": json.dumps([
{ "itemid": "knb", "itemname": "kim nguyen bao", "itemprice": 198400, "itemquantity": 1 }
]),
"amount": 50000,
"description": "ZaloPay Integration Demo",
"bankcode": "zalopayapp"
}
# appid|apptransid|appuser|amount|apptime|embeddata|item
data = "{}|{}|{}|{}|{}|{}|{}".format(order["appid"], order["apptransid"], order["appuser"],
order["amount"], order["apptime"], order["embeddata"], order["item"])
order["mac"] = hmac.new(config['key1'].encode(), data.encode(), hashlib.sha256).hexdigest()
response = urllib.request.urlopen(url=config["endpoint"], data=urllib.parse.urlencode(order).encode())
result = json.loads(response.read())
for k, v in result.items():
print("{}: {}".format(k, v))
curl -X POST https://sandbox.zalopay.com.vn/v001/tpe/createorder \
-H "Content-type: application/x-www-form-urlencoded" \
-d appid=553 \
-d apptransid=190419_41c9c3a0-6248-11e9-8a6f-f5f370222ed3 \
-d appuser=demo \
-d apptime=1555639809242 \
-d item='[{"itemid":"knb","itemname":"kim nguyen bao","itemprice":198400,"itemquantity":1}]' \
-d embeddata='{"merchantinfo":"embeddata123"}' \
-d amount=50000 \
-d description='ZaloPay Intergration Demo' \
-d bankcode=zalopayapp \
-d mac=f02093505c88081d440b79e9de7da9ff73d27942c63713f07607e13b1987775f
API đối tác xây dựng sẽ nhận kết quả thanh toán từ ZaloPay. Khi và chỉ khi ZaloPay đã thu tiền khách hàng thành công thì mới gọi API này để thông báo kết quả.
Nếu trừ tiền user thành công ZaloPay Server callback cho Merchant Server theo CallbackURL
đã cấu hình. Merchant dùng key2
(được cấp lúc đăng ký ứng dụng) để xác thực data do ZaloPay Server POST qua. Để tiện cho việc tích hợp, Merchant có thể xem log callback ở môi trường Sandbox
tại trang Dev Tool ở Merchant Portal
application/json
Tên | Kiểu dữ liệu | Mô tả |
---|---|---|
data |
Json String | Dữ liệu giao dịch ZaloPay gọi về cho ứng dụng |
mac |
String | Thông tin chứng thực của đơn hàng, dùng Callback Key (Key2) được cung cấp để chứng thực đơn hàng |
Dữ liệu của trường data:
Tên |
Kiểu dữ liệu | Mô tả | Ví dụ |
---|---|---|---|
appid |
long | appid của đơn hàng |
5 |
apptransid |
String | apptransid của đơn hàng |
180208181007242 |
apptime |
long | apptime của đơn hàng |
1460543835849 |
appuser |
String | appuser của đơn hàng |
pmqc |
amount |
long | Số tiền ứng dụng nhận được | 50000 |
embeddata |
String | embeddata của đơn hàng |
{"promotioninfo":"","merchantinfo":"du lieu rieng cua ung dung"} |
item |
String | item của đơn hàng |
[{"itemid":"knb","itename":"kim nguyen bao","itemprice":198400,"itemquantity":1}] |
zptransid |
long | Mã giao dịch của ZaloPay | 160413000003083 |
servertime |
long | Thời gian giao dịch của ZaloPay (unix timestamp in miliseconds) | 1460543836370 |
channel |
int | Kênh thanh toán | 38 |
merchantuserid |
string | ZaloPay user đã thanh toán cho đơn hàng | |
userfeeamount |
long | Số tiền phí | 220 |
discountamount |
long | Số tiền giảm giá | 10000 |
Ví dụ:
{
"data":"{\"appid\":2,\"zptransid\":160520000000081,\"apptransid\":\"160520176021926423825\",\"apptime\":1463711618132,\"appuser\":\"160514000002501\",\"item\":\"[{\"itemID\":\"it002\",\"itemName\":\"Color 50K\",\"itemQuantity\":1,\"itemPrice\":50000}]\",\"amount\":1000,\"embeddata\":\"{\"promotioninfo\":\"\",\"merchantinfo\":\"du lieu rieng cua ung dung\"}\",\"servertime\":1463711619269,\"channel\":38,\"merchantuserid\":\"rSVW3nBDryiJ6eN7h4L8ZjFn1OAbTaPoBm0I0JbB9zo\",\"userfeeamount\":220}",
"mac":"16b369598e86411baf15421cff917610119f37d157c064109618496c937b9bc5"
}
reqmac = HMAC(hmac_algorithm, key2, callback_data.data)
if (reqmac == callback_data.mac) {
// callback hợp lệ
} else {
// callback không hợp lệ
}
Trong đó:
HmacSHA256
Giá trị | Kênh thanh toán |
---|---|
36 |
Visa/Master/JCB |
37 |
Bank Account |
38 |
ZaloPay Wallet |
39 |
ATM |
41 |
Visa/Master Debit |
application/json
Tham số | Kiểu dữ liệu | Ý nghĩa |
---|---|---|
returncode |
int |
|
returnmessage |
String | Mô tả chi tiết mã trạng thái |
Ví dụ:
{
"returncode": "[returncode]",
"returnmessage": "[returnmessage]"
}
/**
* .Net core 2.1.505
*/
using System;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using ZaloPay.Helper; // HmacHelper, RSAHelper, HttpHelper, Utils (tải về ở mục DOWNLOADS)
using ZaloPay.Helper.Crypto;
using Newtonsoft.Json; // https://www.newtonsoft.com/json
namespace ZaloPayExample.Controllers
{
[Route("[controller]")]
[ApiController]
public class CallbackController: ControllerBase
{
private string key2 = "eG4r0GcoNtRGbO8";
[HttpPost]
public IActionResult Post([FromBody] dynamic cbdata)
{
var result = new Dictionary<string, object>();
try {
var dataStr = Convert.ToString(cbdata["data"]);
var reqMac = Convert.ToString(cbdata["mac"]);
var mac = HmacHelper.Compute(ZaloPayHMAC.HMACSHA256, key2, dataStr);
Console.WriteLine("mac = {0}", mac);
// kiểm tra callback hợp lệ (đến từ ZaloPay server)
if (!reqMac.Equals(mac)) {
// callback không hợp lệ
result["returncode"] = -1;
result["returnmessage"] = "mac not equal";
}
else {
// thanh toán thành công
// merchant cập nhật trạng thái cho đơn hàng
var dataJson = JsonConvert.DeserializeObject<Dictionary<string, object>>(dataStr);
Console.WriteLine("update order's status = success where apptransid = {0}", dataJson["apptransid"]);
result["returncode"] = 1;
result["returnmessage"] = "success";
}
} catch (Exception ex) {
result["returncode"] = 0; // ZaloPay server sẽ callback lại (tối đa 3 lần)
result["returnmessage"] = ex.Message;
}
// thông báo kết quả cho ZaloPay server
return Ok(result);
}
}
}
/**
* Spring Boot v2.1.4.RELEASE
* */
import org.json.JSONObject; // https://mvnrepository.com/artifact/org.json/json
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.util.logging.Logger;
@RestController
public class CallbackController {
private Logger logger = Logger.getLogger(this.getClass().getName());
private String key2 = "eG4r0GcoNtRGbO8";
private Mac HmacSHA256;
public CallbackController() throws Exception {
HmacSHA256 = Mac.getInstance("HmacSHA256");
HmacSHA256.init(new SecretKeySpec(key2.getBytes(), "HmacSHA256"));
}
@PostMapping("/callback")
public String callback(@RequestBody String jsonStr) {
JSONObject result = new JSONObject();
try {
JSONObject cbdata = new JSONObject(jsonStr);
String dataStr = cbdata.getString("data");
String reqMac = cbdata.getString("mac");
byte[] hashBytes = HmacSHA256.doFinal(dataStr.getBytes());
String mac = DatatypeConverter.printHexBinary(hashBytes).toLowerCase();
// kiểm tra callback hợp lệ (đến từ ZaloPay server)
if (!reqMac.equals(mac)) {
// callback không hợp lệ
result.put("returncode", -1);
result.put("returnmessage", "mac not equal");
} else {
// thanh toán thành công
// merchant cập nhật trạng thái cho đơn hàng
JSONObject data = new JSONObject(dataStr);
logger.info("update order's status = success where apptransid = " + data.getString("apptransid"));
result.put("returncode", 1);
result.put("returnmessage", "success");
}
} catch (Exception ex) {
result.put("returncode", 0); // ZaloPay server sẽ callback lại (tối đa 3 lần)
result.put("returnmessage", ex.getMessage());
}
// thông báo kết quả cho ZaloPay server
return result.toString();
}
}
// go version go1.11.1 linux/amd64
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/zpmep/hmacutil" // go get github.com/zpmep/hmacutil
)
// App config
var (
key2 = "eG4r0GcoNtRGbO8"
)
func main() {
mux := http.DefaultServeMux
mux.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
var cbdata map[string]interface{}
decoder := json.NewDecoder(r.Body)
decoder.Decode(&cbdata)
requestMac := cbdata["mac"].(string)
dataStr := cbdata["data"].(string)
mac := hmacutil.HexStringEncode(hmacutil.SHA256, key2, dataStr)
log.Println("mac =", mac)
result := make(map[string]interface{})
// kiểm tra callback hợp lệ (đến từ ZaloPay server)
if mac != requestMac {
// callback không hợp lệ
result["returncode"] = -1
result["returnmessage"] = "mac not equal"
} else {
// thanh toán thành công
result["returncode"] = 1
result["returnmessage"] = "success"
// merchant cập nhật trạng thái cho đơn hàng
var dataJSON map[string]interface{}
json.Unmarshal([]byte(dataStr), &dataJSON)
log.Println("update order's status = success where apptransid =", dataJSON["apptransid"])
}
// thông báo kết quả cho ZaloPay server
resultJSON, _ := json.Marshal(result)
fmt.Fprintf(w, "%s", resultJSON)
})
log.Println("Server is listening at port :8888")
http.ListenAndServe(":8888", mux)
}
// Node v10.15.3
const CryptoJS = require('crypto-js'); // npm install crypto-js
const express = require('express'); // npm install express
const bodyParser = require('body-parser'); // npm install body-parser
const app = express();
const config = {
key2: "eG4r0GcoNtRGbO8"
};
app.use(bodyParser.json());
app.post('/callback', (req, res) => {
let result = {};
try {
let dataStr = req.body.data;
let reqMac = req.body.mac;
let mac = CryptoJS.HmacSHA256(dataStr, config.key2).toString();
console.log("mac =", mac);
// kiểm tra callback hợp lệ (đến từ ZaloPay server)
if (reqMac !== mac) {
// callback không hợp lệ
result.returncode = -1;
result.returnmessage = "mac not equal";
}
else {
// thanh toán thành công
// merchant cập nhật trạng thái cho đơn hàng
let dataJson = JSON.parse(dataStr, config.key2);
console.log("update order's status = success where apptransid =", dataJson["apptransid"]);
result.returncode = 1;
result.returnmessage = "success";
}
} catch (ex) {
result.returncode = 0; // ZaloPay server sẽ callback lại (tối đa 3 lần)
result.returnmessage = ex.message;
}
// thông báo kết quả cho ZaloPay server
res.json(result);
});
app.listen(8888, function (){
console.log('Server is listening at port :8888');
});
<?php
// PHP Version 7.3.3
$result = [];
try {
$key2 = "eG4r0GcoNtRGbO8";
$postdata = file_get_contents('php://input');
$postdatajson = json_decode($postdata, true);
$mac = hash_hmac("sha256", $postdatajson["data"], $key2);
$requestmac = $postdatajson["mac"];
// kiểm tra callback hợp lệ (đến từ ZaloPay server)
if (strcmp($mac, $requestmac) != 0) {
// callback không hợp lệ
$result["returncode"] = -1;
$result["returnmessage"] = "mac not equal";
} else {
// thanh toán thành công
// merchant cập nhật trạng thái cho đơn hàng
$datajson = json_decode($postdatajson["data"], true);
// echo "update order's status = success where apptransid = ". $dataJson["apptransid"];
$result["returncode"] = 1;
$result["returnmessage"] = "success";
}
} catch (Exception $e) {
$result["returncode"] = 0; // ZaloPay server sẽ callback lại (tối đa 3 lần)
$result["returnmessage"] = $e->getMessage();
}
// thông báo kết quả cho ZaloPay server
echo json_encode($result);
# ruby 2.5.1p57
# rails 5.2.3
# config/routes.rb
Rails.application.routes.draw do
match '/callback' => 'callback#handle', via: :post
end
# app/controllers/callback_controller.rb
require 'json'
require 'openssl' # gem install openssl
class CallbackController < ApplicationController
def initialize
super
@config = {
key2: 'eG4r0GcoNtRGbO8'
}
end
# POST /callback
def handle
result = {}
begin
cbdata = params
mac = OpenSSL::HMAC.hexdigest('sha256', @config[:key2], cbdata['data'])
# kiểm tra callback hợp lệ (đến từ ZaloPay server)
if cbdata['mac'] != mac
# callback không hợp lệ
result[:returncode] = -1
result[:returnmessage] = "mac not equal"
else
# thanh toán thành công
# merchant cập nhật trạng thái cho đơn hàng
dataJson = JSON.parse(cbdata['data'])
puts "update order's status = success where apptransid = " + dataJson['apptransid']
result[:returncode] = 1
result[:returnmessage] = "success"
end
rescue Exception => ex
result[:returncode] = 0 # ZaloPay server sẽ callback lại (tối đa 3 lần)
result[:returnmessage] = ex.message
end
# thông báo kết quả cho ZaloPay server
render json: result, status: :ok
end
end
# coding=utf-8
# Python 3.6
from flask import Flask, request, json # pip3 install Flask
import hmac, hashlib
app = Flask(__name__)
config = {
'key2': 'eG4r0GcoNtRGbO8'
}
@app.route('/callback', methods=['POST'])
def callback():
result = {}
try
cbdata = request.json
mac = hmac.new(config['key2'].encode(), cbdata['data'].encode(), hashlib.sha256).hexdigest()
# kiểm tra callback hợp lệ (đến từ ZaloPay server)
if mac != cbdata['mac']:
# callback không hợp lệ
result['returncode'] = -1
result['returnmessage'] = 'mac not equal'
else:
# thanh toán thành công
# merchant cập nhật trạng thái cho đơn hàng
dataJson = json.loads(cbdata['data'])
print("update order's status = success where apptransid = " + dataJson['apptransid'])
result['returncode'] = 1
result['returnmessage'] = 'success'
except Exception as e
result['returncode'] = 0 # ZaloPay server sẽ callback lại (tối đa 3 lần)
result['returnmessage'] = str(e)
# thông báo kết quả cho ZaloPay server
return json.jsonify(result)
Khi user thanh toán thành công thì ZaloPay sẽ gọi callback (notify) về Merchant, khi đó Merchant cập nhật trạng thái đơn hàng Thành Công trên hệ thống của Merchant. Nhưng trong thực tế callback có thể bị miss do lỗi Network timeout, Merchant Service unavailable/Internal error, ... nên Merchant cần hiện thực việc chủ động gọi API truy vấn trạng thái đơn hàng.
Merchant Server gửi request đến ZaloPay Server để lấy thông tin trạng thái thanh toán của giao dịch.
Environment | Method | Endpoint |
---|---|---|
Sandbox | POST | https://sandbox.zalopay.com.vn/v001/tpe/getstatusbyapptransid |
Real | POST | https://zalopay.com.vn/v001/tpe/getstatusbyapptransid |
application/x-www-form-urlencoded
Tham số |
Kiểu dữ liệu | Bắt buộc | Ý nghĩa |
---|---|---|---|
appid |
int | ✔ | appid của đơn hàng |
apptransid |
String | ✔ | apptransid của đơn hàng |
mac |
String | ✔ | • Thông tin chứng thực dữ liệu • = HMAC(hmac_algorithm, key1, appid+"|"+apptransid+"|"+key1) |
application/json
Tham số |
Kiểu dữ liệu | Ý nghĩa |
---|---|---|
returncode |
int | 1 : thành công <> : chưa thanh toán / thanh toán thất bại / quá thời hạn truy vấn |
returnmessage |
String | Thông tin trạng thái đơn hàng |
isprocessing |
boolean | true : giao dịch đang xử lý false : giao dịch chưa thực hiện / giao dịch đã kết thúc xử lý |
amount |
long | Số tiền giao dịch |
discountamount |
long | Số tiền giảm giá |
zptransid |
long | Mã giao dịch của ZaloPay |
/**
* .Net core 2.1.505
*/
using System;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
using ZaloPay.Helper; // HmacHelper, RSAHelper, HttpHelper, Utils (tải về ở mục DOWNLOADS)
using ZaloPay.Helper.Crypto;
using Newtonsoft.Json; // https://www.newtonsoft.com/json
namespace ZaloPayExample
{
class Program
{
static string appid = "553";
static string key1 = "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q";
static string queryOrderUrl = "https://sandbox.zalopay.com.vn/v001/tpe/getstatusbyapptransid";
static async Task Main(string[] args)
{
var apptransid = "<apptransid>";
var param = new Dictionary<string, string>();
param.Add("appid", appid);
param.Add("apptransid", apptransid);
var data = appid + "|" + apptransid + "|" + key1;
param.Add("mac", HmacHelper.Compute(ZaloPayHMAC.HMACSHA256, key1, data));
var result = await HttpHelper.PostFormAsync(queryOrderUrl, param);
foreach(var entry in result) {
Console.WriteLine("{0} = {1}", entry.Key, entry.Value);
}
}
}
}
// Java version "1.8.0_201"
import org.apache.http.NameValuePair; // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject; // https://mvnrepository.com/artifact/org.json/json
import vn.zalopay.crypto.HMACUtil; // tải về ở mục DOWNLOADS
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
public class GetOrderStatus {
private static Logger logger = Logger.getLogger(App.class.getName());
private static Map<String, String> config = new HashMap<String, String>(){{
put("appid", "553");
put("key1", "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q");
put("key2", "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3");
put("endpoint", "https://sandbox.zalopay.com.vn/v001/tpe/getstatusbyapptransid");
}};
public static void main(String[] args) throws Exception {
String apptransid = "190308_123456";
String data = config.get("appid") +"|"+ apptransid +"|"+ config.get("key1"); // appid|apptransid|key1
String mac = HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, config.get("key1"), data);
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("appid", config.get("appid")));
params.add(new BasicNameValuePair("apptransid", apptransid));
params.add(new BasicNameValuePair("mac", mac));
URIBuilder uri = new URIBuilder(config.get("endpoint"));
uri.addParameters(params);
CloseableHttpClient client = HttpClients.createDefault();
HttpGet get = new HttpGet(uri.build());
CloseableHttpResponse res = client.execute(get);
BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
StringBuilder resultJsonStr = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
resultJsonStr.append(line);
}
JSONObject result = new JSONObject(resultJsonStr.toString());
for (String key : result.keySet()) {
System.out.format("%s = %s\n", key, result.get(key));
}
}
}
// go version go1.11.1 linux/amd64
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"github.com/zpmep/hmacutil" // go get github.com/zpmep/hmacutil
)
var (
appid = "553"
key1 = "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q"
key2 = "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3"
)
func main() {
params := make(url.Values)
params.Add("appid", "553")
params.Add("apptransid", "190308_123456")
data := fmt.Sprintf("%s|%s|%s", appid, params.Get("apptransid"), key1) // appid|apptransid|key1
params.Add("mac", hmacutil.HexStringEncode(hmacutil.SHA256, key1, data))
res, err := http.Get("https://sandbox.zalopay.com.vn/v001/tpe/getstatusbyapptransid?" + params.Encode())
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
var result map[string]interface{}
if err := json.Unmarshal(body, &result); err != nil {
log.Fatal(err)
}
for k, v := range result {
log.Printf("%s = %+v", k, v)
}
}
// Node v10.15.3
const axios = require('axios').default; // npm install axios
const CryptoJS = require('crypto-js'); // npm install crypto-js
const qs = require('qs')
const config = {
appid: "553",
key1: "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
key2: "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
endpoint: "https://sandbox.zalopay.com.vn/v001/tpe/getstatusbyapptransid"
};
let postData = {
appid: config.appid,
apptransid: "<apptransid>", // Input your apptransid
}
let data = postData.appid + "|" + postData.apptransid + "|" + config.key1; // appid|apptransid|key1
postData.mac = CryptoJS.HmacSHA256(data, config.key1).toString();
let postConfig = {
method: 'post',
url: config.endpoint,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: qs.stringify(postData)
};
axios(postConfig)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
<?php
// PHP Version 7.3.3
$config = [
"appid" => 553,
"key1" => "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
"key2" => "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
"endpoint" => "https://sandbox.zalopay.com.vn/v001/tpe/getstatusbyapptransid"
];
$apptransid = "190308_123456";
$data = $config["appid"]."|".$apptransid."|".$config["key1"]; // appid|apptransid|key1
$params = [
"appid" => $config["appid"],
"apptransid" => $apptransid,
"mac" => hash_hmac("sha256", $data, $config["key1"])
];
$resp = file_get_contents($config["endpoint"]."?".http_build_query($params));
$result = json_decode($resp, true);
foreach ($result as $key => $value) {
echo "$key: $value<br>";
}
# ruby 2.5.1p57
require 'json'
require 'openssl' # gem install openssl
require 'net/http'
config = {
appid: '553',
key1: '9phuAOYhan4urywHTh0ndEXiV3pKHr5Q',
key2: 'Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3',
endpoint: 'https://sandbox.zalopay.com.vn/v001/tpe/getstatusbyapptransid'
}
params = {
appid: config[:appid],
apptransid: "190308_123456",
}
data = config[:appid] +"|"+ params[:apptransid] +"|"+ config[:key1] # appid|apptransid|key1
params[:mac] = OpenSSL::HMAC.hexdigest('sha256', config[:key1], data)
uri = URI(config[:endpoint])
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
result = JSON.parse(res.body)
result.each do |key, value|
puts "#{key}: #{value}"
end
# coding=utf-8
# Python 3.6
from time import time
import hmac, hashlib, urllib.parse, urllib.request
config = {
"appid": 553,
"key1": "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
"key2": "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
"endpoint": "https://sandbox.zalopay.com.vn/v001/tpe/getstatusbyapptransid"
}
params = {
"appid": config["appid"],
"apptransid": "190308_123456"
}
data = "{}|{}|{}".format(config["appid"], params["apptransid"], config["key1"]) # appid|apptransid|key1
params["mac"] = hmac.new(config['key1'].encode(), data.encode(), hashlib.sha256).hexdigest()
resposne = urllib.request.urlopen(url=config["endpoint"], data=urllib.parse.urlencode(params).encode())
result = json.loads(response.read())
for k, v in result.items():
print("{}: {}".format(k, v))
curl https://sandbox.zalopay.com.vn/v001/tpe/getstatusbyapptransid \
-d appid=553 \
-d apptransid=190419-123456 \
-d mac=440f389ddd834b40f21f9baed9448b530b6d7a9af722d747f3fa0af68c007c2e
API cho phép đối tác hoàn tiền toàn phần hoặc từng phần của 1 giao dịch thanh toán thành công qua ZaloPay.
HÌNH THỨC THANH TOÁN | NGUỒN TIỀN | HOÀN TIỀN VỀ | THỜI GIAN HOÀN TIỀN | NGÂN HÀNG HỖ TRỢ |
---|---|---|---|---|
Ứng dụng ZaloPay | Ví ZaloPay | Ví ZaloPay | Ngay lập tức | Vietcombank, Vietinbank, BIDV, Sacombank, Eximbank, SCB, Bản Việt, JCB |
ATM / Tài khoản ngân hàng | Ví ZaloPay | Ngay lập tức | ||
Visa / Master / JCB | Thẻ | 5 - 7 ngày làm việc | ||
Thanh toán Thẻ/Tài khoản ngân hàng qua cổng ZaloPay Gateway | ATM / Tài khoản ngân hàng | Tài khoản ngân hàng | 3 - 5 ngày làm việc (tùy ngân hàng) | ABBank, ACB, Agribank, Bắc Á Bank, Bảo Việt Bank, BIDV, Đông Á Bank, Eximbank, GP Bank, HD Bank, Liên Việt Post Bank, Maritime Bank, MB Bank, Nam Á Bank, NCB, Bản Việt, OCB, Ocean Bank, PG Bank, Sacombank, Saigon Bank, SCB, SeA Bank, SHB, Techcombank, TP Bank, VIB |
Visa / Master / JCB | Thẻ | 5 - 7 ngày làm việc (tùy ngân hàng) |
Environment | Method | Endpoint |
---|---|---|
Sandbox | POST | https://sandbox.zalopay.com.vn/v001/tpe/partialrefund |
Real | POST | https://zalopay.com.vn/v001/tpe/partialrefund |
application/x-www-form-urlencoded
Tham số |
Kiểu dữ liệu | Kích thước | Bắt buộc | Ý nghĩa |
---|---|---|---|---|
mrefundid |
String | 45 | ✔ | • Merchant phải tự gen ra mã giao dịch riêng của mình khi submit yêu cầu hoàn tiền. • Định dạng: yymmdd_appid_xxxxxxxxxx |
appid |
int | ✔ | Merchant app id đã được cấp khi đăng ký với ZaloPay. | |
zptransid |
String | 15 | ✔ | • Mã giao dịch muốn hoàn tiền. • Mã này được Zalo Pay trả về khi thanh toán. |
amount |
long | ✔ | Số tiền muốn hoàn lại cho khách hàng | |
timestamp |
long | 13 | ✔ | • Thời điểm thực hiện việc hoàn tiền (unix timestamp in milisecond). • Thời gian tính đến milisecond, và lấy theo current time |
mac |
String | ✔ | Thông tin chứng thực (xem cách tạo thông tin chứng thực bên dưới) | |
description |
String | 100 | Lý do hoàn tiền |
mac = HMAC(hmac_algorithm, key1, hmac_input)
Trong đó:
HmacSHA256
appid +"|"+ zptransid +"|"+ amount +"|"+ description +"|"+ timestamp
application/json
Tham số | Kiểu dữ liệu | Ý nghĩa |
---|---|---|
returncode |
int | 1 : Hoàn tiền giao dịch thành công |
<1 : Hoàn tiền thất bại, cần thực hiện lại giao dịch |
||
>1 : Đang hoàn tiền, gọi getRefundStatus api để lấy trạng thái cuối cùng |
||
returnmessage |
String | Thông tin lỗi |
refundid |
String | Mã giao dịch hoàn tiền của ZaloPay, cần lưu lại để đối chiếu |
/**
* .Net core 2.1.505
*/
using System;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
using ZaloPay.Helper; // HmacHelper, RSAHelper, HttpHelper, Utils (tải về ở mục DOWNLOADS)
using ZaloPay.Helper.Crypto;
using Newtonsoft.Json; // https://www.newtonsoft.com/json
namespace ZaloPayExample
{
class Program
{
static string appid = "553";
static string key1 = "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q";
static string refundUrl = "https://sandbox.zalopay.com.vn/v001/tpe/partialrefund";
static async Task Main(string[] args)
{
var timestamp = Utils.GetTimeStamp().ToString();
var rand = new Random();
var uid = timestamp+""+rand.Next(111, 999).ToString();
Dictionary<string, string> param = new Dictionary<string, string>();
param.Add("appid", appid);
param.Add("mrefundid", DateTime.Now.ToString("yyMMdd") + "_" + appid + "_" + uid);
param.Add("zptransid", "1234567");
param.Add("amount", "1000");
param.Add("timestamp", timestamp);
param.Add("description", "demo");
var data = appid + "|" + param["zptransid"] + "|" + param["amount"] + "|" + param["description"] + "|" + param["timestamp"];
param.Add("mac", HmacHelper.Compute(ZaloPayHMAC.HMACSHA256, key1, data));
var result = await HttpHelper.PostFormAsync(refundUrl, param);
foreach(var entry in result) {
Console.WriteLine("{0} = {1}", entry.Key, entry.Value);
}
}
}
}
// Java version "1.8.0_201"
import org.apache.http.NameValuePair; // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject; // https://mvnrepository.com/artifact/org.json/json
import vn.zalopay.crypto.HMACUtil; // tải về ở mục DOWNLOADS
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.Logger;
public class Refund {
private static Logger logger = Logger.getLogger(App.class.getName());
private static Map<String, String> config = new HashMap<String, String>(){{
put("appid", "553");
put("key1", "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q");
put("key2", "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3");
put("endpoint", "https://sandbox.zalopay.com.vn/v001/tpe/partialrefund");
}};
private static String getCurrentTimeString(String format) {
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT+7"));
SimpleDateFormat fmt = new SimpleDateFormat(format);
fmt.setCalendar(cal);
return fmt.format(cal.getTimeInMillis());
}
public static void main( String[] args ) throws Exception
{
String appid = config.get("appid");
Random rand = new Random();
long timestamp = System.currentTimeMillis(); // miliseconds
String uid = timestamp + "" + (111 + rand.nextInt(888)); // unique id
Map<String, Object> order = new HashMap<String, Object>(){{
put("appid", appid);
put("zptransid", 123456789);
put("mrefundid", getCurrentTimeString("yyMMdd") +"_"+ appid +"_"+uid);
put("timestamp", timestamp);
put("amount", 50000);
put("description", "ZaloPay Intergration Demo");
}};
// appid|zptransid|amount|description|timestamp
String data = order.get("appid") +"|"+ order.get("zptransid") +"|"+ order.get("amount")
+"|"+ order.get("description") +"|"+ order.get("timestamp");
order.put("mac", HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, config.get("key1"), data));
CloseableHttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost(config.get("endpoint"));
List<NameValuePair> params = new ArrayList<>();
for (Map.Entry<String, Object> e : order.entrySet()) {
params.add(new BasicNameValuePair(e.getKey(), e.getValue().toString()));
}
post.setEntity(new UrlEncodedFormEntity(params));
CloseableHttpResponse res = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
StringBuilder resultJsonStr = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
resultJsonStr.append(line);
}
JSONObject result = new JSONObject(resultJsonStr.toString());
for (String key : result.keySet()) {
System.out.format("%s = %s\n", key, result.get(key));
}
}
}
// go version go1.11.1 linux/amd64
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"strconv"
"time"
"github.com/zpmep/hmacutil" // go get github.com/zpmep/hmacutil
)
var (
appid = "553"
key1 = "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q"
key2 = "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3"
)
func main() {
params := make(url.Values)
params.Add("appid", appid)
params.Add("zptransid", "190508000000017")
params.Add("amount", "50000")
params.Add("description", "ZaloPay Refund Demo")
now := time.Now()
timestamp := now.UnixNano() / int64(time.Millisecond) // Miliseconds
params.Add("timestamp", strconv.FormatInt(timestamp, 10))
uid := fmt.Sprintf("%d%d", timestamp, 111+rand.Intn(888))
params.Add("mrefundid", fmt.Sprintf("%02d%02d%02d_%v_%v", now.Year()%100, int(now.Month()), now.Day(), appid, uid))
// appid|zptransid|amount|description|timestamp
data := fmt.Sprintf("%v|%v|%v|%v|%v", appid, params.Get("zptransid"), params.Get("amount"), params.Get("description"), params.Get("timestamp"))
params.Add("mac", hmacutil.HexStringEncode(hmacutil.SHA256, key1, data))
log.Printf("%+v", params)
// Content-Type: application/x-www-form-urlencoded
res, err := http.PostForm("https://sandbox.zalopay.com.vn/v001/tpe/partialrefund", params)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
var result map[string]interface{}
if err := json.Unmarshal(body, &result); err != nil {
log.Fatal(err)
}
for k, v := range result {
log.Printf("%s = %v", k, v)
}
}
// Node v10.15.3
const axios = require('axios').default; // npm install axios
const CryptoJS = require('crypto-js'); // npm install crypto-js
const moment = require('moment'); // npm install moment
const config = {
appid: "553",
key1: "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
key2: "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
endpoint: "https://sandbox.zalopay.com.vn/v001/tpe/partialrefund"
};
const timestamp = Date.now();
const uid = `${timestamp}${Math.floor(111 + Math.random() * 999)}`; // unique id
let params = {
appid: config.appid,
mrefundid: `${moment().format('YYMMDD')}_${config.appid}_${uid}`,
timestamp, // miliseconds
zptransid: '190508000000022',
amount: '50000',
description: 'ZaloPay Refund Demo',
};
// appid|zptransid|amount|description|timestamp
let data = params.appid + "|" + params.zptransid + "|" + params.amount + "|" + params.description + "|" + params.timestamp;
params.mac = CryptoJS.HmacSHA256(data, config.key1).toString();
axios.post(config.endpoint, null, { params })
.then(res => console.log(res.data))
.catch(err => console.log(err));
<?php
// PHP Version 7.3.3
$config = [
"appid" => 553,
"key1" => "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
"key2" => "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
"endpoint" => "https://sandbox.zalopay.com.vn/v001/tpe/partialrefund"
];
$timestamp = round(microtime(true) * 1000); // miliseconds
$uid = "$timestamp".rand(111,999); // unique id
$params = [
"appid" => $config["appid"],
"mrefundid" => date("ymd")."_".$config["appid"]."_".$uid,
"timestamp" => $timestamp,
"zptransid" => 123456789,
"amount" => 50000,
"description" => "ZaloPay Intergration Demo"
];
// appid|zptransid|amount|description|timestamp
$data = $params["appid"]."|".$params["zptransid"]."|".$params["amount"]
."|".$params["description"]."|".$params["timestamp"];
$params["mac"] = hash_hmac("sha256", $data, $config["key1"]);
$context = stream_context_create([
"http" => [
"header" => "Content-type: application/x-www-form-urlencoded\r\n",
"method" => "POST",
"content" => http_build_query($params)
]
]);
$resp = file_get_contents($config["endpoint"], false, $context);
$result = json_decode($resp, true);
foreach ($result as $key => $value) {
echo "$key: $value<br>";
}
# ruby 2.5.1p57
require 'json'
require 'openssl'
require 'net/http'
config = {
appid: '553',
key1: '9phuAOYhan4urywHTh0ndEXiV3pKHr5Q',
key2: 'Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3',
endpoint: 'https://sandbox.zalopay.com.vn/v001/tpe/partialrefund'
}
appid = config[:appid]
timestamp = (Time.now.to_f.round(3) * 1000).to_i
uid = timestamp.to_s + '' + (111 + Random.rand(888)).to_s # unique id
mrefundid = Time.now.strftime('%y%m%d') + '_' + appid + '_' + uid
order = {
appid: appid,
zptransid: "123456789",
mrefundid: mrefundid,
timestamp: timestamp,
amount: 50_000,
description: 'ZaloPay Integration Demo',
}
# appid|zptransid|amount|description|timestamp
data = appid + '|' + order[:zptransid] + '|' + order[:amount].to_s + '|' + order[:description] + '|' + order[:timestamp].to_s
order[:mac] = OpenSSL::HMAC.hexdigest('sha256', config[:key1], data)
res = Net::HTTP.post_form(URI.parse(config[:endpoint]), order)
result = JSON.parse(res.body)
result.each do |key, value|
puts "#{key}: #{value}"
end
# coding=utf-8
# Python 3.6
from time import time
from datetime import datetime
import random, json, hmac, hashlib, urllib.request, urllib.parse
config = {
"appid": 553,
"key1": "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
"key2": "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
"endpoint": "https://sandbox.zalopay.com.vn/v001/tpe/partialrefund"
}
timestamp = int(round(time() * 1000)) # miliseconds
uid = "{}{}".format(timestamp, random.randint(111, 999)) # unique id
order = {
"appid": config["appid"],
"mrefundid": "{:%y%m%d}_{}_{}".format(datetime.today(), config["appid"], uid),
"timestamp": timestamp,
"zptransid": 123456789,
"amount": 1000,
"description": "ZaloPay Integration Demo",
}
# appid|zptransid|amount|description|timestamp
data = "{}|{}|{}|{}|{}".format(order["appid"], order["zptransid"], order["amount"], order["description"], order["timestamp"])
order["mac"] = hmac.new(config['key1'].encode(), data.encode(), hashlib.sha256).hexdigest()
response = urllib.request.urlopen(url=config["endpoint"], data=urllib.parse.urlencode(order).encode())
result = json.loads(response.read())
for k, v in result.items():
print("{}: {}".format(k, v))
curl -X POST https://sandbox.zalopay.com.vn/v001/tpe/partialrefund \
-H "Content-type: application/x-www-form-urlencoded" \
-d appid=553 \
-d mrefundid=190419_553_352a73a0-6249-11e9-b146-9306e752a45c \
-d timestamp=1555640217561 \
-d zptransid=1234567 \
-d amount=1000 \
-d description='ZaloPay Integration Demo' \
-d mac=5d826b55da6b97525d3eb80a7484922300ae5e2be7d51a35be8e34763a899d73
API cho phép đối tác gọi để truy vấn tình trạng hoàn tiền của 1 giao dịch hoàn tiền.
Environment | Method | Endpoint |
---|---|---|
Sandbox | POST | https://sandbox.zalopay.com.vn/v001/tpe/getpartialrefundstatus |
Real | POST | https://zalopay.com.vn/v001/tpe/getpartialrefundstatus |
application/x-www-form-urlencoded
Tham số |
Kiểu dữ liệu | Kích thước | Bắt buộc | Ý nghĩa |
---|---|---|---|---|
appid |
String | ✔ | appid của merchant được cung cấp |
|
mrefundid |
String | 45 | ✔ | • Mã giao dịch merchant tự gen đã truyền qua lúc gọi hoàn tiền. • Định dạng: yymmdd_appid_xxxxxxxxxx |
timestamp |
long | ✔ | Thời điểm gọi api (timestamp in milisecond) | |
mac |
String | ✔ | = HMAC(hmac_algorithm, key1, appid+"|"+mrefundid+"|"+timestamp) |
application/json
Tham số | Kiểu dữ liệu | Ý nghĩa |
---|---|---|
returncode |
int | Mã lỗi |
returnmessage |
String | Thông tin lỗi |
Mã lỗi | Miêu tả ngắn | Ý nghĩa |
---|---|---|
2 |
IN_REFUND_QUEUE | Giao dịch đang được hoàn tiền. |
1 |
REFUND_SUCCESS | Refund thành công. |
0 |
EXCEPTION | Refund có lỗi. |
-1 |
REFUND_PENDING | Refund thất bại. |
-3 |
MAC_INVALID | Sai thông tin chứng thực. |
-10 |
APPID_INVALID | Sai thông tin app. |
-13 |
REFUND_EXPIRE_TIME | Quá thời hạn cho phép hoàn tiền. |
-24 |
INVALID_MERCHANT_REFUNDID_FORMAT | Sai định dạng mrefundid . |
-25 |
INVALID_MERCHANT_REFUNDID_DATE | mrefundid có thời gian không đúng. |
-26 |
INVALID_MERCHANT_REFUNDID_APPID | mrefundid có appId không đúng. |
/**
* .Net core 2.1.505
*/
using System;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
using ZaloPay.Helper; // HmacHelper, RSAHelper, HttpHelper, Utils (tải về ở mục DOWNLOADS)
using ZaloPay.Helper.Crypto;
using Newtonsoft.Json; // https://www.newtonsoft.com/json
namespace ZaloPayExample
{
class Program
{
static string appid = "553";
static string key1 = "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q";
static string getRefundStatusUrl = "https://sandbox.zalopay.com.vn/v001/tpe/getpartialrefundstatus";
static async Task Main(string[] args)
{
Dictionary<string, string> param = new Dictionary<string, string>();
param.Add("appid", appid);
param.Add("timestamp", "123456789");
param.Add("mrefundid", "190308_553_xxxxxx");
var data = appid + "|" + param["mrefundid"] + "|" + param["timestamp"];
param.Add("mac", HmacHelper.Compute(ZaloPayHMAC.HMACSHA256, key1, data));
var result = await HttpHelper.PostFormAsync(getRefundStatusUrl, param);
foreach(var entry in result) {
Console.WriteLine("{0} = {1}", entry.Key, entry.Value);
}
}
}
}
// Java version "1.8.0_201"
import org.apache.http.NameValuePair; // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject; // https://mvnrepository.com/artifact/org.json/json
import vn.zalopay.crypto.HMACUtil; // tải về ở mục DOWNLOADS
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
public class GetRefundStatus {
private static Logger logger = Logger.getLogger(App.class.getName());
private static Map<String, String> config = new HashMap<String, String>(){{
put("appid", "553");
put("key1", "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q");
put("key2", "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3");
put("endpoint", "https://sandbox.zalopay.com.vn/v001/tpe/getpartialrefundstatus");
}};
public static void main(String[] args) throws Exception {
String mrefundid = "190308_553_123456";
String timestamp = Long.toString(System.currentTimeMillis()); // miliseconds
String data = config.get("appid") +"|"+ mrefundid +"|"+ timestamp; // appid|mrefundid|timestamp
String mac = HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, config.get("key1"), data);
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("appid", config.get("appid")));
params.add(new BasicNameValuePair("mrefundid", mrefundid));
params.add(new BasicNameValuePair("timestamp", timestamp));
params.add(new BasicNameValuePair("mac", mac));
URIBuilder uri = new URIBuilder(config.get("endpoint"));
uri.addParameters(params);
CloseableHttpClient client = HttpClients.createDefault();
HttpGet get = new HttpGet(uri.build());
CloseableHttpResponse res = client.execute(get);
BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
StringBuilder resultJsonStr = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
resultJsonStr.append(line);
}
JSONObject result = new JSONObject(resultJsonStr.toString());
for (String key : result.keySet()) {
System.out.format("%s = %s\n", key, result.get(key));
}
}
}
// go version go1.11.1 linux/amd64
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"strconv"
"github.com/zpmep/hmacutil" // go get github.com/zpmep/hmacutil
)
var (
appid = "553"
key1 = "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q"
key2 = "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3"
)
func main() {
params := make(url.Values)
params.Add("appid", "553")
params.Add("mrefundid", "190308_553_123456")
params.Add("timestamp", strconv.Itoa(12345678910)) // miliseconds
data := fmt.Sprintf("%v|%v|%v", appid, params.Get("mrefundid"), params.Get("timestamp")) // appid|mrefundid|timestamp
params.Add("mac", hmacutil.HexStringEncode(hmacutil.SHA256, key1, data))
res, err := http.Get("https://sandbox.zalopay.com.vn/v001/tpe/getpartialrefundstatus?" + params.Encode())
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
var result map[string]interface{}
if err := json.Unmarshal(body, &result); err != nil {
log.Fatal(err)
}
for k, v := range result {
log.Printf("%s = %+v", k, v)
}
}
// Node v10.15.3
const axios = require('axios').default; // npm install axios
const CryptoJS = require('crypto-js'); // npm install crypto-js
const config = {
appid: "553",
key1: "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
key2: "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
endpoint: "https://sandbox.zalopay.com.vn/v001/tpe/getpartialrefundstatus"
};
const params = {
appid: config.appid,
timestamp: Date.now(), // miliseconds
mrefundid: "190312_553_123456",
};
const data = config.appid + "|" + params.mrefundid + "|" + params.timestamp; // appid|mrefundid|timestamp
params.mac = CryptoJS.HmacSHA256(data, config.key1).toString()
axios.get(config.endpoint, { params })
.then(res => console.log(res.data))
.catch(err => console.log(err));
<?php
// PHP Version 7.3.3
$config = [
"appid" => 553,
"key1" => "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
"key2" => "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
"endpoint" => "https://sandbox.zalopay.com.vn/v001/tpe/getpartialrefundstatus"
];
$mrefundid = "190308_553_123456";
$timestamp = round(microtime(true) * 1000); // miliseconds
$data = $config["appid"]."|".$mrefundid."|".$timestamp; // appid|mrefundid|timestamp
$params = [
"appid" => $config["appid"],
"timestamp" => $timestamp,
"mrefundid" => $mrefundid,
"mac" => hash_hmac("sha256", $data, $config["key1"])
];
$resp = file_get_contents($config["endpoint"]."?".http_build_query($params));
$result = json_decode($resp, true);
foreach ($result as $key => $value) {
echo "$key: $value<br>";
}
# ruby 2.5.1p57
require 'json'
require 'openssl' # gem install openssl
require 'net/http'
config = {
appid: '553',
key1: '9phuAOYhan4urywHTh0ndEXiV3pKHr5Q',
key2: 'Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3',
endpoint: 'https://sandbox.zalopay.com.vn/v001/tpe/getpartialrefundstatus'
}
params = {
appid: config[:appid],
mrefundid: "190312_553_123456",
timestamp: (Time.now.to_f.round(3) * 1000).to_i # miliseconds
}
data = config[:appid] +"|"+ params[:mrefundid] +"|"+ params[:timestamp].to_s # appid|mrefundid|timestamp
params[:mac] = OpenSSL::HMAC.hexdigest('sha256', config[:key1], data)
uri = URI(config[:endpoint])
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
result = JSON.parse(res.body)
result.each do |key, value|
puts "#{key}: #{value}"
end
# coding=utf-8
# Python 3.6
from time import time
import hmac, hashlib, urllib.parse, urllib.request
config = {
"appid": 553,
"key1": "9phuAOYhan4urywHTh0ndEXiV3pKHr5Q",
"key2": "Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3",
"endpoint": "https://sandbox.zalopay.com.vn/v001/tpe/getpartialrefundstatus"
}
params = {
"appid": config["appid"],
"timestamp": int(round(time() * 1000)), # miliseconds
"mrefundid": "190409_553_123456",
}
data = "{}|{}|{}".format(config["appid"], params["mrefundid"], params["timestamp"]) # appid|mrefundid|timestamp
params["mac"] = hmac.new(config["key1"].encode(), data.encode(), hashlib.sha256).hexdigest()
resposne = urllib.request.urlopen(url=config["endpoint"], data=urllib.parse.urlencode(params).encode())
result = json.loads(response.read())
for k, v in result.items():
print("{}: {}".format(k, v))
curl https://sandbox.zalopay.com.vn/v001/tpe/getpartialrefundstatus \
-d appid=553 \
-d timestamp=1555640469224 \
-d mrefundid=190308_553_123456 \
-d mac=4255035bae2e65118887bc17110ab4b43a1cdd7c513aad9b25a5ef27e187196e