Coder Social home page Coder Social logo

midtrans / midtrans-nodejs-client Goto Github PK

View Code? Open in Web Editor NEW
171.0 11.0 56.0 396 KB

Official Midtrans Payment API Client for Node JS | https://midtrans.com

License: MIT License

JavaScript 99.77% Dockerfile 0.20% Shell 0.02%
payment-gateway api-client node-js nodejs javascript npm-package midtrans payment

midtrans-nodejs-client's Introduction

Midtrans Client - Node JS

NPM

npm version Build Status NPM download/month NPM download total

Midtrans โค๏ธ Node JS!

This is the Official Node JS API client/library for Midtrans Payment API. Visit https://midtrans.com. More information about the product and see documentation at http://docs.midtrans.com for more technical details.

1. Installation

1.a Using NPM

npm install --save midtrans-client

1.b Manual Installation

If you are not using NPM, you can clone or download this repository. Then require from index.js file.

let midtransClient = require('./midtrans-client-nodejs/index.js');

2. Usage

2.1 Choose Product/Method

We have 2 different products of payment that you can use:

  • Snap - Customizable payment popup will appear on your web/app (no redirection). doc ref
  • Snap Redirect - Customer need to be redirected to payment url hosted by midtrans. doc ref
  • Core API (VT-Direct) - Basic backend implementation, you can customize the frontend embedded on your web/app as you like (no redirection). doc ref

Choose one that you think best for your unique needs.

2.2 Client Initialization and Configuration

Get your client key and server key from Midtrans Dashboard

Create API client object

const midtransClient = require('midtrans-client');
// Create Core API instance
let coreApi = new midtransClient.CoreApi({
        isProduction : false,
        serverKey : 'YOUR_SERVER_KEY',
        clientKey : 'YOUR_CLIENT_KEY'
    });
const midtransClient = require('midtrans-client');
// Create Snap API instance
let snap = new midtransClient.Snap({
        isProduction : false,
        serverKey : 'YOUR_SERVER_KEY',
        clientKey : 'YOUR_CLIENT_KEY'
    });

You can also re-set config using Snap.apiConfig.set( ... ) example:

const midtransClient = require('midtrans-client');

// Create Snap API instance, empty config
let snap = new midtransClient.Snap();
snap.apiConfig.set({
        isProduction : false,
        serverKey : 'YOUR_SERVER_KEY',
        clientKey : 'YOUR_CLIENT_KEY'
    });

// You don't have to re-set using all the options, 
// i.e. set serverKey only
snap.apiConfig.set({serverKey : 'YOUR_SERVER_KEY'});

You can also set config directly from attribute

const midtransClient = require('midtrans-client');

// Create Snap API instance, empty config
let snap = new midtransClient.Snap();

snap.apiConfig.isProduction = false;
snap.apiConfig.serverKey = 'YOUR_SERVER_KEY';
snap.apiConfig.clientKey = 'YOUR_CLIENT_KEY';

2.2.A Snap

You can see Snap example here.

Available methods for Snap class

// return Snap API /transaction response as Promise of Object
createTransaction(parameter)

// return Snap API /transaction token as Promise of String
createTransactionToken(parameter)

// return Snap API /transaction redirect_url as Promise of String
createTransactionRedirectUrl(parameter)

parameter is Object or String of JSON of SNAP Parameter

Get Snap Token

const midtransClient = require('midtrans-client');
// Create Snap API instance
let snap = new midtransClient.Snap({
        isProduction : false,
        serverKey : 'YOUR_SERVER_KEY',
        clientKey : 'YOUR_CLIENT_KEY'
    });

let parameter = {
    "transaction_details": {
        "order_id": "test-transaction-123",
        "gross_amount": 200000
    }, "credit_card":{
        "secure" : true
    }
};


snap.createTransaction(parameter)
    .then((transaction)=>{
        // transaction token
        let transactionToken = transaction.token;
        console.log('transactionToken:',transactionToken);
    })

// alternative way to create transactionToken
// snap.createTransactionToken(parameter)
//     .then((transactionToken)=>{
//         console.log('transactionToken:',transactionToken);
//     })

Initialize Snap JS when customer click pay button

On frontend / html: Replace PUT_TRANSACTION_TOKEN_HERE with transactionToken acquired above

<html>
  <body>
    <button id="pay-button">Pay!</button>
    <pre><div id="result-json">JSON result will appear here after payment:<br></div></pre> 

<!-- TODO: Remove ".sandbox" from script src URL for production environment. Also input your client key in "data-client-key" -->
    <script src="https://app.sandbox.midtrans.com/snap/snap.js" data-client-key="<Set your ClientKey here>"></script>
    <script type="text/javascript">
      document.getElementById('pay-button').onclick = function(){
        // SnapToken acquired from previous step
        snap.pay('PUT_TRANSACTION_TOKEN_HERE', {
          // Optional
          onSuccess: function(result){
            /* You may add your own js here, this is just example */ document.getElementById('result-json').innerHTML += JSON.stringify(result, null, 2);
          },
          // Optional
          onPending: function(result){
            /* You may add your own js here, this is just example */ document.getElementById('result-json').innerHTML += JSON.stringify(result, null, 2);
          },
          // Optional
          onError: function(result){
            /* You may add your own js here, this is just example */ document.getElementById('result-json').innerHTML += JSON.stringify(result, null, 2);
          }
        });
      };
    </script>
  </body>
</html>

Implement Notification Handler

Refer to this section

2.2.B Snap Redirect

Also available as examples here.

Get Redirection URL of a Payment Page

const midtransClient = require('midtrans-client');
// Create Snap API instance
let snap = new midtransClient.Snap({
        isProduction : false,
        serverKey : 'YOUR_SERVER_KEY',
        clientKey : 'YOUR_CLIENT_KEY'
    });

let parameter = {
    "transaction_details": {
        "order_id": "test-transaction-123",
        "gross_amount": 200000
    }, "credit_card":{
        "secure" : true
    }
};

snap.createTransaction(parameter)
    .then((transaction)=>{
        // transaction redirect_url
        let redirectUrl = transaction.redirect_url;
        console.log('redirectUrl:',redirectUrl);
    })

// alternative way to create redirectUrl
// snap.createTransactionRedirectUrl(parameter)
//     .then((redirectUrl)=>{
//         console.log('redirectUrl:',redirectUrl);
//     })

Implement Notification Handler

Refer to this section

2.2.C Core API (VT-Direct)

You can see some Core API examples here.

Available methods for CoreApi class

/**
 * Do `/charge` API request to Core API
 * @param  {Object} parameter - object of Core API JSON body as parameter, will be converted to JSON (more params detail refer to: https://api-docs.midtrans.com)
 * @return {Promise} - Promise contains Object from JSON decoded response
 */
charge(parameter={})

/**
 * Do `/capture` API request to Core API
 * @param  {Object} parameter - object of Core API JSON body as parameter, will be converted to JSON (more params detail refer to: https://api-docs.midtrans.com)
 * @return {Promise} - Promise contains Object from JSON decoded response
 */
capture(parameter={})

/**
 * Do `/card/register` API request to Core API
 * @param  {Object} parameter - object of Core API JSON body as parameter, will be converted to JSON (more params detail refer to: https://api-docs.midtrans.com)
 * @return {Promise} - Promise contains Object from JSON decoded response
 */
cardRegister(parameter={})

/**
 * Do `/token` API request to Core API
 * @param  {Object} parameter - object of Core API JSON body as parameter, will be converted to JSON (more params detail refer to: https://api-docs.midtrans.com)
 * @return {Promise} - Promise contains Object from JSON decoded response
 */
cardToken(parameter={})

/**
 * Do `/point_inquiry/<tokenId>` API request to Core API
 * @param  {String} tokenId - tokenId of credit card (more params detail refer to: https://api-docs.midtrans.com)
 * @return {Promise} - Promise contains Object from JSON decoded response
 */
cardPointInquiry(tokenId)

parameter is Object or String of JSON of Core API Parameter

Credit Card Get Token

Get token should be handled on Frontend please refer to API docs

Credit Card Charge

const midtransClient = require('midtrans-client');
// Create Core API instance
let core = new midtransClient.CoreApi({
        isProduction : false,
        serverKey : 'YOUR_SERVER_KEY',
        clientKey : 'YOUR_CLIENT_KEY'
    });

let parameter = {
    "payment_type": "credit_card",
    "transaction_details": {
        "gross_amount": 12145,
        "order_id": "test-transaction-54321",
    },
    "credit_card":{
        "token_id": 'CREDIT_CARD_TOKEN', // change with your card token
        "authentication": true
    }
};

// charge transaction
core.charge(parameter)
    .then((chargeResponse)=>{
        console.log('chargeResponse:');
        console.log(chargeResponse);
    });

Credit Card 3DS Authentication

The credit card charge result may contains redirect_url for 3DS authentication. 3DS Authentication should be handled on Frontend please refer to API docs

For full example on Credit Card 3DS transaction refer to:

2.2.D Subscription API

You can see some Subscription API examples here, Subscription API Docs

Subscription API for Credit Card

To use subscription API for credit card, you should first obtain the 1-click saved token, refer to this docs.

You will receive saved_token_id as part of the response when the initial card payment is accepted (will also available in the HTTP notification's JSON), refer to this docs.

const midtransClient = require('midtrans-client');
// Create Core API / Snap instance (both have shared `transactions` methods)
let core = new midtransClient.CoreAPi({
        isProduction : false,
        serverKey : 'YOUR_SERVER_KEY',
        clientKey : 'YOUR_CLIENT_KEY'
    });
// prepare parameter 
let parameter = {
  "name": "MONTHLY_2021",
  "amount": "14000",
  "currency": "IDR",
  "payment_type": "credit_card",
  "token": "521111gmWqMegyejqCQmmopnCFRs1117",
  "schedule": {
    "interval": 1,
    "interval_unit": "month",
    "max_interval": 12,
    "start_time": "2021-11-25 07:25:01 +0700"
  },
  "metadata": {
    "description": "Recurring payment for A"
  },
  "customer_details": {
    "first_name": "John",
    "last_name": "Doe",
    "email": "[email protected]",
    "phone": "+62812345678"
  }
};

core.createSubscription(parameter)
        .then((response)=>{
          // do something to `response` object
        });

// get subscription by subscriptionId
core.getSubscription(subscriptionId)
        .then((response)=>{
          // do something to `response` object
        });

// enable subscription by subscriptionId
core.enableSubscription(subscriptionId)
        .then((response)=>{
          // do something to `response` object
        });

// update subscription by subscriptionId and updateSubscriptionParam
let updateSubscriptionParam = {
  "name": "MONTHLY_2021",
  "amount": "300000",
  "currency": "IDR",
  "token": savedTokenId,
  "schedule": {
    "interval": 1
  }
}
core.updateSubscription(subscriptionId, updateSubscriptionParam)
        .then((response)=>{
          // do something to `response` object
        });

Subscription API for Gopay

To use subscription API for gopay, you should first link your customer gopay account with gopay tokenization API, refer to this section

You will receive gopay payment token using getPaymentAccount API call

You can see some Subscription API examples here

2.2.E Tokenization API

You can see some Tokenization API examples here, Tokenization API Docs

const midtransClient = require('midtrans-client');
// Create Core API / Snap instance (both have shared `transactions` methods)
let core = new midtransClient.CoreApi({
        isProduction : false,
        serverKey : 'YOUR_SERVER_KEY',
        clientKey : 'YOUR_CLIENT_KEY'
    });

// prepare parameter 
let parameter = {
  "payment_type": "gopay",
  "gopay_partner": {
    "phone_number": "81212345678",
    "country_code": "62",
    "redirect_url": "https://www.gojek.com"
  }
};

// link Payment Account
core.linkPaymentAccount(parameter)
        .then((response)=>{
          // do something to `response` object
        });

// Get payment account by account id
core.getPaymentAccount(activeAccountId)
        .then((response)=>{
          // do something to `response` object
        });

// unlink payment account by accountId
core.unlinkPaymentAccount(activeAccountId)
        .then((response)=>{
          // do something to `response` object
        });

2.3 Handle HTTP Notification

IMPORTANT NOTE: To update transaction status on your backend/database, DO NOT solely rely on frontend callbacks! For security reason to make sure the status is authentically coming from Midtrans, only update transaction status based on HTTP Notification or API Get Status.

Create separated web endpoint (notification url) to receive HTTP POST notification callback/webhook. HTTP notification will be sent whenever transaction status is changed. Example also available here

const midtransClient = require('midtrans-client');
// Create Core API / Snap instance (both have shared `transactions` methods)
let apiClient = new midtransClient.Snap({
        isProduction : false,
        serverKey : 'YOUR_SERVER_KEY',
        clientKey : 'YOUR_CLIENT_KEY'
    });

apiClient.transaction.notification(notificationJson)
    .then((statusResponse)=>{
        let orderId = statusResponse.order_id;
        let transactionStatus = statusResponse.transaction_status;
        let fraudStatus = statusResponse.fraud_status;

        console.log(`Transaction notification received. Order ID: ${orderId}. Transaction status: ${transactionStatus}. Fraud status: ${fraudStatus}`);

        // Sample transactionStatus handling logic

        if (transactionStatus == 'capture'){
            // capture only applies to card transaction, which you need to check for the fraudStatus
            if (fraudStatus == 'challenge'){
                // TODO set transaction status on your databaase to 'challenge'
            } else if (fraudStatus == 'accept'){
                // TODO set transaction status on your databaase to 'success'
            }
        } else if (transactionStatus == 'settlement'){
            // TODO set transaction status on your databaase to 'success'
        } else if (transactionStatus == 'deny'){
            // TODO you can ignore 'deny', because most of the time it allows payment retries
            // and later can become success
        } else if (transactionStatus == 'cancel' ||
          transactionStatus == 'expire'){
            // TODO set transaction status on your databaase to 'failure'
        } else if (transactionStatus == 'pending'){
            // TODO set transaction status on your databaase to 'pending' / waiting payment
        }
    });

2.4 Transaction Action

Also available as examples here

Get Status

// get status of transaction that already recorded on midtrans (already `charge`-ed) 
apiClient.transaction.status('YOUR_ORDER_ID OR TRANSACTION_ID')
    .then((response)=>{
        // do something to `response` object
    });

Get Status B2B

// get transaction status of VA b2b transaction
apiClient.transaction.statusb2b('YOUR_ORDER_ID OR TRANSACTION_ID')
    .then((response)=>{
        // do something to `response` object
    });

Approve Transaction

// approve a credit card transaction with `challenge` fraud status
apiClient.transaction.approve('YOUR_ORDER_ID OR TRANSACTION_ID')
    .then((response)=>{
        // do something to `response` object
    });

Deny Transaction

// deny a credit card transaction with `challenge` fraud status
apiClient.transaction.deny('YOUR_ORDER_ID OR TRANSACTION_ID')
    .then((response)=>{
        // do something to `response` object
    });

Cancel Transaction

apiClient.transaction.cancel('YOUR_ORDER_ID OR TRANSACTION_ID')
    .then((response)=>{
        // do something to `response` object
    });

Expire Transaction

apiClient.transaction.expire('YOUR_ORDER_ID OR TRANSACTION_ID')
    .then((response)=>{
        // do something to `response` object
    });

Refund Transaction

let parameter = {
    "refund_key": "order1-ref1",
    "amount": 5000,
    "reason": "Item out of stock"
}
apiClient.transaction.refund('YOUR_ORDER_ID OR TRANSACTION_ID',parameter)
    .then((response)=>{
        // do something to `response` object
    });

Refund Transaction with Direct Refund

let parameter = {
    "refund_key": "order1-ref1",
    "amount": 5000,
    "reason": "Item out of stock"
}
apiClient.transaction.refundDirect('YOUR_ORDER_ID OR TRANSACTION_ID',parameter)
    .then((response)=>{
        // do something to `response` object
    });

3. Handling Error / Exception

When using function that result in Midtrans API call e.g: core.charge(...) or snap.createTransaction(...) there's a chance it may throw error (MidtransError object), the error object will contains below properties that can be used as information to your error handling logic:

snap.createTransaction(parameter)
      .then((res)=>{
      })
      .catch((e)=>{
        e.message // basic error message string
        e.httpStatusCode // HTTP status code e.g: 400, 401, etc.
        e.ApiResponse // JSON of the API response 
        e.rawHttpClientData // raw Axios response object
      })

4. Advanced Usage

Custom Http Client Config

Under the hood this API wrapper is using Axios as http client. You can override the default config.

You can set via the value of this <api-client-instance>.httpClient.http_client.defaults object, like described in Axios guide. e.g:

// create instance of api client
let snap = new midtransClient.Snap({
        isProduction : false,
        serverKey : 'YOUR_SERVER_KEY',
        clientKey : 'YOUR_CLIENT_KEY'
    });

// set Axios timeout config to 2500
snap.httpClient.http_client.defaults.timeout = 2500; 

// set custom HTTP header for every request from this instance
snap.httpClient.http_client.defaults.headers.common['My-Header'] = 'my-custom-value';

Custom Http Client Interceptor

As Axios also support interceptor, you can also apply it here. e.g:

// Add a request interceptor
snap.httpClient.http_client.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

It can be used for example to customize/manipulate http request's body, header, etc. before it got sent to the destination API url.

Override Http Notification Url

As described in API docs, merchant can opt to change or add custom notification urls on every transaction. It can be achieved by adding additional HTTP headers into charge request.

This can be achived by:

// create instance of api client
let snap = new midtransClient.Snap({
        isProduction : false,
        serverKey : 'YOUR_SERVER_KEY',
        clientKey : 'YOUR_CLIENT_KEY'
});

// set custom HTTP header that will be used by Midtrans API to override notification url:
snap.httpClient.http_client.defaults.headers.common['X-Override-Notification'] = 'https://mysite.com/midtrans-notification-handler';

or append notification:

snap.httpClient.http_client.defaults.headers.common['X-Append-Notification'] = 'https://mysite.com/midtrans-notification-handler';

5. Iris Disbursement API

Iris is Midtransโ€™ cash management solution that allows you to disburse payments to any bank accounts in Indonesia securely and easily. Iris connects to the banksโ€™ hosts to enable seamless transfer using integrated APIs.

For more details please visit: https://iris-docs.midtrans.com

5.1 Client Initialization

Get your API key from Midtrans Iris Dashboard

Create API client object. Note: the serverKey means your API key.

const midtransClient = require('midtrans-client');
// Create Core API instance
let iris = new midtransClient.Iris({
        isProduction : false,
        serverKey : 'YOUR_API_KEY'
    });

Then perform one of the available functions, using the payload described on Iris docs, e.g:

let iris = new midtransClient.Iris({
        isProduction : false,
        serverKey : 'YOUR_API_KEY'
    });

iris.createBeneficiaries({
  "name": "Budi Susantoo",
  "account": "0611101146",
  "bank": "bca",
  "alias_name": "budisusantoo",
  "email": "[email protected]"
})
  .then((res)=>{
    // do something based on the API response
  })
  .catch((err)=>{
    // do something based on the Error object & message
  })

5.2 Available methods of Iris API

  /**
   * Do `/ping` API request to Iris API
   * @return {Promise} - Promise contains String response
   */
  ping()
  /**
   * Do create `/beneficiaries` API request to Iris API
   * @param  {Object} parameter - object of Iris API JSON body as parameter, will be converted to JSON (more params detail refer to: https://iris-docs.midtrans.com)
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  createBeneficiaries(parameter={})
  /**
   * Do update `/beneficiaries/<alias_name>` API request to Iris API
   * @param  {String} parameter - alias_name of the beneficiaries that need to be updated
   * @param  {Object} parameter - object of Iris API JSON body as parameter, will be converted to JSON (more params detail refer to: https://iris-docs.midtrans.com)
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  updateBeneficiaries(aliasName,parameter={})
  /**
   * Do `/beneficiaries` API request to Iris API
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  getBeneficiaries()
  /**
   * Do create `/payouts` API request to Iris API
   * @param  {Object} parameter - object of Iris API JSON body as parameter, will be converted to JSON (more params detail refer to: https://iris-docs.midtrans.com)
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  createPayouts(parameter={})
  /**
   * Do approve `/payouts/approve` API request to Iris API
   * @param  {Object} parameter - object of Iris API JSON body as parameter, will be converted to JSON (more params detail refer to: https://iris-docs.midtrans.com)
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  approvePayouts(parameter={})
  /**
   * Do reject `/payouts/reject` API request to Iris API
   * @param  {Object} parameter - object of Iris API JSON body as parameter, will be converted to JSON (more params detail refer to: https://iris-docs.midtrans.com)
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  rejectPayouts(parameter={})
  /**
   * Do `/payouts/<reference_no>` API request to Iris API
   * @param  {String} parameter - reference_no of the payout
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  getPayoutDetails(referenceNo)
  /**
   * Do `/statements` API request to Iris API
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  getTransactionHistory(parameter={})
  /**
   * Do `/channels` API request to Iris API
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  getTopupChannels()
  /**
   * Do `/balance` API request to Iris API
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  getBalance()
  /**
   * Do `/bank_accounts` API request to Iris API
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  getFacilitatorBankAccounts()
  /**
   * Do `/bank_accounts/<bank_account_id>/balance` API request to Iris API
   * @param  {String} parameter - bank_account_id of the bank account
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  getFacilitatorBalance(bankAccountId)
  /**
   * Do `/beneficiary_banks` API request to Iris API
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  getBeneficiaryBanks()
  /**
   * Do `/account_validation` API request to Iris API
   * @param  {Object} parameter - object of Iris API JSON body as parameter, will be converted to GET Query param (more params detail refer to: https://iris-docs.midtrans.com)
   * @return {Promise} - Promise contains Object from JSON decoded response
   */
  validateBankAccount(parameter={})

You can also refer to Iris test cases for sample usage for now. Dedicated sample usage might be written later in the future.

Examples

Examples are available on /examples folder. There are:

Notes

Not Designed for Frontend Usage

This library/package is mainly NOT FOR FRONTEND (Browser's javascript) usage, but for backend (Node JS server) usage:

  • This is mainly for backend usage, to do secure server-to-server/backend-to-backend API call.
  • You may/will encounter CORS issue if you are using this to do API request from frontend.
  • Your API ServerKey may also be exposed to public if you are using this on frontend.
  • If what you need is to display Snap payment page on your frontend, please follow this official documentation

Get help

midtrans-nodejs-client's People

Contributors

andrenzo17 avatar aris-creator avatar cahyonobagus avatar dependabot[bot] avatar omarxp avatar rizdaprasetya avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

midtrans-nodejs-client's Issues

Custom fields on snap api?

It is possible to add custom field in snap API? My goal is to attach additional data (e.g customer_id) on HTTP notification webhook.

I found this on api docs:

Set Custom Fields is a feature that enables merchants to charge a transaction with a unique data according to the merchant's need. Midtrans provides merchants with 3 custom fields that can be used for various utilities.

It seems I could not find my way there using snap API.

I've already added the desired field label name from general settings in my merchant admin portal, and send it upon createTransaction() call (alongside the required data such as transaction_details, payment_type, etc). But everytime I received the HTTP notification POST data, I can't find my custom field data.

Thank you in advance.

Custom VA Number is not working

Saya baru dalam menggunakan Midtrans, dan mencoba untuk menggunakan CoreAPI serta Custom VA. Tapi, kenapa va_number yang di return selalu berbeda ? Tidak sama dengan apa yang saya kirimkan. Di dokumentasi - Bank Transfer Object, ada peraturan terkait seberapa panjang Custom VA Number,
Sebagai contoh untuk Permata, saya buat sebuah row di database, dan menggunakan account_number sebagai VA,

  let va_number = '6374912369123123123'
  bank_account = await models.BankAccount.create({
      account_number: va_number,
      account_name: data.method,
      description: 'Permata Virtual Account',
      bank_id: data.bank_id,
      tenant_id: tenant.id,
      virtual: true,
      created_by: tenant.name,
      updated_by: tenant.name
  })

Returnya adalah error 400, dengan message One or more parameters in the payload is invalid., [bank_transfer.va_number length must be equal to 10]. Case nya di sini, kalau dibuat sesuai, dengan panjang va_number 10 (misalnya 8273645263), returnya malah seperti ini,

{
    "status_code": "201",
    "status_message": "Success, PERMATA VA transaction is successful",
    "transaction_id": "19092cc6-f60e-47f8-9c01-a32763e28cfe",
    "order_id": "DEP2021061578348",
    "gross_amount": "100000.00",
    "currency": "IDR",
    "payment_type": "bank_transfer",
    "transaction_time": "2021-06-15 12:53:45",
    "transaction_status": "pending",
    "fraud_status": "accept",
    "permata_va_number": "996007792398731",
    "merchant_id": "XXXXXX5"
}

Lain kalau BCA, rulenya adalah Accepts 6-11 digits, tapi berapapun yang saya kirim, sukses, tanpa error, tapi VA Number nya ngga sesuai dengan apa yang dikirim.

Mungkin kalau BNI dan BRI beda lagi, tapi ya ini dulu lah.

Terimakasih

Cors

Saya sedang mengintegraskan dengan menggunakan CoreAPI dan next js
tapi kenapa selalu kena cors ya?

Hapus bagian BACK TO MERCHANTS WEB

Screenshot_2022-11-29-11-29-14-93

bagaimana cara menghapus bagian
BACK TO MERCHANTS WEB pada gambari di atas
Dan menghapus fungsi redirecting

Saya ingin polos aja . Ga ada redirect redirect
Kalo bisa . Di bagian mana yg harus saya edit

Terima kasih

callback pending run twice

window.snap.pay(post.transaction.redirect_url, {
  onSuccess: async (result) => {
    console.log(result, "result");
  },
  onPending: async (result) => {
    return alert("Pending");
    // return settemp(temp.concat(result));
  },
  onError: async (result) => {
    return alert("Error");
    // return settemp(temp.concat(result));
  },
});

says membuat website dimana pembayaran menggunakan midtrans semua berjalan baik baik saja sampai callback pending berjalan dua kali

Type on Typescript

Hi Midtrans team

I have built some types to use this library in Typescript,
because I couldn't use this library on typescript, now I could do it

this is my repo on git
github

and repo on npm
npm

Please mention me if need

Kenapa Costumer Detail & Shipping Address Tidak Tampil di Popup Snap

Kenapa popup Snap tidak menampilkan informasi costumer detail dan shipping address? Saya lihat di halaman demo bisa menampilkan informasi tersebut https://demo.midtrans.com/

Screenshot: https://prnt.sc/ysbpzy

Backend REST API

....

const midtransSnapAPI = new midtransClient.Snap({
  isProduction: false,
  serverKey: "XXX",
  clientKey: "XXX",
});
 const snapOrderParameter = {
      transaction_details: {
        order_id: generateOrderID(userID),
        gross_amount: planDetail.planPrice.price,
      },
      item_details: {
        id: planID,
        quantity: 1,
        name: planDetail.name,
        price: planDetail.planPrice.price,
      },
      costumer_details: {
        first_name: firstName,
        last_name: lastName,
        email: email,
      },
      shipping_address: {
        first_name: "TEST",
        last_name: "MIDTRANSER",
        email: "[email protected]",
        phone: "0 8128-75 7-9338",
        address: "Sudirman",
        city: "Jakarta",
        postal_code: "12190",
        country_code: "IDN",
      },
    };

    const snapOrderParameterToJSON = JSON.stringify(snapOrderParameter);

    const midtransResult = await midtransSnapAPI.createTransaction(
      snapOrderParameterToJSON
    );

...
 console.log(midtransResult);

{
  token: '81ec1e51-39e8-xxxxxxxx',
  redirect_url: 'https://app.sandbox.midtrans.com/snap/v2/vtweb/81ec1e51-xxxxx'
}
console.log(snapOrderParameterToJSON);

{
   "transaction_details":{
      "order_id":"10-xxxxx",
      "gross_amount":125000
   },
   "item_details":{
      "id":"2",
      "quantity":1,
      "name":"Standard",
      "price":125000
   },
   "costumer_details":{
      "first_name":"Mimin",
      "last_name":"Sirimin",
      "email":"[email protected]"
   },
   "shipping_address":{
      "first_name":"TEST",
      "last_name":"MIDTRANSER",
      "email":"[email protected]",
      "phone":"0 8128-75 7-9338",
      "address":"Sudirman",
      "city":"Jakarta",
      "postal_code":"12190",
      "country_code":"IDN"
   }
}

NextJS/ReactJS:

const ProductCard = (props) => {
  const [snapCheckoutToken, setSnapCheckoutToken] = useState("");

  useEffect(() => {
    if (typeof window !== "undefined") {
      const myScript = document.createElement("script");
      myScript.setAttribute(
        "src",
        "https://app.sandbox.midtrans.com/snap/snap.js"
      );
      myScript.setAttribute(
        "data-client-key",
        "SB-Mid-client-XXX"
      );
      document.head.appendChild(myScript);
    }
  }, []);

  useEffect(() => {
    if (snapCheckoutToken && typeof window !== "undefined") {
      window.snap.pay(snapCheckoutToken, {
        onSuccess: function (result) {
          console.log("onsuccess", result);
        },
        // Optional
        onPending: function (result) {
          console.log("onPending", result);
        },
        // Optional
        onError: function (result) {
          console.log("oneerror", result);
        },
      });
    }
  }, [snapCheckoutToken]);

  const handleOrderButton = (id) => {
    axiosAuth
      .post(`/payment/checkout/${id}`)
      .then((result) => {
        console.log(result);
        setSnapCheckoutToken(result.data.data.token);
      })
      .catch((error) => {
        console.log(error);
      });
  };

  return (
      <button
        className={styles.orderButton}
        onClick={() => handleOrderButton(id)}
      >
        Pilih Sekarang
      </button>
  );
};

export default ProductCard;

Terimakasih sebelumnya,

Transaction cannot be authorized with the current client/server key

Kenapa server mengirimkan response status 401 di mode production?

Sebelumnya saya test di mode sandbox berhasil tidak ada kendala.

Berikut adalah response yang saya dapet di mode production:

{
    "status_code": "401",
    "status_message": "Transaction cannot be authorized with the current client/server key.",
    "id": "1679fb5e-31b2-49e0-bbae-cec703a5cdde"
}

Berikut adalah request dari servernya:

const midtransClient = require('midtrans-client');

const midtrans = new midtransClient.CoreApi({
  isProduction: true,
  serverKey: 'SERVER_KEY',
  clientKey: 'CLIENT_KEY',
});

module.exports.charge = async (req, res) => {
  try {
    const promise = await midtrans.charge(req.body);
    return res.send(promise);
  } catch (err) {
    return res.status(err.httpStatusCode).send(err.ApiResponse);
  }
};

Mungkin ada yang bisa bantu jawab, saya pertama kali menggunakan midtrans sampe di mode production, atau apakah musti kontak pihak midtrans jika mau mengganti mode ke production?

Terima kasih

Bagaimana cara melakukan callback midtrans setelah melakukan pembayaran.

Halo mas @rizdaprasetya maaf mas, saya ingin bertanya. saya di sini kesulitan terkait melakukan callback midtrans setelah user melakukan pembayaran yang dimana saya harus mengupdate status transaksi saya dengan mengecek apakah fraud status nya ini accept, failure dll. Di sini lebih tepat nya saya harus menggunakan method yang mana dan mohon maaf mas bisa berikan contoh implementasinya agar saya bisa lebih mengerti cara penggunaan nya mas. Terima kasih :)

Cara melanjutkan transaksi

Hi, saya ingin bertanya apakah ada cara, referensi, atau dokumentasi untuk melanjutkan transaksi yang telah terbuat sebelumnya? Saya mendapatkan kesulitan mencari permasalahan yang saya cari, baik di website dokumentasi resmi, google, dan lainnya. Terima kasih.

Problem with order_id that have '/'

Tanya, tolong berikan best practice,

Jika order_id = 00561/05/ADI-IL/24JKT, dan ini adalah ketentuan tempat bekerja,
maka saat GET transaction_status seperti:

 return Transaction::status('00561/05/ADI-IL/24JKT')

pasti error, dengan response:

 {
     "timestamp":"2024-05-17T06:24:01.223+0000",
     "status":404,
     "error":"Not Found",
     "message":"Not Found",
     "path":"/v2/00561/05/ADI-IL/24JKT/status"
}

path nya jadi tidak sesuai. Terima kasih.

Dan, jika mengguanakan Transaction::status($param), dimana $param tidak bisa menggunakan order_id, melainkan harus transaction_id

"No MID/TID for this transaction"

Halo, saya mendapatkan error "Credit card token is no longer available. Please create a new one." ketika implementasi card payment. untuk token sendiri aku dapatkan dari response success midtrans-new-3ds. bagaimana mengatasinya?

env = production

Tidak bisa menjalankan pembayaran snap ui menggunakan flutter webview 4.0.2

Assalamu'alaikum teman-teman. Saya mau minta tolong. Disini saya sedang membuat pembayaran di aplikasi menggunakan Snap dari Midtrans. Tapi terkendala ketika memilih salah satu metode pembayarannya tidak bisa jalan. Saya menggunakan webview_flutter versi 4.0.2.

di log muncul [INFO:CONSOLE(1)] "Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://app.sandbox.midtrans.com') does not match the recipient window's origin ('null').", source: https://app.sandbox.midtrans.com/snap/snap.js (1)

Screen Shot 2023-02-04 at 20 52 56

What is the different using CoreAPI to get transaction response, or use transaction respon directly from req.body that send by Midtrans HTTP Post Notification?

I've seen this example how to handle the transaction status
https://github.com/Midtrans/midtrans-nodejs-client/blob/master/examples/expressApp/app.js#L87

But what if i just use the req.body to handle transaction status directly, instead of
core.transaction.status(req.body.transaction_id).then(transactionObject) to get transaction status and handle it from that.

Aren't they basically same data?
Is it has "secure" thing purposes using CoreAPI rather than the req.body itself?

Example, i can get the transaction_id directly from req.body.transaction_id instead of transactionObject.transaction_id

midtrans register API

Hello Pak Rizda, izin bertanya apakah midtrans memungkingkan registrasi user melalui API kedepannya, pak? Terima kasih.

menggunakan fungsi snap pay di component

  1. bagaimana cara import
    <script src="https://app.sandbox.midtrans.com/snap/snap.js" data-client-key="<Set your ClientKey here>"></script>
    di react js component?

  2. bagaimana menggunakan snap.pay('SNAP_TOKEN') di react js component?

ERROR in ./node_modules/midtrans-client/lib/httpClient.js 9:18-40 Module not found: Error: Can't resolve 'querystring' in 'C:\Users\[Username]\Documents\[Project-name]\node_modules\midtrans-client\lib'

Halo. Saya ingin bertanya. Saya mengerjakan projek react.js dan ingin menggunakan library ini. Saya menginstallnya dengan menggunakan npm install midtrans-nodejs-client. Tetapi setelah itu, saat saya mencoba memanggilnya menggunakan const midtransClient = require('midtrans-client'); muncul pesan error berikut :

ERROR in ./node_modules/midtrans-client/lib/httpClient.js 9:18-40
Module not found: Error: Can't resolve 'querystring' in 'C:\Users[Username]\Documents[Project-name]\node_modules\midtrans-client\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "querystring": require.resolve("querystring-es3") }'
- install 'querystring-es3'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "querystring": false }

Saya mohon bantuannya. Terimakasih

Ambiguous transaction status & layout problem

Sorry if this issue not belongs this repo but I don't see any special repository for snap products.

"expired" status is ambiguous on a transaction detail/status and when receiving a callback.
On the transaction status, I get a json response with "expire" word. But at the time of the callback, the status is "expired" (there is letter d). Is this really intentional or is there an error?
It is recommended that this be generalized to prevent future errors.

Then, I want to report a layout problem with snap for the customer section that should be corrected because there was a not used bootstrap column (col-md-6). It should be removed just so that the customer email can be sideways.

image

Thanks!

Missing "Direct Refund" feature

Halo developers ๐Ÿ‘‹
Thanks for your awesome sdk.
But currently I need a direct refund feature and I can't find any function for direct refund like on this link.

Are you have any plan to add this feature on the sdk ?

Converting circular structure to JSON

sudo journalctl -u node-xxx -n 100 --no-pager

(node:1671271) UnhandledPromiseRejectionWarning: TypeError: Converting circular structure to JSON
Oct 26 16:05:24 imt node-[1671271]:     --> starting at object with constructor 'ClientRequest'
Oct 26 16:05:24 imt node-[1671271]:     |     property 'socket' -> object with constructor 'TLSSocket'
Oct 26 16:05:24 imt node-[1671271]:     --- property '_httpMessage' closes the circle
Oct 26 16:05:24 imt node-[1671271]:     at JSON.stringify (<anonymous>)
Oct 26 16:05:24 imt node-[1671271]:     at stringify (/var/www/html/api/xxxx/node_modules/express/lib/response.js:1123:12)
Oct 26 16:05:24 imt node-[1671271]:     at ServerResponse.json (/var/www/html/api/xxxx/node_modules/express/lib/response.js:260:14)
Oct 26 16:05:24 imt node-[1671271]:     at ServerResponse.send (/var/www/html/api/xxxx/node_modules/express/lib/response.js:158:21)
Oct 26 16:05:24 imt node-[1671271]:     at Object.exports.err (/var/www/html/api/xxxx/src/utils/res.js:17:26)
Oct 26 16:05:24 imt node-[1671271]:     at /var/www/html/api/xxxx/src/controllers/notification.controller.js:55:26
Oct 26 16:05:24 imt node-[1671271]:     at processTicksAndRejections (internal/process/task_queues.js:93:5)
Oct 26 16:05:24 imt node-[1671271]: (Use `node --trace-warnings ...` to show where the warning was created)

https://docs.midtrans.com/en/after-payment/http-notification

        let notificationJson = req.body;
        apiClient.transaction.notification(notificationJson)

not solve dunno why, https://stackoverflow.com/questions/4816099/chrome-sendrequest-error-typeerror-converting-circular-structure-to-json , i have seen on #34 its work properly right ?

      let notificationJson = stringify(req.body);
      let sss = JSON.stringify({ ...req.body });
      let sssd = req.body;

      console.log(`notificationJson : ${notificationJson}`);
      console.log(`notificationJson  : ${req.body}`);
      console.log(`notificationJson  : ${sss}`);
      console.log(`notificationJson  : ${sssd}`);

serverKey : SB-Mid-server-xxx. clientKey : SB-Mid-client-xx-xxx
Oct 26 17:32:11 imt xx[1676873]: notificationJson : [{"statusResponse":"1"},{"transaction_time":"2","no":"3"},"yogi","as"]
Oct 26 17:32:11 imt xx[1676873]: notificationJson  : [object Object]
Oct 26 17:32:11 imt xx[1676873]: notificationJson  : {"statusResponse":{"transaction_time":"yogi","no":"as"}}
Oct 26 17:32:11 imt xx[1676873]: notificationJson  : [object Object]

Type for Typescript

I'm using TypeScript and don't see any type from your library.
And it bothers me a lot.

I create my own using this command
tsc ./node_modules/midtrans-client/index.js ./node_modules/midtrans-client/lib/*.js --declaration --allowjs --emitDeclarationOnly --outFile @types/midtrans.d.ts

I thing you can provide better one with creating npm package @types/midtrans-client.
You are a big company. and it's a shame if you can't give something like that (at least for me).

IRIS API Access denied

halo, saya mendapatkan response HTTP status code: 401. HTTP Basic: Access denied untuk API IRIS getBeneficiaryBanks tetapi saat menggunakan API Core maupun Snap berjalan dengan normal. Apakah ada config yang kurang?

Support for ejs import

Hi, thanks for the library, currently i have problem with the import statement
how can I import the package using ejs syntax in my client?
import snap from 'midtrans-client'
currently the available docs only explain about common js import
const blah = require('midtrans-client')
thank you

iOS 12 Error: snap.pay is not allowed to be called in this state

Hi, thanks for great snapjs payment to ease us doing a payment!
disclaimer: Im using https://app.sandbox.midtrans.com/snap/snap.js, am i put this issue in the correct place? I can't find the repo regarding this snap js to put an issue.

This issue only happened in iOS 12, but it is fine in latest iOS. Here full log:

Error: snap.pay is not allowed to be called in this state. Invalid state transition from PopupInView to PopupInView (anonymous function) โ€” snap.js:232
  ex โ€” 8967.304662da3cf90d03.js:148
  onSuccess โ€” 8967.304662da3cf90d03.js:144
  promiseReactionJob

I call the window snap like:

if (!('snap' in window)) {
  const script = document.createElement('script')
  script.type = 'text/javascript'
  script.dataset.clientKey = process.env.NEXT_PUBLIC_MIDTRANS_CLIENT_KEY ?? '' // prettier-ignore
  script.src = midtrans('/snap/snap.js')
  script.onload = () => onCallback(token, payload)

  document.head.append(script)
  return
}

onCallback(token, payload)

where onCallback is:

window.snap.pay(token, {
  onSuccess: (result: unknown) => {
    const { transaction: trx } = paymentType.shape
    const transaction = trx.parse(result)

    checkout([...detail.payment, { ...payload, transaction }])
  },
})

Help to explain why the error happened, or snap.js not supported in iOS 12 ? Thankyou!
snap.js: https://app.sandbox.midtrans.com/snap/snap.js

Issue di Frontend, user tidak bisa input di SNAP UI Ketika Pembayaran Menggunakan Pilihan Kartu Kredit

Describe the existing unexpected scenario

Overall untuk case payment menggunakan Midtrans semuanya aman, kecuali 1 case yaitu ketika user menggunakan kartu kredit, semua input-an tidak bisa di masukan data apapun oleh user

To Reproduce

Steps to reproduce the Unexpected Behavior :

  1. Go to https://siswa-dev.shinkenjuku.co.id/
  2. Klik button Daftar
  3. Pilih Paket & klik label "Di Sini"
  4. Di Bawah Total Pembayaran, klik button pembayaran (Akan Muncul Modal Pop Up "Selamat Datang")
  5. Arahkan/ Klik ke Tab "Daftar" (Akan muncul Modal Pop Up "Pernyataan Persetujuan")
  6. Klik Centang kemudian klik button "Saya Setuju"
  7. Isi semua data registrasi (Tidak apa2 di submit dengan data "Testing")
  8. Kemudian Lanjutkan pembayaran (Akan Muncul Pop Up Payment Midtrans
  9. Arahkan ke Pembayaran menggunakan KARTU KREDIT

existing skenario yang terjadi skrng adalah tidak bisa input sama sekali semua field

Expected Behavior
Ketika Modal Pop Payment Midtrans muncul, maka dapat input data Kartu Kredit, CC, dll

Informasi Video ScreenRecorder
https://photos.app.goo.gl/BLCcgWyxjSCw7AT78

Environment Platform of FE

NextJS v10.0.5

Bagaimana Penerapan Code yang kami lakukan untuk implementasi SnapMidatrans ?

Kami mengimplementasikan SnapMidtrans kurang lebih seperti ini

notificationJson Error not found

saat saya menjalankan code midatransSnap.transaction.notification(notificationJson);
saya mendapatkan error
2021-08-19T17:32:49.789Z error: /v1/transaction/payment_status - 127.0.0.1 - ReferenceError: notificationJson is not defined
apakah bisa dibantu? Terima kasih

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.