Skip to main content

Signature Algorithm

note
  • Signature algorithm is used to sign your payment API request with a private key to obtain additional security.
info
  • Data object needs to be sorted, the Nested object also needs to be sorted.

Step 1 : Prepare a Request Parameter

Method : POST

note
  • Refer to which API endpoint you are calling , below request parameter is just an EXAMPLE

Example of Web/Mobile Payment

ParameterTypeRequiredDescriptionExample
orderObjectYesObject of order(Refer to explanation below)
customerObjectYesObject of customer(Refer to explanation below)
method[]StringYesRM currently supported method[]
typeStringYesObject of type(Refer to explanation below)
storeIdStringYesID of the store to create QR code"10946114768247530"
redirectUrlStringYesURL to redirect after payment is made"https://google.com"
notifyUrlStringYesExample of Notify URL Response"https://google.com"
layoutVersionStringOptionalSelect layout for Web paymentv1 / v2 (Supported Credit Card) / v3 (Supported Credit Card and FPX)

Order object (order):
ParameterTypeRequiredDescriptionExample
titleStringYesOrder title, max: 32"Sales"
detailStringYesOrder detail, max: 600"1 x iPhone X; 2 x SAMSUNG S8"
additionalDataStringYesOrder description"Sales"
amountUintYesAmount of order in cent. Only required when "isPrefillAmount" = true. (min RM 0.10 or amount: 10)100
currencyTypeStringYesCurrency notation (currently only support MYR)"MYR"
idStringOrder ID"6170506694335521334"

Customer object (customer):
ParameterTypeRequiredDescriptionExample
userIdStringYesif tokenization enable need userId"13245876"
emailStringOptionalCustomer Email""
countryCodeStringOptionalCustomer Country Code""
phoneNumberStringOptionalCustomer Phone Number""

Type Object (type):
ParameterTypeRequiredExample
typeStringYes"WEB_PAYMENT"
typeStringYes"MOBILE_PAYMENT"

Example Request

{
"order": {
"title": "hello",
"detail": "",
"additionalData": "world",
"amount": 10,
"currencyType": "MYR",
"id": "7211"
},
"customer": {
"userId": "13245876",
"email": ""
},
"method": [],
"type": "WEB_PAYMENT",
"storeId": "1608123035564538121",
"redirectUrl": "https://revenuemonster.my",
"notifyUrl": "https://dev-rm-api.ap.ngrok.io",
"layoutVersion": "v3"
}
info
  • Sort the above json key alphabetically and make it compact

  • Replace following special character on the json body:
    < to \u003c
    > to \u003e
    & to \u0026

Step 2 : Encode the data using Base64 format

note

ewogICAgIm9yZGVyIjogewogICAgCSJ0aXRsZSI6ICJoZWxsbyIsCiAgICAJImRldGFpbCI6ICIiLAogICAgCSJhZGRpdGlvbmFsRGF0YSI6ICJ3b3JsZCIsCgkgICAgImFtb3VudCI6IDEwLAoJICAgICJjdXJyZW5jeVR5cGUiOiAiTVlSIiwKCSAgICAiaWQiOiAgIjcyMTEiCiAgICB9LAogICAgImN1c3RvbWVyIjogewogICAgInVzZXJJZCI6ICIiLAogICAgImVtYWlsIjogIiIKfSwKICAgICJtZXRob2QiOltdLAogICAgInR5cGUiOiAiV0VCX1BBWU1FTlQiLAogICAgInN0b3JlSWQiOiAiMTYwODEyMzAzNTU2NDUzODEyMSIsCiAgICAicmVkaXJlY3RVcmwiOiAiaHR0cHM6Ly9yZXZlbnVlbW9uc3Rlci5teSIsCiAgICAibm90aWZ5VXJsIjogImh0dHBzOi8vZGV2LXJtLWFwaS5hcC5uZ3Jvay5pbyIsCiAgICAibGF5b3V0VmVyc2lvbiI6InYzIgp9

Step 3: Construct plain text parameters

info
  • if the body is empty then the data parameter can be skip
  • if it's verifying our callback then the requestUrl can be skip
ParameterTypeRequiredDescriptionExample
dataStringYesBase64 data body from Step 2.Refer to Step 2
methodStringYesHTTP call method used"post"
nonceStrStringYesRandom string"VYNknZohxwicZMaWbNdBKUrnrxDtaRhN"
requestUrlStringYesAPI URL that you call must be exactly the same, together with URL.https://sb-open.revenuemonster.my/v3/payment/online
signTypeStringYesSign Type, prefer SHA-256"sha256"
timestampStringYesUNIX timestamp of request"1527407052"

Example

note

data=ewogICAgIm9yZGVyIjogewogICAgCSJ0aXRsZSI6ICJoZWxsbyIsCiAgICAJImRldGFpbCI6ICIiLAogICAgCSJhZGRpdGlvbmFsRGF0YSI6ICJ3b3JsZCIsCgkgICAgImFtb3VudCI6IDEwLAoJICAgICJjdXJyZW5jeVR5cGUiOiAiTVlSIiwKCSAgICAiaWQiOiAgIjcyMTEiCiAgICB9LAogICAgImN1c3RvbWVyIjogewogICAgInVzZXJJZCI6ICIiLAogICAgImVtYWlsIjogIiIKfSwKICAgICJtZXRob2QiOltdLAogICAgInR5cGUiOiAiV0VCX1BBWU1FTlQiLAogICAgInN0b3JlSWQiOiAiMTYwODEyMzAzNTU2NDUzODEyMSIsCiAgICAicmVkaXJlY3RVcmwiOiAiaHR0cHM6Ly9yZXZlbnVlbW9uc3Rlci5teSIsCiAgICAibm90aWZ5VXJsIjogImh0dHBzOi8vZGV2LXJtLWFwaS5hcC5uZ3Jvay5pbyIsCiAgICAibGF5b3V0VmVyc2lvbiI6InYzIgp9&method=post&nonceStr=VYNknZohxwicZMaWbNdBKUrnrxDtaRhN&requestUrl=https://sb-open.revenuemonster.my/v3/payment/online&signType=sha256&timestamp=1527407052

Step 4: Sign with CLIENT PRIVATE KEY

info
  • Sign this content using sha256 with rsa private key and make sure the public key have been uploaded to RM Merchant Portal
<!--TypeRequiredDescription
StringYesSign the request data in Step 3 using CLIENT PRIVATE KEYResponse show as below
note

Example of Signature

sha256 IrBg6t73VsH7ieEnQDB4CXHFjMWUkp8Dtddpxqw+4Gvz6Tag7Dx6nrfAt2ofYK8xZN9aBCvAKAfmAOGWIXnsTXfhFBnMA2kadiga7ufUJ81ozyhllbiliRM2ugw1OcqSTLRHWBPhrVwhHBxgDiG9wbuI3FKURrz+CufYYakFoCw=

Step 5: Signature of Request Data

note

Put this Signature into header under X-Signature, construct the request as below and call API endpoint:

curl --request POST
--url 'https://sb-open.revenuemonster.my/v3/payment/online'
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjIwMTgtMDMtMTMiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOlsiKiJdLCJleHAiOjE1MjE2MjkyNTYsImlhdCI6MTUyMTYyMjA1NywiaXNzIjoiaHR0cHM6Ly9zYi1vYXV0aC5yZXZlbnVlbW9uc3Rlci5teSIsImp0aSI6IkVod0tFRTlCZFhSb1FXTmpaWE56Vkc5clpXNFF5cmYza3EzTDY4QnoiLCJuYmYiOjE1MjE2MjIwNTcsInN1YiI6IkVoUUtDRTFsY21Ob1lXNTBFSlhWemQzd3JhcVRPUklRQ2dSVmMyVnlFSXlKcUl6dnlNUFZjUSJ9.dJknY9MZHLNrKx1p7gZxS0_oA3uXLWplDU1r1dpwxIbmdB6yw4tQBTXKlWArDfKLlBDn6v22_gT5Px7sdCMj7e5M9eRoJoMnoPnslgYpmJJ5kjqAbKU7dUxKb1OzFLrvmtSK9r-FRLVtMFHioWYpwgSvSPBgZ6lAYkUyDzH7aKadFYtQcBuJR0hlq2CXtP0mzbHOeu2q6giONf3E5-XqS8lLRtuHPAbJ7_YFwo0Oe2zc6h05IOocmx_NvBVPfDBnuygTU063h70Q987MYeGDV_Os4N6N_I4b-GoHprEPtmntB1RJPrFrY28hvvoUfDHXHZVXT1GlrsozrkWV4EjbTw'
--header 'Content-Type: application/json'
--header 'X-Nonce-Str: VYNknZohxwicZMaWbNdBKUrnrxDtaRhN'
--header 'X-Signature: sha256 IrBg6t73VsH7ieEnQDB4CXHFjMWUkp8Dtddpxqw+4Gvz6Tag7Dx6nrfAt2ofYK8xZN9aBCvAKAfmAOGWIXnsTXfhFBnMA2kadiga7ufUJ81ozyhllbiliRM2ugw1OcqSTLRHWBPhrVwhHBxgDiG9wbuI3FKURrz+CufYYakFoCw='
--header 'X-Timestamp: 1527407052'
--data '{
"order": {
"title": "hello",
"detail": "",
"additionalData": "world",
"amount": 10,
"currencyType": "MYR",
"id": "7211"
},
"customer": {
"userId": "13245876",
"email": ""
},
"method": [],
"type": "WEB_PAYMENT",
"storeId": "1608123035564538121",
"redirectUrl": "https://revenuemonster.my",
"notifyUrl": "https://dev-rm-api.ap.ngrok.io",
"layoutVersion": "v3"
}'

Response Parameters

ParameterTypeDescriptionExample
itemObjectitem object(Refer to explanation below)
codeStringSuccessfully call this endpoint. If fail, will return error code object (Refer Appendix 1: Error Codes)"SUCCESS"

item Object (item):
ParameterTypeDescriptionExample
checkoutIdStringCode to identify web payment url"1548316308361173347"
urlStringExample to form checkout URL. Note: to change base URL to desired URL."https://sb-pg.revenuemonster.my/checkout?checkoutId=1548316308361173347"

Example Response

{
"item": {
"checkoutId": "1548316308361173347",
"url": "https://sb-pg.revenuemonster.my/checkout?checkoutId=1548316308361173347"
},
"code": "SUCCESS"
}

Using RM Merchant Portal to get Signature

Step 1 : Create New Application

Go to Merchant Portal > Developer > Applications tab (last on the list) and you will see the following page:

image

Step 2 : Obtain Credential

Click on the Applications created in Step 1. You may edit and update relevant information here :


If you would like to disable the application , simply toggle the "ON/OFF" switch button at the top right.


image

Click on Show to reveal your clientSecret:

image


Generate RSA KEYS

If you need help to generate a key, go to Merchant portal > Developer > Application > Generator RSA Key Suggested key size: 2048 Bit. Keep your private keys in a safe place! Or use our Generate RSA key tool.

  • Private Keys are required to sign API request(s) contents.
  • Public Keys are used to verify content received.

image


Optional Tool: Signature Debugger

Public Keys needs to have be wrap as following :

image
For security purposes, we enhanced our authentication flow and Open API by adding layers of encryption to our endpoints. You may develop your own encryption tool on your desired application directly, or use our Signature Debugger to do signing/verification using private/public keys as obtained from the previous step. Refer more on Signature Debugger

image


Invalid Request Signature

note

You can refer the below Response if you received INVALID_REQUEST_SIGNATURE
we will guide you step by step to fix the issue

{
"debug": {
"preVerifyContent": {
"step1": {
"content": "{\"layoutVersion\":\"v2\",\"method\":[\"GOBIZ_MY\"],\"notifyUrl\":\"https://dev-rm-api.ap.ngrok.io\",\"order\":{\"additionalData\":\"world\",\"amount\":10,\"currencyType\":\"MYR\",\"detail\":\"hello\",\"id\":\"721115\",\"title\":\"hello\"},\"redirectUrl\":\"https://revenuemonster.my\",\"storeId\":\"10946114768247530\",\"type\":\"WEB_PAYMENT\"}",
"remark": "Sort the json key alphabetically"
},
"step2": {
"content": "eyJsYXlvdXRWZXJzaW9uIjoidjIiLCJtZXRob2QiOlsiR09CSVpfTVkiXSwibm90aWZ5VXJsIjoiaHR0cHM6Ly9kZXYtcm0tYXBpLmFwLm5ncm9rLmlvIiwib3JkZXIiOnsiYWRkaXRpb25hbERhdGEiOiJ3b3JsZCIsImFtb3VudCI6MTAsImN1cnJlbmN5VHlwZSI6Ik1ZUiIsImRldGFpbCI6ImhlbGxvIiwiaWQiOiI3MjExMTUiLCJ0aXRsZSI6ImhlbGxvIn0sInJlZGlyZWN0VXJsIjoiaHR0cHM6Ly9yZXZlbnVlbW9uc3Rlci5teSIsInN0b3JlSWQiOiIxMDk0NjExNDc2ODI0NzUzMCIsInR5cGUiOiJXRUJfUEFZTUVOVCJ9",
"remark": "Encode the data using Base64 format"
},
"step3": {
"content": "data=eyJsYXlvdXRWZXJzaW9uIjoidjIiLCJtZXRob2QiOlsiR09CSVpfTVkiXSwibm90aWZ5VXJsIjoiaHR0cHM6Ly9kZXYtcm0tYXBpLmFwLm5ncm9rLmlvIiwib3JkZXIiOnsiYWRkaXRpb25hbERhdGEiOiJ3b3JsZCIsImFtb3VudCI6MTAsImN1cnJlbmN5VHlwZSI6Ik1ZUiIsImRldGFpbCI6ImhlbGxvIiwiaWQiOiI3MjExMTUiLCJ0aXRsZSI6ImhlbGxvIn0sInJlZGlyZWN0VXJsIjoiaHR0cHM6Ly9yZXZlbnVlbW9uc3Rlci5teSIsInN0b3JlSWQiOiIxMDk0NjExNDc2ODI0NzUzMCIsInR5cGUiOiJXRUJfUEFZTUVOVCJ9&method=post&nonceStr=XAYZRZNLGCKSTURRFKBIGYALUKLCLJOG&requestUrl=https://sb-open.revenuemonster.my/v3/payment/online&signType=sha256&timestamp=1599467903",
"remark": "Construct plain text parameters on this format, if the body is empty then the `data` parameter can be skip"
},
"step4": {
"content": "data=eyJsYXlvdXRWZXJzaW9uIjoidjIiLCJtZXRob2QiOlsiR09CSVpfTVkiXSwibm90aWZ5VXJsIjoiaHR0cHM6Ly9kZXYtcm0tYXBpLmFwLm5ncm9rLmlvIiwib3JkZXIiOnsiYWRkaXRpb25hbERhdGEiOiJ3b3JsZCIsImFtb3VudCI6MTAsImN1cnJlbmN5VHlwZSI6Ik1ZUiIsImRldGFpbCI6ImhlbGxvIiwiaWQiOiI3MjExMTUiLCJ0aXRsZSI6ImhlbGxvIn0sInJlZGlyZWN0VXJsIjoiaHR0cHM6Ly9yZXZlbnVlbW9uc3Rlci5teSIsInN0b3JlSWQiOiIxMDk0NjExNDc2ODI0NzUzMCIsInR5cGUiOiJXRUJfUEFZTUVOVCJ9&method=post&nonceStr=XAYZRZNLGCKSTURRFKBIGYALUKLCLJOG&requestUrl=https://sb-open.revenuemonster.my/v3/payment/online&signType=sha256&timestamp=1599467903",
"remark": "Sign this content using sha256 with rsa private key and make sure the public key have been uploaded to the portal"
},
"step5": {
"remark": "The signature that generated from step 4, pass on the header X-Signature with prefix the sign type, e.g: sha256 {{ signatureContent }}l"
}
},
"requestHeader": {
"X-Nonce-Str": {
"currentValue": "XAYZRZNLGCKSTURRFKBIGYALUKLCLJOG",
"isValid": true,
"remark": "Make sure the nonce str is should not contain space and must unique at least for 120 second, if not the server will throw duplicate request error"
},
"X-Signature": {
"currentValue": "sha256 XvedDW8H2gqGL5gMzTHqDy1PXX3OqRF09WuQDkeCDwuinOAsPstcPOSefUwkyHPM9WPNKKHyR5qXbKNLC7UgQyGi8Ynio03kDo0p+g3BqXaUT1tpo5D8kv42Kh2S8CW4RkX2Dkf+Yxi2XMQ8l3kzPZaRyhudaGerUZony4Npzf63p4+oTBbXE01uX/4x/WL57+zkaaVRc1KlJsLdGsBmLlPOHLana7udJffJyxXhOmyokBuJ4GoOC8JpDG9oaKCNMZ88ow9CWWB0yRPrK2KeaEDwzCm2Jh8IFKw1gS6avQAwsjychZWv5XmAXkZ8ZQrnLXJquA09QpLxPTtOeQC9SA==",
"isValid": false,
"remark": "The signature is invalid, please check preVerifyContent parameter on how to generate the signature or go to our API documentation https://doc.revenuemonster.my/docs/quickstart/signature-algorithm"
},
"X-Timestamp": {
"currentValue": "1599467903",
"isValid": false,
"remark": "Make sure the timestamp generated on UTC timezone and must be maximum the time difference is 120 second from the request send to the server, if not the server will throw invalid timestamp"
}
}
},
"error": {
"code": "INVALID_REQUEST_SIGNATURE",
"message": "The request signature is invalid"
}
}
  • Check your Private key and Public key
  • No space in JSON data
  • To access all wallets, use method:[]
  • For amount:100 is RM 1.00