Overview
Secara umum, hampir setiap pemanggilan web-service, harus dicantumkan beberapa variabel yang dibutuhkan untuk menambahkan informasi ataupun untuk proses validasi yang dikirim pada HTTP Header, antara lain:
Nama Header
|
Contoh Nilai
|
Keterangan
|
Accept
|
application/xml, application/json
|
format data yang diinginkan
|
X-cons-id
|
743627386
|
consumer ID dari ASKES
|
X-timestamp
|
234234234
|
generated unix-based timestamp
|
X-signature
|
DogC5UiQurNcigrBdQ3QN5oYvXeUF5E82I/LHUcI9v0=
|
generated signature dengan pola HMAC-256
|
- Accept, diisi sesuai permintaan dari client. Jika menginginkan hasil balik dari web-service dalam format XML, maka diisi dengan application/xml. Ataupun jika menginginkan hasil balik dari web-service dalam berupa JSON, maka dapat diisi dengan application/json. Secara default (jika tidak ditulis) maka hasil balik berupa JSON.
- X-cons-id, merupakan kode consumer (pengakses web-service). Kode ini akan diberikan oleh ASKES.
- X-timestamp, merupakan waktu yang akan di-generate oleh client saat ingin memanggil setiap service. Format waktu ini ditulis dengan format unix-based-time (berisi angka, tidak dalam format tanggal sebagaimana mestinya). Format waktu menggunakan Coordinated Universal Time ( UTC), dalam penggunaannya untuk mendapatkan timestamp, rumus yang digunakan adalah (local time in UTC timezone in seconds) - (1970-01-01 in seconds).
contoh penggunaan dalam php yaitu :
date_default_timezone_set('UTC');
$tStamp = strval(time()-strtotime('1970-01-01 00:00:00'));
|
- X-signature, merupakan hasil dari pembuatan signature yang dibuat oleh client. Signature yang digunakan menggunakan pola HMAC-SHA256.
Untuk dapat mengakses web-service dari BPJS Kesehatan (service provider), pemanggil web service (service consumer) akan mendapatkan:
- Consumer ID
- Consumer Secret
Informasi Consumer Secret, hanya disimpan oleh service consumer. Tidak dikirim ke server web-service, hal ini untuk menjaga pengamanan yang lebih baik. Sedangkan kebutuhan Consumer Secret ini adalah untuk men-generate Signature (X-signature).
Contoh:
consumerID : 1234
consumerSecret : pwd
timestamp : 433223232
variabel1 : consumerID×tamp
variabel1 : 1234&433223232
Signature : HMAC-256(value : key)
value : variabel1
key : consumerSecret
Signature : HMAC-256(variabel1 : consumerSecret)
|
TOOLS TESTING WEB SERVICE
Sebelum mengakses web service melalui aplikasi, bisa digunakan tools tambahan (add-ons). Add-ons ini bisa di dapat dari software tambahan atau extension dari masing-masing browser favorit anda. Berikut link aplikasi
Advanced Rest Client yang bisa digunakan dan di-download dari
Chrome Web Store.
SIGNATURE
Metode signature yang digunakan adalah menggunakan HMAC-SHA256, dimana paramater saat generate signature dibutuhkan parameter message dan key.
Berikut contoh hasil generate HMAC-SHA256
message : aaa
key : bbb
hasil generate HMAC-SHA256 : 20BKS3PWnD3XU4JbSSZvVlGi2WWnDa8Sv9uHJ+wsELA=
Diatas
adalah hasil generate dari server BPJS Kesehatan
Berikut contoh pembuatan signature dari berbagai platform:
Java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.springframework.security.crypto.codec.Base64;
public class BpjsApi {
public static void main(String[] args) throws GeneralSecurityException, IOException {
String secretKey = "secretKey";
String salt = "0123456789";
String generateHmacSHA256Signature = generateHmacSHA256Signature(salt, secretKey);
System.out.println("Signature: " + generateHmacSHA256Signature);
String urlEncodedSign = URLEncoder.encode(generateHmacSHA256Signature, "UTF-8");
System.out.println("Url encoded value: " + urlEncodedSign);
}
public static String generateHmacSHA256Signature(String data, String key) throws GeneralSecurityException {
byte[] hmacData = null;
try {
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKey);
hmacData = mac.doFinal(data.getBytes("UTF-8"));
return new Base64Encoder().encode(hmacData);
} catch (UnsupportedEncodingException e) {
throw new GeneralSecurityException(e);
}
}
}
|
PHP
$data = "testtesttest";
$secretKey = "secretkey";
// Computes the timestamp
date_default_timezone_set('UTC');
$tStamp = strval(time()-strtotime('1970-01-01 00:00:00'));
// Computes the signature by hashing the salt with the secret key as the key
$signature = hash_hmac('sha256', $data."&".$tStamp, $secretKey, true);
// base64 encode…
$encodedSignature = base64_encode($signature);
// urlencode…
// $encodedSignature = urlencode($encodedSignature);
echo "X-cons-id: " .$data ." ";
echo "X-timestamp:" .$tStamp ." ";
echo "X-signature: " .$encodedSignature;
?>
|
C#
namespace BpjsIntegration
{
class Program
{
static void Main()
{
var data = "testtesttest";
var secretKey = "secretkey";
// Initialize the keyed hash object using the secret key as the key
HMACSHA256 hashObject = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey));
// Computes the signature by hashing the salt with the secret key as the key
var signature = hashObject.ComputeHash(Encoding.UTF8.GetBytes(data));
// Base 64 Encode
var encodedSignature = Convert.ToBase64String(signature);
// URLEncode
// encodedSignature = System.Web.HttpUtility.UrlEncode(encodedSignature);
Console.WriteLine("Voila! A signature: " + encodedSignature);
Console.ReadKey();
}
}
}
|
VB.Net
Imports System.Security.Cryptography
Imports System.Text
Namespace BpjsIntegration
Class Program
Private Shared Sub Main()
Dim data = "testtesttest"
Dim secretKey = "secretkey"
' Initialize the keyed hash object using the secret key as the key
Dim hashObject As New HMACSHA256(Encoding.UTF8.GetBytes(secretKey))
' Computes the signature by hashing the salt with the secret key as the key
Dim signature = hashObject.ComputeHash(Encoding.UTF8.GetBytes(data))
' Base 64 Encode
Dim encodedSignature = Convert.ToBase64String(signature)
' URLEncode
' encodedSignature = System.Web.HttpUtility.UrlEncode(encodedSignature)
Console.WriteLine("Voila! A signature: " & encodedSignature)
Console.ReadKey()
End Sub
End Class
End Namespace
|
Ruby
# Required Libraries
require 'openssl'
require 'base64'
require 'URI'
data = "testtesttest"
secret_key = "secretkey"
# URL encode
def urlncode(string)
URI.escape(string, Regexp.new("[Generating an API Signature^#{URI::PATTERN::UNRESERVED}]"))
end
# Computes the signature by hashing the salt with the secret key as the key
hash = OpenSSL::HMAC.digest('sha256', secret_key, data)
# base64 encode...
# signature = urlncode(Base64.encode64(hash));
|
Phyton
import hashlib
import random
import base64
import urllib
import hmac
data = "testtesttest"
secretkey = "secretkey"
# Computes the signature by hashing the data with the secret key as the key
signature = hmac.new(secretkey, msg=data, digestmod=hashlib.sha256).digest()
# base64 encode...
encodedSignature = base64.encodestring(signature).replace('\n', '')
# urlencode...
# encodedSignature = urllib.quote(encodedSignature)
print "Voila! A signature: " + encodedSignature
|
Cocoa (iOS and Mac)
-(NSUInteger)GenerateSalt
{
// random number (change the modulus to the length you'd like)
NSUInteger r = arc4random() % 100000;
return r;
}
-(NSString *)GenerateSignatureUsingSalt:(NSUInteger)salt
{
/*
Make sure you import:
#import
*/
NSString *key = SECRET_KEY; // define your Secret Key string
NSString *data = [NSString stringWithFormat:@"%u", salt]; // convert your random number
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
const char *cData = [data cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
// Hash the salt with the secret key
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
// Create a data structure
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC
length:sizeof(cHMAC)];
// Base64-encode the signature
NSString *hash = [HMAC base64Encoding];
// URL-encode the signature
// NSString * signatureURL = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)hash,
NULL,
(CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
kCFStringEncodingUTF8 );
return signatureURL;
}
|
Daftar Service
Service yang tersedia adalah sebagai berikut:
1. Cari peserta berdasarkan no.kartu BPJS
Parameter:
noKartu : no kartu BPJS
Output:
Format_Peserta
Contoh:
2. Cari peserta berdasarkan NIK
Parameter:
Nik : nomor induk kependudukan / no e-KTP
Output:
Format_Peserta
Contoh:
Format_Peserta
{
"response":{
"peserta":{
"noKartu":"0000142495694",
"nik":" ",
"nama":"MUJADID ANWAR HASAN",
"pisa":"2",
"sex":"P",
"tglLahir":"1979-05-13 00:00:00",
"tglCetakKartu":"1979-05-13 00:00:00",
"provUmum":{
"kdProvider":"1301U007",
"nmProvider":"MAULIDA JUNIAR, dr",
"kdCabang":null,
"nmCabang":null
},
"jenisPeserta":{
"kdJenisPeserta":"1",
"nmJenisPeserta":"PNS PUSAT"
},
"kelasTanggungan":{
"kdKelas":null,
"nmKelas":null
}
}
},"metaData":{
"message":"200",
"code":200
}
}
|
3. Cari data rujukan berdasarkan no.rujukan
Parameter :
noRujukan : no rujukan pasien BPJS melalui aplikasi PCare (Puskesmas/dokkel)
Output:
Format_Rujukan
Contoh:
4. Cari data rujukan berdasarkan no.kartu BPJS
Parameter:
noKartu : no kartu BPJS
Output:
Format_Rujukan
Contoh:
Format_Rujukan
{
"response":{
"item":{
"noKunjungan":"000108011213Y000004",
"tglKunjungan":"2013-12-14 00:00:00",
"provKunjungan":{
"kdProvider":"00010801",
"nmProvider":"PUSK LANGSA BARO",
"kdCabang":null,
"nmCabang":null
},
"peserta":{
"noKartu":"0001089159052",
"nik":"",
"nama":"mr ganteng kaya sholeh",
"pisa":"2",
"sex":"L",
"tglLahir":"1984-06-16 00:00:00",
"tglCetakKartu":null,
"provUmum":{
"kdProvider":"00010801",
"nmProvider":"PUSK LANGSA BARO",
"kdCabang":null,
"nmCabang":null
},
"jenisPeserta":null,
"kelasTanggungan":null
},
"keluhan":"sakit gigi",
"diagnosa":{
"kdDiag":"K05",
"nmDiag":"GINGTIVIS AND PERIODONTAL DISEA."
},
"catatan":"rujuk",
"pemFisikLain":"",
"provRujukan":{
"kdProvider":"0105R001",
"nmProvider":"RSU LANGSA",
"kdCabang":null,
"nmCabang":null
},
"poliRujukan":{
"kdPoli":"GIG",
"nmPoli":"Poli Gigi"
}
}
}
,"metaData":{
"message":"200",
"code":200
}
}
|
5. Cari daftar pasien yang di-rujuk berdasarkan tanggal rujukan
Paramter :
{tglRujukan} = tanggal dengan format yyyy-MM-dd
{start} = start/mulai urutan data
{limit} = jumlah data
Output:
Format_Rujukan_list
Contoh:
Mengambil data dari urutan no.1 sebanyak 10 data
Mengambil data dari urutan no.11 sebanyak 10 data
Fungsi {start} dan {limit} berguna untuk paging pada layout tampilan aplikasi, dengan parameter {start} selalu berubah sesuai parameter, sedangkan parameter {limit} selalu sama.
- menampilkan {start} – {limit} dari {count} records
- menampilkan 1 – 10 dari 73 records
Format_Rujukan_list
{
"response":{
"start":1,
"limit":10,
"count":7,
"list":[{
"noKunjungan":"000108031213Y000005",
"tglKunjungan":"2013-12-14 00:00:00",
"provKunjungan":{
"kdProvider":"00010803",
"nmProvider":"PUSK LANGSA KOTA",
"kdCabang":null,
"nmCabang":null
},
"peserta":{
"noKartu":"0000149156998",
"nik":" ",
"nama":"ITA ELLYZA",
"pisa":"3",
"sex":"P",
"tglLahir":"1979-04-17 00:00:00",
"tglCetakKartu":null,
"provUmum":{
"kdProvider":"00010803",
"nmProvider":"PUSK LANGSA KOTA",
"kdCabang":null,
"nmCabang":null
},
"jenisPeserta":null,
"kelasTanggungan":null
},
"keluhan":"dispepsia",
"diagnosa":{
"kdDiag":"M23",
"nmDiag":"INTERNAL DERANGEMENT OF KNEE"
},
"catatan":",,,,,,,,,,",
"pemFisikLain":"",
"provRujukan":{
"kdProvider":"0105R001",
"nmProvider":"RSU LANGSA",
"kdCabang":null,
"nmCabang":null
},
"poliRujukan":{
"kdPoli":"INT",
"nmPoli":"Poli Penyakit Dalam"
}
},
. . . .
. . . .
. . . .
. . . .
{
"noKunjungan":"000108031213Y000009",
"tglKunjungan":"2013-12-14 00:00:00",
"provKunjungan":{
"kdProvider":"00010803",
"nmProvider":"PUSK LANGSA KOTA",
"kdCabang":null,
"nmCabang":null
},
"peserta":{
"noKartu":"0001089159276",
"nik":"1174023107830003",
"nama":"DEDE KURNIAWAN",
"pisa":"1",
"sex":"L",
"tglLahir":"1985-07-07 00:00:00",
"tglCetakKartu":null,
"provUmum":{
"kdProvider":"00010803",
"nmProvider":"PUSK LANGSA KOTA",
"kdCabang":null,
"nmCabang":null
},
"jenisPeserta":null,
"kelasTanggungan":null
},
"keluhan":"gigi berlubang",
"diagnosa":{
"kdDiag":"K02",
"nmDiag":"DENTAL CARIES"
},
"catatan":"cabut",
"pemFisikLain":"",
"provRujukan":{
"kdProvider":"0105R001",
"nmProvider":"RSU LANGSA",
"kdCabang":null,
"nmCabang":null
},
"poliRujukan":{
"kdPoli":"GIG",
"nmPoli":"Poli Gigi"
}
}]
},"metaData":{
"message":"200",
"code":200
}
}
|
6. Pembuatan SEP
(hanya untuk testing data. Untuk production, akan di-deploy WebService pada server lokal di RS)
Mulai Versi WS 1.4, URL Create SEP untuk Production menjadi
Request Method : POST
Header :
Content-type: application/xml
x-cons-id: ….
x-timestamp: ….
x-signature: ...
Data:
2013-07-26 13:05:03
2013-07-26 13:05:03
1234590000300003
1
dari WS
B010
2
JD
1234
Keterangan:
noKartu : no kartu BPJS
tglSep : tanggal kedatangan/tanggal transaksi
tglRujukan : tanggal kunjungan ke puskesmas/dokter keluarga
noRujukan : no rujukan dari puskesmas/dokter keluarga
ppkRujukan : kode puskesmas/dokter keluarga (versi BPJS)
ppkPelayanan: kode RS anda (versi BPJS), akan di-validasi oleh service, pastikan gunakan userID service yang sesuai
jnsPelayanan : 1: Rawat Inap, 2: Rawat Jalan
catatan : catatan tambahan
diagAwal : diagnosa dari puskesmas/dokter keluarga (ICD X, sama seperti INA-CBG)
poliTujuan : poli tujuan di RS
klsRawat : kelas rawat tanggungan peserta
user : username pengguna aplikasi
noMr : no medical records RS dari pasien
7. Update tanggal pulang pada SEP >> hanya ada pada Web Service lokal
Terjadi penolakan saat pembuatan SEP jika sistem mengidentifikasi bahwa pasien masih dalam status menginap. Untuk mengisi tanggal pulang pada sistem BPJS/SEP, hanya dapat dilakukan dengan menerima file hasil entrian dari sistem INA-CBGs (kemenkes). Namun hal ini biasa dilakukan/diberikan oleh pihak RS kepada pihak BPJS pada beberapa hari kemudian.
Untuk mengantisipasi kasus penolakan terhadap pasien, dibutuhkan suatu sistem yang dapat meng-update data pasien pada BPJS melalui sistem RS. Disinilah fungsi ini berguna untuk meng-update tanggal pulang pasien pada data BPJS yang mana saat sistem RS melakukan update tanggal pulang pada sistem RS, sekaligus mengakses WebService ini agar data pasien terupdate pada server BPJS.
Request Method : PUT
Header :
Content-type: application/xml
x-cons-id: ….
x-timestamp: ….
x-signature: ...
Data:
2013-07-26 13:05:03
Keterangan:
noSep : no transaksi SEP
tglPlg : tanggal pulang pasien
ppkPelayanan: kode RS anda (versi BPJS), akan di-validasi oleh service, pastikan gunakan userID service yang sesuai
8. Menyimpan mapping data transaksi >> hanya ada pada Web Service lokal
Setelah sistem RS men-generate SEP dan menyimpan transaksi pendaftaran pada sistem RS, maka data masing-masing no transaksi unik disimpan pada 2 sistem (BPJS dan RS). Fungsi ini berguna untuk menyimpan no transaksi tersebut, agar nantinya dapat melakukan audit trail yang lebih efisien
Request Method : POST
Header :
Content-type: application/xml
x-cons-id: ….
x-timestamp: ….
x-signature: ...
Data:
98765432109876543210
Keterangan:
noSep : no transaksi SEP
noTrans : no transaksi pada aplikasi RS
ppkPelayanan: kode RS anda (versi BPJS), akan di-validasi oleh service, pastikan gunakan userID service yang sesuai
9. Menghapus data transaksi SEP >> hanya ada pada Web Service lokal
Data SEP yang dapat dihapus hanya jika data tersebut belum dibuatkan FPK/tagihan ke Kantor Cabang BPJS setempat.
Request Method : DELETE
Header :
Content-type: application/xml
x-cons-id: ….
x-timestamp: ….
x-signature: ...
Data:
Keterangan:
noSep : no transaksi SEP
ppkPelayanan: kode RS anda (versi BPJS), akan di-validasi oleh service, pastikan gunakan userID service yang sesuai
10. Mencari 5 (lima) riwayat kunjungan terakhir peserta >> hanya ada pada Web Service lokal
Melihat data 5 (lima) riwayat kunjungan terakhir peserta yang dimaksud. Dapat digunakan untuk menjadi acuan dalam meng-update tanggal pulang peserta, jika telah pulang.
Request Method : GET
Parameter:
noKartu : no kartu BPJS
Output:
Format_Riwayat_Kunjungan_Peserta
Contoh:
Format_Riwayat_Kunjungan_Peserta
{
response : {
start : 1
limit : 5
count: 5
list: [5]
0: {
noSep: "0902R00106140001988"
tglSep: "2014-06-03 00:00:00"
tglPulang: "1900-01-01 12:00:00"
jnsPelayanan: "Rawat Jalan"
-poliTujuan: {
kdPoli: "JIW"
nmPoli: "Poli Penyakit Jiwa"
}
}
-1:
{
noSep: "0902R00105140001855"
tglSep: "2014-05-05 00:00:00"
tglPulang: "2014-05-05 00:00:00"
jnsPelayanan: "Rawat Jalan"
-poliTujuan: {
kdPoli: "JIW"
nmPoli: "Poli Penyakit Jiwa"
}
}
-2:
{
noSep: "0902R00104140003884"
tglSep: "2014-04-04 00:00:00"
tglPulang: "2014-04-04 00:00:00"
jnsPelayanan: "Rawat Jalan"
-poliTujuan: {
kdPoli: "JIW"
nmPoli: "Poli Penyakit Jiwa"
}
}
-3:
{
noSep: "0902R00103140022235"
tglSep: "2014-03-24 00:00:00"
tglPulang: "2014-03-24 00:00:00"
jnsPelayanan: "Rawat Jalan"
-poliTujuan: {
kdPoli: "JIW"
nmPoli: "Poli Penyakit Jiwa"
}
}
-4:
{
noSep: "0902R00103140014204"
tglSep: "2014-03-13 00:00:00"
tglPulang: "2014-03-13 00:00:00"
jnsPelayanan: "Rawat Jalan"
-poliTujuan: {
kdPoli: "JIW"
nmPoli: "Poli Penyakit Jiwa"
}
}
}
-metaData:
{
message: "OK"
code: 200
}
}
|
11. Mencari detail SEP >> hanya ada pada Web Service lokal
Melihat detail keterangan dari SEP .
Request Method : GET
Parameter:
noSEP : no Transaksi SEP
Output:
Format_Detail_SEP
Contoh:
Format_Detail_SEP
{
-response: {
sep: {
noSep: "0902R00101140000004"
-peserta: {
noKartu: "0000047622846"
nik: null
nama: "HJ.UMRAH-HERRIYANRI"
pisa: "3"
sex: "P"
tglLahir: "1951-10-16 00:00:00"
tglCetakKartu: "2009-10-30 00:00:00"
provUmum:
{
kdProvider: "10050201"
nmProvider: "CIPUTAT"
kdCabang: null
nmCabang: null
}
jenisPeserta: {
kdJenisPeserta: "15"
nmJenisPeserta: "BUKAN PEKERJA LAIN-LAIN"
}
kelasTanggungan:
{
kdKelas: "1"
nmKelas: "Kelas I"
}
}
tglSep: "2014-01-02 00:00:00"
tglRujukan: "2014-01-02 00:00:00"
tglPulang: "2014-01-02 00:00:00"
noRujukan: ""
provRujukan:
{
kdProvider: "09020100"
nmProvider: "KEC TEBET"
kdCabang: null
nmCabang: null
}
provPelayanan: {
kdProvider: "0902R001"
nmProvider: "RSUP FATMAWATI"
kdCabang: null
nmCabang: null
}
jnsPelayanan: "Rawat Jalan"
catatan: ""
diagAwal: {
kdDiag: "T843"
nmDiag: "Mechanical comp other bone devices implants & grafts"
}
poliTujuan: {
kdPoli: "BED"
nmPoli: "Poli Bedah"
}
klsRawat: {
kdKelas: "3"
nmKelas: "Kelas III"
}
statSep: {
kdStatSep: "40"
nmStatSep: "40_Proses_Cabang"
}
byTagihan: 378878
}
}
-metaData:
{
message: "OK"
code: 200
}
}
|
12. Mencari PPK Rujukan >> hanya ada pada Web Service lokal
Mencari PPK berdasarkan kode atau nama untuk mengisi PPK rujukan.
Request Method : GET
Parameter:
xxx : Kode PPK atau Nama PPK
Output:
Format_Nama_PPK
Contoh:
Format_Nama_PPK
{
response: {
start: 1
limit: 10
count: 76
list: [4]
0: {
kdProvider: "09020500"
nmProvider: "KEC KEBAYORAN BARU (Puskesmas)"
kdCabang: "0902"
nmCabang: "JAKARTA SELATAN"
}
-1: {
kdProvider: "09020600"
nmProvider: "KEC KEBAYORAN LAMA (Puskesmas)"
kdCabang: "0902"
nmCabang: "JAKARTA SELATAN"
}
-2: {
kdProvider: "09020601"
nmProvider: "KEL KEBAYORAN LAMA UTARA (Puskesmas)"
kdCabang: "0902"
nmCabang: "JAKARTA SELATAN"
}
-3: {
kdProvider: "09020608"
nmProvider: "KEL KEBAYORAN LAMA SELATAN (Puskesmas)"
kdCabang: "0902"
nmCabang: "JAKARTA SELATAN"
}
}
-metaData:
{
message: "200"
code: 200
}
}
|