Mini App Overview
Introduction
Superapps are comprehensive mobile or web applications that provide a wide range of services and functionalities within a single platform. These apps aim to become an ecosystem of various mini apps or features that users can access without leaving the main application. Here's an overview of mini apps in the context of superapps:
What are Mini Apps?
Mini apps are lightweight, sub-applications embedded within a superapp. They provide specific services or functionalities and can be developed by third-party developers or the superapp's team. These mini apps are designed to be fast, easy to use, and require minimal resources.
Benefits of Mini Apps in Superapps
- Convenience: Users can access multiple services without switching between different apps, saving time and effort.
- Enhanced User Engagement: A wide range of services keeps users engaged within the superapp, increasing user retention.
- Cross-Selling Opportunities: Superapps can cross-promote services within mini apps, boosting overall usage and revenue.
- Reduced Storage Space: Mini apps consume less storage space on users' devices compared to having multiple standalone apps.
- Streamlined Updates: Superapps can update mini apps independently, ensuring that users always have access to the latest features and improvements.
Objective
The objectives of mini apps within superapps are multifaceted, aiming to enhance user experience, Optimizing Resource Usage, and Enhancing Security and Compliance. Here are some key objectives:
- Enhancing User Convenience
- Unified Access: Provide users with a one-stop platform where they can access multiple services without the need to download or switch between different apps.
- Streamlined Experience: Simplify the user journey by integrating various functionalities within a single app, reducing the friction associated with using multiple standalone apps.
- Optimizing Resource Usage
- Reduced Storage: Mini apps are lightweight, consuming less device storage and data compared to full-fledged apps, making them more accessible to users with limited resources.
- Efficient Updates: Facilitate more efficient updates and maintenance, as mini apps can be updated independently without requiring users to update the entire superapp.
- Enhancing Security and Compliance
- Centralized Management: Provide a secure and compliant environment for transactions and data management, ensuring user trust and safety.
- Standardized Practices: Maintain high security and compliance standards across all mini apps within the superapp, protecting user data and privacy.
Interactive Launch Process
The following diagram illustrates the sequence of events when a superapp application is started.
The authentication process begins with the user providing their credentials to the superapp. Once these credentials are verified and the superapp successfully authenticates the user, it generates a token. This token serves as proof of authentication and is securely stored in the session storage. When the user accesses a mini app, the superapp retrieves the token from the session storage and passes it to the mini app. The mini app then uses this token to confirm the user's authenticated status, allowing them to proceed with using the mini app without needing to re-enter their credentials. This streamlined process ensures a seamless and secure user experience across different components of the application ecosystem.
Launch Mini App
Launch Setup
In the Mini App launch flow, there are several essential items that must be in place to successfully open the mini app. Firstly, the authentication token generated by the superapp is critical. This token verifies the user's identity and ensures they have the necessary permissions to access the mini app. Secondly, a secure session storage mechanism is required to store and retrieve the token. This ensures that the token is available when the mini app is launched and that it remains secure throughout the session.
- Launch Request
Parameter | Location | Description |
---|---|---|
app_url | Address | The url of application to launch the program also Identifies as app url. |
SMART_TOKEN | Session Storage | The payload of the token response typically contains several key pieces of information that are essential for the authentication and authorization process. |
AUTH_URL | Session Storage | Issue url form identity server https://id.mobile.mhnexus.com/realms/person| |
FHIR_URL | Session Storage | Fhir server endpoint to retrieve the data. https://veinscdr.mhnexus.com/baseR4| |
A launch might cause the browser to navigate to:
- Template: {{app_url} } Session Storage : Payload of token
- Location: https://miniapp.mhnexus.com
Note: Please request to us for register the app URL to our server before development
- Credential Request
Key | Value |
---|---|
token_url | https://id.mobile.mhnexus.com/realms/person/protocol/openidconnect/token |
client_id | Person-portal |
username | haziq@mhnexus.com |
password | P@ssw0rd |
grant_type | P@ssw0rd |
scope openid | offline_access |
Content-Type | application/x-www-form-urlencoded |
HTTP Method | POST |
Request
curl --location 'https://id.mobile.mhnexus.com/realms/person/protocol/openidconnect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=person-portal' \
--data-urlencode 'username=haziq@mhnexus.com' \
--data-urlencode 'password=P@ssw0rd' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'scope=offline_access openid'
Response
{
"access_token":
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6S0dPWnBlZmFoNkJqTVl
6VFA4MGZMSTBQM2JNb3pjVUVPWmpPMFpGT0c4In0.eyJleHAiOjE3MjA0ODI3O
TgsImlhdCI6MTcyMDA1MDc5OCwianRpIjoiODdlZjdiOWYtMzllYS00NTc1LWIyN2It
NWRhNDAzOTQwZGJkIiwiaXNzIjoiaHR0cHM6Ly9pZC5tb2JpbGUubWhuZXh1cy5j
b20vcmVhbG1zL3BlcnNvbiIsInN1YiI6ImEyZGFhZmZmLWRhZDMtNGM4NS1iODY
0LTcyNWNkNWJkOTg3NSIsInR5cCI6IkJlYXJlciIsImF6cCI6InBlcnNvbi1wb3J0YWwi
LCJzZXNzaW9uX3N0YXRlIjoiMmI4M2NmMGEtYjk4My00NjMwLTliMjQtNjM4YWNi
Njc1Y2ViIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyIvKiIsImh0dHA6Ly9sb2
NhbGhvc3Q6OTIwMCIsImh0dHA6Ly9sb2NhbGhvc3Q6NDEwMCIsImh0dHA6Ly8x
OTIuODIuNjMuNTA6OTYwMCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGV
mYXVsdC1yb2xlcy1tb2JpbGUiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3Jpe
mF0aW9uIl19LCJzY29wZSI6Im9wZW5pZCBvZmZsaW5lX2FjY2VzcyBwcm9maWxl
IGVtYWlsIiwic2lkIjoiMmI4M2NmMGEtYjk4My00NjMwLTliMjQtNjM4YWNiNjc1Y2ViIi
wiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwaG9uZU51bWJlciI6Iis2MDEzNjA1N
Tg1MCIsIm5hbWUiOiJBaG1hZCBBaW1hbiBIYXppcSBBaG1hZCB0YXJtaWR6aSIs
InByZWZlcnJlZF91c2VybmFtZSI6ImhhemlxQG1obmV4dXMuY29tIiwiZ2l2ZW5fbmF
tZSI6IkFobWFkIEFpbWFuIEhhemlxIiwiaWRObyI6Ijk1MDcyODEwNjA1MSIsImZhb
WlseV9uYW1lIjoiQWhtYWQgdGFybWlkemkiLCJlbWFpbCI6ImhhemlxQG1obmV4d
XMuY29tIn0.P88t2URlsQjDNBARuUiMWurPZXUlN7pQ36_fDMiDWwluOuQSFyd6PIJmXNhtL5zTWHuJhjOEmRfNt
R3O5_vSHs5g3on_l1Cat2pAqa9CJ1x1ZFWx73NcHCD4--
S9O9LTQZrK_g5yWj1PGIVs8blmLxszXTye7Y8xKbJCMtVsoknysEO3JnaJtdmF9Ju
UBNCAxDbtVCY88g19fFwfyknILrFBqaumFDVuBOaPPdqXDAYUs5Itwgm5DsSrk_Qj6bNs3T7yWqywDxKqXh4gXdoMVmclFIr8kNbQthTQSHZdMZ8Y_-
Hunopa6eTnD3AwkXiMC20a9ckmVD2Gmt-4d6aA",
"expires_in": 432000,
"refresh_expires_in": 0,
"refresh_token":
"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxZmM4NjQwYi1lYjk1LTQ3N
DAtYjliYi04YTNlMjQxZjNkMzQifQ.eyJpYXQiOjE3MjAwNTA3OTgsImp0aSI6IjdhZW
FiMmNiLThhMWMtNDAxNS04MjM0LWU4OGNhOTFmNjE1NSIsImlzcyI6Imh0dHBz
Oi8vaWQubW9iaWxlLm1obmV4dXMuY29tL3JlYWxtcy9wZXJzb24iLCJhdWQiOiJod
HRwczovL2lkLm1vYmlsZS5taG5leHVzLmNvbS9yZWFsbXMvcGVyc29uIiwic3ViIjoi
YTJkYWFmZmYtZGFkMy00Yzg1LWI4NjQtNzI1Y2Q1YmQ5ODc1IiwidHlwIjoiT2Zm
bGluZSIsImF6cCI6InBlcnNvbi1wb3J0YWwiLCJzZXNzaW9uX3N0YXRlIjoiMmI4M2
NmMGEtYjk4My00NjMwLTliMjQtNjM4YWNiNjc1Y2ViIiwic2NvcGUiOiJvcGVuaWQg
b2ZmbGluZV9hY2Nlc3MgcHJvZmlsZSBlbWFpbCIsInNpZCI6IjJiODNjZjBhLWI5OD
MtNDYzMC05YjI0LTYzOGFjYjY3NWNlYiJ9.js70UreVyChsOReT6rlY9X62aySG26j
Om5RJuYnohkE",
"token_type": "Bearer",
"id_token":
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6S0dPWnBlZmFoNkJqTVl
6VFA4MGZMSTBQM2JNb3pjVUVPWmpPMFpGT0c4In0.eyJleHAiOjE3MjA0ODI3O
TgsImlhdCI6MTcyMDA1MDc5OCwiYXV0aF90aW1lIjowLCJqdGkiOiI3YWI4MWY3Z
S1jM2ExLTQ0NzEtYmJhNC1kZjQ1NmMxZGIyMTUiLCJpc3MiOiJodHRwczovL2lkL
m1vYmlsZS5taG5leHVzLmNvbS9yZWFsbXMvcGVyc29uIiwiYXVkIjoicGVyc29uLXB
vcnRhbCIsInN1YiI6ImEyZGFhZmZmLWRhZDMtNGM4NS1iODY0LTcyNWNkNWJk
OTg3NSIsInR5cCI6IklEIiwiYXpwIjoicGVyc29uLXBvcnRhbCIsInNlc3Npb25fc3RhdG
UiOiIyYjgzY2YwYS1iOTgzLTQ2MzAtOWIyNC02MzhhY2I2NzVjZWIiLCJhdF9oYXN
oIjoia3FVTW9Kdi16eW5EZ2VkbkZ0bVB4dyIsImFjciI6IjEiLCJzaWQiOiIyYjgzY2YwY
S1iOTgzLTQ2MzAtOWIyNC02MzhhY2I2NzVjZWIiLCJlbWFpbF92ZXJpZmllZCI6Zm
Fsc2UsInBob25lTnVtYmVyIjoiKzYwMTM2MDU1ODUwIiwibmFtZSI6IkFobWFkIEFp
bWFuIEhhemlxIEFobWFkIHRhcm1pZHppIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiaG
F6aXFAbWhuZXh1cy5jb20iLCJnaXZlbl9uYW1lIjoiQWhtYWQgQWltYW4gSGF6aXE
iLCJpZE5vIjoiOTUwNzI4MTA2MDUxIiwiZmFtaWx5X25hbWUiOiJBaG1hZCB0YXJt
aWR6aSIsImVtYWlsIjoiaGF6aXFAbWhuZXh1cy5jb20ifQ.PwPXOVLHAY27n240xTHMA33xIQNnFOpoT7oH2g6DrX3W28qXmhqvnX55cGLsrrUnfzMB4ai0HJET
FqB9dX9rEThyXxMwoi4phZ1xdAh2MRSl4GphXiMcKWxSnf57j_kX4g4bLUb7ui7CT
d1pN8hJdo_S-F9MZ74gAponmfjmWIpXcX5LCNkbmZUltuNPkEWBtyhvv7EjlurtH2xjy7O_ie2LI05LF5ga
IpjL6QY5n41o_QiEonTpb79Sh4B_sf3UW4p0-1vNGyC7UIP2ctyZL2mPqjangwbrjjvOuUsw0uqqOgjOleiGC-RNPgOsL6eoMkZeWyX56IkF8bnAMUQ",
"not-before-policy": 0,
"session_state": "2b83cf0a-b983-4630-9b24-638acb675ceb",
"scope": "openid offline_access profile email"
}
- Refresh Token Request
Key | Value |
---|---|
token_url | https://id.mobile.mhnexus.com/realms/person/protocol/openidconnect/token| |
client_id | Person-portal |
refresh_token | {{refresh_token} } |
grant_type | refresh_token |
scope openid | offline_access |
Content-Type | application/x-www-form-urlencoded |
HTTP Method | POST |
Request
curl --location 'https://veinssso.mhnexus.com/realms/person/protocol/openidconnect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=person-portal' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode
'refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI4OWU4ZjEy
Yy1iY2ZhLTRmNGItOTU3Ny03NTQ1MDE0MTk3M2EifQ.eyJleHAiOjE3MjAwMTc2
MTgsImlhdCI6MTcyMDAxNzMxOCwianRpIjoiY2RiMTMzYjUtYzlhMi00N2ZlLWI3Y
WQtYmIxMWRjNTlhNDYzIiwiaXNzIjoiaHR0cHM6Ly92ZWluc3Nzby5taG5leHVzLm
NvbS9yZWFsbXMvcGVyc29uIiwiYXVkIjoiaHR0cHM6Ly92ZWluc3Nzby5taG5leHVz
LmNvbS9yZWFsbXMvcGVyc29uIiwic3ViIjoiM2JhMjExOTAtMmQwZC00NmNhLTg0
NjktMDI4YjBmYTIwNTZjIiwidHlwIjoiUmVmcmVzaCIsImF6cCI6InBlcnNvbi1wb3J0Y
WwiLCJzZXNzaW9uX3N0YXRlIjoiNTZhNTc3OGQtZGQwMy00MzJiLTg5Y2QtNTRi
MWI3MDAyNDIzIiwic2NvcGUiOiJsYXVuY2gvcGF0aWVudCBzc28tb3BlbmlkLWNvb
m5lY3QgcGF0aWVudC8qLndyaXRlIGVtYWlsIHBhdGllbnQvKi5yZWFkIHByb2ZpbG
UiLCJzaWQiOiI1NmE1Nzc4ZC1kZDAzLTQzMmItODljZC01NGIxYjcwMDI0MjMifQ.
7wEDJazB_W2AKM2h8HweMcxKJ8PVGMtmGV5pNZMj-To'
Response
{
"access_token":
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6S0dPWnBlZmFoNkJqTVl
6VFA4MGZMSTBQM2JNb3pjVUVPWmpPMFpGT0c4In0.eyJleHAiOjE3MjA1MDMy
ODIsImlhdCI6MTcyMDA3MTI4MiwianRpIjoiM2VjODA0YWQtZmZiOS00Zjk2LTgwZ
DctZDFiMmZhZWIzZjk4IiwiaXNzIjoiaHR0cHM6Ly9pZC5tb2JpbGUubWhuZXh1cy5j
b20vcmVhbG1zL3BlcnNvbiIsInN1YiI6ImEyZGFhZmZmLWRhZDMtNGM4NS1iODY
0LTcyNWNkNWJkOTg3NSIsInR5cCI6IkJlYXJlciIsImF6cCI6InBlcnNvbi1wb3J0YWwi
LCJzZXNzaW9uX3N0YXRlIjoiNzU4MDM4OTAtZGZiMy00MmQ4LTljMTktOGFhMz
U3MmQ4MzI0IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyIvKiIsImh0dHA6Ly
9sb2NhbGhvc3Q6OTIwMCIsImh0dHA6Ly9sb2NhbGhvc3Q6NDEwMCIsImh0dHA6
Ly8xOTIuODIuNjMuNTA6OTYwMCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsi
ZGVmYXVsdC1yb2xlcy1tb2JpbGUiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3
JpemF0aW9uIl19LCJzY29wZSI6Im9wZW5pZCBvZmZsaW5lX2FjY2VzcyBwcm9ma
WxlIGVtYWlsIiwic2lkIjoiNzU4MDM4OTAtZGZiMy00MmQ4LTljMTktOGFhMzU3Mm
Q4MzI0IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwaG9uZU51bWJlciI6Iis2MD
EzNjA1NTg1MCIsIm5hbWUiOiJBaG1hZCBBaW1hbiBIYXppcSBBaG1hZCB0YXJta
WR6aSIsInByZWZlcnJlZF91c2VybmFtZSI6ImhhemlxQG1obmV4dXMuY29tIiwiZ2l2
ZW5fbmFtZSI6IkFobWFkIEFpbWFuIEhhemlxIiwiaWRObyI6Ijk1MDcyODEwNjA1MS
IsImZhbWlseV9uYW1lIjoiQWhtYWQgdGFybWlkemkiLCJlbWFpbCI6ImhhemlxQG1
obmV4dXMuY29tIn0.hwJtzgMcCLyyu31FrRTF2DsnLdzIxwqgWsnC3PtotXQ3OiUKgbLxIRcJn1yn185Dkh2zMJf7j4CEdD2oYJTYjBU1PO6TvePJsoRx2sF9Xo
ij_VgHigDQiJ9U_7f2vh0gXFA0hZzwwkyxqP-vOJWb_hcj1MF2wuF1T8VBVEhdYRi2meGkY2lyDiI9RxSEjBMgYNMlC2YFJQG3AptJs6l_hvUbl7YhWDEePOsvqCWvn7Wudp_hXJlEdm5
PX2G1Q5_QGfTk9fZ6lLybuT3SUHFttrAdoKNEzGOzekzr6Wj--
CZFrSdBbxmy5lxNe7EYxxzS1rq5k6BXv9n_2sNQrCg",
"expires_in": 432000,
"refresh_expires_in": 0,
"refresh_token":
"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxZmM4NjQwYi1lYjk1LTQ3N
DAtYjliYi04YTNlMjQxZjNkMzQifQ.eyJpYXQiOjE3MjAwNzEyODIsImp0aSI6ImEzMT
g2YWM3LTA0N2QtNDY1Ny04YTUyLWM5MmM5MWMzOWY0ZCIsImlzcyI6Imh0d
HBzOi8vaWQubW9iaWxlLm1obmV4dXMuY29tL3JlYWxtcy9wZXJzb24iLCJhdWQi
OiJodHRwczovL2lkLm1vYmlsZS5taG5leHVzLmNvbS9yZWFsbXMvcGVyc29uIiwic3
ViIjoiYTJkYWFmZmYtZGFkMy00Yzg1LWI4NjQtNzI1Y2Q1YmQ5ODc1IiwidHlwIjoiT
2ZmbGluZSIsImF6cCI6InBlcnNvbi1wb3J0YWwiLCJzZXNzaW9uX3N0YXRlIjoiNzU4
MDM4OTAtZGZiMy00MmQ4LTljMTktOGFhMzU3MmQ4MzI0Iiwic2NvcGUiOiJvcGV
uaWQgb2ZmbGluZV9hY2Nlc3MgcHJvZmlsZSBlbWFpbCIsInNpZCI6Ijc1ODAzODk
wLWRmYjMtNDJkOC05YzE5LThhYTM1NzJkODMyNCJ9._uTxE_WHvYEBF6IfWk
naj7KNdJ5E479ukSYIu4sKsNg",
"token_type": "Bearer",
"id_token":
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6S0dPWnBlZmFoNkJqTVl
6VFA4MGZMSTBQM2JNb3pjVUVPWmpPMFpGT0c4In0.eyJleHAiOjE3MjA1MDMy
ODIsImlhdCI6MTcyMDA3MTI4MiwiYXV0aF90aW1lIjowLCJqdGkiOiIwMmI5N2QxZ
C1hN2EzLTRhODMtOTZmYS0yZThlN2FmMGRmNjAiLCJpc3MiOiJodHRwczovL2l
kLm1vYmlsZS5taG5leHVzLmNvbS9yZWFsbXMvcGVyc29uIiwiYXVkIjoicGVyc29uL
XBvcnRhbCIsInN1YiI6ImEyZGFhZmZmLWRhZDMtNGM4NS1iODY0LTcyNWNkN
WJkOTg3NSIsInR5cCI6IklEIiwiYXpwIjoicGVyc29uLXBvcnRhbCIsInNlc3Npb25fc3R
hdGUiOiI3NTgwMzg5MC1kZmIzLTQyZDgtOWMxOS04YWEzNTcyZDgzMjQiLCJhd
F9oYXNoIjoiUkhfSTN1U2F4T2JpOFJiMjdnRHJOQSIsImFjciI6IjEiLCJzaWQiOiI3NT
gwMzg5MC1kZmIzLTQyZDgtOWMxOS04YWEzNTcyZDgzMjQiLCJlbWFpbF92ZXJ
pZmllZCI6ZmFsc2UsInBob25lTnVtYmVyIjoiKzYwMTM2MDU1ODUwIiwibmFtZSI6Ik
FobWFkIEFpbWFuIEhhemlxIEFobWFkIHRhcm1pZHppIiwicHJlZmVycmVkX3VzZXJ
uYW1lIjoiaGF6aXFAbWhuZXh1cy5jb20iLCJnaXZlbl9uYW1lIjoiQWhtYWQgQWltYW
4gSGF6aXEiLCJpZE5vIjoiOTUwNzI4MTA2MDUxIiwiZmFtaWx5X25hbWUiOiJBaG1
hZCB0YXJtaWR6aSIsImVtYWlsIjoiaGF6aXFAbWhuZXh1cy5jb20ifQ.G_PbgGb91W
wa28AYW84pewpRRGvcej4eYd5-v3-
X8iQmSirvbhIDuIvEhUPglR7dKSaQ4KwxkhOgksYHBE4PiPMg8MCw0kjfl1MSebfMuXGru7HaItJoLaHZ2JP9ibzuStEHp1yXHzMRpA47RvC
Ly5DrELsGM4p5Knx1O0E22Gg0hA2mEPv2bkJxM275Wswky_xVxmKUMCQdZCc3QDkRa-xPypAzOeAT0h9fnpcM7EmPYJLVQvBHAPZebOCnINTXj1Xt697ul78s8a59Xk2oWVCu0VPYo
Wcpu6O5D75D6azOvCfZUt8s6Pr2FTowUOoNThj8V_wJR-_qvfNaXCg",
"not-before-policy": 1720051279,
"session_state": "75803890-dfb3-42d8-9c19-8aa3572d8324",
"scope": "openid offline_access profile email"
}
- UserInfo Request
Key | Value |
---|---|
url | https://id.mobile.mhnexus.com/realms/person/protocol/openidconnect/userinfo |
Authorization | Bearer {{access_token} } |
HTTP Method | GET |
Request
curl --location 'https://id.mobile.mhnexus.com/realms/person/protocol/openidconnect/userinfo' \
--header 'Authorization: Bearer
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6S0dPWnBlZmFoNkJqTVl6
VFA4MGZMSTBQM2JNb3pjVUVPWmpPMFpGT0c4In0.eyJleHAiOjE3MjA0ODI3O
TgsImlhdCI6MTcyMDA1MDc5OCwianRpIjoiODdlZjdiOWYtMzllYS00NTc1LWIyN2It
NWRhNDAzOTQwZGJkIiwiaXNzIjoiaHR0cHM6Ly9pZC5tb2JpbGUubWhuZXh1cy5j
b20vcmVhbG1zL3BlcnNvbiIsInN1YiI6ImEyZGFhZmZmLWRhZDMtNGM4NS1iODY
0LTcyNWNkNWJkOTg3NSIsInR5cCI6IkJlYXJlciIsImF6cCI6InBlcnNvbi1wb3J0YWwi
LCJzZXNzaW9uX3N0YXRlIjoiMmI4M2NmMGEtYjk4My00NjMwLTliMjQtNjM4YWNi
Njc1Y2ViIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyIvKiIsImh0dHA6Ly9sb2
NhbGhvc3Q6OTIwMCIsImh0dHA6Ly9sb2NhbGhvc3Q6NDEwMCIsImh0dHA6Ly8x
OTIuODIuNjMuNTA6OTYwMCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGV
mYXVsdC1yb2xlcy1tb2JpbGUiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3Jpe
mF0aW9uIl19LCJzY29wZSI6Im9wZW5pZCBvZmZsaW5lX2FjY2VzcyBwcm9maWxl
IGVtYWlsIiwic2lkIjoiMmI4M2NmMGEtYjk4My00NjMwLTliMjQtNjM4YWNiNjc1Y2ViIi
wiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwaG9uZU51bWJlciI6Iis2MDEzNjA1N
Tg1MCIsIm5hbWUiOiJBaG1hZCBBaW1hbiBIYXppcSBBaG1hZCB0YXJtaWR6aSIs
InByZWZlcnJlZF91c2VybmFtZSI6ImhhemlxQG1obmV4dXMuY29tIiwiZ2l2ZW5fbmF
tZSI6IkFobWFkIEFpbWFuIEhhemlxIiwiaWRObyI6Ijk1MDcyODEwNjA1MSIsImZhb
WlseV9uYW1lIjoiQWhtYWQgdGFybWlkemkiLCJlbWFpbCI6ImhhemlxQG1obmV4d
XMuY29tIn0.P88t2URlsQjDNBARuUiMWurPZXUlN7pQ36_fDMiDWwluOuQSFyd6PIJmXNhtL5zTWHuJhjOEmRfNt
R3O5_vSHs5g3on_l1Cat2pAqa9CJ1x1ZFWx73NcHCD4--
S9O9LTQZrK_g5yWj1PGIVs8blmLxszXTye7Y8xKbJCMtVsoknysEO3JnaJtdmF9Ju
UBNCAxDbtVCY88g19fFwfyknILrFBqaumFDVuBOaPPdqXDAYUs5Itwgm5DsSrk_Qj6bNs3T7yWqywDxKqXh4gXdoMVmclFIr8kNbQthTQSHZdMZ8Y_-
Hunopa6eTnD3AwkXiMC20a9ckmVD2Gmt-4d6aA'
Response
{
"access_token":
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6S0dPWnBlZmFoNkJqTVl
6VFA4MGZMSTBQM2JNb3pjVUVPWmpPMFpGT0c4In0.eyJleHAiOjE3MjA1MDMy
ODIsImlhdCI6MTcyMDA3MTI4MiwianRpIjoiM2VjODA0YWQtZmZiOS00Zjk2LTgwZ
DctZDFiMmZhZWIzZjk4IiwiaXNzIjoiaHR0cHM6Ly9pZC5tb2JpbGUubWhuZXh1cy5j
b20vcmVhbG1zL3BlcnNvbiIsInN1YiI6ImEyZGFhZmZmLWRhZDMtNGM4NS1iODY
0LTcyNWNkNWJkOTg3NSIsInR5cCI6IkJlYXJlciIsImF6cCI6InBlcnNvbi1wb3J0YWwi
LCJzZXNzaW9uX3N0YXRlIjoiNzU4MDM4OTAtZGZiMy00MmQ4LTljMTktOGFhMz
U3MmQ4MzI0IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyIvKiIsImh0dHA6Ly
9sb2NhbGhvc3Q6OTIwMCIsImh0dHA6Ly9sb2NhbGhvc3Q6NDEwMCIsImh0dHA6
Ly8xOTIuODIuNjMuNTA6OTYwMCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsi
ZGVmYXVsdC1yb2xlcy1tb2JpbGUiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3
JpemF0aW9uIl19LCJzY29wZSI6Im9wZW5pZCBvZmZsaW5lX2FjY2VzcyBwcm9ma
WxlIGVtYWlsIiwic2lkIjoiNzU4MDM4OTAtZGZiMy00MmQ4LTljMTktOGFhMzU3Mm
Q4MzI0IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwaG9uZU51bWJlciI6Iis2MD
EzNjA1NTg1MCIsIm5hbWUiOiJBaG1hZCBBaW1hbiBIYXppcSBBaG1hZCB0YXJta
WR6aSIsInByZWZlcnJlZF91c2VybmFtZSI6ImhhemlxQG1obmV4dXMuY29tIiwiZ2l2
ZW5fbmFtZSI6IkFobWFkIEFpbWFuIEhhemlxIiwiaWRObyI6Ijk1MDcyODEwNjA1MS
IsImZhbWlseV9uYW1lIjoiQWhtYWQgdGFybWlkemkiLCJlbWFpbCI6ImhhemlxQG1
obmV4dXMuY29tIn0.hwJtzgMcCLyyu31FrRTF2DsnLdzIxwqgWsnC3PtotXQ3OiUKgbLxIRcJn1yn185Dkh2zMJf7j4CEdD2oYJTYjBU1PO6TvePJsoRx2sF9Xo
ij_VgHigDQiJ9U_7f2vh0gXFA0hZzwwkyxqP-vOJWb_hcj1MF2wuF1T8VBVEhdYRi2meGkY2lyDiI9RxSEjBMgYNMlC2YFJQG3AptJs6l_hvUbl7YhWDEePOsvqCWvn7Wudp_hXJlEdm5
PX2G1Q5_QGfTk9fZ6lLybuT3SUHFttrAdoKNEzGOzekzr6Wj--
CZFrSdBbxmy5lxNe7EYxxzS1rq5k6BXv9n_2sNQrCg",
"expires_in": 432000,
"refresh_expires_in": 0,
"refresh_token":
"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxZmM4NjQwYi1lYjk1LTQ3N
DAtYjliYi04YTNlMjQxZjNkMzQifQ.eyJpYXQiOjE3MjAwNzEyODIsImp0aSI6ImEzMT
g2YWM3LTA0N2QtNDY1Ny04YTUyLWM5MmM5MWMzOWY0ZCIsImlzcyI6Imh0d
HBzOi8vaWQubW9iaWxlLm1obmV4dXMuY29tL3JlYWxtcy9wZXJzb24iLCJhdWQi
OiJodHRwczovL2lkLm1vYmlsZS5taG5leHVzLmNvbS9yZWFsbXMvcGVyc29uIiwic3
ViIjoiYTJkYWFmZmYtZGFkMy00Yzg1LWI4NjQtNzI1Y2Q1YmQ5ODc1IiwidHlwIjoiT
2ZmbGluZSIsImF6cCI6InBlcnNvbi1wb3J0YWwiLCJzZXNzaW9uX3N0YXRlIjoiNzU4
MDM4OTAtZGZiMy00MmQ4LTljMTktOGFhMzU3MmQ4MzI0Iiwic2NvcGUiOiJvcGV
uaWQgb2ZmbGluZV9hY2Nlc3MgcHJvZmlsZSBlbWFpbCIsInNpZCI6Ijc1ODAzODk
wLWRmYjMtNDJkOC05YzE5LThhYTM1NzJkODMyNCJ9._uTxE_WHvYEBF6IfWk
naj7KNdJ5E479ukSYIu4sKsNg",
"token_type": "Bearer",
"id_token":
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6S0dPWnBlZmFoNkJqTVl
6VFA4MGZMSTBQM2JNb3pjVUVPWmpPMFpGT0c4In0.eyJleHAiOjE3MjA1MDMy
ODIsImlhdCI6MTcyMDA3MTI4MiwiYXV0aF90aW1lIjowLCJqdGkiOiIwMmI5N2QxZ
C1hN2EzLTRhODMtOTZmYS0yZThlN2FmMGRmNjAiLCJpc3MiOiJodHRwczovL2l
kLm1vYmlsZS5taG5leHVzLmNvbS9yZWFsbXMvcGVyc29uIiwiYXVkIjoicGVyc29uL
XBvcnRhbCIsInN1YiI6ImEyZGFhZmZmLWRhZDMtNGM4NS1iODY0LTcyNWNkN
WJkOTg3NSIsInR5cCI6IklEIiwiYXpwIjoicGVyc29uLXBvcnRhbCIsInNlc3Npb25fc3R
hdGUiOiI3NTgwMzg5MC1kZmIzLTQyZDgtOWMxOS04YWEzNTcyZDgzMjQiLCJhd
F9oYXNoIjoiUkhfSTN1U2F4T2JpOFJiMjdnRHJOQSIsImFjciI6IjEiLCJzaWQiOiI3NT
gwMzg5MC1kZmIzLTQyZDgtOWMxOS04YWEzNTcyZDgzMjQiLCJlbWFpbF92ZXJ
pZmllZCI6ZmFsc2UsInBob25lTnVtYmVyIjoiKzYwMTM2MDU1ODUwIiwibmFtZSI6Ik
FobWFkIEFpbWFuIEhhemlxIEFobWFkIHRhcm1pZHppIiwicHJlZmVycmVkX3VzZXJ
uYW1lIjoiaGF6aXFAbWhuZXh1cy5jb20iLCJnaXZlbl9uYW1lIjoiQWhtYWQgQWltYW
4gSGF6aXEiLCJpZE5vIjoiOTUwNzI4MTA2MDUxIiwiZmFtaWx5X25hbWUiOiJBaG1
hZCB0YXJtaWR6aSIsImVtYWlsIjoiaGF6aXFAbWhuZXh1cy5jb20ifQ.G_PbgGb91W
wa28AYW84pewpRRGvcej4eYd5-v3-
X8iQmSirvbhIDuIvEhUPglR7dKSaQ4KwxkhOgksYHBE4PiPMg8MCw0kjfl1MSebfMuXGru7HaItJoLaHZ2JP9ibzuStEHp1yXHzMRpA47RvC
Ly5DrELsGM4p5Knx1O0E22Gg0hA2mEPv2bkJxM275Wswky_xVxmKUMCQdZCc3QDkRa-xPypAzOeAT0h9fnpcM7EmPYJLVQvBHAPZebOCnINTXj1Xt697ul78s8a59Xk2oWVCu0VPYo
Wcpu6O5D75D6azOvCfZUt8s6Pr2FTowUOoNThj8V_wJR-_qvfNaXCg",
"not-before-policy": 1720051279,
"session_state": "75803890-dfb3-42d8-9c19-8aa3572d8324",
"scope": "openid offline_access profile email"
}
- Patient data request
Key | Value |
---|---|
url | https://veinscdr.mhnexus.com/baseR4/Patient/74c778d4-19a4-442e-8918-620733047fce |
Authorization | Bearer {{access_token} } |
HTTP Method | GET |
Request
curl --location 'https://veinscdr.mhnexus.com/baseR4/Patient/74c778d4-19a4-442e8918-620733047fce' \
--header 'Authorization: ••••••'
Response
{
"resourceType": "Patient",
"id": "74c778d4-19a4-442e-8918-620733047fce",
"meta": {
"versionId": "6",
"lastUpdated": "2024-05-21T20:04:25.955+08:00",
"source": "http://provider.hie.moh.gov.my#TfYivuSnxXRxzgqB",
"profile": [
"http://fhir.hie.moh.gov.my/StructureDefinition/Patient-my-core"
]
},
"extension": [
{
"url": "http://fhir.hie.moh.gov.my/StructureDefinition/person-category-army-my-core",
"valueCodeableConcept": {
"coding": [
{
"system": "http://fhir.hie.moh.gov.my/CodeSystem/person-category-army-my-core",
"code": "04",
"display": "Awam"
}
]
}
},
{
"url": "http://fhir.hie.moh.gov.my/StructureDefinition/ethnic-my-core",
"valueCodeableConcept": {
"coding": [
{
"system": "http://fhir.hie.moh.gov.my/CodeSystem/ethnic-my-core",
"code": "01",
"display": "Melayu"
}
]
}
},
{
"url": "http://fhir.hie.moh.gov.my/StructureDefinition/citizenship-my-core",
"extension": [
{
"url": "citizenship",
"valueBoolean": true
}
]
},
{
"url": "http://fhir.hie.moh.gov.my/StructureDefinition/audit-my-core",
"extension": [
{
"url": "recorder",
"valueReference": {
"reference": "PractitionerRole/880c2474-35fb-4d66-881a-a02c4a00e611/_history/1",
"display": "SITI KASTURI"
}
},
{
"url": "recordedDate",
"valueDateTime": "2022-12-21T10:03:58+08:00"
},
{
"url": "lastUpdater",
"valueReference": {
"reference": "PractitionerRole/ca8ce33d-89c7-479e-a807-
a4b621b3074a/_history/3",
"display": "SAIFULDAULAH BIN MOHD HAFIZ NGOO"
}
}
]
}
],
"identifier": [
{
"use": "official",
"system": "http://fhir.hie.moh.gov.my/sid/my-kad-no",
"value": "950728106051"
},
{
"use": "official",
"system": "http://fhir.hie.moh.gov.my/sid/patient-mrn",
"value": "HIE-00000305"
}
],
"active": true,
"name": [
{
"extension": [
{
"url": "http://fhir.hie.moh.gov.my/StructureDefinition/person-title-my-core",
"valueCodeableConcept": {
"coding": [
{
"system": "http://fhir.hie.moh.gov.my/CodeSystem/person-title-my-core",
"code": "C011",
"display": "Tan Sri Dr"
}
]
}
}
],
"use": "official",
"text": "AHMAD AIMAN HAZIQ BIN AHMAD TARMIDZI",
"given": [
"AHMAD AIMAN HAZIQ BIN AHMAD TARMIDZI"
]
}
],
"telecom": [
{
"system": "phone",
"value": "0136055850",
"use": "mobile"
}
],
"gender": "male",
"birthDate": "1995-07-28",
"deceasedBoolean": false,
"address": [
{
"extension": [
{
"url": "http://fhir.hie.moh.gov.my/StructureDefinition/address-district-my-core",
"valueCodeableConcept": {
"coding": [
{
"system": "http://fhir.hie.moh.gov.my/CodeSystem/district-my-core",
"code": "1401",
"display": "W.P. Kuala Lumpur"
}
]
}
},
{
"url": "http://fhir.hie.moh.gov.my/StructureDefinition/address-state-my-core",
"valueCodeableConcept": {
"coding": [
{
"system": "http://fhir.hie.moh.gov.my/CodeSystem/state-my-core",
"code": "14",
"display": "Wilayah Persekutuan Kuala Lumpur"
}
]
}
}
],
"line": [
"T3 TOWER 3"
],
"city": "AMPANG",
"postalCode": "50600",
"country": "MYS"
}
],
"managingOrganization": {
"reference": "Organization/SDHH"
}
}
Mini App Development
- Creating the App Creating a basic Progressive Web App (PWA) with login and home pages using JavaScript involves several steps. Here is a simple example to get you started. Your project structure will look something like this:
Mini-app/
│
├── index.html
├── login.html
├── home.html
├── package.json
- Creating login page This page will contain a simple login form. In this section the response of the payload will store inside session storage.
- hightlight : sessionStorage.setItem('SMART_TOKEN', JSON.stringify(result));
Code Snippet
- Creating home.html This page will be the home page after the user logs in. It will display the profile of authorized user.
Code Snippet
Mini Apps
This is the home page of the mini apps. They are discovered and activated by super
app users and once
used they can also be easily removed from the UI. In general, mini apps are
developed to complete one or
more specific tasks of a larger app, such as the functionality to contract services, buy
a product, make
donations, and rent something, among others.
User Information
Code Snippet
// do checkin session storage if smart token is exist
if (sessionStorage.getItem("SMART_TOKEN") == null) {
//if the smart token not exist redirect to login
window.location.href = 'login';
} else {
//if the smart token is exist do a process to get userinfo
var AUTH_URL = sessionStorage.getItem("AUTH_URL");
var FHIR_URL = sessionStorage.getItem("FHIR_URL");
var SMART_TOKEN = sessionStorage.getItem("SMART_TOKEN");
var token = JSON.parse(SMART_TOKEN);
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
myHeaders.append("Authorization", "bearer " + token.access_token);
const requestOptions = {
method: "GET",
headers: myHeaders,
};
var patientId = null;
fetch(AUTH_URL + "/protocol/openid-connect/userinfo", requestOptions)
.then((response) => response.json())
.then((result) => {
console.log(result);
document.getElementById('sub').textContent = result.sub;
document.getElementById('email_verified').textContent = result.email_verified;
document.getElementById('phoneNumber').textContent = result.phoneNumber;
document.getElementById('name').textContent = result.name;
document.getElementById('preferred_username').textContent =
result.preferred_username;
document.getElementById('given_name').textContent = result.given_name;
document.getElementById('idNo').textContent = result.idNo;
document.getElementById('family_name').textContent = result.family_name;
document.getElementById('email').textContent = result.email;
document.getElementById('patient').textContent = result.patient;
document.getElementById('fhir_url').textContent = FHIR_URL;
const myHeaders2 = new Headers();
myHeaders2.append("Authorization", "bearer " + token.access_token);
const requestOptions2 = {
method: "GET",
headers: myHeaders2,
};
fetch(FHIR_URL + "/Patient/" + result.patient, requestOptions2)
.then((response) => response.json())
.then((result) => {
console.log(result);
document.getElementById('patient_id').textContent = result.id;
document.getElementById('patient_resource').textContent = result.resourceType;
document.getElementById('patient_source').textContent = result.meta.source;
document.getElementById('patient_identifier').textContent = result.identifier[0].value;
document.getElementById('patient_name').textContent = result.name[0].text;
document.getElementById('patient_gender').textContent = result.gender;
document.getElementById('patient_birthdate').textContent = result.birthDate;
for (var i = 0; i < result.telecom.length; i++) {
if (result.telecom[i].system == "phone") {
document.getElementById('patient_phone').textContent = result.telecom[i].value;
}
if (result.telecom[i].system == "email") {
document.getElementById('patient_email').textContent = result.telecom[i].value;
}
}
for (var i = 0; i < result.address.length; i++) {
document.getElementById('patient_address').textContent = result.address[i].line[0] +
result.address[i].postalCode + " " + result.address[i].city;
}
})
.catch((error) => {
console.error(error);
document.getElementById('info').textContent = 'An error occurred. Please try again.';
});
})
.catch((error) => {
console.error(error);
document.getElementById('info').textContent = 'An error occurred. Please try again.';
});
}
- Creating index.html page This page will contain initiate page. In this section. The page will do a checking on session storage to validate the SMART_TOKEN.
- hightlight : sessionStorage.getItem("SMART_TOKEN")
Code Snippet
Run and Test App
Now that the Mini App is created and Authorization is configured, we need to make sure that everything is functioning correctly.
- Open the “terminal/command” prompt.
- Navigate to the “project directory,” then run the following command:
- cd
Note:
replace the
a. Run the following command: npm install Note: this will install required dependencies for a node project listed in the package.json file. (You need to run this command only once unless you make any changes in the package.json file.)
b. Run the command to start the server: npm start
c. Copy and paste the following URL into the address bar:
http://localhost:9200
After launching, an authentication page similar to the image below will appear:
Enter the credentials then select “Login,” (Use the credential of the user created in the previous section.) The authorization screen should appear like the image below: Username: haziq@mhnexus.com Password: P@ssw0rd
Congrats, you’ve now successfully created and tested your first mini app. SMART on FHIR is a data standard that enables applications to access information in electronic health record (EHR) systems. An application developer can write a single application that connects to any EHR system that has adopted the standard.