jamm 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jamm-0.1.0/LICENSE +21 -0
- jamm-0.1.0/MANIFEST.in +11 -0
- jamm-0.1.0/PKG-INFO +394 -0
- jamm-0.1.0/README.md +352 -0
- jamm-0.1.0/jamm/__init__.py +83 -0
- jamm-0.1.0/jamm/api/__init__.py +15 -0
- jamm-0.1.0/jamm/api/bank_api.py +179 -0
- jamm-0.1.0/jamm/api/client.py +656 -0
- jamm-0.1.0/jamm/api/customer_api.py +104 -0
- jamm-0.1.0/jamm/api/healthcheck_api.py +19 -0
- jamm-0.1.0/jamm/api/payment_api.py +189 -0
- jamm-0.1.0/jamm/api/validation.py +232 -0
- jamm-0.1.0/jamm/auth/__init__.py +0 -0
- jamm-0.1.0/jamm/auth/oauth.py +66 -0
- jamm-0.1.0/jamm/bank.py +167 -0
- jamm-0.1.0/jamm/charge.py +168 -0
- jamm-0.1.0/jamm/client.py +122 -0
- jamm-0.1.0/jamm/config/__init__.py +0 -0
- jamm-0.1.0/jamm/config/settings.py +31 -0
- jamm-0.1.0/jamm/contract.py +106 -0
- jamm-0.1.0/jamm/customer.py +213 -0
- jamm-0.1.0/jamm/environment/__init__.py +0 -0
- jamm-0.1.0/jamm/environment/env.py +49 -0
- jamm-0.1.0/jamm/errors.py +37 -0
- jamm-0.1.0/jamm/healthcheck.py +54 -0
- jamm-0.1.0/jamm/http/__init__.py +0 -0
- jamm-0.1.0/jamm/http/client.py +48 -0
- jamm-0.1.0/jamm/import_hook.py +42 -0
- jamm-0.1.0/jamm/models/__init__.py +162 -0
- jamm-0.1.0/jamm/models/banking.py +47 -0
- jamm-0.1.0/jamm/models/common.py +51 -0
- jamm-0.1.0/jamm/models/customer.py +26 -0
- jamm-0.1.0/jamm/models/healthcheck.py +10 -0
- jamm-0.1.0/jamm/models/payment.py +80 -0
- jamm-0.1.0/jamm/payment.py +145 -0
- jamm-0.1.0/jamm/version.py +1 -0
- jamm-0.1.0/jamm/webhook.py +192 -0
- jamm-0.1.0/jamm.egg-info/PKG-INFO +394 -0
- jamm-0.1.0/jamm.egg-info/SOURCES.txt +72 -0
- jamm-0.1.0/jamm.egg-info/dependency_links.txt +1 -0
- jamm-0.1.0/jamm.egg-info/requires.txt +16 -0
- jamm-0.1.0/jamm.egg-info/top_level.txt +1 -0
- jamm-0.1.0/lib/__init__.py +0 -0
- jamm-0.1.0/lib/proto/api/v1/bank_pb2.py +93 -0
- jamm-0.1.0/lib/proto/api/v1/bank_pb2.pyi +108 -0
- jamm-0.1.0/lib/proto/api/v1/bank_pb2_grpc.py +317 -0
- jamm-0.1.0/lib/proto/api/v1/common_pb2.py +127 -0
- jamm-0.1.0/lib/proto/api/v1/common_pb2.pyi +434 -0
- jamm-0.1.0/lib/proto/api/v1/common_pb2_grpc.py +3 -0
- jamm-0.1.0/lib/proto/api/v1/customer_pb2.py +139 -0
- jamm-0.1.0/lib/proto/api/v1/customer_pb2.pyi +137 -0
- jamm-0.1.0/lib/proto/api/v1/customer_pb2_grpc.py +285 -0
- jamm-0.1.0/lib/proto/api/v1/healthcheck_pb2.py +49 -0
- jamm-0.1.0/lib/proto/api/v1/healthcheck_pb2.pyi +17 -0
- jamm-0.1.0/lib/proto/api/v1/healthcheck_pb2_grpc.py +84 -0
- jamm-0.1.0/lib/proto/api/v1/merchant_webhooks_pb2.py +77 -0
- jamm-0.1.0/lib/proto/api/v1/merchant_webhooks_pb2.pyi +208 -0
- jamm-0.1.0/lib/proto/api/v1/merchant_webhooks_pb2_grpc.py +93 -0
- jamm-0.1.0/lib/proto/api/v1/openapi_pb2.py +38 -0
- jamm-0.1.0/lib/proto/api/v1/openapi_pb2.pyi +5 -0
- jamm-0.1.0/lib/proto/api/v1/openapi_pb2_grpc.py +3 -0
- jamm-0.1.0/lib/proto/api/v1/payment_pb2.py +268 -0
- jamm-0.1.0/lib/proto/api/v1/payment_pb2.pyi +465 -0
- jamm-0.1.0/lib/proto/api/v1/payment_pb2_grpc.py +549 -0
- jamm-0.1.0/lib/proto/buf/validate/validate_pb2.py +812 -0
- jamm-0.1.0/lib/proto/common/v1/webapp_pb2.py +111 -0
- jamm-0.1.0/lib/proto/common/v1/webapp_pb2.pyi +490 -0
- jamm-0.1.0/lib/proto/common/v1/webapp_pb2_grpc.py +3 -0
- jamm-0.1.0/lib/proto/error/v1/error_pb2.py +35 -0
- jamm-0.1.0/lib/proto/error/v1/error_pb2.pyi +47 -0
- jamm-0.1.0/lib/proto/error/v1/error_pb2_grpc.py +3 -0
- jamm-0.1.0/pyproject.toml +79 -0
- jamm-0.1.0/setup.cfg +4 -0
- jamm-0.1.0/setup.py +3 -0
jamm-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Jamm Pay
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
jamm-0.1.0/MANIFEST.in
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
include README.md
|
|
2
|
+
include LICENSE
|
|
3
|
+
include pyproject.toml
|
|
4
|
+
recursive-include jamm *.py
|
|
5
|
+
recursive-include jamm *.pyi
|
|
6
|
+
recursive-include lib *.py
|
|
7
|
+
recursive-include lib *.pyi
|
|
8
|
+
exclude tests/*
|
|
9
|
+
exclude test.e2e/*
|
|
10
|
+
exclude .gitignore
|
|
11
|
+
exclude Makefile
|
jamm-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jamm
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Jamm API Python SDK
|
|
5
|
+
Author: Jamm Team
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://jamm-pay.jp
|
|
8
|
+
Project-URL: Bug Tracker, https://jamm-pay.jp
|
|
9
|
+
Project-URL: Documentation, https://docs.jamm.pay/sdk/python
|
|
10
|
+
Project-URL: Source, https://jamm-pay.jp
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: grpcio>=1.73.0
|
|
25
|
+
Requires-Dist: protobuf>=6.31.1
|
|
26
|
+
Requires-Dist: pydantic>=2.11.7
|
|
27
|
+
Requires-Dist: requests>=2.32.4
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
31
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
32
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
33
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
35
|
+
Requires-Dist: types-protobuf>=5.29.0; extra == "dev"
|
|
36
|
+
Requires-Dist: types-requests>=2.32.0; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
39
|
+
Requires-Dist: Faker>=37.4.0; extra == "dev"
|
|
40
|
+
Requires-Dist: protoc-gen-openapiv2>=0.0.1; extra == "dev"
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
|
|
43
|
+
# Jamm SDK for Python
|
|
44
|
+
|
|
45
|
+
A Python client SDK for interacting with the Jamm API using Protocol Buffers over HTTP.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install -e .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
import jamm
|
|
57
|
+
|
|
58
|
+
# Basic configuration
|
|
59
|
+
client = jamm.configure(
|
|
60
|
+
client_id="your_client_id",
|
|
61
|
+
client_secret="your_client_secret",
|
|
62
|
+
env="develop" # or "staging", "production", etc.
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Make a healthcheck request
|
|
66
|
+
response = client.healthcheck()
|
|
67
|
+
print(response)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Configuration
|
|
71
|
+
|
|
72
|
+
The SDK can be configured using environment variables or programmatically:
|
|
73
|
+
|
|
74
|
+
### Programmatic Configuration
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from jamm import JammClient, ClientConfig
|
|
78
|
+
|
|
79
|
+
config = ClientConfig(
|
|
80
|
+
api_base_url="https://api.staging.jamm.com/v1",
|
|
81
|
+
client_id="your_client_id",
|
|
82
|
+
client_secret="your_client_secret"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
client = JammClient(config)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Features
|
|
89
|
+
|
|
90
|
+
The Jamm SDK provides comprehensive functionality for payment processing, customer management, and banking operations:
|
|
91
|
+
|
|
92
|
+
- **Health Check**: Verify API connectivity
|
|
93
|
+
- **Customer Management**: Create, update, get, and delete customers
|
|
94
|
+
- **Payment Processing**: On-session and off-session payments
|
|
95
|
+
- **Contract Management**: Create contracts with or without charges
|
|
96
|
+
- **Charge Operations**: Create charges with/without redirects, retrieve and list charges
|
|
97
|
+
- **Banking**: Search banks, get bank information, and manage bank branches
|
|
98
|
+
|
|
99
|
+
## API Reference
|
|
100
|
+
|
|
101
|
+
### Health Check
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
# Verify API connectivity
|
|
105
|
+
response = client.healthcheck()
|
|
106
|
+
print(response)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Customer Management
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
# Create a customer
|
|
113
|
+
from datetime import datetime, timedelta
|
|
114
|
+
|
|
115
|
+
buyer_data = {
|
|
116
|
+
"email": "customer@example.com",
|
|
117
|
+
"name": "John Doe",
|
|
118
|
+
"katakana_last_name": "ドウ",
|
|
119
|
+
"katakana_first_name": "ジョン",
|
|
120
|
+
"address": "123 Tokyo Street, Shibuya",
|
|
121
|
+
"birth_date": "1990-01-01",
|
|
122
|
+
"gender": "male",
|
|
123
|
+
"force_kyc": False,
|
|
124
|
+
"metadata": {"source": "api"}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
customer = client.customers.create(buyer=buyer_data)
|
|
128
|
+
print(f"Created customer: {customer['customer']['customer']['id']}")
|
|
129
|
+
|
|
130
|
+
# Get a customer
|
|
131
|
+
customer = client.customers.get("cus-customer_id_here")
|
|
132
|
+
|
|
133
|
+
# Update a customer
|
|
134
|
+
updated_customer = client.customers.update(
|
|
135
|
+
customer_id="cus-customer_id_here",
|
|
136
|
+
data={
|
|
137
|
+
"name": "Updated Name",
|
|
138
|
+
"metadata": {"updated": True}
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Get customer's contract
|
|
143
|
+
contract = client.customers.get_contract("cus-customer_id_here")
|
|
144
|
+
|
|
145
|
+
# Delete a customer
|
|
146
|
+
result = client.customers.delete("cus-customer_id_here")
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Payment Processing
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from datetime import datetime, timedelta
|
|
153
|
+
|
|
154
|
+
# Calculate expiration date
|
|
155
|
+
expires_at = (datetime.now() + timedelta(days=2)).isoformat() + "Z"
|
|
156
|
+
|
|
157
|
+
# Off-session payment (no user interaction required)
|
|
158
|
+
result = client.payments.off_session(
|
|
159
|
+
customer_id="cus-customer_id_here",
|
|
160
|
+
price="1000", # Amount in smallest currency unit (e.g., cents)
|
|
161
|
+
description="Monthly subscription",
|
|
162
|
+
expires_at=expires_at
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# On-session payment with redirect URLs
|
|
166
|
+
result = client.payments.on_session(
|
|
167
|
+
customer_id="cus-customer_id_here",
|
|
168
|
+
price="1000",
|
|
169
|
+
description="One-time payment",
|
|
170
|
+
redirect_urls={
|
|
171
|
+
"success_url": "https://yoursite.com/success",
|
|
172
|
+
"failure_url": "https://yoursite.com/cancel"
|
|
173
|
+
},
|
|
174
|
+
expires_at=expires_at
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Create contract without charge (setup only)
|
|
178
|
+
result = client.payments.on_session(
|
|
179
|
+
buyer=buyer_data,
|
|
180
|
+
redirect_urls={
|
|
181
|
+
"success_url": "https://yoursite.com/success",
|
|
182
|
+
"failure_url": "https://yoursite.com/cancel"
|
|
183
|
+
},
|
|
184
|
+
expires_at=expires_at
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# Create contract with initial charge
|
|
188
|
+
result = client.payments.on_session(
|
|
189
|
+
buyer=buyer_data,
|
|
190
|
+
charge={
|
|
191
|
+
"price": "1000",
|
|
192
|
+
"description": "Initial payment"
|
|
193
|
+
},
|
|
194
|
+
redirect_urls={
|
|
195
|
+
"success_url": "https://yoursite.com/success",
|
|
196
|
+
"failure_url": "https://yoursite.com/cancel"
|
|
197
|
+
},
|
|
198
|
+
expires_at=expires_at
|
|
199
|
+
)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Contract Management
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
# Create contract with charge
|
|
206
|
+
contract = client.contracts.create_with_charge(
|
|
207
|
+
buyer=buyer_data,
|
|
208
|
+
charge={
|
|
209
|
+
"price": 1000,
|
|
210
|
+
"description": "Setup fee",
|
|
211
|
+
"expires_at": expires_at
|
|
212
|
+
},
|
|
213
|
+
redirect={
|
|
214
|
+
"success_url": "https://yoursite.com/success",
|
|
215
|
+
"failure_url": "https://yoursite.com/cancel"
|
|
216
|
+
}
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
# Create contract without charge
|
|
220
|
+
contract = client.contracts.create_without_charge(
|
|
221
|
+
buyer=buyer_data,
|
|
222
|
+
redirect={
|
|
223
|
+
"success_url": "https://yoursite.com/success",
|
|
224
|
+
"failure_url": "https://yoursite.com/cancel"
|
|
225
|
+
}
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
# Get existing contract
|
|
229
|
+
contract = client.contracts.get("cus-customer_id_here")
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Charge Operations
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
# Create charge without redirect (direct processing)
|
|
236
|
+
charge = client.charges.create_without_redirect(
|
|
237
|
+
customer_id="cus-customer_id_here",
|
|
238
|
+
price=1500,
|
|
239
|
+
description="Product purchase",
|
|
240
|
+
expires_at=expires_at,
|
|
241
|
+
metadata={"order_id": "12345"}
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
# Create charge with redirect (user will be redirected to payment page)
|
|
245
|
+
charge = client.charges.create_with_redirect(
|
|
246
|
+
customer_id="cus-customer_id_here",
|
|
247
|
+
price=2000,
|
|
248
|
+
success_url="https://yoursite.com/success",
|
|
249
|
+
failure_url="https://yoursite.com/failure",
|
|
250
|
+
description="Premium service",
|
|
251
|
+
expires_at=expires_at,
|
|
252
|
+
metadata={"service": "premium"}
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
# Get specific charge
|
|
256
|
+
charge = client.charges.get("trx-charge_id_here")
|
|
257
|
+
|
|
258
|
+
# List charges for a customer
|
|
259
|
+
charges = client.charges.list(
|
|
260
|
+
customer_id="cus-customer_id_here",
|
|
261
|
+
page_size=10
|
|
262
|
+
)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Banking Operations
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
# Get specific bank information
|
|
269
|
+
bank = client.banks.get("0001") # Bank code
|
|
270
|
+
|
|
271
|
+
# Get major banks
|
|
272
|
+
major_banks = client.banks.get_major_banks()
|
|
273
|
+
for bank_key, bank_info in major_banks.items():
|
|
274
|
+
print(f"{bank_info['name']} - Code: {bank_info['code']}")
|
|
275
|
+
|
|
276
|
+
# Search banks
|
|
277
|
+
search_results = client.banks.search("みずほ") # Search for Mizuho Bank
|
|
278
|
+
for bank in search_results.get("banks", []):
|
|
279
|
+
print(f"{bank['name']} - Code: {bank['code']}")
|
|
280
|
+
|
|
281
|
+
# Get specific bank branch
|
|
282
|
+
branch = client.bank_branches.get("0001", "001") # Bank code, branch code
|
|
283
|
+
|
|
284
|
+
# Search branches within a bank
|
|
285
|
+
branches = client.bank_branches.search("0001", "東京") # Bank code, search term
|
|
286
|
+
for branch in branches[:5]: # First 5 results
|
|
287
|
+
print(f"{branch['name']} - Branch Code: {branch['branchCode']}")
|
|
288
|
+
|
|
289
|
+
# List all branches for a bank
|
|
290
|
+
all_branches = client.bank_branches.list_for_bank("0001")
|
|
291
|
+
print(f"Total branches: {len(all_branches)}")
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Authentication
|
|
295
|
+
|
|
296
|
+
The SDK automatically handles OAuth 2.0 authentication flows using your client credentials.
|
|
297
|
+
|
|
298
|
+
## Development
|
|
299
|
+
|
|
300
|
+
### Setup Development Environment
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
# Clone the repository
|
|
304
|
+
cd jamm-sdk
|
|
305
|
+
|
|
306
|
+
# Create virtual environment
|
|
307
|
+
python -m venv venv
|
|
308
|
+
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
309
|
+
|
|
310
|
+
# Install dependencies
|
|
311
|
+
pip install -e .
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Running Tests
|
|
315
|
+
|
|
316
|
+
You can run the comprehensive test suite that covers all SDK functionality:
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
# Run the test script with your credentials
|
|
320
|
+
python tests/test_sdk.py --client-id your_client_id --client-secret your_client_secret --env develop
|
|
321
|
+
|
|
322
|
+
# The test script will verify:
|
|
323
|
+
# - Health check functionality
|
|
324
|
+
# - Customer CRUD operations
|
|
325
|
+
# - Payment processing (on-session and off-session)
|
|
326
|
+
# - Contract management
|
|
327
|
+
# - Charge operations
|
|
328
|
+
# - Banking and branch operations
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
The test script includes realistic examples of:
|
|
332
|
+
- Creating customers with Japanese names and addresses
|
|
333
|
+
- Processing payments with proper expiration dates
|
|
334
|
+
- Managing contracts and charges
|
|
335
|
+
- Banking operations with Japanese bank codes
|
|
336
|
+
- Error handling and debugging information
|
|
337
|
+
|
|
338
|
+
### Example Test Output
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
✅ Successfully retrieved response: {...}
|
|
342
|
+
✅ Successfully created customer: {...}
|
|
343
|
+
✅ Successfully created off session: {...}
|
|
344
|
+
✅ Successfully created charge with redirect: {...}
|
|
345
|
+
✅ Successfully retrieved major banks: {...}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## Helper Functions
|
|
349
|
+
|
|
350
|
+
### Generating Test Data
|
|
351
|
+
|
|
352
|
+
The SDK test suite includes a helpful `generate_buyer()` function for creating realistic customer data:
|
|
353
|
+
|
|
354
|
+
```python
|
|
355
|
+
from faker import Faker
|
|
356
|
+
import time
|
|
357
|
+
|
|
358
|
+
def generate_buyer(base_email=None, name=None, force_kyc=False):
|
|
359
|
+
"""Generate realistic buyer data for testing"""
|
|
360
|
+
fake_en = Faker("en_US")
|
|
361
|
+
fake_jp = Faker("ja_JP")
|
|
362
|
+
timestamp = int(time.time())
|
|
363
|
+
|
|
364
|
+
return {
|
|
365
|
+
"email": f"{fake_en.user_name()}+{timestamp}@jamm-pay.jp",
|
|
366
|
+
"name": name or fake_en.name(),
|
|
367
|
+
"katakana_last_name": fake_jp.last_kana_name(),
|
|
368
|
+
"katakana_first_name": fake_jp.first_kana_name(),
|
|
369
|
+
"address": fake_jp.address(),
|
|
370
|
+
"birth_date": fake_en.date_of_birth(minimum_age=20, maximum_age=70).strftime("%Y-%m-%d"),
|
|
371
|
+
"gender": fake_en.random_element(["male", "female"]),
|
|
372
|
+
"force_kyc": force_kyc,
|
|
373
|
+
"metadata": {"source": "faker_generated", "timestamp": str(timestamp)}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
# Usage
|
|
377
|
+
buyer_data = generate_buyer()
|
|
378
|
+
customer = client.customers.create(buyer=buyer_data)
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## Error Handling
|
|
382
|
+
|
|
383
|
+
The SDK provides detailed error information for debugging:
|
|
384
|
+
|
|
385
|
+
```python
|
|
386
|
+
try:
|
|
387
|
+
customer = client.customers.get("invalid-id")
|
|
388
|
+
except Exception as e:
|
|
389
|
+
print(f"Error: {e}")
|
|
390
|
+
# Check authentication headers if needed
|
|
391
|
+
if hasattr(client.customers, "_get_auth_headers"):
|
|
392
|
+
headers = client.customers._get_auth_headers()
|
|
393
|
+
print(f"Auth headers: {headers}")
|
|
394
|
+
```
|