You are currently viewing Lấy access token từ Salesforce Marketing Cloud

Lấy access token từ Salesforce Marketing Cloud

Nếu chỉ đơn thuần dùng các chức năng có sẵn trong UI Marketing Cloud, chắc hẳn các bạn sẽ thấy khó khăn trong việc điều chỉnh và thiết kế ra các giải pháp linh hoạt đáp ứng được như cầu thương mại của doanh nghiệp. Để có thể phát huy sức mạnh tuyệt đối của platform này ta sẽ cần dùng đến API để giao tiếp, kết nối, ứng dụng được xây dựng sẵn.
Ở bài này, Gâu Đần sẽ giúp các bạn build một cơ chế lấy access token (hay authentication token), mà token này sẽ được sử dụng rất nhiều trong các REST API.

Don’t be afraid to make mistakes, just be afraid of not learning from them.

Có thể hiểu nôm na thế này nè, để muốn dùng REST API hay SOAP API trong Marketing Cloud thì: 

  • Yêu cầu API integration với Marketing Cloud sử dụng installed package. 
  • Từ đó gửi yêu cầu đến MC lấy Access token – là một chuỗi các ký tự bảo mật ứng với thời gian token có hiệu lực.
  • Access token hết hiệu lực sau 20 phút (token v2) theo như trên tài liệu Salesforce công bố (thực tế là ngắn hơn khoảng 17, 18 phút gì đó)
  • Access token này sau đó tùy mục đích sẽ được sử dụng với các endpoint khác. Mà các endpoint này sẽ có các chức năng khác nhau tùy nhà sản xuất đã build (chẳng hạn thêm contact vào journey, gửi email, sms…)
  • Dùng REST API dĩ nhiên là nhanh và bảo mật hơn.

Các bước lấy access token server to server trong Marketing Cloud

Okay vào việc nào. Ta sẽ lấy access token (token v2) server to server nhé. Ta sẽ cần làm 3 bước sau:

  1. Tạo một installed package để lấy thông tin của client
  2. Tạo một data extension để trữ access token
  3. Viết code gọi API đến MC để lấy access token này

Step 1: Tạo installed package

Setup/ Installed Packages/ New / đặt tên cho installed package/ Add component

Chọn API Integration/ Server-To-Server type/ Chọn Scope
Mình sẽ có ví dụ về dùng API cho Journey ở một bài khác. Nên ở đây bạn cứ chọn Scope cho Journey rồi Save lại nhé.

Best practice: Không chọn hết, chỉ chọn scope phù hợp với mục đích mình sẽ dùng!

Từ đây ta sẽ có thông tin của Client là Client ID, Client Secret và Authentication Base URI.

Step 2: Tạo DE trữ access token

DE name: Token response
Sendable: No

FieldTypeLengthNullableDefault Value
access_tokenText1024No
token_typeText50No
expires_inText50No
time_outText50No
remarkText50Nomy token

Step 3: viết code gọi Auth đến Marketing Cloud để lấy token

Chi tiết của access token (v2 token) này bạn có thể xem ở ĐÂY.
Ở đây Gâu Đần sẽ dùng Script.Util.HttpRequest thay vì Http.POST vì có nhiều ưu điểm hơn. Mà trong số đó Đần đánh giá cao nhất là mình có thể chỉ định method sử dụng, chứ không chỉ dùng Http.POST hoặc Http.GET. Đần cũng recommend mọi người dùng cách này để sử dụng với REST API.

<script runat="server">
Platform.Load("Core","1.1.1");
var debugging = true;

// Client information
var client_id = 'YourClientID';
var client_sc = 'YourClientSecret';
var payload = {
    "grant_type": "client_credentials",
    "client_id": client_id,
    "client_secret": client_sc
};
var url = 'https://YourSubdomain.auth.marketingcloudapis.com/v2/token';
var req = new Script.Util.HttpRequest(url);
req.emptyContentHandling = 0;
req.retries = 2;
req.continueOnError = true;
req.contentType = "application/json"; 
req.method = "POST";
// auth = 'Bearer ' + accesstoken;
// req.setHeader("Authorization", auth); 
req.postData = Stringify(payload); 
var resp = req.send();
var resultJSON = Platform.Function.ParseJSON(String(resp.content));
if (debugging) {
    Write('access token: ' + resultJSON.access_token + '<br>');
    Write('expire in: ' + resultJSON.expires_in + '<br>');
};
</script>

Thay thông tin bạn lấy được từ bước 1 vào line 6, 7, 13. Line 19 là method sử dụng. Line 20, 21 sử dụng cho REST API khác có cần đến Authentication Token hay còn biết đến chính là access token này. Debugging mode để print out ra màn hình. Đọc thêm cách develop code trong MC tại ĐÂY.
Vậy là Đần đã có thể lấy access token ra rồi nhưng như vậy vẫn chưa kết thúc bởi:

  • Cần vào trữ vào DE chứ không phải khơi khơi in ra màn hình như vậy
  • Renew access token khi token này hết hạn và sử dụng token cũ khi hạn vẫn còn

Best practices: không gọi API lấy token mới khi token cũ vẫn còn hạn.Thông tin thêm cho bạn là, nếu token vẫn còn hạn mà gọi token mới thì token trước sẽ invalid không xài được nữa.

Ta có thể hiểu flow để gọi và trữ access token theo như biểu đồ sau:

Final code:

<script runat="server">

Platform.Load("Core","1.1.1");
var debugging = true;
var now = new Date();
var time = now.getTime(); // milliseconds
var accesstoken;

/* 
Validation to check whether the access token is expired or not
- If the DE is empty then call api to create and store a new token
- If the DE is having a access token then check the expiry 
    token is expired -> create a new token
    token is still usable -> keep using old token
*/
var DEname = 'Token response'; // DE stores access token
var data = Platform.Function.LookupRows(DEname,['remark'], ['my token']);
if (data != null && (data[0].time_out > time) ) {
    Write('Using old token.<br>');
    accesstoken = data[0].access_token;
} else {    
        Write('Creating a new token.<br>');        
        accesstoken = get_token(DEname, time, debugging);
        }

function get_token(DEname, time, debugging) {
    /*
    DEname: DE stores access token
    time: time at calling function
    debugging: debugging mode  
    */

    // Client information
    var client_id = 'YourClientID';
    var client_sc = 'YourClientSecret';
    var payload = {
        "grant_type": "client_credentials",
        "client_id": client_id,
        "client_secret": client_sc
    };
    var url = 'https://YourSubdomain.auth.marketingcloudapis.com/v2/token';
    var req = new Script.Util.HttpRequest(url);
    req.emptyContentHandling = 0;
    req.retries = 2;
    req.continueOnError = true;
    req.contentType = "application/json"; 
    req.method = "POST";
    // auth = 'Bearer ' + accesstoken;
    // req.setHeader("Authorization", auth); 
    req.postData = Stringify(payload); 
    var resp = req.send();
    var resultJSON = Platform.Function.ParseJSON(String(resp.content));

    if (debugging) {
        Write('access token: ' + resultJSON.access_token + '<br>');
        Write('expire in: ' + resultJSON.expires_in + '<br>');
    };

    var token_type = resultJSON.token_type
    var access_token = resultJSON.access_token
    var expires_in = resultJSON.expires_in //seconds
        expires_in = expires_in * 1000 // convert to millisecond
    var time_out = time + expires_in;

    // store access token and other information into 'access token' DE
    Platform.Function.UpsertDE(DEname, ['remark'], ['my token'], 
    ['access_token', 'token_type', 'expires_in', 'time_out'],
    [access_token, token_type, expires_in, time_out]);

    return access_token;

    }
</script>

Output:

Ở đây Đần có viết thêm Validation để kiểm tra token đang có hay không, nếu có thì có hết hạn hay chưa. Chú ý là giá trị expires_in trả về có đơn vị là second , Đần đã quy đổi về cùng millisecond để có thể tính toán ra thời gian time_out.

Conclusion:

Yayyy! Vậy là Gâu Đần đã build xong cơ chế gửi yêu cầu và nhận token, từ đây chúng ta sẽ có nhiều lựa chọn tốt và linh hoạt hơn trong việc xây dựng các giải pháp trong Marketing Cloud!

Bonus
Các property trong object Script.Util.HttpRequest

PropertyDescription
emptyContentHandlingBằng 1 (true) tiếp tục gọi không báo lỗi nếu payload rỗng. Bằng 0 (false) báo lỗi nếu payload rỗng.
retriesSố lần thử lại trước khi lần gọi thất bại
continueOnErrorBằng 1 (true) sẽ tiếp tục request kể cả khi xuất hiện lỗi. Bằng 0 (false), lần gọi sẽ thất bại nếu có lỗi
contentTypeĐịnh ra content-type header
methodĐịnh ra request method. Chẳng hạn:GETPOSTDELETEHEADOPTIONSPATCHPUT
postDataPayload được gửi cùng với request

Property response thì các bạn đọc ở ĐÂY
Các method của object này:

MethodDescription
setHeader()Pass header name và header value vào khi dùng GET request. Ví dụ: req.setHeader(“x-api-key”, “accessKey”)
removeHeader()gỡ header từ request
clearHeader()xóa tất cả các custom header
send()thực hiện request

Leave a Reply