App server establish order information then send to ZaloPay server to create order.
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
The order includes the following information:
Parameter |
DataType | Length | Required | Description | Example |
---|---|---|---|---|---|
appid |
int | ✔ | Identification of the application that was provided by ZaloPay. | 1 |
|
appuser |
String | 50 | ✔ | Identification information of the application user. Ex: Id/Username/Name/Phone/Email. | user123 |
apptime |
long | ✔ | The time of order creation, which calculated in milliseconds, and couldn't over 15 minutes from the time of payment | 1459823610957 |
|
amount |
long | ✔ | The amount of the order (VND) | 50000 |
|
apptransid |
String | 40 | ✔ | Order's transaction code. Must be preceded by yymmdd of the current date. The transaction-code's format should be yymmdd_Order-identifier Note: yymmdd is correct TimeZone Vietnam (GMT+7) (Because of cross check transactions is in Vietnam time and date) ' |
180208_007242 |
embeddata |
String | 1024 | ✔ | Application's own data. This will be returned to AppServer upon successful payment (Callback). If not, then leave the empty string | {"promotioninfo":"","merchantinfo":"du lieu rieng cua ung dung"} |
item |
String | 2048 | ✔ | Order's item, defined by the application itself | [{"itemid":"knb","itename":"kim nguyen bao","itemprice":198400,"itemquantity":1}] |
mac |
String | ✔ | Authentication information of the order, see how to create authentication information for orders | c8f49d523336f0a182586a70b71c20da96 4d37954711de9273152b500df74c0d |
|
bankcode |
String | 20 | ✔ (*) | Bank code, See how to get the list of supported banks | VTB |
description |
String | 256 | The description of the order, used to display to users on the ZaloPay app | <Merchant/Service name> - Payment for the order #<Order ID> Example: Lazada - Payment for the order #180208_007242 |
|
phone |
String | 50 | User's phone number | 0934568239 |
|
email |
String | 100 | User's email | example@gmail.com |
|
address |
String | 1024 | User's address | TPHCM |
|
subappid |
String | 50 | Identification of the service / service group that partner was registered with ZaloPay (only applicable to special partners) | sub123 |
Name |
DataType | Format | Description | Example |
---|---|---|---|---|
redirecturl |
String | URL | Redirect to this url after successful / failure payment via ZaloPay Gateway (This will override the merchant's redirect url registered with ZaloPay) |
{"redirecturl": "https://docs.zalopay.vn/result"} |
columninfo |
JSON String | {"column_name": "value"} |
Add information into the section Quản lý giao dịch chi tiết on Merchant site, If the column does not yet exist, please go to the Cài đặt hiển thị dữ liệu setting to configure Note: For offline payment, it is necessary to transmit information such as 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"} |
Use to launch promotions campaign | {"promotioninfo": "{\"campaigncode\":\"blackfriday\"}"} |
zlppaymentid |
String | -Payment information -Only needed when you need to receive money for different accounts. -ZaloPay system will generate a Payment code (corresponding to each partner bank account provided) and send it back to the partner to set up. |
{"zlppaymentid": "P4201372"} |
mac = HMAC(hmac_algorihtm, key1, hmac_input)
With:
HmacSHA256
appid +”|”+ apptransid +”|”+ appuser +”|”+ amount +"|"+ apptime +”|”+ embeddata +"|"+ item
Example:
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
Parameter |
Datatype | Description |
---|---|---|
returncode |
int |
|
returnmessage |
String | Details of the status code |
orderurl |
String | Used to create QR code or forward users to ZaloPay Gateway page |
zptranstoken |
String | Combine with appid to create QR code Deprecated Example: |
Example:
{
"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 (download at DOWNLOADS page)
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); // the trading code must be in the format 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; // download at DOWNLOADS page
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()); // the trading code must be in the format 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)) // the trading code must be in the format 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()}`, // the trading code must be in the format 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(), // the trading code must be in the format 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, # the trading code must be in the format 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()), # the trading code must be in the format 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
Merchant Server receives payment's results from ZaloPay Server, only when ZaloPay has received money from user successfully
If ZaloPay successfully get money from user, then ZaloPayServer will callback to MerchantServer by CallbackURL
which had been registered with ZaloPay. MerchantServer use key2
(provided by ZaloPay) to validate callback's data. Merchant can check callback log in Sandbox
environment at Dev Tool on Merchant Site
application/json
Name | DataType | Description |
---|---|---|
data |
Json String | ZaloPay transaction data callback to the application |
mac |
String | Confirmation of order information, using Callback Key (Key2) (had been provided) to verify the order |
Data field:
Name |
DataType | Description | Example |
---|---|---|---|
appid |
long | Order's appid |
5 |
apptransid |
String | Order's apptransid |
180208181007242 |
apptime |
long | Order's apptime |
1460543835849 |
appuser |
String | Order's appuser |
pmqc |
amount |
long | Amount received (VND) | 50000 |
embeddata |
String | Order's embeddata |
{"promotioninfo":"","merchantinfo":"du lieu rieng cua ung dung"} |
item |
String | Order's item |
[{"itemid":"knb","itename":"kim nguyen bao","itemprice":198400,"itemquantity":1}] |
zptransid |
long | ZaloPay's Transaction code | 160413000003083 |
servertime |
long | ZaloPay's Transaction trading time (unix timestamp in milliseconds)' | 1460543836370 |
channel |
int | Payment channel | 38 |
merchantuserid |
string | ZaloPay user, who paid for the order | |
userfeeamount |
long | Fee (VND) | 220 |
discountamount |
long | Discount (VND) | 10000 |
Example:
{
"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) {
// valid callback
} else {
// invalid callback
}
With:
HmacSHA256
Value | Payment channel |
---|---|
36 |
Visa/Master/JCB |
37 |
Bank Account |
38 |
ZaloPay Wallet |
39 |
ATM |
41 |
Visa/Master Debit |
application/json
Parameter | Datatype | Description |
---|---|---|
returncode |
int |
|
returnmessage |
String | Details of the status code |
Example:
{
"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 (download at DOWNLOADS page)
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);
// check if the callback is valid (from ZaloPay server)
if (!reqMac.Equals(mac)) {
// callback is invalid
result["returncode"] = -1;
result["returnmessage"] = "mac not equal";
}
else {
// payment success
// merchant update status for order's status
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; // callback again (up to 3 times)
result["returnmessage"] = ex.Message;
}
// returns the result for 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();
// check if the callback is valid (from ZaloPay server)
if (!reqMac.equals(mac)) {
// callback is invalid
result.put("returncode", -1);
result.put("returnmessage", "mac not equal");
} else {
// payment success
// merchant update status for order's status
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); // callback again (up to 3 times)
result.put("returnmessage", ex.getMessage());
}
// returns the result for 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{})
// check if the callback is valid (from ZaloPay server)
if mac != requestMac {
// callback is invalid
result["returncode"] = -1
result["returnmessage"] = "mac not equal"
} else {
// payment success
result["returncode"] = 1
result["returnmessage"] = "success"
// merchant update status for order's status
var dataJSON map[string]interface{}
json.Unmarshal([]byte(dataStr), &dataJSON)
log.Println("update order's status = success where apptransid =", dataJSON["apptransid"])
}
// returns the result for 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);
// check if the callback is valid (from ZaloPay server)
if (reqMac !== mac) {
// callback is invalid
result.returncode = -1;
result.returnmessage = "mac not equal";
}
else {
// payment success
// merchant update status for order's status
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; // callback again (up to 3 times)
result.returnmessage = ex.message;
}
// returns the result for 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"];
// check if the callback is valid (from ZaloPay server)
if (strcmp($mac, $requestmac) != 0) {
// callback is invalid
$result["returncode"] = -1;
$result["returnmessage"] = "mac not equal";
} else {
// payment success
// merchant update status for order's status
$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; // callback again (up to 3 times)
$result["returnmessage"] = $e->getMessage();
}
// returns the result for 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'])
# check if the callback is valid (from ZaloPay server)
if cbdata['mac'] != mac
# callback is invalid
result[:returncode] = -1
result[:returnmessage] = "mac not equal"
else
# payment success
# merchant update status for order's status
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 # callback again (up to 3 times)
result[:returnmessage] = ex.message
end
# returns the result for 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()
# check if the callback is valid (from ZaloPay server)
if mac != cbdata['mac']:
# callback is invalid
result['returncode'] = -1
result['returnmessage'] = 'mac not equal'
else:
# payment success
# merchant update status for order's status
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 # callback again (up to 3 times)
result['returnmessage'] = str(e)
# returns the result for ZaloPay server
return json.jsonify(result)
When the payment is successful, ZaloPay will call the callback (notify) to the Merchant, then the Merchant updates the status of Successful orders on the Merchant's system. But in reality, the callback may be missed due to Network timeout, Merchant Service unavailable Internal error, ... so Merchant needs to make the call of the API to query the order status.
Merchant Server send request to ZaloPay Server to get the transaction's payment status.
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
Parameter |
Datatype | Required | Description |
---|---|---|---|
appid |
int | ✔ | Order's appid |
apptransid |
String | ✔ | Order's apptransid |
mac |
String | ✔ | • Authenticate data information' • = HMAC(hmac_algorithm, key1, appid+"|"+apptransid+"|"+key1) |
application/json
Parameter |
Datatype | Description |
---|---|---|
returncode |
int | 1 : successful <> : not paid / fail / timeout |
returnmessage |
String | Order's status information |
isprocessing |
boolean | true : processing false : not paid / completed |
amount |
long | Purchase amount |
discountamount |
long | Discount |
zptransid |
long | ZaloPay's transaction code |
/**
* .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 (download at DOWNLOADS page)
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; // download at DOWNLOADS page
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 allows to refund all or a part of the transaction's amount that has been successfully paid via ZaloPay.
PAYMENT METHOD | WALLET | REFUND TO | REFUND TIME | SUPPORTED BANKS |
---|---|---|---|---|
ZaloPay App | ZaloPay Walet | ZaloPay Walet | Immediately | Vietcombank, Vietinbank, BIDV, Sacombank, Eximbank, SCB, Viet Capital Bank, JCB |
ATM / Bank Account | ZaloPay Walet | Immediately | ||
Visa / Master / JCB | Card | 5 - 7 working days | ||
Card payment / Bank Account via ZaloPay Gateway | ATM / Bank Account | Bank Account | 3 - 5 working days (depend on the bank) | ABBank, ACB, Agribank, Bac A Bank, Bao Viet Bank, BIDV, DongA Bank, Eximbank, GP Bank, HD Bank, Lien Viet Post Bank, Maritime Bank, MB Bank, NamA Bank, NCB, Viet Capital Bank, OCB, Ocean Bank, PG Bank, Sacombank, Saigon Bank, SCB, SeA Bank, SHB, Techcombank, TP Bank, VIB |
Visa / Master / JCB | Card | 5 - 7 working days (depend on the bank) |
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
Parameter |
Datatype | Length | Required | Description |
---|---|---|---|---|
mrefundid |
String | 45 | ✔ | • Merchant must be generate merchant own transaction code when submit refund requirement. • Format: yymmdd_appid_xxxxxxxxxx |
appid |
int | ✔ | Merchant app id, which was provided by ZaloPay when registering. | |
zptransid |
String | 15 | ✔ | • Transaction code, which want to be refund. • Transaction code of ZaloPay, retrieved from callback data |
amount |
long | ✔ | Refund amount for users | |
timestamp |
long | 13 | ✔ | • Time to refund (unix timestamp in millisecond). • The time of making the refund, is calculated in milliseconds |
mac |
String | ✔ | Authenticate information (See how to create authenticate information) | |
description |
String | 100 | Refund reason |
mac = HMAC(hmac_algorithm, key1, hmac_input)
With:
HmacSHA256
appid +"|"+ zptransid +"|"+ amount +"|"+ description +"|"+ timestamp
application/json
Parameter | Datatype | Description |
---|---|---|
returncode |
int | 1 : Successful refund |
<1 : Refund failure, need to redo |
||
>1 : Refunding processing, call getRefundStatus API to get final result |
||
returnmessage |
String | Error code information |
refundid |
String | ZaloPay refund's transaction code, need to save for cross-check then |
/**
* .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 (download at DOWNLOADS page)
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; // download at DOWNLOADS page
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 is agree merchant to query the refund status of the Refund transaction.
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
Parameter |
Datatype | Length | Required | Description |
---|---|---|---|---|
appid |
String | ✔ | appid provided by ZaloPay |
|
mrefundid |
String | 45 | ✔ | • The transaction code, which was generated by merchant when querying refund transaction. • Format: yymmdd_appid_xxxxxxxxxx |
timestamp |
long | ✔ | The time call API (timestamp in millisecond) | |
mac |
String | ✔ | = HMAC(hmac_algorithm, key1, appid+"|"+mrefundid+"|"+timestamp) |
application/json
Parameter | Datatype | Description |
---|---|---|
returncode |
int | error code |
returnmessage |
String | error information |
Error code | Short description | Meaning |
---|---|---|
2 |
IN_REFUND_QUEUE | The transaction is being refunding. |
1 |
REFUND_SUCCESS | Successful refund. |
0 |
EXCEPTION | An error occurred. |
-1 |
REFUND_PENDING | Refund failed. |
-3 |
MAC_INVALID | Invalid authentication infor. |
-10 |
APPID_INVALID | Invalid app info. |
-13 |
REFUND_EXPIRE_TIME | Over the time allow refund. |
-24 |
INVALID_MERCHANT_REFUNDID_FORMAT | Invalid mrefundid . |
-25 |
INVALID_MERCHANT_REFUNDID_DATE | mrefundid 's time [ yymmdd ] invalid format. |
-26 |
INVALID_MERCHANT_REFUNDID_APPID | mrefundid 's appid is invalid. |
/**
* .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 (download at DOWNLOADS page)
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; // download at DOWNLOADS page
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