|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This is a Ruby gem that provides a client library for the Midtrans Payment Gateway API. The gem wraps various Midtrans API endpoints (payment transactions, virtual accounts, disbursements, merchant management, etc.) with a clean Ruby interface. |
| 8 | + |
| 9 | +## Development Commands |
| 10 | + |
| 11 | +### Running Tests |
| 12 | +```bash |
| 13 | +rake spec # Run all tests |
| 14 | +bundle exec rspec spec/path/to/file_spec.rb # Run specific test file |
| 15 | +bundle exec rspec spec/path/to/file_spec.rb:LINE # Run specific test at line |
| 16 | +``` |
| 17 | + |
| 18 | +### Interactive Console |
| 19 | +```bash |
| 20 | +bin/console # IRB console with the gem loaded |
| 21 | +``` |
| 22 | + |
| 23 | +### Build and Install |
| 24 | +```bash |
| 25 | +bundle exec rake install # Install gem locally |
| 26 | +bundle exec rake release # Release new version (tags, pushes to rubygems) |
| 27 | +``` |
| 28 | + |
| 29 | +## Architecture |
| 30 | + |
| 31 | +### Client Architecture |
| 32 | +The gem follows a layered architecture pattern: |
| 33 | + |
| 34 | +1. **Client Layer** (`lib/midtrans_api/client.rb`) |
| 35 | + - Main entry point that users interact with |
| 36 | + - Manages Faraday HTTP connection with Basic Auth |
| 37 | + - Provides convenience methods that return API instances (e.g., `client.gopay_charge`, `client.merchant`) |
| 38 | + - Supports three API environments via configuration: production, sandbox, and partner API |
| 39 | + - HTTP methods: `get()`, `post()`, `patch()` |
| 40 | + |
| 41 | +2. **API Layer** (`lib/midtrans_api/api/*`) |
| 42 | + - Each API endpoint has its own class that inherits from `MidtransApi::Api::Base` |
| 43 | + - Organized by feature domain (e.g., `Merchant::Create`, `Gopay::Charge`, `Transaction::Expire`) |
| 44 | + - API classes define the endpoint `PATH` constant and HTTP method (e.g., `post()`, `patch()`) |
| 45 | + - Responsible for making HTTP requests via the client and returning Model instances |
| 46 | + |
| 47 | +3. **Model Layer** (`lib/midtrans_api/model/*`) |
| 48 | + - Each API response is mapped to a Model class that inherits from `MidtransApi::Model::Base` |
| 49 | + - Models use `resource_attributes` macro to define accessible response fields |
| 50 | + - Base class handles initialization from API response hash via `assign_attributes` |
| 51 | + - Models implement `resolve_params_attr()` for key transformation (typically identity transform) |
| 52 | + |
| 53 | +4. **Configuration** (`lib/midtrans_api/configure.rb`) |
| 54 | + - Manages API credentials (client_key, server_key) |
| 55 | + - Environment selection (sandbox vs production vs partner API) |
| 56 | + - Optional features: notification URL override, logging, timeout settings |
| 57 | + |
| 58 | +### Adding New API Endpoints |
| 59 | + |
| 60 | +To add a new Midtrans API endpoint: |
| 61 | + |
| 62 | +1. **Create API class** at `lib/midtrans_api/api/{domain}/{action}.rb`: |
| 63 | + ```ruby |
| 64 | + class MyApi < MidtransApi::Api::Base |
| 65 | + PATH = 'endpoint/path' |
| 66 | + |
| 67 | + def post(params, additional_headers_params) |
| 68 | + response = client.post(PATH, params, { |
| 69 | + 'X-CUSTOM-HEADER': additional_headers_params |
| 70 | + }) |
| 71 | + MidtransApi::Model::Domain::MyApi.new(response) |
| 72 | + end |
| 73 | + end |
| 74 | + ``` |
| 75 | + |
| 76 | +2. **Create Model class** at `lib/midtrans_api/model/{domain}/{action}.rb`: |
| 77 | + ```ruby |
| 78 | + class MyApi < MidtransApi::Model::Base |
| 79 | + resource_attributes :field1, :field2, :field3 |
| 80 | + |
| 81 | + def resolve_params_attr(attr) |
| 82 | + attr.to_s # or custom transformation |
| 83 | + end |
| 84 | + end |
| 85 | + ``` |
| 86 | + |
| 87 | +3. **Register in Client** (`lib/midtrans_api/client.rb`): |
| 88 | + - Add `require` statements at the top for both API and Model files |
| 89 | + - Add convenience method to instantiate the API class: |
| 90 | + ```ruby |
| 91 | + def my_api |
| 92 | + @my_api ||= MidtransApi::Api::Domain::MyApi.new(self) |
| 93 | + end |
| 94 | + ``` |
| 95 | + - If using new HTTP verb, add method (e.g., `put()`, `delete()`) |
| 96 | + |
| 97 | +4. **Create test file** at `spec/lib/midtrans_api/api/{domain}/{action}_spec.rb`: |
| 98 | + - Use WebMock to stub HTTP requests |
| 99 | + - Test that correct model instance is returned |
| 100 | + - Test that proper headers are sent |
| 101 | + - Follow pattern from existing specs (e.g., `merchant/create_spec.rb`) |
| 102 | + |
| 103 | +### Error Handling |
| 104 | +- Custom errors defined in `lib/midtrans_api/errors.rb` |
| 105 | +- Middleware `HandleResponseException` intercepts HTTP errors and raises appropriate exceptions |
| 106 | +- See Midtrans API documentation for status codes |
| 107 | + |
| 108 | +### Logging and Security |
| 109 | +- Uses Faraday middleware for logging |
| 110 | +- `FaradayLogFormatter` provides custom log formatting |
| 111 | +- `JsonMasker` and `UrlMasker` utilities mask sensitive data in logs |
| 112 | +- Configure via `filtered_logs` and `mask_params` client options |
0 commit comments