Skip to content

Commit f57a539

Browse files
committed
Align SDK with noebs and release v26.3.0
1 parent 8bc87d6 commit f57a539

15 files changed

Lines changed: 527 additions & 124 deletions

File tree

.github/workflows/gradle.yml

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ name: Java CI with Gradle
1010
on:
1111
push:
1212
branches: [ "master" ]
13+
tags: [ "v*" ]
1314
pull_request:
1415
branches: [ "master" ]
1516

@@ -34,17 +35,11 @@ jobs:
3435
with:
3536
arguments: build -x test
3637

37-
- name: Set short git commit SHA
38-
id: vars
39-
run: echo "short_sha=$(git rev-parse --short ${{ github.sha }})" >> "$GITHUB_OUTPUT"
40-
41-
42-
# The USERNAME and TOKEN need to correspond to the credentials environment variables used in
43-
# the publishing section of your build.gradle
4438
- name: Publish to GitHub Packages
39+
if: startsWith(github.ref, 'refs/tags/v')
4540
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
4641
with:
47-
arguments: publish -Pversion=${{ steps.vars.outputs.short_sha }}
42+
arguments: publish
4843
env:
4944
USERNAME: ${{ github.actor }}
5045
TOKEN: ${{ secrets.GITHUB_TOKEN }}

README.md

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,12 @@ import com.tuti.api.TutiApiClient
112112
import com.tuti.api.wallet.v1.EnsureWalletRequest
113113
114114
val client = TutiApiClient(noebsServer = "http://localhost:8000/")
115-
client.authToken = "Bearer <jwt>" // if your deployment requires auth
115+
client.authToken = "Bearer <jwt>" // required for /wallet routes on current noebs
116+
client.defaultHeaders = mapOf(
117+
// Optional: needed when your deployment relies on extra headers such as tenant or admin key.
118+
"X-Tenant-ID" to "tenant_1",
119+
// "X-Admin-Key" to "<admin-key>",
120+
)
116121
117122
client.wallet.ensureWallet(
118123
EnsureWalletRequest(
@@ -145,27 +150,30 @@ val ws = client.openChatSocket(object : WebSocketListener() {
145150
```
146151
147152
# Deployment notes
148-
149-
We will still be sticking to jitpack, at least for the public builds. However, we are using github package (using gradle repository).
150-
151-
## noebs sdk versioning
152-
153-
We are using CalVer, it is very convenient as it shows actual progress against time. Seems more concrete than say semver. Jitpack relies on git tags, so the easiest way is to always tag your commits following CalVer semantics (vYY.MM.versionNumber)
154-
155-
## how to deploy noebs to Github Packages
156-
157-
- Update the version number manually in `gradle.properties` version to reflect the new CalVer changes
158-
- In `lib/build.gradle`, update the username and password with the appropriate Github issues keys (note the password is a a personal access token, and not your password)
159-
160-
```groovy
161-
repositories {
162-
maven {
163-
name = "GitHubPackages"
164-
url = uri("https://maven.pkg.github.com/tutipay/java-sdk")
165-
credentials {
166-
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
167-
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
168-
}
153+
154+
Public tagged releases are exposed through JitPack, and the same tagged version is published to GitHub Packages by GitHub Actions.
155+
156+
## noebs sdk versioning
157+
158+
We are using CalVer (`YY.MM.patch`). JitPack relies on git tags, so releases should be tagged as `vYY.MM.patch`.
159+
160+
## how to deploy noebs to Github Packages
161+
162+
- Update `gradle.properties` to the next CalVer release.
163+
- Run `./gradlew test`.
164+
- Commit the release, tag it as `v<version>`, and push `master` plus the tag.
165+
- GitHub Actions publishes `noebs:lib:<version>` to GitHub Packages when the tag is pushed.
166+
- For local manual publishing, use your GitHub username plus a personal access token with package write access.
167+
168+
```groovy
169+
repositories {
170+
maven {
171+
name = "GitHubPackages"
172+
url = uri("https://maven.pkg.github.com/noebs/sdk")
173+
credentials {
174+
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
175+
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
176+
}
169177
}
170178
}
171179
```
@@ -176,13 +184,13 @@ repositories {
176184
177185
- Update your `build.gradle` files to include github package
178186
179-
```groovy
180-
maven {
181-
url = uri("https://maven.pkg.github.com/tutipay/java-sdk")
182-
credentials {
183-
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
184-
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
185-
}
186-
}
187-
```
188-
- add to your app's gradle file the implementation, which is `implementation 'noebs:lib:-latest-version'`
187+
```groovy
188+
maven {
189+
url = uri("https://maven.pkg.github.com/noebs/sdk")
190+
credentials {
191+
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
192+
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
193+
}
194+
}
195+
```
196+
- add to your app's gradle file the implementation, which is `implementation 'noebs:lib:<version>'`

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
group=noebs
2-
version=26.2.1
2+
version=26.3.0

lib/src/main/java/com/tuti/api/TutiApiClient.kt

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class TutiApiClient(
6666

6767
var isSingleThreaded = false
6868
@Volatile var authToken: String = ""
69+
@Volatile var defaultHeaders: Map<String, String> = emptyMap()
6970
var ipinUsername: String = ""
7071
var ipinPassword: String = ""
7172
var ebsKey: String = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANx4gKYSMv3CrWWsxdPfxDxFvl+Is/0kc1dvMI1yNWDXI3AgdI4127KMUOv7gmwZ6SnRsHX/KAM0IPRe0+Sa0vMCAwEAAQ=="
@@ -102,6 +103,22 @@ class TutiApiClient(
102103
return request
103104
}
104105

106+
private fun normalizeLegacyAuthRequest(
107+
credentials: SignInRequest?,
108+
): com.tuti.model.SignInRequest? {
109+
if (credentials == null) {
110+
return null
111+
}
112+
return com.tuti.model.SignInRequest(
113+
password = credentials.password,
114+
otp = credentials.otp,
115+
mobile = credentials.mobile.ifBlank { credentials.username },
116+
auth = credentials.oldToken,
117+
signature = credentials.signature,
118+
message = credentials.message,
119+
)
120+
}
121+
105122
@Deprecated(
106123
message = "Replace with SignIn with new kotlin classes instead.",
107124
replaceWith = ReplaceWith("SignIn")
@@ -114,7 +131,7 @@ class TutiApiClient(
114131
sendRequest(
115132
RequestMethods.POST,
116133
consumerURL + Operations.SIGN_IN,
117-
credentials,
134+
normalizeLegacyAuthRequest(credentials),
118135
onResponse,
119136
onError
120137
)
@@ -309,7 +326,7 @@ class TutiApiClient(
309326
sendRequest(
310327
RequestMethods.POST,
311328
consumerURL + Operations.SINGLE_SIGN_IN,
312-
credentials,
329+
normalizeLegacyAuthRequest(credentials),
313330
onResponse,
314331
onError
315332
)
@@ -355,7 +372,7 @@ class TutiApiClient(
355372
sendRequest(
356373
RequestMethods.POST,
357374
consumerURL + Operations.GENERATE_LOGIN_OTP_INSECURE,
358-
credentials,
375+
normalizeLegacyAuthRequest(credentials),
359376
onResponse,
360377
onError
361378
)
@@ -406,7 +423,7 @@ class TutiApiClient(
406423
sendRequest(
407424
RequestMethods.POST,
408425
consumerURL + Operations.REFRESH_TOKEN,
409-
credentials,
426+
normalizeLegacyAuthRequest(credentials),
410427
onResponse,
411428
onError
412429
)
@@ -1045,14 +1062,9 @@ class TutiApiClient(
10451062

10461063

10471064
/**
1048-
* billInfo gets a bill from EBS using a pre-stored data, only send applicable bill fields
1049-
* plus the type of transaction
1050-
*
1051-
* @param billInfo
1052-
* @param onResponse
1053-
* @param onError
1065+
* Calls the legacy `/consumer/bills` helper, where the server injects its configured inquiry PAN/IPIN.
10541066
*/
1055-
fun billInquiry(
1067+
fun getBills(
10561068
billInfo: BillInfo,
10571069
onResponse: (TutiResponse) -> Unit,
10581070
onError: (TutiResponse?, Exception?) -> Unit,
@@ -1066,6 +1078,39 @@ class TutiApiClient(
10661078
)
10671079
}
10681080

1081+
/**
1082+
* Retained for compatibility. This overload maps to `/consumer/bills`.
1083+
* Use [getBills] for this flow, or [billInquiry] with [EBSRequest] for `/consumer/bill_inquiry`.
1084+
*/
1085+
@Deprecated(
1086+
message = "This overload calls /consumer/bills. Use getBills(BillInfo, ...) or billInquiry(EBSRequest, ...).",
1087+
replaceWith = ReplaceWith("getBills(billInfo, onResponse, onError)")
1088+
)
1089+
fun billInquiry(
1090+
billInfo: BillInfo,
1091+
onResponse: (TutiResponse) -> Unit,
1092+
onError: (TutiResponse?, Exception?) -> Unit,
1093+
): Call {
1094+
return getBills(billInfo, onResponse, onError)
1095+
}
1096+
1097+
/**
1098+
* Direct bill inquiry against `/consumer/bill_inquiry` using an explicit EBS-style request.
1099+
*/
1100+
fun billInquiry(
1101+
request: EBSRequest,
1102+
onResponse: (TutiResponse) -> Unit,
1103+
onError: (TutiResponse?, Exception?) -> Unit,
1104+
): Call {
1105+
return sendRequest(
1106+
RequestMethods.POST,
1107+
consumerURL + Operations.BILL_INQUIRY,
1108+
request,
1109+
onResponse,
1110+
onError,
1111+
)
1112+
}
1113+
10691114
fun cardTransfer(
10701115
card: Card,
10711116
ipin: String,
@@ -1684,6 +1729,10 @@ class TutiApiClient(
16841729
if (token.isNotBlank()) {
16851730
requestBuilder.header("Authorization", token)
16861731
}
1732+
val headerSnapshot = defaultHeaders
1733+
headerSnapshot.forEach { (key, value) ->
1734+
requestBuilder.header(key, value)
1735+
}
16871736
return okHttpClient.newWebSocket(requestBuilder.build(), listener)
16881737
}
16891738

@@ -1713,6 +1762,10 @@ class TutiApiClient(
17131762
requestBuilder.header("Authorization", tokenSnapshot)
17141763
}
17151764
requestBuilder.header("Accept", "application/json")
1765+
val defaultHeaderSnapshot = defaultHeaders
1766+
defaultHeaderSnapshot.forEach { (key, value) ->
1767+
requestBuilder.header(key, value)
1768+
}
17161769

17171770
// add additional headers set by the user
17181771
headers?.forEach { (key, value) ->
Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
package com.tuti.api.authentication
2-
3-
import kotlinx.serialization.SerialName
4-
5-
@kotlinx.serialization.Serializable
6-
data class SignInResponse (
7-
@SerialName("authorization")
8-
val authorizationJWT: String = "",
9-
val user: User = User()
10-
)
1+
package com.tuti.api.authentication
2+
3+
import kotlinx.serialization.SerialName
4+
5+
@kotlinx.serialization.Serializable
6+
data class SignInResponse (
7+
@SerialName("authorization")
8+
val authorizationJWT: String = "",
9+
val user: User = User(),
10+
val message: String = "",
11+
val status: String = "",
12+
val result: String = "",
13+
val code: String = "",
14+
@SerialName("pubkey")
15+
val publicKey: String = "",
16+
)

lib/src/main/java/com/tuti/api/authentication/SignUpRequest.kt

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ package com.tuti.api.authentication
33
import kotlinx.serialization.SerialName
44

55
@kotlinx.serialization.Serializable
6-
data class SignUpRequest (
7-
val username: String? = null,
8-
val password: String? = null,
9-
10-
@SerialName("firebase_token")
11-
val firebaseVerificationID: String? = null,
12-
13-
@SerialName("public_key")
14-
val userPubKey: String? = null,
15-
16-
@SerialName("device_id")
17-
val deviceId: String? = null,
6+
data class SignUpRequest (
7+
val username: String? = null,
8+
val password: String? = null,
9+
10+
@SerialName("firebase_token")
11+
val firebaseVerificationID: String? = null,
12+
13+
@SerialName("user_pubkey")
14+
val userPubKey: String? = null,
15+
16+
@SerialName("device_id")
17+
val deviceId: String? = null,
1818
val fullname: String? = null,
1919
val birthday: String? = null,
2020
val email: String? = null,
@@ -24,4 +24,4 @@ data class SignUpRequest (
2424

2525
@SerialName("is_merchant")
2626
val isMerchant: Boolean = false
27-
)
27+
)
Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
package com.tuti.api.authentication
2-
3-
import kotlinx.serialization.SerialName
4-
5-
@kotlinx.serialization.Serializable
6-
data class SignUpResponse (
7-
@SerialName("details")
8-
var user: User = User()
9-
)
1+
package com.tuti.api.authentication
2+
3+
import kotlinx.serialization.SerialName
4+
5+
@kotlinx.serialization.Serializable
6+
data class SignUpResponse (
7+
@SerialName("details")
8+
var user: User = User(),
9+
val result: String = "",
10+
val message: String = "",
11+
val code: String = "",
12+
)
Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
1-
package com.tuti.api.authentication
2-
3-
import kotlinx.serialization.SerialName
4-
5-
@kotlinx.serialization.Serializable
6-
data class User(
7-
val id: Int = 0,
8-
val createdAt: String = "",
9-
val updateAt: String = "",
10-
val deletedAt: String = "",
11-
val username: String = "",
12-
val fullname: String = "",
13-
val birthday: String = "",
1+
package com.tuti.api.authentication
2+
3+
import kotlinx.serialization.SerialName
4+
5+
@kotlinx.serialization.Serializable
6+
data class User(
7+
@SerialName("ID")
8+
val id: Int = 0,
9+
@SerialName("CreatedAt")
10+
val createdAt: String = "",
11+
@SerialName("UpdatedAt")
12+
val updateAt: String = "",
13+
@SerialName("DeletedAt")
14+
val deletedAt: String = "",
15+
val username: String = "",
16+
val fullname: String = "",
17+
val birthday: String = "",
1418

1519
@SerialName("mobile")
1620
val mobileNumber: String = "",
1721
val email: String = "",
1822

1923
@SerialName("is_merchant")
2024
val isMerchant: Boolean = false,
21-
)
25+
)

0 commit comments

Comments
 (0)