diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index dc8c990e..869955d8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,5 +31,7 @@ jobs:
env:
RAZORPAY_API_KEY: ${{ secrets.RAZORPAY_API_KEY }}
RAZORPAY_API_SECRET: ${{ secrets.RAZORPAY_API_SECRET }}
+ RAZORPAY_PARTNER_API_KEY: ${{ secrets.RAZORPAY_PARTNER_API_KEY }}
+ RAZORPAY_PARTNER_API_SECRET: ${{ secrets.RAZORPAY_PARTNER_API_SECRET }}
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
diff --git a/.gitignore b/.gitignore
index 226a82d8..4100c39b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
composer.lock
phpunit.xml
vendor/
+reports/
**/.DS_Store
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1588499..18dae71a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,15 @@ Changelog for Razorpay-PHP SDK. Follows [keepachangelog.com](https://keepachange
## Unreleased
+## [2.8.6] - 2023-06-16
+[#348](https://github.com/razorpay/razorpay-php/pull/348) [`68b2028`](https://github.com/razorpay/razorpay-php/commit/68b2028bafda49af970a098d6d11aa8e5a575d40) feat: Added new API endpoints
+
+* Added account onboarding API (create, fetch, edit, delete)
+* Added stakeholders API (create, fetch, fetchAll, edit)
+* Added product configuration API (requestProductConfiguration, fetch, edit, fetchTnc)
+* Added webhooks API (create, fetch, fetchAll, edit, delete)
+* Added token sharing API (create, fetch, delete, processPaymentOnAlternatePAorPG)
+
## [2.8.5] - 2022-10-19
### Added
@@ -231,4 +240,4 @@ Changelog for Razorpay-PHP SDK. Follows [keepachangelog.com](https://keepachange
[2.5.0]: https://github.com/razorpay/razorpay-php/compare/2.4.0-beta...2.5.0
[2.8.0]: https://github.com/razorpay/razorpay-php/compare/2.7.1...2.8.0
[2.8.1]: https://github.com/razorpay/razorpay-php/compare/2.8.0...2.8.1
-[2.8.2]: https://github.com/razorpay/razorpay-php/compare/2.8.0...2.8.2
\ No newline at end of file
+[2.8.2]: https://github.com/razorpay/razorpay-php/compare/2.8.0...2.8.2
diff --git a/README.md b/README.md
index a874b3f3..f0ba58a9 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,7 @@ The resources can be accessed via the `$api` object. All the methods invocations
$api->payment->fetch($paymentId);
```
## Supported Resources
+- [Account](documents/account.md)
- [Customer](documents/customer.md)
- [Token](documents/token.md)
- [Order](documents/order.md)
@@ -65,7 +66,9 @@ The resources can be accessed via the `$api` object. All the methods invocations
- [Subscriptions](documents/subscription.md)
- [Add-on](documents/addon.md)
- [Payment Links](documents/paymentLink.md)
+- [Product Configuration](documents/productConfiguration.md)
- [Smart Collect](documents/virtualaccount.md)
+- [Stakeholder](documents/stakeholder.md)
- [Transfer](documents/transfer.md)
- [QR Code](documents/qrcode.md)
- [Emandate](documents/emandate.md)
@@ -75,6 +78,7 @@ The resources can be accessed via the `$api` object. All the methods invocations
- [Register Emandate and Charge First Payment Together](documents/registeremandate.md)
- [Register NACH and Charge First Payment Together](documents/registernach.md)
- [Payment Verification](documents/paymentVerfication.md)
+- [Webhook](documents/webhook.md)
## Development
@@ -95,4 +99,4 @@ Steps to follow for a release:
## License
-The Razorpay PHP SDK is released under the MIT License. See [LICENSE](LICENSE) file for more details.
+The Razorpay PHP SDK is released under the MIT License. See [LICENSE](LICENSE) file for more details.
\ No newline at end of file
diff --git a/documents/account.md b/documents/account.md
new file mode 100644
index 00000000..0696c5cf
--- /dev/null
+++ b/documents/account.md
@@ -0,0 +1,387 @@
+## Account
+
+### Create an Account
+```php
+$api->account->create(array(
+ "email" => "gauriagain.kumar@example.org",
+ "phone" => "9000090000",
+ "legal_business_name" => "Acme Corp",
+ "business_type" => "partnership",
+ "customer_facing_business_name" => "Example",
+ "profile" => array(
+ "category" => "healthcare",
+ "subcategory" => "clinic",
+ "description" => "Healthcare E-commerce platform",
+ "addresses" => array(
+ "operation" => array(
+ "street1" => "507, Koramangala 6th block",
+ "street2" => "Kormanagala",
+ "city" => "Bengaluru",
+ "state" => "Karnataka",
+ "postal_code" => 560047,
+ "country" => "IN"
+ ),
+ "registered" => array(
+ "street1" => "507, Koramangala 1st block",
+ "street2" => "MG Road",
+ "city" => "Bengaluru",
+ "state" => "Karnataka",
+ "postal_code" => 560034,
+ "country" => "IN"
+ )
+ ),
+ "business_model" => "Online Clothing ( men, women, ethnic, modern ) fashion and lifestyle, accessories, t-shirt, shirt, track pant, shoes."
+ ),
+ "legal_info" => array(
+ "pan" => "AAACL1234C",
+ "gst" => "18AABCU9603R1ZM"
+ ),
+ "brand" => array(
+ "color" => "FFFFFF"
+ ),
+ "notes" => array(
+ "internal_ref_id" => "123123"
+ ),
+ "contact_name" => "Gaurav Kumar",
+ "contact_info" => array(
+ "chargeback" => array(
+ "email" => "cb@example.org"
+ ),
+ "refund" => array(
+ "email" => "cb@example.org"
+ ),
+ "support" => array(
+ "email" => "support@example.org",
+ "phone" => "9999999998",
+ "policy_url" => "https://www.google.com"
+ )
+ ),
+ "apps" => array(
+ "websites" => array(
+ "https://www.example.org"
+ ),
+ "android" => array(
+ array(
+ "url" => "playstore.example.org",
+ "name" => "Example"
+ )
+ ),
+ "ios" => array(
+ array(
+ "url" => "appstore.example.org",
+ "name" => "Example"
+ )
+ )
+ )
+));
+
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| email* | string | The sub-merchant's business email address. |
+| phone* | integer | The sub-merchant's business phone number. The minimum length is 8 characters and the maximum length is 15. |
+| legal_business_name* | string | The name of the sub-merchant's business. For example, Acme Corp. The minimum length is 4 characters and the maximum length is 200. |
+| customer_facing_business_name | string | The sub-merchant billing label as it appears on the Razorpay Dashboard. The minimum length is 1 character and the maximum length is 255. |
+| business_type | string | The type of business operated by the sub-merchant.Possible value is `proprietorship`, `partnership`, `private_limited`, `public_limited`, `llp`, `ngo`, `trust`, `society`, `not_yet_registered`, `huf` |
+| reference_id | string | Partner's external account reference id. The minimum length is 1 character and the maximum length is 512. |
+| profile | object | All keys listed [here](https://razorpay.com/docs/api/partners/account-onboarding/#create-an-account) are supported |
+| legal_info | object | All keys listed [here](hhttps://razorpay.com/docs/api/partners/account-onboarding/#create-an-account) are supported |
+| brand | object | All keys listed [here](https://razorpay.com/docs/api/partners/account-onboarding/#create-an-account) are supported |
+| notes | object | A key-value pair |
+| contact_name* | string | The name of the contact. The minimum length is 4 and the maximum length is 255 characters. |
+| contact_info | object | All keys listed [here](https://razorpay.com/docs/api/partners/account-onboarding/#create-an-account) are supported |
+| apps | object | All keys listed [here](https://razorpay.com/docs/api/partners/account-onboarding/#create-an-account) are supported |
+
+
+**Response:**
+```json
+{
+ "id": "acc_GRWKk7qQsLnDjX",
+ "type": "standard",
+ "status": "created",
+ "email": "gauriagain.kumar@example.org",
+ "profile": {
+ "category": "healthcare",
+ "subcategory": "clinic",
+ "addresses": {
+ "registered": {
+ "street1": "507, Koramangala 1st block",
+ "street2": "MG Road",
+ "city": "Bengaluru",
+ "state": "KARNATAKA",
+ "postal_code": 560034,
+ "country": "IN"
+ },
+ "operation": {
+ "street1": "507, Koramangala 6th block",
+ "street2": "Kormanagalo",
+ "city": "Bengaluru",
+ "state": "KARNATAKA",
+ "country": "IN",
+ "postal_code": 560047
+ }
+ },
+ "business_model": "Online Clothing ( men, women, ethnic, modern ) fashion and lifestyle, accessories, t-shirt, shirt, track pant, shoes."
+ },
+ "notes": {
+ "internal_ref_id": "123123"
+ },
+ "created_at": 1611136837,
+ "phone": "9000090000",
+ "business_type": "partnership",
+ "legal_business_name": "Acme Corp",
+ "customer_facing_business_name": "Example",
+ "legal_info": {
+ "pan": "AAACL1234C",
+ "gst": "18AABCU9603R1ZM"
+ },
+ "apps": {
+ "websites": [
+ "https://www.example.org"
+ ],
+ "android": [
+ {
+ "url": "playstore.example.org",
+ "name": "Example"
+ }
+ ],
+ "ios": [
+ {
+ "url": "appstore.example.org",
+ "name": "Example"
+ }
+ ]
+ },
+ "brand": {
+ "color": "#FFFFFF"
+ },
+ "contact_info": {
+ "chargeback": {
+ "email": "cb@example.org",
+ "phone": null,
+ "policy_url": null
+ },
+ "refund": {
+ "email": "cb@example.org",
+ "phone": null,
+ "policy_url": null
+ },
+ "support": {
+ "email": "support@example.org",
+ "phone": "9999999998",
+ "policy_url": "https://www.google.com"
+ }
+ }
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+### Edit Account
+
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$api->account->edit($accountId,array(
+ "customer_facing_business_name" => "ABCD Ltd"
+));
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| phone | integer | The sub-merchant's business phone number. The minimum length is 8 characters and the maximum length is 15. |
+| legal_business_name | string | The name of the sub-merchant's business. For example, Acme Corp. The minimum length is 4 characters and the maximum length is 200. |
+| customer_facing_business_name | string | The sub-merchant billing label as it appears on the Razorpay Dashboard. The minimum length is 1 character and the maximum length is 255. |
+| profile | object | All keys listed [here](https://razorpay.com/docs/api/partners/account-onboarding/#update-an-account) are supported |
+| legal_info | object | All keys listed [here](hhttps://razorpay.com/docs/api/partners/account-onboarding/#update-an-account) are supported |
+| brand | object | All keys listed [here](https://razorpay.com/docs/api/partners/account-onboarding/#update-an-account) are supported |
+| notes | object | A key-value pair |
+| contact_name* | string | The name of the contact. The minimum length is 4 and the maximum length is 255 characters. |
+| contact_info | object | All keys listed [here](https://razorpay.com/docs/api/partners/account-onboarding/#update-an-account) are supported |
+| apps | object | All keys listed [here](https://razorpay.com/docs/api/partners/account-onboarding/#update-an-account) are supported |
+
+**Response:**
+```json
+{
+ "id": "acc_GP4lfNA0iIMn5B",
+ "type": "standard",
+ "status": "created",
+ "email": "gauri@example.org",
+ "profile": {
+ "category": "healthcare",
+ "subcategory": "clinic",
+ "addresses": {
+ "registered": {
+ "street1": "507, Koramangala 1st block",
+ "street2": "MG Road-1",
+ "city": "Bengalore",
+ "state": "KARNATAKA",
+ "postal_code": "560034",
+ "country": "IN"
+ }
+ }
+ },
+ "notes": [],
+ "created_at": 1610603081,
+ "phone": "9000090000",
+ "reference_id": "randomId",
+ "business_type": "partnership",
+ "legal_business_name": "Acme Corp",
+ "customer_facing_business_name": "ABCD Ltd"
+}
+```
+-------------------------------------------------------------------------------------------------------
+
+### Delete an account
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+$api->account->delete($accountId);
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account that must be deleted. |
+
+**Response:**
+```json
+{
+ "id": "acc_GXQAkO2MrvBYg4",
+ "type": "standard",
+ "status": "suspended",
+ "email": "gaurav.kumar@acme.org",
+ "profile": {
+ "category": "healthcare",
+ "subcategory": "clinic",
+ "addresses": {
+ "registered": {
+ "street1": "507, Koramangala 1st block",
+ "street2": "MG Road",
+ "city": "Bengaluru",
+ "state": "KARNATAKA",
+ "postal_code": "560034",
+ "country": "IN"
+ },
+ "operation": {
+ "street1": "507, Koramangala 1st block",
+ "street2": "MG Road",
+ "city": "Bengaluru",
+ "state": "KARNATAKA",
+ "country": "IN",
+ "postal_code": "560034"
+ }
+ },
+ "business_model": "Online Clothing ( men, women, ethnic, modern ) fashion and lifestyle, accessories, t-shirt, shirt, track pant, shoes."
+ },
+ "notes": {
+ "internal_ref_id": "123123"
+ },
+ "created_at": 1612425180,
+ "suspended_at": 1612425235,
+ "phone": "9000090000",
+ "reference_id": "account_COdeRandom",
+ "business_type": "partnership",
+ "legal_business_name": "Acme Corp Pvt Ltd",
+ "customer_facing_business_name": "Acme",
+ "legal_info": {
+ "pan": "AAACL1234C",
+ "gst": "18AABCU9603R1ZM"
+ },
+ "apps": {
+ "websites": [
+ "https://www.acme.org"
+ ],
+ "android": [
+ {
+ "url": "playstore.acme.org",
+ "name": "Acme"
+ }
+ ],
+ "ios": [
+ {
+ "url": "appstore.acme.org",
+ "name": "Acme"
+ }
+ ]
+ },
+ "brand": {
+ "color": "#FFFFFF"
+ },
+ "contact_name": "Gaurav Kumar",
+ "contact_info": {
+ "chargeback": {
+ "email": "cb@acme.org",
+ "phone": "9000090000",
+ "policy_url": "https://www.google.com"
+ },
+ "refund": {
+ "email": "cb@acme.org",
+ "phone": "9898989898",
+ "policy_url": "https://www.google.com"
+ },
+ "support": {
+ "email": "support@acme.org",
+ "phone": "9898989898",
+ "policy_url": "https://www.google.com"
+ }
+ }
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+### Fetch an account
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+$api->account->fetch($accountId);
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+
+**Response:**
+```json
+{
+ "id": "acc_GP4lfNA0iIMn5B",
+ "type": "standard",
+ "status": "created",
+ "email": "gauri@example.org",
+ "profile": {
+ "category": "healthcare",
+ "subcategory": "clinic",
+ "addresses": {
+ "registered": {
+ "street1": "507, Koramangala 1st block",
+ "street2": "MG Road-1",
+ "city": "Bengalore",
+ "state": "KARNATAKA",
+ "postal_code": "560034",
+ "country": "IN"
+ }
+ }
+ },
+ "notes": [],
+ "created_at": 1610603081,
+ "phone": "9000090000",
+ "reference_id": "randomId",
+ "business_type": "partnership",
+ "legal_business_name": "Acme Corp",
+ "customer_facing_business_name": "Example Pvt. Ltd."
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+**PN: * indicates mandatory fields**
+
+
+**For reference click [here](https://razorpay.com/docs/api/partners/account-onboarding/)**
\ No newline at end of file
diff --git a/documents/card.md b/documents/card.md
index 087bdeff..5c81cfe9 100644
--- a/documents/card.md
+++ b/documents/card.md
@@ -499,6 +499,48 @@ $api->customer->fetch($customerId)->tokens()->delete($tokenId);
```
-------------------------------------------------------------------------------------------------------
+## Using Card Number/ Tokenised Card Number
+
+```php
+$api->card->requestCardReference(array("number" =>"4854980604708430"));
+```
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|---------|------------------------------------------------------------------------------|
+| number* | string | The card number whose PAR or network reference id should be retrieved. |
+| tokenised | string | Determines if the card is saved as a token. Possible value is `true` or `false` |
+
+**Response:**
+```json
+{
+ "network": "Visa",
+ "payment_account_reference": "V0010013819231376539033235990",
+ "network_reference_id": null
+}
+```
+-------------------------------------------------------------------------------------------------------
+
+## Using Razporpay token
+
+```php
+$api->card->requestCardReference(array("token" =>"token_4lsdksD31GaZ09"));
+```
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|---------|------------------------------------------------------------------------------|
+| token* | string | The token whose PAR or network reference id should be retrieved.|
+
+**Response:**
+```json
+{
+ "network": "Visa",
+ "payment_account_reference": "V0010013819231376539033235990",
+ "network_reference_id": null
+}
+```
+-------------------------------------------------------------------------------------------------------
**PN: * indicates mandatory fields**
diff --git a/documents/payment.md b/documents/payment.md
index b184579d..b1389b24 100644
--- a/documents/payment.md
+++ b/documents/payment.md
@@ -655,6 +655,49 @@ Doc reference [doc](https://razorpay.com/docs/payments/payment-methods/cards/aut
}
```
+-------------------------------------------------------------------------------------------------------
+### Token IIN API
+
+```php
+$tokenIin = "412345";
+$api->iin->fetch($tokenIin);
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|------------|--------|-----------------------------------|
+| tokenIin* | string | The token IIN. |
+
+**Response:**
+```json
+{
+ "iin": "412345",
+ "entity": "iin",
+ "network": "Visa",
+ "type": "credit",
+ "sub_type": "business",
+ "issuer_code": "HDFC",
+ "issuer_name": "HDFC Bank Ltd",
+ "international": false,
+ "is_tokenized": true,
+ "card_iin": "411111",
+ "emi":{
+ "available": true
+ },
+ "recurring": {
+ "available": true
+ },
+ "authentication_types": [
+ {
+ "type":"3ds"
+ },
+ {
+ "type":"otp"
+ }
+ ]
+}
+```
-------------------------------------------------------------------------------------------------------
**PN: * indicates mandatory fields**
diff --git a/documents/productConfiguration.md b/documents/productConfiguration.md
new file mode 100644
index 00000000..00f08c0d
--- /dev/null
+++ b/documents/productConfiguration.md
@@ -0,0 +1,604 @@
+## Product Configuration
+
+### Request a Product Configuration
+```php
+
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$api->account->fetch($accountId)->products()->requestProductConfiguration(array(
+ "product_name" => "payment_gateway",
+ "tnc_accepted" => true,
+ "ip" => "233.233.233.234"
+));
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| product_name* | string | The product(s) to be configured. Possible value is `payment_gateway`, `payment_links` |
+| tnc_accepted | boolean | Pass this parameter to accept terms and conditions. Send this parameter along with the ip parameter when the tnc is accepted. Possible values is `true` |
+| ip | integer | The IP address of the merchant while accepting the terms and conditions. Send this parameter along with the `tnc_accepted` parameter when the `tnc` is accepted. |
+
+**Response:**
+```json
+{
+ "requested_configuration": {
+ "payment_methods": []
+ },
+ "active_configuration": {
+ "payment_capture": {
+ "mode": "automatic",
+ "refund_speed": "normal",
+ "automatic_expiry_period": 7200
+ },
+ "settlements": {
+ "account_number": null,
+ "ifsc_code": null,
+ "beneficiary_name": null
+ },
+ "checkout": {
+ "theme_color": "#FFFFFF",
+ "flash_checkout": true,
+ "logo": "https://example.com/your_logo"
+ },
+ "refund": {
+ "default_refund_speed": "normal"
+ },
+ "notifications": {
+ "whatsapp": true,
+ "sms": false,
+ "email": [
+ "b963e252-1201-45b0-9c39-c53eceb0cfd6_load@gmail.com"
+ ]
+ },
+ "payment_methods": {
+ "netbanking": {
+ "enabled": true,
+ "instrument": [
+ {
+ "type": "retail",
+ "bank": [
+ "hdfc",
+ "sbin",
+ "utib",
+ "icic",
+ "scbl",
+ "yesb"
+ ]
+ }
+ ]
+ },
+ "wallet": {
+ "enabled": true,
+ "instrument": [
+ "airtelmoney",
+ "freecharge",
+ "jiomoney",
+ "olamoney",
+ "payzapp",
+ "mobikwik"
+ ]
+ },
+ "upi": {
+ "enabled": true,
+ "instrument": [
+ "upi"
+ ]
+ }
+ }
+ },
+ "requirements": [
+ {
+ "field_reference": "individual_proof_of_address",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders/{stakeholderId}/documents",
+ "status": "required",
+ "reason_code": "document_missing"
+ },
+ {
+ "field_reference": "individual_proof_of_identification",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders/{stakeholderId}/documents",
+ "status": "required",
+ "reason_code": "document_missing"
+ },
+ {
+ "field_reference": "business_proof_of_identification",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/documents",
+ "status": "required",
+ "reason_code": "document_missing"
+ },
+ {
+ "field_reference": "settlements.beneficiary_name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/products/acc_prd_HEgNpywUFctQ9e",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "settlements.account_number",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/products/acc_prd_HEgNpywUFctQ9e",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "settlements.ifsc_code",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/products/acc_prd_HEgNpywUFctQ9e",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "contact_name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "customer_facing_business_name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "kyc.pan",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders",
+ "status": "required",
+ "reason_code": "field_missing"
+ }
+ ],
+ "tnc":{
+ "id": "tnc_IgohZaDBHRGjPv",
+ "accepted": true,
+ "accepted_at": 1641550798
+ },
+ "id": "acc_prd_HEgNpywUFctQ9e",
+ "account_id": "acc_HQVlm3bnPmccC0",
+ "product_name": "payment_gateway",
+ "activation_status": "needs_clarification",
+ "requested_at": 162547884
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+### Edit a Product Configuration
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+$productId = "acc_prd_HEgNpywUFctQ9e";
+
+$api->account->fetch($accountId)->products()->edit($productId, array(
+ "notifications" => array(
+ "email" => array(
+ "gaurav.kumar@example.com",
+ "acd@gmail.com"
+ )
+ ),
+ "checkout" => array(
+ "theme_color" => "#528FFF"
+ ),
+ "refund" => array(
+ "default_refund_speed" => "optimum"
+ ),
+ "settlements" => array(
+ "account_number" => "1234567890",
+ "ifsc_code" => "HDFC0000317",
+ "beneficiary_name" => "Gaurav Kumar"
+ ),
+ "tnc_accepted" => true,
+ "ip" => "233.233.233.234"
+));
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| notifications | object | All keys listed [here](https://razorpay.com/docs/api/partners/product-configuration/#update-a-product-configuration) are supported |
+| checkout | object | All keys listed [here](https://razorpay.com/docs/api/partners/product-configuration/#update-a-product-configuration) are supported |
+| refund | object | All keys listed [here](https://razorpay.com/docs/api/partners/product-configuration/#update-a-product-configuration) are supported |
+| settlements | object | All keys listed [here](https://razorpay.com/docs/api/partners/product-configuration/#update-a-product-configuration) are supported |
+| tnc_accepted | boolean | Pass this parameter to accept terms and conditions. Send this parameter along with the ip parameter when the tnc is accepted. Possible value is `true` |
+| ip | string | The IP address of the merchant while accepting the terms and conditions. Send this parameter along with the tnc_accepted parameter when the `tnc` is accepted. |
+| payment_methods | All keys listed [here](https://razorpay.com/docs/api/partners/product-configuration/#update-a-product-configuration) are supported |
+| type | string | Possible value is `domestic` |
+| issuer | string | The card issuer. Possible values for issuer are `amex`, `dicl`, `maestro`, `mastercard`, `rupay`, `visa`. |
+| wallet | object | All keys listed [here](https://razorpay.com/docs/api/partners/product-configuration/#update-a-product-configuration) are supported |
+| instrument(wallet) | string | The wallet issuer. Possible values are `airtelmoney`, `amazonpay`, `freecharge`, `jiomoney`, `mobiwik`, `mpesa`, `olamoney`, `paytm`, `payzapp`, `payumoney`, `phonepe`, `phonepeswitch`, `sbibuddy` |
+| instrument(wallet) | string | The wallet issuer. Possible values are `airtelmoney`, `amazonpay`, `freecharge`, `jiomoney`, `mobiwik`, `mpesa`, `olamoney`, `paytm`, `payzapp`, `payumoney`, `phonepe`, `phonepeswitch`, `sbibuddy` |
+| upi | object | All keys listed [here](https://razorpay.com/docs/api/partners/product-configuration/#update-a-product-configuration) are supported |
+| instrument(upi) | string | The UPI service provider. Possible values are `google_pay`, `upi`|
+| paylater | object | All keys listed [here](https://razorpay.com/docs/api/partners/product-configuration/#update-a-product-configuration) are supported |
+| instrument(emi) | string | The Paylater service provider. Possible values are `epaylater`, `getsimpl`|
+| emi | object | All keys listed [here](https://razorpay.com/docs/api/partners/product-configuration/#update-a-product-configuration) are supported |
+
+**Response:**
+```json
+{
+ "id": "acc_GP4lfNA0iIMn5B",
+ "type": "standard",
+ "status": "created",
+ "email": "gauri@example.org",
+ "profile": {
+ "category": "healthcare",
+ "subcategory": "clinic",
+ "addresses": {
+ "registered": {
+ "street1": "507, Koramangala 1st block",
+ "street2": "MG Road-1",
+ "city": "Bengalore",
+ "state": "KARNATAKA",
+ "postal_code": "560034",
+ "country": "IN"
+ }
+ }
+ },
+ "notes": [],
+ "created_at": 1610603081,
+ "phone": "9000090000",
+ "reference_id": "randomId",
+ "business_type": "partnership",
+ "legal_business_name": "Acme Corp",
+ "customer_facing_business_name": "ABCD Ltd"
+}
+```
+-------------------------------------------------------------------------------------------------------
+
+### Fetch a product configuration
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$productId = "acc_prd_HEgNpywUFctQ9e";
+
+$api->account->fetch($accountId)->products()->fetch($productId);
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+| productId* | string | The unique identifier of a product generated by Razorpay. |
+
+**Response:**
+```json
+{
+ "requested_configuration": {
+ "payment_methods": []
+ },
+ "active_configuration": {
+ "payment_capture": {
+ "mode": "automatic",
+ "refund_speed": "normal",
+ "automatic_expiry_period": 7200
+ },
+ "settlements": {
+ "account_number": null,
+ "ifsc_code": null,
+ "beneficiary_name": null
+ },
+ "checkout": {
+ "theme_color": "#FFFFFF",
+ "flash_checkout": true
+ },
+ "refund": {
+ "default_refund_speed": "normal"
+ },
+ "notifications": {
+ "whatsapp": true,
+ "sms": false,
+ "email": [
+ "b963e252-1201-45b0-9c39-c53eceb0cfd6_load@gmail.com"
+ ]
+ },
+ "payment_methods": {
+ "netbanking": {
+ "enabled": true,
+ "instrument": [
+ {
+ "type": "retail",
+ "bank": [
+ "hdfc",
+ "sbin",
+ "utib",
+ "icic",
+ "scbl",
+ "yesb"
+ ]
+ }
+ ]
+ },
+ "wallet": {
+ "enabled": true,
+ "instrument": [
+ "airtelmoney",
+ "freecharge",
+ "jiomoney",
+ "olamoney",
+ "payzapp",
+ "mobikwik"
+ ]
+ },
+ "upi": {
+ "enabled": true,
+ "instrument": [
+ "upi"
+ ]
+ }
+ }
+ },
+ "requirements": [
+ {
+ "field_reference": "individual_proof_of_address",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders/{stakeholderId}/documents",
+ "status": "required",
+ "reason_code": "document_missing"
+ },
+ {
+ "field_reference": "individual_proof_of_identification",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders/{stakeholderId}/documents",
+ "status": "required",
+ "reason_code": "document_missing"
+ },
+ {
+ "field_reference": "business_proof_of_identification",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/documents",
+ "status": "required",
+ "reason_code": "document_missing"
+ },
+ {
+ "field_reference": "settlements.beneficiary_name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/products/acc_prd_HEgNpywUFctQ9e",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "settlements.account_number",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/products/acc_prd_HEgNpywUFctQ9e",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "settlements.ifsc_code",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/products/acc_prd_HEgNpywUFctQ9e",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "contact_name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "customer_facing_business_name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "kyc.pan",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders",
+ "status": "required",
+ "reason_code": "field_missing"
+ }
+ ],
+ "tnc":{
+ "id": "tnc_IgohZaDBHRGjPv",
+ "accepted": true,
+ "accepted_at": 1641550798
+ },
+ "id": "acc_prd_HEgNpywUFctQ9e",
+ "account_id": "acc_HQVlm3bnPmccC0",
+ "product_name": "payment_gateway",
+ "activation_status": "needs_clarification",
+ "requested_at": 1625478849
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+### Fetch Terms and Conditions for a Sub-Merchant
+```php
+
+$productName = "payments";
+
+$api->product->fetchTnc($productName);
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|-------------|---------------------------------------------|
+| productName* | string | The product family for which the relevant product to be requested for the sub-merchant. Possible value is `payments` |
+
+**Response:**
+```json
+{
+ "entity": "tnc_map",
+ "product_name": "payments",
+ "id": "tnc_map_HjOVhIdpVDZ0FB",
+ "tnc": {
+ "terms": "https://razorpay.com/terms",
+ "privacy": "https://razorpay.com/privacy",
+ "agreement": "https://razorpay.com/agreement"
+ },
+ "last_published_at": 1640589653
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+### Fetch a product configuration
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$productId = "acc_prd_HEgNpywUFctQ9e";
+
+$api->account->fetch($accountId)->products()->fetch($productId);
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+| productId* | string | The unique identifier of a product generated by Razorpay. |
+
+**Response:**
+```json
+{
+ "requested_configuration": {
+ "payment_methods": []
+ },
+ "active_configuration": {
+ "payment_capture": {
+ "mode": "automatic",
+ "refund_speed": "normal",
+ "automatic_expiry_period": 7200
+ },
+ "settlements": {
+ "account_number": null,
+ "ifsc_code": null,
+ "beneficiary_name": null
+ },
+ "checkout": {
+ "theme_color": "#FFFFFF",
+ "flash_checkout": true
+ },
+ "refund": {
+ "default_refund_speed": "normal"
+ },
+ "notifications": {
+ "whatsapp": true,
+ "sms": false,
+ "email": [
+ "b963e252-1201-45b0-9c39-c53eceb0cfd6_load@gmail.com"
+ ]
+ },
+ "payment_methods": {
+ "netbanking": {
+ "enabled": true,
+ "instrument": [
+ {
+ "type": "retail",
+ "bank": [
+ "hdfc",
+ "sbin",
+ "utib",
+ "icic",
+ "scbl",
+ "yesb"
+ ]
+ }
+ ]
+ },
+ "wallet": {
+ "enabled": true,
+ "instrument": [
+ "airtelmoney",
+ "freecharge",
+ "jiomoney",
+ "olamoney",
+ "payzapp",
+ "mobikwik"
+ ]
+ },
+ "upi": {
+ "enabled": true,
+ "instrument": [
+ "upi"
+ ]
+ }
+ }
+ },
+ "requirements": [
+ {
+ "field_reference": "individual_proof_of_address",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders/{stakeholderId}/documents",
+ "status": "required",
+ "reason_code": "document_missing"
+ },
+ {
+ "field_reference": "individual_proof_of_identification",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders/{stakeholderId}/documents",
+ "status": "required",
+ "reason_code": "document_missing"
+ },
+ {
+ "field_reference": "business_proof_of_identification",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/documents",
+ "status": "required",
+ "reason_code": "document_missing"
+ },
+ {
+ "field_reference": "settlements.beneficiary_name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/products/acc_prd_HEgNpywUFctQ9e",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "settlements.account_number",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/products/acc_prd_HEgNpywUFctQ9e",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "settlements.ifsc_code",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/products/acc_prd_HEgNpywUFctQ9e",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "contact_name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "customer_facing_business_name",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0",
+ "status": "required",
+ "reason_code": "field_missing"
+ },
+ {
+ "field_reference": "kyc.pan",
+ "resolution_url": "/accounts/acc_HQVlm3bnPmccC0/stakeholders",
+ "status": "required",
+ "reason_code": "field_missing"
+ }
+ ],
+ "tnc":{
+ "id": "tnc_IgohZaDBHRGjPv",
+ "accepted": true,
+ "accepted_at": 1641550798
+ },
+ "id": "acc_prd_HEgNpywUFctQ9e",
+ "account_id": "acc_HQVlm3bnPmccC0",
+ "product_name": "payment_gateway",
+ "activation_status": "needs_clarification",
+ "requested_at": 1625478849
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+**PN: * indicates mandatory fields**
+
+
+**For reference click [here](https://razorpay.com/docs/api/partners/product-configuration/)**
\ No newline at end of file
diff --git a/documents/stakeholder.md b/documents/stakeholder.md
new file mode 100644
index 00000000..83d4bd4a
--- /dev/null
+++ b/documents/stakeholder.md
@@ -0,0 +1,275 @@
+## Stakeholders
+
+### Create an Stakeholder
+```php
+
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$api->account->fetch("acc_GP4lfNA0iIMn5B")->stakeholders()->create(array(
+ "percentage_ownership" => 10,
+ "name" => "Gaurav Kumar",
+ "email" => "gaurav.kumar@example.com",
+ "relationship" => array(
+ "director" => true,
+ "executive" => false
+ ),
+ "phone" => array(
+ "primary" => "7474747474",
+ "secondary" => "7474747474"
+ ),
+ "addresses" => array(
+ "residential" => array(
+ "street" => "506, Koramangala 1st block",
+ "city" => "Bengaluru",
+ "state" => "Karnataka",
+ "postal_code" => "560034",
+ "country" => "IN"
+ )
+ ),
+ "kyc" => array(
+ "pan" => "AVOPB1111K"
+ ),
+ "notes" => array(
+ "random_key_by_partner" => "random_value"
+ )
+));
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| email | string | The sub-merchant's business email address. |
+| name* | string | The stakeholder's name as per the PAN card. The maximum length is 255 characters. |
+| percentage_ownership | float | The stakeholder's ownership of the business in percentage. Only two decimal places are allowed. For example, `87.55`. The maximum length is 100 characters. |
+| relationship | boolean | The stakeholder's relationship with the account’s business. |
+| phone | object | All keys listed [here](https://razorpay.com/docs/api/partners/stakeholder/#create-a-stakeholder) are supported |
+| addresses | object | All keys listed [here](https://razorpay.com/docs/api/partners/stakeholder/#create-a-stakeholder) are supported |
+| kyc | object | All keys listed [here](https://razorpay.com/docs/api/partners/stakeholder/#create-a-stakeholder) are supported |
+| notes | object | A key-value pair |
+
+**Response:**
+```json
+{
+ "entity": "stakeholder",
+ "relationship": {
+ "director": true
+ },
+ "phone": {
+ "primary": "7474747474",
+ "secondary": "7474747474"
+ },
+ "notes": {
+ "random_key_by_partner": "random_value"
+ },
+ "kyc": {
+ "pan": "AVOPB1111K"
+ },
+ "id": "sth_GLGgm8fFCKc92m",
+ "name": "Gaurav Kumar",
+ "email": "gaurav.kumar@example.com",
+ "percentage_ownership": 10,
+ "addresses": {
+ "residential": {
+ "street": "506, Koramangala 1st block",
+ "city": "Bengaluru",
+ "state": "Karnataka",
+ "postal_code": "560034",
+ "country": "IN"
+ }
+ }
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+### Edit Stakeholder
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+$stakeholderId = "sth_GOQ4Eftlz62TSL";
+
+$api->account->fetch($accountId)->stakeholders()->edit($stakeholderId, array(
+ "percentage_ownership" => 20,
+ "name" => "Gauri Kumar",
+ "relationship" => array(
+ "director" => false,
+ "executive" => true
+ ),
+ "phone" => array(
+ "primary" => "9898989898",
+ "secondary" => "9898989898"
+ ),
+ "addresses" => array(
+ "residential" => array(
+ "street" => "507, Koramangala 1st block",
+ "city" => "Bangalore",
+ "state" => "Karnataka",
+ "postal_code" => "560035",
+ "country" => "IN"
+ )
+ ),
+ "kyc" => array(
+ "pan" => "AVOPB1111J"
+ ),
+ "notes" => array(
+ "random_key_by_partner" => "random_value2"
+ )
+));
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+| stakeholderId* | string | The unique identifier of the stakeholder whose details are to be fetched. |
+| name | string | The stakeholder's name as per the PAN card. The maximum length is 255 characters. |
+| percentage_ownership | float | The stakeholder's ownership of the business in percentage. Only two decimal places are allowed. For example, `87.55`. The maximum length is 100 characters. |
+| relationship | boolean | The stakeholder's relationship with the account’s business. |
+| phone | object | All keys listed [here](https://razorpay.com/docs/api/partners/stakeholder/#update-a-stakeholder) are supported |
+| addresses | object | All keys listed [here](https://razorpay.com/docs/api/partners/stakeholder/#update-a-stakeholder) are supported |
+| kyc | object | All keys listed [here](https://razorpay.com/docs/api/partners/stakeholder/#update-a-stakeholder) are supported |
+| notes | object | A key-value pair |
+
+**Response:**
+```json
+{
+ "id": "acc_GP4lfNA0iIMn5B",
+ "type": "standard",
+ "status": "created",
+ "email": "gauri@example.org",
+ "profile": {
+ "category": "healthcare",
+ "subcategory": "clinic",
+ "addresses": {
+ "registered": {
+ "street1": "507, Koramangala 1st block",
+ "street2": "MG Road-1",
+ "city": "Bengalore",
+ "state": "KARNATAKA",
+ "postal_code": "560034",
+ "country": "IN"
+ }
+ }
+ },
+ "notes": [],
+ "created_at": 1610603081,
+ "phone": "9000090000",
+ "reference_id": "randomId",
+ "business_type": "partnership",
+ "legal_business_name": "Acme Corp",
+ "customer_facing_business_name": "ABCD Ltd"
+}
+```
+-------------------------------------------------------------------------------------------------------
+
+### Fetch all accounts
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$api->account->fetch($accountId)->stakeholders()->all();
+
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+
+**Response:**
+```json
+{
+ "entity": "collection",
+ "items": [
+ {
+ "id": "GZ13yPHLJof9IE",
+ "entity": "stakeholder",
+ "relationship": {
+ "director": true
+ },
+ "phone": {
+ "primary": "9000090000",
+ "secondary": "9000090000"
+ },
+ "notes": {
+ "random_key_by_partner": "random_value"
+ },
+ "kyc": {
+ "pan": "AVOPB1111K"
+ },
+ "name": "Gaurav Kumar",
+ "email": "gaurav.kumar@acme.org",
+ "percentage_ownership": 10,
+ "addresses": {
+ "residential": {
+ "street": "506, Koramangala 1st block",
+ "city": "Bengaluru",
+ "state": "Karnataka",
+ "postal_code": "560034",
+ "country": "in"
+ }
+ }
+ }
+ ],
+ "count": 1
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+### Fetch an stakeholder
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$stakeholderId = "sth_GOQ4Eftlz62TSL";
+
+$api->account->fetch($accountId)->stakeholders()->fetch($stakeholderId);
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+| stakeholderId* | string | The unique identifier of the stakeholder whose details are to be fetched. |
+
+**Response:**
+```json
+{
+ "entity": "stakeholder",
+ "relationship": {
+ "director": true
+ },
+ "phone": {
+ "primary": "9000090000",
+ "secondary": "9000090000"
+ },
+ "notes": {
+ "random_key_by_partner": "random_value2"
+ },
+ "kyc": {
+ "pan": "AVOPB1111J"
+ },
+ "id": "sth_GOQ4Eftlz62TSL",
+ "name": "Gauri Kumar",
+ "email": "gauri@example.com",
+ "percentage_ownership": 20,
+ "addresses": {
+ "residential": {
+ "street": "507, Koramangala 1st block",
+ "city": "Bangalore",
+ "state": "Karnataka",
+ "postal_code": "560035",
+ "country": "in"
+ }
+ }
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+**PN: * indicates mandatory fields**
+
+
+**For reference click [here](https://razorpay.com/docs/api/partners/stakeholder)**
\ No newline at end of file
diff --git a/documents/token.md b/documents/token.md
index 63fa0fef..35f62f13 100644
--- a/documents/token.md
+++ b/documents/token.md
@@ -238,6 +238,152 @@ $api->customer->fetch($customerId)->tokens()->all();
}
```
-------------------------------------------------------------------------------------------------------
+
+### Create a token
+
+```php
+
+$api->token->create(array(
+ "customer_id" => "cust_1Aa00000000001",
+ "method" => "card",
+ "card" => array(
+ "number" => "4111111111111111",
+ "cvv" => "123",
+ "expiry_month" => "12",
+ "expiry_year" => "21",
+ "name" => "Gaurav Kumar"
+ ),
+ "authentication" => array(
+ "provider" => "razorpay",
+ "provider_reference_id" => "pay_123wkejnsakd",
+ "authentication_reference_number" => "100222021120200000000742753928"
+ ),
+ "notes" => array()
+));
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| customerId* | string | The id of the customer to be fetched |
+| method* | string | The type of object that needs to be tokenised. Currently, `card` is the only supported value. |
+| card* | object | All keys listed [here](https://razorpay.com/docs/partners/aggregators/partner-auth/token-sharing/#create-token-on-behalf-of-a-sub-merchant) are supported
+|
+| authentication | object | All keys listed [here](https://razorpay.com/docs/partners/aggregators/partner-auth/token-sharing/#create-token-on-behalf-of-a-sub-merchant) are supported |
+
+**Response:**
+```json
+{
+ "id": "token_IJmat4GwYATMtx",
+ "entity": "token",
+ "method": "card",
+ "card": {
+ "last4": "1111",
+ "network": "Visa",
+ "type": "credit",
+ "issuer": "IDFB",
+ "international": false,
+ "emi": false,
+ "sub_type": "consumer"
+ },
+ "customer": {
+ "id": "cust_1Aa00000000001",
+ "entity": "customer",
+ "name": "Bob",
+ "email": "bob@gmail.com",
+ "contact": "9000090000",
+ "gstin": null,
+ "notes": {
+ "notes_key_1": "Tea, Earl Grey, Hot",
+ "notes_key_2": "Tea, Earl Grey… decaf."
+ },
+ "created_at": 1658390470
+ },
+ "expired_at": 1701368999,
+ "customer_id": "cust_1Aa00000000001",
+ "compliant_with_tokenisation_guidelines": true,
+ "status": "active",
+ "notes": []
+}
+```
+-------------------------------------------------------------------------------------------------------
+
+### Fetch token
+```php
+$api->token->fetch(array("id" => "token_4lsdksD31GaZ09"));
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|-------------|---------------------------------------------|
+| id* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+
+**Response:**
+```json
+{
+ "id": "token_4lsdksD31GaZ09",
+ "entity": "token",
+ "customer_id": "cust_1Aa00000000001",
+ "method": "card",
+ "card": {
+ "last4": "3335",
+ "network": "Visa",
+ "type": "debit",
+ "issuer": "HDFC",
+ "international": false,
+ "emi": true,
+ "sub_type": "consumer",
+ "token_iin": "453335"
+ },
+ "compliant_with_tokenisation_guidelines": true,
+ "expired_at": 1748716199,
+ "status": "active",
+ "status_reason": null,
+ "notes": []
+}
+```
+-------------------------------------------------------------------------------------------------------
+### Delete a token
+```php
+$api->token->delete(array("id" => "token_4lsdksD31GaZ09"));
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|-------------|---------------------------------------------|
+| id* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+
+**Response:**
+```json
+[]
+```
+-------------------------------------------------------------------------------------------------------
+
+### Process a Payment on another PA/PG with Token
+```php
+$api->token->processPaymentOnAlternatePAorPG(array("id"=>"spt_4lsdksD31GaZ09"));
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|-------------|---------------------------------------------|
+| id* | string | The unique identifier of the token whose details are to be fetched. |
+
+**Response:**
+```json
+{
+ "card": {
+ "number": "4016981500100002",
+ "expiry_month" : "12",
+ "expiry_year" : 2021
+ }
+}
+```
+-------------------------------------------------------------------------------------------------------
**PN: * indicates mandatory fields**
diff --git a/documents/webhook.md b/documents/webhook.md
new file mode 100644
index 00000000..d9855c14
--- /dev/null
+++ b/documents/webhook.md
@@ -0,0 +1,223 @@
+## Webhook
+
+### Create a Webhook
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$api->account->fetch($accountId)->webhooks()->create(array(
+ "url" => "https://google.com",
+ "alert_email" => "gaurav.kumar@example.com",
+ "secret" => "12345",
+ "events" => array(
+ "payment.authorized",
+ "payment.failed",
+ "payment.captured",
+ "payment.dispute.created",
+ "refund.failed",
+ "refund.created"
+ )
+));
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+| url* | string | The URL where you receive the webhook payload when an event is triggered. The maximum length is 255 characters. |
+| alert_email | string | This is the email address to which notifications must be sent in case of webhook failure. |
+| secret | string | A secret for the webhook endpoint that is used to validate that the webhook is from Razorpay. |
+| events | string | The required events from the list of Active Events. For example `payment.authorized`, `payment.captured`, `payment.failed`, `payment.dispute.created`, `refund.failed`, `refund.created` and so on. |
+
+**Response:**
+```json
+{
+ "id": "JebiXkKGYwua5L",
+ "created_at": 1654605478,
+ "updated_at": 1654605478,
+ "service": "beta-api-live",
+ "owner_id": "JOGUdtKu3dB03d",
+ "owner_type": "merchant",
+ "context": [],
+ "disabled_at": 0,
+ "url": "https://google.com",
+ "alert_email": "gaurav.kumar@example.com",
+ "secret_exists": true,
+ "entity": "webhook",
+ "active": true,
+ "events": [
+ "payment.authorized",
+ "payment.failed",
+ "payment.captured",
+ "payment.dispute.created",
+ "refund.failed",
+ "refund.created"
+ ]
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+### Edit Webhook
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$webhookId = "HK890egfiItP3H";
+
+$api->account->fetch($accountId)->webhooks()->edit($webhookId, array(
+ "url" => "https://www.linkedin.com",
+ "events" => array(
+ "refund.created"
+ )
+));
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+| webhookId* | string | The unique identifier of the webhook whose details are to be updated |
+| url | string | The URL where you receive the webhook payload when an event is triggered. The maximum length is 255 characters. |
+| events | string | The required events from the list of Active Events. For example `payment.authorized`, `payment.captured`, `payment.failed`, `payment.dispute.created`, `refund.failed`, `refund.created` and so on. |
+
+**Response:**
+```json
+{
+ "id": "HK890egfiItP3H",
+ "created_at": 1623060358,
+ "updated_at": 1623067148,
+ "service": "beta-api-test",
+ "owner_id": "H3kYHQ635sBwXG",
+ "owner_type": "merchant",
+ "context": [],
+ "disabled_at": 0,
+ "url": "https://www.linkedin.com",
+ "alert_email": "gaurav.kumar@example.com",
+ "secret_exists": true,
+ "entity": "webhook",
+ "active": true,
+ "events": [
+ "refund.created"
+ ]
+}
+```
+-------------------------------------------------------------------------------------------------------
+
+### Delete an account
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$webhookId = "HK890egfiItP3H";
+
+$api->account->fetch($accountId)->webhooks()->delete($webhookId);
+
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|---------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account that must be deleted. |
+| webhookId* | string | The unique identifier of the webhook whose details are to be updated |
+
+**Response:**
+```json
+[]
+```
+
+-------------------------------------------------------------------------------------------------------
+
+### Fetch a webhook
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$webhookId = "HK890egfiItP3H";
+
+$api->account->fetch($accountId)->webhooks()->fetch($webhookId);
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+| webhookId* | string | The unique identifier of the webhook whose details are to be updated |
+
+**Response:**
+```json
+{
+ "id": "HK890egfiItP3H",
+ "created_at": 1623060358,
+ "updated_at": 1623060358,
+ "owner_id": "H3kYHQ635sBwXG",
+ "owner_type": "merchant",
+ "context": [],
+ "disabled_at": 0,
+ "url": "https://en1mwkqo5ioct.x.pipedream.net",
+ "alert_email": "gaurav.kumar@example.com",
+ "secret_exists": true,
+ "entity": "webhook",
+ "active": true,
+ "events": [
+ "payment.authorized",
+ "payment.failed",
+ "payment.captured",
+ "payment.dispute.created",
+ "refund.failed",
+ "refund.created"
+ ]
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+### Fetch all Webhooks
+```php
+$accountId = "acc_GP4lfNA0iIMn5B";
+
+$api->account->fetch($accountId)->webhooks()->all();
+```
+
+**Parameters:**
+
+| Name | Type | Description |
+|-------------|-------------|---------------------------------------------|
+| accountId* | string | The unique identifier of a sub-merchant account generated by Razorpay. |
+| from | integer | Timestamp, in seconds, from when the webhooks are to be fetched. |
+| to | integer | Timestamp, in seconds, till when the webhooks are to be fetched. |
+| count | integer | Number of webhooks to be fetched. The default value is `10` and the maximum value is `100`. This can be used for pagination, in combination with `skip`. |
+| skip | integer | Number of records to be skipped while fetching the webhooks. This can be used for pagination, in combination with `count`. |
+
+**Response:**
+```json
+{
+ "id": "HK890egfiItP3H",
+ "created_at": 1623060358,
+ "updated_at": 1623060358,
+ "owner_id": "H3kYHQ635sBwXG",
+ "owner_type": "merchant",
+ "context": [],
+ "disabled_at": 0,
+ "url": "https://en1mwkqo5ioct.x.pipedream.net",
+ "alert_email": "gaurav.kumar@example.com",
+ "secret_exists": true,
+ "entity": "webhook",
+ "active": true,
+ "events": [
+ "payment.authorized",
+ "payment.failed",
+ "payment.captured",
+ "payment.dispute.created",
+ "refund.failed",
+ "refund.created"
+ ]
+}
+```
+
+-------------------------------------------------------------------------------------------------------
+
+**PN: * indicates mandatory fields**
+
+
+**For reference click [here](https://razorpay.com/docs/api/partners/webhooks)**
\ No newline at end of file
diff --git a/src/Account.php b/src/Account.php
new file mode 100644
index 00000000..66b6adcb
--- /dev/null
+++ b/src/Account.php
@@ -0,0 +1,62 @@
+getEntityUrl();
+
+ return $this->request('POST', $entityUrl, $attributes, 'v2');
+ }
+
+ public function fetch($id)
+ {
+ $entityUrl = $this->getEntityUrl();
+
+ return $this->request('GET', $entityUrl . $id, null, 'v2');
+ }
+
+ public function delete()
+ {
+ $entityUrl = $this->getEntityUrl();
+
+ return $this->request('DELETE', $entityUrl . $this->id, null, 'v2');
+ }
+
+ public function edit($attributes = array())
+ {
+ $url = $this->getEntityUrl() . $this->id;
+
+ return $this->request('PATCH', $url, $attributes, 'v2');
+ }
+
+ public function stakeholders()
+ {
+ $stakeholder = new Stakeholder();
+
+ $stakeholder['account_id'] = $this->id;
+
+ return $stakeholder;
+ }
+
+ public function products()
+ {
+ $product = new Product();
+
+ $product['account_id'] = $this->id;
+
+ return $product;
+ }
+
+ public function webhooks()
+ {
+ $webhook = new Webhook();
+
+ $webhook['account_id'] = $this->id;
+
+ return $webhook;
+ }
+}
diff --git a/src/Api.php b/src/Api.php
index 16709ed6..bd91f30f 100644
--- a/src/Api.php
+++ b/src/Api.php
@@ -4,7 +4,7 @@
class Api
{
- protected static $baseUrl = 'https://api.razorpay.com/v1/';
+ protected static $baseUrl = 'https://api.razorpay.com';
protected static $key = null;
@@ -16,7 +16,7 @@ class Api
*/
public static $appsDetails = array();
- const VERSION = '2.8.5';
+ const VERSION = '2.8.6';
/**
* @param string $key
@@ -84,8 +84,8 @@ public static function getSecret()
return self::$secret;
}
- public static function getFullUrl($relativeUrl)
+ public static function getFullUrl($relativeUrl, $apiVersion = "v1")
{
- return self::getBaseUrl() . $relativeUrl;
+ return self::getBaseUrl() . "/". $apiVersion . "/". $relativeUrl;
}
}
diff --git a/src/Card.php b/src/Card.php
index d9f77eff..186815b9 100644
--- a/src/Card.php
+++ b/src/Card.php
@@ -11,4 +11,11 @@ public function fetch($id)
{
return parent::fetch($id);
}
+
+ public function requestCardReference($attributes = array())
+ {
+ $entityUrl = $this->getEntityUrl() . '/fingerprints';
+
+ return $this->request('POST', $entityUrl, $attributes);
+ }
}
diff --git a/src/Entity.php b/src/Entity.php
index feb98507..caf17c5c 100644
--- a/src/Entity.php
+++ b/src/Entity.php
@@ -82,14 +82,15 @@ protected function snakeCase($input)
* @param string $relativeUrl
* @param array $data
* @param array $additionHeader
+ * @param string $apiVersion
*
* @return Entity
*/
- protected function request($method, $relativeUrl, $data = null)
+ protected function request($method, $relativeUrl, $data = null, $apiVersion = "v1")
{
$request = new Request();
- $response = $request->request($method, $relativeUrl, $data);
+ $response = $request->request($method, $relativeUrl, $data, $apiVersion);
if ((isset($response['entity'])) and ($response['entity'] == $this->getEntity()))
{
diff --git a/src/Iin.php b/src/Iin.php
new file mode 100644
index 00000000..c2f26530
--- /dev/null
+++ b/src/Iin.php
@@ -0,0 +1,11 @@
+account_id .'/'.$this->getEntityUrl();
+
+ return $this->request('POST', $url, $attributes, 'v2');
+ }
+
+ public function fetch($id)
+ {
+ $entityUrl = 'accounts/'.$this->account_id .'/'.$this->getEntityUrl().'/'.$id;
+
+ return $this->request('GET', $entityUrl, null, 'v2');
+ }
+
+ public function edit($id, $attributes = array())
+ {
+ $entityUrl = 'accounts/'.$this->account_id .'/'.$this->getEntityUrl().'/'.$id;
+
+ return $this->request('PATCH', $entityUrl, $attributes, 'v2');
+ }
+
+ public function fetchTnc($product_name)
+ {
+ $entityUrl = $this->getEntityUrl().'/'.$product_name.'/tnc';
+
+ return $this->request('GET', $entityUrl,null , 'v2');
+ }
+}
diff --git a/src/Request.php b/src/Request.php
index 78ea5919..2ccab02e 100644
--- a/src/Request.php
+++ b/src/Request.php
@@ -35,12 +35,13 @@ class Request
* @param string $url Relative URL for the request
* @param array $data Data to be passed along the request
* @param array $additionHeader headers to be passed along the request
+ * @param string $apiVersion version to be passed along the request
* @return array Response data in array format. Not meant
* to be used directly
*/
- public function request($method, $url, $data = array())
- {
- $url = Api::getFullUrl($url);
+ public function request($method, $url, $data = array(), $apiVersion = "v1")
+ {
+ $url = Api::getFullUrl($url, $apiVersion);
$hooks = new Requests_Hooks();
diff --git a/src/Stakeholder.php b/src/Stakeholder.php
new file mode 100644
index 00000000..05cf5971
--- /dev/null
+++ b/src/Stakeholder.php
@@ -0,0 +1,34 @@
+account_id .'/'.$this->getEntityUrl();
+
+ return $this->request('POST', $url, $attributes, 'v2');
+ }
+
+ public function fetch($id)
+ {
+ $entityUrl = 'accounts/'.$this->account_id .'/'.$this->getEntityUrl().'/'.$id;
+
+ return $this->request('GET', $entityUrl, null, 'v2');
+ }
+
+ public function all($options = array())
+ {
+ $relativeUrl = 'accounts/'.$this->account_id.'/'.$this->getEntityUrl();
+
+ return $this->request('GET', $relativeUrl, $options, 'v2');
+ }
+
+ public function edit($id, $attributes = array())
+ {
+ $entityUrl = 'accounts/'.$this->account_id .'/'.$this->getEntityUrl().'/'.$id;
+
+ return $this->request('PATCH', $entityUrl, $attributes, 'v2');
+ }
+}
diff --git a/src/Token.php b/src/Token.php
index 4a2e5634..8f55874c 100644
--- a/src/Token.php
+++ b/src/Token.php
@@ -3,7 +3,15 @@
namespace Razorpay\Api;
class Token extends Entity
-{
+{
+
+ public function create($attributes = array())
+ {
+ $url = $this->getEntityUrl();
+
+ return $this->request('POST', $url, $attributes);
+ }
+
/**
* @param $id Token id
*/
@@ -14,6 +22,13 @@ public function fetch($id)
return $this->request('GET', $relativeUrl);
}
+ public function fetchCardPropertiesByToken($attributes = array())
+ {
+ $relativeUrl = $this->getEntityUrl(). '/fetch';
+
+ return $this->request('POST', $relativeUrl, $attributes);
+ }
+
public function all($options = array())
{
$relativeUrl = 'customers/'.$this->customer_id.'/'.$this->getEntityUrl();
@@ -27,4 +42,18 @@ public function delete($id)
return $this->request('DELETE', $relativeUrl);
}
+
+ public function deleteToken($attributes = array())
+ {
+ $relativeUrl = $this->getEntityUrl(). '/delete';
+
+ return $this->request('POST', $relativeUrl, $attributes);
+ }
+
+ public function processPaymentOnAlternatePAorPG($attributes = array())
+ {
+ $relativeUrl = $this->getEntityUrl().'service_provider_tokens/token_transactional_data';
+
+ return $this->request('POST', $relativeUrl, $attributes);
+ }
}
diff --git a/src/Webhook.php b/src/Webhook.php
index b2728d80..a0e9d9ac 100644
--- a/src/Webhook.php
+++ b/src/Webhook.php
@@ -10,16 +10,34 @@ class Webhook extends Entity
*/
public function create($attributes = array())
{
+ if(isset($this->account_id))
+ {
+ $url = 'accounts/'. $this->account_id . '/' .$this->getEntityUrl();
+
+ return $this->request('POST', $url, $attributes, 'v2');
+ }
return parent::create($attributes);
}
public function fetch($id)
{
+ if(isset($this->account_id))
+ {
+ $url = 'accounts/'. $this->account_id . '/' .$this->getEntityUrl() . $id;
+
+ return $this->request('GET', $url, null, 'v2');
+ }
return parent::fetch($id);
}
public function all($options = array())
{
+ if(isset($this->account_id))
+ {
+ $url = 'accounts/'. $this->account_id . '/' .$this->getEntityUrl();
+
+ return $this->request('GET', $url, $options, 'v2');
+ }
return parent::all($options);
}
@@ -33,7 +51,20 @@ public function all($options = array())
public function edit($attributes, $id)
{
$url = $this->getEntityUrl() . $id;
-
+
+ if(isset($this->account_id))
+ {
+ $url = 'accounts/'.$this->account_id .'/'. $url;
+
+ return $this->request('PATCH', $url, $attributes, 'v2');
+ }
return $this->request(Requests::PUT, $url, $attributes);
}
+
+ public function delete($id)
+ {
+ $url = 'accounts/'. $this->account_id . '/' .$this->getEntityUrl(). $id;
+
+ return $this->request('DELETE', $url, null, 'v2');
+ }
}
diff --git a/tests/ApiTest.php b/tests/ApiTest.php
index 27b50914..b9ded097 100644
--- a/tests/ApiTest.php
+++ b/tests/ApiTest.php
@@ -9,7 +9,7 @@ class ApiTest extends TestCase
private $title = "codecov_test";
- private $url = 'https://api.razorpay.com/v1/';
+ private $url = 'https://api.razorpay.com';
public function setUp(): void
{
@@ -59,8 +59,16 @@ public function testGetSecret()
public function testFullUrl()
{
$pattern = '/^(https?:\/\/)?([a-z0-9-]+\.)+[a-z]{2,}(\/.*)?$/i';
- $url = $this->api->getFullUrl($this->api->getBaseUrl()."orders");
+ $url = $this->api->getFullUrl($this->api->getBaseUrl()."orders","v1");
$this->assertTrue(preg_match($pattern, $url, $matches)==true);
}
+ /**
+ * @covers \Request
+ */
+ public function testgetheader()
+ {
+ $data = Request::getHeaders();
+ $this->assertTrue(is_array($data));
+ }
}
\ No newline at end of file
diff --git a/tests/CoverageTest.php b/tests/CoverageTest.php
index cc92a6d1..b60a5b52 100644
--- a/tests/CoverageTest.php
+++ b/tests/CoverageTest.php
@@ -6,6 +6,84 @@
class CoverageTest extends TestCase
{
+ /**
+ * @covers \Razorpay\Api\Token::all
+ * @covers \Razorpay\Api\Token::fetch
+ * @covers \Razorpay\Api\Token::create
+ * @covers \Razorpay\Api\Token::fetchCardPropertiesByToken
+ * @covers \Razorpay\Api\Token::deleteToken
+ */
+ public function testTokenCoverage(){
+ $transfer = new TokenTest();
+ $transfer->setup();
+ $transfer->testFetchTokenByCustomerId();
+ $transfer->testCreateToken();
+ $transfer->testFetchTokenByPaymentId();
+ $transfer->testProcessPaymentOnAlternatePAorPG();
+ $transfer->testDeleteToken();
+ }
+
+ /**
+ * @covers \Razorpay\Api\Account::create
+ * @covers \Razorpay\Api\Account::fetch
+ * @covers \Razorpay\Api\Account::edit
+ * @covers \Razorpay\Api\Account::delete
+ */
+ public function testAccountCoverage(){
+ $account = new PartnerTest();
+ $account->setup();
+ $account->testCreateAccount();
+ $account->testFetchAccount();
+ //$account->testEditAccount();
+ $account->testDeleteAccount();
+ }
+
+ /**
+ * @covers \Razorpay\Api\Stakeholder::create
+ * @covers \Razorpay\Api\Stakeholder::fetch
+ * @covers \Razorpay\Api\Stakeholder::all
+ */
+ public function testStakeholderCoverage(){
+ $stakeholder = new PartnerTest();
+ $stakeholder->setup();
+ $stakeholder->testCreateStakerholder();
+ $stakeholder->testFetchStakerholder();
+ $stakeholder->testFetchAllStakerholder();
+ }
+
+ /**
+ * @covers \Razorpay\Api\Product::requestProductConfiguration
+ * @covers \Razorpay\Api\Product::fetch
+ * @covers \Razorpay\Api\Product::edit
+ * @covers \Razorpay\Api\Product::fetchTnc
+ * @covers \Razorpay\Api\Stakeholder::edit
+ */
+ public function testProductCoverage(){
+ $product = new PartnerTest();
+ $product->setup();
+ $product->testProductConfiguration();
+ $product->testProductFetch();
+ $product->testProductEdit();
+ $product->testFetchTnc();
+ //$product->testEditStakerholder();
+ }
+
+ /**
+ * @covers \Razorpay\Api\Webhook::create
+ * @covers \Razorpay\Api\Webhook::fetch
+ * @covers \Razorpay\Api\Webhook::all
+ * @covers \Razorpay\Api\Webhook::edit
+ * @covers \Razorpay\Api\Webhook::delete
+ */
+ public function testWebhookCoverage(){
+ $webhook = new PartnerTest();
+ $webhook->setup();
+ $webhook->testWebhookCreate();
+ $webhook->testWebhookFetch();
+ $webhook->testFetchAllWebhook();
+ $webhook->testEditWebhook();
+ $webhook->testDeleteWebhook();
+ }
/**
* @covers \Razorpay\Api\Api::getAppsDetails
* @uses \Razorpay\Api\Api::setAppDetails
@@ -14,6 +92,9 @@ class CoverageTest extends TestCase
* @cover \Razorpay\Api\Api::getKey
* @cover \Razorpay\Api\Api::getSecret
* @cover \Razorpay\Api\Api::getFullUrl
+ * @cover \Razorpay\Api\Api::testgetheader
+ * @cover \Razorpay\Api\Request::addHeader
+ * @cover \Razorpay\Api\Request::getHeader
*/
public function testApiInstance(){
$instance = new ApiTest();
@@ -23,7 +104,9 @@ public function testApiInstance(){
$instance->testGetkey();
$instance->testGetSecret();
$instance->testFullUrl();
+ $instance->testgetheader();
}
+
/**
* @covers \Razorpay\Api\Plan::create
* @covers \Razorpay\Api\Plan::fetch
@@ -66,10 +149,8 @@ public function testRefundCoverage(){
$refund = new RefundTest();
$refund->setup();
$refund->testFetchRefund();
- $refund->testUpdateRefund();
$refund->testFetchAllRefund();
$refund->testFetchMultipalRefund();
- $refund->testFetchRefund();
}
/**
@@ -116,9 +197,25 @@ public function testAddonCoverage(){
/**
* @covers \Razorpay\Api\Customer::create
+ * @covers \Razorpay\Api\Entity::create
* @covers \Razorpay\Api\Customer::edit
+ * @covers \Razorpay\Api\Entity::getEntityUrl
* @covers \Razorpay\Api\Customer::all
+ * @covers \Razorpay\Api\Entity::all
* @covers \Razorpay\Api\Customer::fetch
+ * @covers \Razorpay\Api\Entity::fetch
+ * @covers \Razorpay\Api\Entity::validateIdPresence
+ * @covers \Razorpay\Api\Entity::snakeCase
+ * @covers \Razorpay\Api\Entity::request
+ * @covers \Razorpay\Api\Entity::buildEntity
+ * @covers \Razorpay\Api\Entity::getDefinedEntitiesArray
+ * @covers \Razorpay\Api\Entity::getEntityClass
+ * @covers \Razorpay\Api\Entity::getEntity
+ * @covers \Razorpay\Api\Entity::fill
+ * @covers \Razorpay\Api\Entity::isAssocArray
+ * @covers \Razorpay\Api\Entity::toArray
+ * @covers \Razorpay\Api\Entity::convertToArray
+ * @covers \Razorpay\Api\Collection::count
*/
public function testCustomerCoverage(){
$customer = new CustomerTest();
@@ -132,6 +229,11 @@ public function testCustomerCoverage(){
/**
* @covers \Razorpay\Api\Card::fetch
+ * @covers \Razorpay\Api\Request::request
+ * @covers \Razorpay\Api\Request::checkErrors
+ * @covers \Razorpay\Api\Request::getRequestHeaders
+ * @covers \Razorpay\Api\Request::constructUa
+ * @covers \Razorpay\Api\Request::getAppDetailsUa
*/
public function testCardCoverage(){
$card = new CardTest();
@@ -271,13 +373,16 @@ public function testTransferCoverage(){
}
/**
- * @covers \Razorpay\Api\Token::all
- * @covers \Razorpay\Api\Token::fetch
+ * @covers \Razorpay\Api\Utility::verifyPaymentSignature
+ * @covers \Razorpay\Api\Utility::verifySignature
+ * @covers \Razorpay\Api\Utility::hashEquals
+ * @covers \Razorpay\Api\Errors\SignatureVerificationError
*/
- public function testTokenCoverage(){
- $transfer = new TokenTest();
- $transfer->setup();
- $transfer->testFetchTokenByCustomerId();
- $transfer->testFetchTokenByPaymentId();;
+ public function testUtilityCoverage(){
+ $utility = new SignatureVerificationTest();
+ $utility->setup();
+ $utility->testPaymentVerification();
+ $utility->testPaymentLinkVerification();
+ $utility->testSubscriptionVerification();
}
}
diff --git a/tests/CustomerTest.php b/tests/CustomerTest.php
index 63d72b8d..cc6269f7 100644
--- a/tests/CustomerTest.php
+++ b/tests/CustomerTest.php
@@ -51,6 +51,8 @@ public function testFetchAll()
$this->assertTrue(is_array($data->toArray()));
+ $this->assertTrue(is_numeric($data->count()));
+
$this->assertTrue(is_array($data['items']));
}
diff --git a/tests/PartnerTest.php b/tests/PartnerTest.php
new file mode 100644
index 00000000..505b460a
--- /dev/null
+++ b/tests/PartnerTest.php
@@ -0,0 +1,282 @@
+load();
+}
+
+
+class PartnerTest extends TestCase
+{
+ protected $instance;
+
+ protected static $account_id;
+
+ protected static $stakeholder_id;
+
+ protected static $product_id;
+
+ protected static $webhook_id;
+
+ public function setUp(): void
+ {
+ $apiKey = getenv("RAZORPAY_API_KEY") ? getenv("RAZORPAY_PARTNER_API_KEY") : "";
+ $apiSecret = getenv("RAZORPAY_API_SECRET") ? getenv("RAZORPAY_PARTNER_API_SECRET") : "";
+ $this->instance = new Api( $apiKey, $apiSecret);
+ }
+
+
+ public function testCreateAccount()
+ {
+ $account = $this->instance->account->create($this->accountAttributes());
+
+ self::$account_id = $account['id'];
+
+ $this->assertTrue(is_array($account->toArray()));
+ $this->assertTrue(is_array((array) $account['legal_info']));
+ }
+
+ public function testCreateStakerholder()
+ {
+ $stakeholder = $this->instance->account->fetch(self::$account_id)->stakeholders()->create($this->stakeholderAttributes());
+
+ $this->assertTrue(is_array($stakeholder->toArray()));
+
+ self::$stakeholder_id = $stakeholder['id'];
+
+ $this->assertTrue(is_array((array) $stakeholder['phone']));
+ }
+
+ public function testFetchStakerholder()
+ {
+ $stakeholder = $this->instance->account->fetch(self::$account_id)->stakeholders()->fetch(self::$stakeholder_id);
+
+ $this->assertTrue(is_array($stakeholder->toArray()));
+
+ $this->assertTrue(is_array((array) $stakeholder['phone']));
+ }
+
+ public function testFetchAllStakerholder()
+ {
+ $stakeholder = $this->instance->account->fetch(self::$account_id)->stakeholders()->all();
+
+ $this->assertTrue(is_array($stakeholder->toArray()));
+
+ $this->assertTrue(is_array((array) $stakeholder['items']));
+ }
+
+ public function testEditStakerholder()
+ {
+ $stakeholder = $this->instance->account->fetch(self::$account_id)->stakeholders()->edit(self::$stakeholder_id, $this->stakeholderAttributes());
+
+ $this->assertTrue(is_array($stakeholder->toArray()));
+
+ $this->assertTrue(is_array((array) $stakeholder['phone']));
+ }
+
+ public function testProductConfiguration(){
+ $product = $this->instance->account->fetch(self::$account_id)->products()->requestProductConfiguration([
+ "product_name" => "payment_gateway",
+ "tnc_accepted" => true,
+ "ip" => "233.233.233.234"
+ ]);
+ self::$product_id = $product['id'];
+ $this->assertTrue(is_array($product->toArray()));
+ $this->assertTrue(is_array((array) $product['requirements']));
+ }
+
+ public function testProductFetch(){
+ $product = $this->instance->account->fetch(self::$account_id)->products()->fetch(self::$product_id);
+ $this->assertTrue(is_array($product->toArray()));
+ $this->assertTrue(is_array((array) $product['requirements']));
+ }
+
+ public function testProductEdit(){
+ $product = $this->instance->account->fetch(self::$account_id)->products()->edit(self::$product_id,[
+ "tnc_accepted" => true,
+ "ip" => "233.233.233.224"
+ ]);
+
+ $this->assertTrue(is_array($product->toArray()));
+ }
+
+ public function testFetchTnc()
+ {
+ $webhook = $this->instance->product->fetchTnc("payments");
+
+ $this->assertTrue(is_array($webhook->toArray()));
+ }
+
+ public function testWebhookCreate()
+ {
+ $webhook = $this->instance->account->fetch(self::$account_id)->webhooks()->create($this->webhookAttributes());
+ self::$webhook_id = $webhook['id'];
+
+ $this->assertTrue(is_array($webhook->toArray()));
+
+ $this->assertTrue(is_array((array) $webhook['id']));
+ }
+
+ public function testWebhookFetch()
+ {
+ $webhook = $this->instance->account->fetch(self::$account_id)->webhooks()->fetch(self::$webhook_id);
+
+ $this->assertTrue(is_array($webhook->toArray()));
+
+ $this->assertTrue(is_array((array) $webhook['id']));
+ }
+
+ public function testFetchAllWebhook()
+ {
+ $webhook = $this->instance->account->fetch(self::$account_id)->webhooks()->all();
+
+ $this->assertTrue(is_array($webhook->toArray()));
+
+ $this->assertTrue(is_array((array) $webhook['items']));
+ }
+
+ public function testEditWebhook()
+ {
+ $webhook = $this->instance->account->fetch(self::$account_id)->webhooks()->edit([
+ "url" => "https://www.linkedin.com",
+ "events" => ["refund.created"],
+ ],self::$webhook_id);
+
+ $this->assertTrue(is_array($webhook->toArray()));
+
+ $this->assertTrue(is_array((array) $webhook['events']));
+ }
+
+ public function testDeleteWebhook()
+ {
+ $webhook = $this->instance->account->fetch(self::$account_id)->webhooks()->delete(self::$webhook_id);
+
+ $this->assertTrue(is_array($webhook->toArray()));
+ }
+
+ public function testDeleteAccount()
+ {
+ $account = $this->instance->account->fetch(self::$account_id)->delete();
+
+ $this->assertTrue(is_array($account->toArray()));
+
+ $this->assertTrue(is_array((array) $account['legal_info']));
+ }
+
+ public function testFetchAccount()
+ {
+ $account = $this->instance->account->fetch(self::$account_id);
+
+ $this->assertTrue(is_array($account->toArray()));
+
+ $this->assertTrue(is_array((array) $account['legal_info']));
+ }
+
+ public function testEditAccount()
+ {
+ $request = ["customer_facing_business_name" => "Ltd"];
+
+ $account = $this->instance->account->fetch(self::$account_id)->edit($request);
+
+ $this->assertTrue(is_array($account->toArray()));
+
+ $this->assertTrue(is_array((array) $account['legal_info']));
+ }
+
+ public function accountAttributes(){
+ return $arrayVar = [
+ "email" => "gauriagain".time()."@example.org",
+ "phone" => "9000090000",
+ "legal_business_name" => "Acme Corp",
+ "business_type" => "partnership",
+ "customer_facing_business_name" => "Example",
+ "profile" => [
+ "category" => "healthcare",
+ "subcategory" => "clinic",
+ "description" => "Healthcare E-commerce platform",
+ "addresses" => [
+ "operation" => [
+ "street1" => "507, Koramangala 6th block",
+ "street2" => "Kormanagala",
+ "city" => "Bengaluru",
+ "state" => "Karnataka",
+ "postal_code" => 560047,
+ "country" => "IN",
+ ],
+ "registered" => [
+ "street1" => "507, Koramangala 1st block",
+ "street2" => "MG Road",
+ "city" => "Bengaluru",
+ "state" => "Karnataka",
+ "postal_code" => 560034,
+ "country" => "IN",
+ ],
+ ],
+ "business_model" =>
+ "Online Clothing ( men, women, ethnic, modern ) fashion and lifestyle, accessories, t-shirt, shirt, track pant, shoes.",
+ ],
+ "legal_info" => ["pan" => "AAACL1234C", "gst" => "18AABCU9603R1ZM"],
+ "brand" => ["color" => "FFFFFF"],
+ "notes" => ["internal_ref_id" => "123123"],
+ "contact_name" => "Gaurav Kumar",
+ "contact_info" => [
+ "chargeback" => ["email" => "cb@example.org"],
+ "refund" => ["email" => "cb@example.org"],
+ "support" => [
+ "email" => "support@example.org",
+ "phone" => "9999999998",
+ "policy_url" => "https://www.google.com",
+ ],
+ ],
+ "apps" => [
+ "websites" => ["https://www.example.org"],
+ "android" => [["url" => "playstore.example.org", "name" => "Example"]],
+ "ios" => [["url" => "appstore.example.org", "name" => "Example"]],
+ ],
+ ];
+ }
+
+ public function stakeholderAttributes(){
+ return $arrayVar = [
+ "percentage_ownership" => 10,
+ "name" => "Gaurav Kumar",
+ "email" => "gaurav". time() .".kumar@example.com",
+ "relationship" => ["director" => true, "executive" => false],
+ "phone" => ["primary" => "7474747474", "secondary" => "7474747474"],
+ "addresses" => [
+ "residential" => [
+ "street" => "506, Koramangala 1st block",
+ "city" => "Bengaluru",
+ "state" => "Karnataka",
+ "postal_code" => "560034",
+ "country" => "IN",
+ ],
+ ],
+ "kyc" => ["pan" => "AVOPB1111K"],
+ "notes" => ["random_key_by_partner" => "random_value"],
+ ];
+ }
+
+ public function webhookAttributes(){
+ return $arrayVar = [
+ "url" => "https://google.com",
+ "alert_email" => "gaurav.kumar@example.com",
+ "secret" => "12345",
+ "events" => [
+ "payment.authorized",
+ "payment.failed",
+ "payment.captured",
+ "payment.dispute.created",
+ "refund.failed",
+ "refund.created",
+ ],
+ ];
+ }
+}
diff --git a/tests/PlanTest.php b/tests/PlanTest.php
index b0b1c8a1..00f9d9db 100644
--- a/tests/PlanTest.php
+++ b/tests/PlanTest.php
@@ -32,6 +32,7 @@ public function testCreatePlan()
/**
* Fetch all plans
+ * @covers \Razorpay\Api\Collection::count
*/
public function testFetchAllPlans()
{
@@ -39,6 +40,8 @@ public function testFetchAllPlans()
$this->assertTrue(is_array($data->toArray()));
+ $this->assertTrue($data->count() >= 0);
+
$this->assertTrue(is_array($data['items']));
}
diff --git a/tests/RequestTest.php b/tests/RequestTest.php
new file mode 100644
index 00000000..1bb79590
--- /dev/null
+++ b/tests/RequestTest.php
@@ -0,0 +1,64 @@
+api->customer->create(array('name' => 'Razorpay User 38', 'email' => 'customer38@razorpay.com' ,'fail_existing'=>'0'));
+
+ $this->assertTrue(is_array($data->toArray()));
+
+ $this->assertTrue(in_array('customer',$data->toArray()));
+ }
+
+ /**
+ * Edit customer
+ */
+ public function testEditCustomer()
+ {
+ $data = $this->api->customer->fetch($this->customerId)->edit(array('name' => 'Razorpay User 21' ,'contact'=>'9123456780'));
+
+ $this->assertTrue(is_array($data->toArray()));
+
+ $this->assertTrue(in_array($this->customerId, $data->toArray()));
+ }
+
+ /**
+ * Fetch customer All
+ */
+ public function testFetchAll()
+ {
+ $data = $this->api->customer->all();
+
+ $this->assertTrue(is_array($data->toArray()));
+
+ $this->assertTrue(is_numeric($data->count()));
+
+ $this->assertTrue(is_array($data['items']));
+ }
+
+ /**
+ * Fetch a customer
+ */
+ public function testFetchCustomer()
+ {
+ $data = $this->api->customer->fetch($this->customerId);
+
+ $this->assertTrue(is_array($data->toArray()));
+
+ $this->assertTrue(in_array($this->customerId, $data->toArray()));
+ }
+}
\ No newline at end of file
diff --git a/tests/SignatureVerificationTest.php b/tests/SignatureVerificationTest.php
index 5a3e86f0..1037676a 100644
--- a/tests/SignatureVerificationTest.php
+++ b/tests/SignatureVerificationTest.php
@@ -20,9 +20,9 @@ public function testPaymentVerification()
{
$orderId = 'order_IEIaMR65cu6nz3';
$paymentId = 'pay_IH4NVgf4Dreq1l';
- $signature = '0d4e745a1838664ad6c9c9902212a32d627d68e917290b0ad5f08ff4561bc50f';
+ $signature = '97f18ee6577a33ca7c37b949912de807b379afb3f39ccb571ffd76017463f8e5';
- $this->assertTrue(true,$this->api->utility->verifyPaymentSignature(array(
+ $this->assertNull($this->api->utility->verifyPaymentSignature(array(
'razorpay_order_id' => $orderId,
'razorpay_payment_id' => $paymentId,
'razorpay_signature' => $signature
@@ -38,9 +38,9 @@ public function testPaymentLinkVerification()
$paymentId = 'pay_IH3d0ara9bSsjQ';
$paymentLinkReferenceId = 'TSsd1989';
$paymentLinkStatus = 'paid';
- $signature = '07ae18789e35093e51d0a491eb9922646f3f82773547e5b0f67ee3f2d3bf7d5b';
+ $signature = '57bab821bfe7ebcf41b32e362d16aa23d408b76c36317f960ae99a9301e4d364';
- $this->assertTrue(true,$this->api->utility->verifyPaymentSignature(array(
+ $this->assertNull($this->api->utility->verifyPaymentSignature(array(
'razorpay_payment_link_id' => $paymentLinkId,
'razorpay_payment_link_reference_id' => $paymentLinkReferenceId,
'razorpay_payment_link_status' => $paymentLinkStatus,
@@ -56,9 +56,9 @@ public function testSubscriptionVerification()
{
$subscriptionId = 'sub_ID6MOhgkcoHj9I';
$paymentId = 'pay_IDZNwZZFtnjyym';
- $signature = '601f383334975c714c91a7d97dd723eb56520318355863dcf3821c0d07a17693';
+ $signature = 'cbbaabf163d61fc9346b794b5f906bc2f6b0d944be71bc0e6b5c35fa21eade44';
- $this->assertTrue(true,$this->api->utility->verifyPaymentSignature(array(
+ $this->assertNull($this->api->utility->verifyPaymentSignature(array(
'razorpay_subscription_id' => $subscriptionId,
'razorpay_payment_id' => $paymentId,
'razorpay_signature' => $signature
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 8f4426c3..2bcf0a6e 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -24,4 +24,4 @@ public function setUp(): void
$this->api = new Api( $apiKey, $apiSecret);
}
-}
\ No newline at end of file
+}
diff --git a/tests/TokenTest.php b/tests/TokenTest.php
index 38340f36..a82a36bc 100644
--- a/tests/TokenTest.php
+++ b/tests/TokenTest.php
@@ -18,6 +18,8 @@ class TokenTest extends TestCase
private $tokenId = "token_IEcux6sQtS8eLx";
+ protected static $partnerTokenId ;
+
public function setUp(): void
{
parent::setUp();
@@ -59,4 +61,57 @@ public function testFetchTokenByCustomerId()
$this->assertTrue(in_array('payment',$data->toArray()));
}
+ public function testCreateToken()
+ {
+ $data = $this->api->token->create($this->requestAttribute($this->customerId));
+
+ self::$partnerTokenId = $data['id'];
+
+ $this->assertTrue(is_array($data->toArray()));
+
+ $this->assertTrue(in_array('card',$data->toArray()));
+ }
+
+ public function testFetchToken()
+ {
+ $data = $this->api->token->fetchCardPropertiesByToken(['id'=>self::$partnerTokenId]);
+
+ $this->assertTrue(is_array($data->toArray()));
+
+ $this->assertTrue(in_array('card',$data->toArray()));
+ }
+
+ public function testProcessPaymentOnAlternatePAorPG()
+ {
+ $data = $this->api->token->processPaymentOnAlternatePAorPG(['id'=>self::$partnerTokenId]);
+
+ $this->assertTrue(is_array($data->toArray()));
+ }
+
+ public function testDeleteToken()
+ {
+ $data = $this->api->token->deleteToken(['id'=>self::$partnerTokenId]);
+
+ $this->assertTrue(is_array($data->toArray()));
+ }
+
+ public function requestAttribute($customerId){
+ return [
+ "customer_id" => $customerId,
+ "method" => "card",
+ "card" => [
+ "number" => "4854980604708430",
+ "cvv" => "123",
+ "expiry_month" => "12",
+ "expiry_year" => "24",
+ "name" => "Gaurav Kumar",
+ ],
+ "authentication" => [
+ "provider" => "razorpay",
+ "provider_reference_id" => "pay_123wkejnsakd"
+ ],
+ "notes" => [],
+ ];
+ }
+
}
\ No newline at end of file