python-nicepay 1.1.1
This is the Official Python API client / library for NICEPAY Payment API
Keywords: pypi, config, nicepay

## NICEPAY - PYTHON
![Python](https://img.shields.io/badge/Python-v3.11.9-blue.svg)
 [![PyPI Package](https://img.shields.io/pypi/v/python-nicepay.svg?label=PyPI%20Package&color=green)](https://pypi.org/project/python-nicepay/)

The **Nicepay Python** provides integration access to the **Nicepay APIs**.  
This is designed to make it easier for developers to call Nicepay’s REST APIs in Python applications.

### **Information** 
This library provides access to Nicepay APIs :
- `SNAP`
- `V1 Enterprise (Direct)`
- `V1 Professional (Redirect)`
- `V2 Enterprise (Direct)`
- `V2 Professional (Redirect)`

For more information about the product, please refer to the  [NICEPAY Docs](https://docs.nicepay.co.id/)  for detailed technical guidance

## 1. Install the Package
### a. PyPI
```bash
pip install python-nicepay
```
You can also view the package at: https://pypi.org/project/python-nicepay/1.1.1/
### b.  Manually Installation
You can clone or [download](https://github.com/nicepay-dev/python-nicepay) our source code, then import `PYTHON-NICEPAY` manually into your project.
#####
Clone Repository :
```bash
git clone https://github.com/nicepay-dev/python-nicepay.git
```
## 2. Usage
Get your credentials from [Nicepay Dashboard](http://103.20.51.40:8012/logIn.do)
initialize Nicepay config

**Notes :**
If the merchant uses their own IMID, please configure the data using the setter method (`setSnapConfiguration` or `setNonSnapConfiguration`) in `constantGeneral`. For usage examples, refer to the following files:  
- For SNAP: `testAccessToken.py`
```bash
# Case if merchant using different config with the constant
class testAccessToken:
    clientKey = "_CLIENT_KEY_MERCHANT"
    clientSecret = "_CLIENT_SECRET_MERCHANT"
    privateKey= "_PRIVATE_KEY_MERCHANT"

    ConstantsGeneral.setSnapConfiguration(clientKey, clientSecret, privateKey)
```
- For Non SNAP : `testEwallet.py`
```bash
# Case if merchant using different config with the constant
class testEwallet:
    imid = "_YOUR_I_MID"
    merchantKey = "_YOUR_MERCHANT_KEY"
    callbackUrl = "_YOUR_CALLBACK_URL"
    dbProcessUrl = "_YOUR_DB_PROCESS_URL"
    billingPhone = "_YOUR_BILLING_PHONE"
    ConstantsGeneral.setNonSnapConfiguration(imid, merchantKey, dbProcessUrl, callbackUrl)
    ConstantsGeneral.setBillingPhone(billingPhone)
```

#### 2.1 Client Initialization and Configuration
Credentials used here are for testing purposes
```bash
# Instantiate SNAP API instance
class ConstantsGeneral:
_CLIENT_KEY = "_YOUR_CLIENT_KEY"
_PRIVATE_KEY = "_YOUR_PRIVATE_KEY"
_CLIENT_SECRET = "_YOUR_CLIENT_SECRET"
```
```bash
# Instantiate Non SNAP API instance
class ConstantsGeneral:
_I_MID = "_YOUR_I_MID"
_MERCHANT_KEY = "_YOUR_MERCHANT_KEY"
```

```bash
# Instantiate change if production environment
environment = (builderEnvironment.BuildEnvirontment()
                   .isCloud(False)
                   .isProduction(True)
                   .build())
```

#### 2.2 Request for Access-Token
```bash
# create for access token
class testAccessToken:
    bodyCreateToken = (
        builderAccessToken.BuildAccessToken()
        .setGrantType("client_credentials")
        .setAdditionalInfo("")
        .build()
    )
environment = (builderEnvironment.BuildEnvirontment()
                   .isCloud(False)
                   .isProduction(False)
                   .build())

Result = SnapService.serviceOAUTH(bodyCreateToken.jsonAccessToken())
```
Here's the sample result 
```bash
AccessToken : eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJJT05QQVlURVNUIiwiaXNzIjoiTklDRVBBWSIsIm5hbWUiOiJCRElOIiwiZXhwIjoiMjAyNC0xMS0xMlQyMDowNTo1NFoifQ==.RfeDzCn7sk5VT54f8NTPnbbeQvaPmQg6wtLWXIbmBCI=
```
#### 2.3 Request for Generate VA SNAP (i.e. Virtual Account)
```bash
class testVirtualAccount:
    bodyCreateToken = (
        builderAccessToken.BuildAccessToken()
        .setGrantType("client_credentials")
        .setAdditionalInfo("")
        .build()
    )

    totalAmount = {"value": "10000.00",
                   "currency": "IDR"
                   }

    additionalInfo = {"bankCd": "BRIN",
                      "goodsNm": "Merchant Goods 1",
                      "dbProcessUrl": "_YOUR_DB_PROCESS_URL",
                      "vacctValidDt": "",
                      "vacctValidTm": "",
                      "msId": "",
                      "msFee": "",
                      "msFeeType": "",
                      "mbFee": "",
                      "mbFeeType": ""
                      }

    bodyCreateVA = (
        builderVirtualAccount.BuildCreateVA()
        .setPartnerServiceId("_MANDATORY_")
        .setCustomerNo("_MANDATORY_")
        .setVirtualAccountNo("")
        .setVirtualAccountName("John Doe")
        .setTrxId("123")
        .setTotalAmount(totalAmount)
        .setAdditionalInfo(additionalInfo)
        .build()
    )

    result = SnapService.serviceTransaction(bodyCreateToken.jsonAccessToken(),
                                            bodyCreateVA.jsonVACreate(),
                                            ConstantsEndpoints.createVA())
```
Here's the sample result 
```bash
body request :
{"partnerServiceId": "", "customerNo": "", "virtualAccountNo": "", "virtualAccountName": "John Doe", "trxId": "123", "totalAmount": {"value": "10000.00", "currency": "IDR"}, "additionalInfo": {"bankCd": "BRIN", "goodsNm": "Merchant Goods 1", "dbProcessUrl": "https://webhook.site/e15ef201-98a9-428c-85d4-a0c6458939c3", "vacctValidDt": "", "vacctValidTm": "", "msId": "", "msFee": "", "msFeeType": "", "mbFee": "", "mbFeeType": ""}}

body response :
{"responseCode": "2002700", "responseMessage": "Successful", "virtualAccountData": {"partnerServiceId": "88480004", "customerNo": "0254370152", "virtualAccountNo": "884800040254370152", "virtualAccountName": "John Doe", "trxId": "123", "totalAmount": {"value": "10000.00", "currency": "IDR"}, "additionalInfo": {"msId": "", "msFee": "", "msFeeType": "", "mbFee": "", "mbFeeType": "", "bankCd": "BRIN", "tXidVA": "IONPAYTEST022024111302543xxxxx", "goodsNm": "Merchant Goods 1", "vacctValidDt": "20241115", "vacctValidTm": "025437"}}}
```
#### 2.4 Verify Signature 
- for Access Token
```bash
class Signature:
    log = Log()

    @staticmethod
    def signSHA256RSA(stringToSign, privateKey):
        try:
            b1 = base64.b64decode(privateKey)
            key = RSA.importKey(b1)
            signer = PKCS1_v1_5.new(key)
            digest = SHA256.new()
            digest.update(stringToSign.encode('utf-8'))
            signature = signer.sign(digest)
            hexSignature = base64.b64encode(signature).decode('utf-8')
            return hexSignature
        except Exception as e:
            Signature.log.error("Error Generate Signature:" + e)
            return ''

@staticmethod
    def sha256EncodeHex(data):
        sha256Hash = hashlib.sha256(data.encode('utf-8')).digest()
        hexEncoded = sha256Hash.hex()
        return hexEncoded
```
**Notes :**
`stringToSign` = `"_YOUR_CLIENT_KEY" + "|" + "_TIMESTAMP";`

- for Signature Service
```bash
@staticmethod
    def getSignature(accessToken, requestBody, endpoint, timestamp, staticKey, httpMethod):
        Signature.log.info("util - Request Endpoint : " + endpoint)
        data = f"{httpMethod}:{endpoint}:{accessToken}:{requestBody}:{timestamp}"
        Signature.log.info("util - StringDataToSign: " + data)
        try:
            sign = Signature.hmacSHA512EncodeBase64(staticKey, data)
            Signature.log.info("util - Signature: " + sign)
            return sign
        except:
            Signature.log.error("Error Generate Signature - getSignature")

 @staticmethod
    def hmacSHA512EncodeBase64(key, data):
        hmacObj = hmac.new(key.encode('utf-8'), data.encode('utf-8'), hashlib.sha512)
        hmacBytes = hmacObj.digest()
        base64Encoded = base64.b64encode(hmacBytes).decode('utf-8')
        return base64Encoded
```
Here’s the result of create VA signature service.
```bash
StringDataToSign: POST:/api/v1.0/transfer-va/create-va:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJJT05QQVlURVNUIiwiaXNzIjoiTklDRVBBWSIsIm5hbWUiOiJCRElOIiwiZXhwIjoiMjAyNC0xMS0xMlQyMDowOTozN1oifQ==.4djzd9Z1jZE8AXkFRmCrxm8IMfdhuk2RjFz0LSzRXIY=:d04af00b1f17c7045dde178f377b77e385a3d6cecd22fe6822de1ee053489078:2024-11-13T02:54:37+07:00

Signature: w7BpJ392jzRkAgvWC79Zawvztm/l1D+bxIJWgGq59xih0SuAi4PoTtUAUIXcOLuvZ3pYaSs8Mc1QZxhbVMMBqQ==
```

You can view a code example in the following **[UtilSignature.py](https://github.com/nicepay-dev/python-nicepay/blob/main/util/utilSignature.py)** class.

## 3. Environments
Configured to use a different environment for making API calls. 
#### Available environments are:

| Name          | Description                            |
|:--------------|:---------------------------------------|
| `Production`  | Nicepay Live Environment               |
| `Development` | **Default** Nicepay Sandbox Environment|



## 4. Other Sample

##### Integration test are available for SNAP :
- [Virtual Account Regist Unit Test](https://github.com/nicepay-dev/python-nicepay/blob/main/test/snap/testVirtualAccount.py)
- [E-Wallet Regist Unit Test](https://github.com/nicepay-dev/python-nicepay/blob/main/test/snap/testDirectDebit.py)
- [Qris Regist Unit Test](https://github.com/nicepay-dev/python-nicepay/blob/main/test/snap/testQris.py)
- [Payout Regist Unit Test](https://github.com/nicepay-dev/python-nicepay/blob/main/test/snap/testPayout.py)

##### Integration test are available for V2 APIs :
- [Virtual Account V2 Unit Test](https://github.com/nicepay-dev/python-nicepay/blob/main/test/v2/enterprise/testVirtualAccount.py)
- [Inquiry V2 Unit Test](https://github.com/nicepay-dev/python-nicepay/blob/main/test/v2/enterprise/testInquiry.py)
- [Payment V2 Unit Test](https://github.com/nicepay-dev/python-nicepay/blob/main/test/v2/enterprise/testPayment.py)
- [Cancel V2 Unit Test](https://github.com/nicepay-dev/python-nicepay/blob/main/test/v2/enterprise/testCancel.py)

## 5. Get Help
- [Nicepay](https://nicepay.co.id/id/)
- [Nicepay Docs](https://docs.nicepay.co.id/)
- [Nicepay Dashboard](http://103.20.51.40:8012/logIn.do)
- [SNAP documentation](https://docs.nicepay.co.id/nicepay-api-snap)
- [V1 Enterprise documentation](https://docs.nicepay.co.id/nicepay-v1-enterprise)
- [V1 Professional documentation](https://docs.nicepay.co.id/nicepay-api-v1-professional)
- [V2 Enterprise documentation](https://docs.nicepay.co.id/nicepay-api-v2-payment-api)
- [V2 Professional documentation](https://docs.nicepay.co.id/nicepay-api-v2-checkout-api)


Can't find answer you looking for? email to `integration@nicepay.co.id `

**Thank you and Have a NICEPAY!** 

![Logo](https://nicepay.co.id/wp-content/uploads/2019/09/logo-150.svg )