// Java version "1.8.0_201"importorg.apache.http.NameValuePair;// https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclientimportorg.apache.http.client.methods.CloseableHttpResponse;importorg.apache.http.client.methods.HttpGet;importorg.apache.http.client.utils.URIBuilder;importorg.apache.http.impl.client.CloseableHttpClient;importorg.apache.http.impl.client.HttpClients;importorg.apache.http.message.BasicNameValuePair;importorg.json.JSONObject;// https://mvnrepository.com/artifact/org.json/jsonimportorg.json.JSONArray;importvn.zalopay.crypto.HMACUtil;// download at DOWNLOADS pageimportjava.io.BufferedReader;importjava.io.InputStreamReader;importjava.util.*;publicclassGetBankList{privatestaticMap<String,String>config=newHashMap<String,String>(){{put("appid","2553");put("key1","PcY4iZIKFCIdgZvA6ueMcMHHUbRLYjPL");put("key2","kLtgPl8HHhfvMuDHPwKfgfsY4Ydm9eIz");put("endpoint","https://sbgateway.zalopay.vn/api/getlistmerchantbanks");}};publicstaticvoidmain(String[]args)throwsException{Stringappid=config.get("appid");Stringreqtime=Long.toString(System.currentTimeMillis());Stringdata=appid+"|"+reqtime;Stringmac=HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256,config.get("key1"),data);List<NameValuePair>params=newArrayList<>();params.add(newBasicNameValuePair("appid",appid));params.add(newBasicNameValuePair("reqtime",reqtime));// milisecondsparams.add(newBasicNameValuePair("mac",mac));URIBuilderuri=newURIBuilder(config.get("endpoint"));uri.addParameters(params);CloseableHttpClientclient=HttpClients.createDefault();HttpGetget=newHttpGet(uri.build());CloseableHttpResponseres=client.execute(get);BufferedReaderrd=newBufferedReader(newInputStreamReader(res.getEntity().getContent()));StringBuilderresultJsonStr=newStringBuilder();Stringline;while((line=rd.readLine())!=null){resultJsonStr.append(line);}JSONObjectresult=newJSONObject(resultJsonStr.toString());JSONObjectbanksObject=result.getJSONObject("banks");System.out.format("returncode = %s",result.getInt("returncode"));System.out.format("returnmessage = %s",result.getString("returnmessage"));for(Stringpmcid:banksObject.keySet()){JSONArraybanks=banksObject.getJSONArray(pmcid);banks.forEach(bank->{System.out.format("%s. %s\n",pmcid,bank.toString());});}}}
// go version go1.11.1 linux/amd64packagemainimport("encoding/json""fmt""io/ioutil""log""net/http""net/url""strconv""time""github.com/zpmep/hmacutil"// go get github.com/zpmep/hmacutil)var(appid="2553"key1="PcY4iZIKFCIdgZvA6ueMcMHHUbRLYjPL"key2="kLtgPl8HHhfvMuDHPwKfgfsY4Ydm9eIz")funcmain(){params:=make(url.Values)params.Add("appid","2553")params.Add("reqtime",strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond),10))// milisecondsdata:=fmt.Sprintf("%v|%v",params.Get("appid"),params.Get("reqtime"))//appid|reqtimeparams.Add("mac",hmacutil.HexStringEncode(hmacutil.SHA256,key1,data))res,err:=http.Get("https://sbgateway.zalopay.vn/api/getlistmerchantbanks?"+params.Encode())iferr!=nil{log.Fatal(err)}deferres.Body.Close()body,_:=ioutil.ReadAll(res.Body)varresultmap[string]interface{}iferr:=json.Unmarshal(body,&result);err!=nil{log.Fatal(err)}fork,v:=rangeresult{log.Printf("%s = %+v",k,v)}}
After the user has finished paying, they will be redirected to the Merchant page (according to RedirectURL Merchant provided to ZaloPay) to display the results.
The query string data when ZaloPay redirect to the Merchant page
Use to check redirect is valid or not HMAC(hmac_algorithm, key2, appid +"|"+ apptransid +"|"+ pmcid +"|"+ bankcode +"|"+ amount +"|"+ discountamount +"|"+ status)
Sample code
/*
ASP.Net core
*/usingMicrosoft.AspNetCore.Mvc;usingZaloPay.Helper;// HmacHelper, RSAHelper, HttpHelper, Utils (download at DOWNLOADS page)usingZaloPay.Helper.Crypto;namespaceZaloPayExample.Controllers{[Route("[controller]")][ApiController]publicclassRedirectController:ControllerBase{privatestringkey2="Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3";[HttpGet]publicIActionResultGet(){vardata=Request.Query;varchecksumData=data["appid"]+"|"+data["apptransid"]+"|"+data["pmcid"]+"|"+data["bankcode"]+"|"+data["amount"]+"|"+data["discountamount"]+"|"+data["status"];varchecksum=HmacHelper.Compute(ZaloPayHMAC.HMACSHA256,key2,checksumData);if(!checksum.Equals(data["checksum"])){returnStatusCode(400,"Bad Request");}else{// check if the callback has been received, if not Merchant should use getOrderStatus API to get final resultreturnStatusCode(200,"OK");}}}}
importorg.json.JSONObject;importorg.springframework.http.ResponseEntity;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importjavax.crypto.Mac;importjavax.crypto.spec.SecretKeySpec;importjavax.xml.bind.DatatypeConverter;importjava.util.Map;importjava.util.logging.Logger;@ControllerpublicclassRedirectController{privateLoggerlogger=Logger.getLogger(this.getClass().getName());privateStringkey2="Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3";privateMacHmacSHA256;publicRedirectController()throwsException{HmacSHA256=Mac.getInstance("HmacSHA256");HmacSHA256.init(newSecretKeySpec(key2.getBytes(),"HmacSHA256"));}@GetMapping("/redirect-from-zalopay")publicResponseEntityredirect(@RequestParamMap<String,String>data){StringchecksumData=data.get("appid")+"|"+data.get("apptransid")+"|"+data.get("pmcid")+"|"+data.get("bankcode")+"|"+data.get("amount")+"|"+data.get("discountamount")+"|"+data.get("status");byte[]checksumBytes=HmacSHA256.doFinal(checksumData.getBytes());Stringchecksum=DatatypeConverter.printHexBinary(checksumBytes).toLowerCase();JSONObjectresult=newJSONObject();if(!checksum.equals(data.get("checksum"))){returnResponseEntity.badRequest().body("Bad Request");}else{// check if the callback has been received, if not Merchant should use getOrderStatus API to get final resultreturnResponseEntity.ok("OK");}}}
// go version go1.11.1 linux/amd64packagemainimport("fmt""log""net/http""github.com/zpmep/hmacutil")// App configvar(key2="Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3")funcmain(){mux:=http.DefaultServeMuxmux.HandleFunc("/redirect-from-zalopay",func(whttp.ResponseWriter,r*http.Request){r.ParseForm()data:=r.FormchecksumData:=data.Get("appid")+"|"+data.Get("apptransid")+"|"+data.Get("pmcid")+"|"+data.Get("bankcode")+"|"+data.Get("amount")+"|"+data.Get("discountamount")+"|"+data.Get("status")checksum:=hmacutil.HexStringEncode(hmacutil.SHA256,key2,checksumData)ifchecksum!=data.Get("checksum"){w.WriteHeader(400)fmt.Fprint(w,"Bad Request")}else{// check if the callback has been received, if not Merchant should use getOrderStatus API to get final resultfmt.Fprint(w,"Ok")}})log.Println("Server is listening at port :8001")http.ListenAndServe(":8001",mux)}
// Node v10.15.3constCryptoJS=require('crypto-js');constexpress=require('express');constapp=express();constconfig={key2:"Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3"};app.get('/redirect-from-zalopay',(req,res)=>{letdata=req.query;letchecksumData=data.appid+'|'+data.apptransid+'|'+data.pmcid+'|'+data.bankcode+'|'+data.amount+'|'+data.discountamount+'|'+data.status;letchecksum=CryptoJS.HmacSHA256(checksumData,config.key2).toString();if(checksum!=data.checksum){res.sendStatus(400);}else{// check if the callback has been received, if not Merchant should use getOrderStatus API to get final resultres.sendStatus(200);}});app.listen(8001,function(){console.log('Server is listening at port :8001');});
<?php// PHP Version 7.3.3
$key2="Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3";$data=$GET;$checksumData=$data["appid"]."|".$data["apptransid"]."|".$data["pmcid"]."|".$data["bankcode"]."|".$data["amount"]."|".$data["discountamount"]."|".$data["status"];$checksum=hash_hmac("sha256",$checksumData,$key2);if(strcmp($mac,$data["checksum"])!=0){http_response_code(400);echo"Bad Request";}else{// check if the callback has been received, if not Merchant should use getOrderStatus API to get final result
http_response_code(200);echo"Ok";}
# ruby 2.5.1p57# rails 5.2.3# config/routes.rb# Rails.application.routes.draw do# match '/redirect-from-zalopay' => 'redirect#handle', via: :get# end# app/controllers/redirect_controller.rbrequire'json'require'openssl'classRedirectController<ApplicationControllerdefinitializesuper@config={key2: 'Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3'}end# POST /callbackdefhandledata=request.query_parameterschecksumData=data["appid"]+"|"+data["apptransid"]+"|"+data["pmcid"]+"|"+data["bankcode"]+"|"+data["amount"]+"|"+data["discountamount"]+"|"+data["status"]checksum=OpenSSL::HMAC.hexdigest('sha256',@config[:key2],checksumData)ifchecksum!=data['checksum']rendertext: 'Bad Request',status: :bad_requestelse# check if the callback has been received, if not Merchant should use getOrderStatus API to get final resultrendertext: 'OK',status: :okendendend
# coding=utf-8# Python 3.6fromflaskimportFlask,request,jsonimporthmac,hashlibapp=Flask(__name__)config={'key2':'Iyz2habzyr7AG8SgvoBCbKwKi3UzlLi3'}@app.route('/redirect-from-zalopay',methods=['GET'])defredirect():data=request.argschecksumData="{}|{}|{}|{}|{}|{}|{}".format(data.get('appid'),data.get('apptransid'),data.get('pmcid'),data.get('bankcode'),data.get('amount'),data.get('discountamount'),data.get('status'))checksum=hmac.new(config['key2'].encode(),checksumData,hashlib.sha256).hexdigest()ifchecksum!=data.get('checksum'):return"Bad Request",400else:# check if the callback has been received, if not Merchant should use getOrderStatus API to get final resultreturn"Ok",200if__name__=='__main__':app.run(host='0.0.0.0',port=8001)