์๋๋ก์ด๋ ๋ค์ดํฐ๋ธ ์ฑ์์ ๊ฒฐ์ ๊ฐ๋ฐ์ ๊ฐํธํ๊ฒ ๋์์ฃผ๋ ์์ํฌํธ SDK ์ ๋๋ค.
-
CHAI ๊ฐํธ๊ฒฐ์ ๋ Native ์ฐ๋๋์ด ์์ต๋๋ค.
-
๊ทธ์ธ PG ๋ค์ WebView ๊ธฐ๋ฐ์ผ๋ก ์ฐ๋๋์ด ์์ต๋๋ค.
-
์ถํ ์์ฐจ์ ์ผ๋ก ํ ๊ฐํธ๊ฒฐ์ ๋ค๋ ๋ค์ดํฐ๋ธ ์ฐ๋ ์์ ์ ๋๋ค.
project build.gradle
maven {
url 'https://jitpack.io'
}
app build.gradle $SDK-VERSION
implementation 'com.github.iamport:iamport-android:$SDK-VERSION'
ํ์๊ตฌํ ์ฌํญ
// ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ
// ์ฌ์ฉํ์๋ ์๋๋ก์ด๋ ์ดํ๋ฆฌ์ผ์ด์
ํด๋์ค์ ์ถ๊ฐํ์ธ์
class BaseApplication : Application() {
override fun onCreate() {
..
Iamport.create(this)
}
}
// DI ๋ก koin ์ ์ฌ์ฉํ์๋ ๊ฒฝ์ฐ
// ์์ฑ๋ koinApplication ์ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ฃผ์
์ผ ํฉ๋๋ค
class BaseApplication : Application() {
override fun onCreate() {
..
val koinApp = startKoin { .. }
Iamport.create(this, koinApp)
}
// KoinApplication ์ด ํ์ํ ๊ฒฝ์ฐ
Iamport.getKoinApplition()
}
// SDK ์ด๊ธฐํ
// activity ์์ ํธ์ถ์ : LifecycleOwners must call register before they are STARTED.
// fragement ์์ ํธ์ถ์ : Fragments must call before they are created (i.e. initialization, onAttach(), or onCreate())
fun onCreate() {
Iamport.init(this)
..
}
// SDK ์ข
๋ฃ
// activity ์์ ํธ์ถ์ : onDestroy
// fragement ์์ ํธ์ถ์ : onDestroy, onDetach ๋ฑ
// ๊ณตํต : ํ๋ฉด์ ๋๊ฐ๋ ์์ , ๊บผ์ง๋ ์์ ๋ฑ์ ์ถ๊ฐ
fun onDestroy() {
Iamport.close()
..
}
// SDK ์ ๊ฒฐ์ ์์ฒญํ ๋ฐ์ดํฐ ๊ตฌ์ฑ
val request = IamPortRequest(
pg = "chai", // PG ์ฌ
pay_method = PayMethod.trans, // ๊ฒฐ์ ์๋จ
name = "์ฌ๊ธฐ์ฃผ๋ฌธ์ด์", // ์ฃผ๋ฌธ๋ช
merchant_uid = "mid_123456", // ์ฃผ๋ฌธ๋ฒํธ
amount = "3000", // ๊ฒฐ์ ๊ธ์ก
buyer_name = "ํ๊ธธ๋"
)
// ๊ฒฐ์ ์์ฒญ
Iamport.payment("imp123456", request,
approveCallback = { /* (Optional) ์ฐจ์ด ์ต์ข
๊ฒฐ์ ์ ์ฝ๋ฐฑ ํจ์. */ },
paymentResultCallback = { /* ์ต์ข
๊ฒฐ์ ํ ์ฝ๋ฐฑํจ์ */ })
- ์ฐจ์ด ๊ฒฐ์ ์์ approveCallback ์ด ์์ ๋ (์ต์ข ๊ฒฐ์ ์ ์ฌ๊ณ ํ์ธ ๋ฑ์ด ํ์ํ ๋)
์ฝ๋ฐฑ ์ ๋ฌ ๋ฐ์ ํ์ chaiPayment ํจ์ ํธ์ถ
(ํ์์์ : CONST.CHAI_FINAL_PAYMENT_TIME_OUT_SEC)
Iamport.chaiPayment(iamPortApprove) // ์ฌ๊ณ ๋ฑ ํ์ธ ํ, ์ฐจ์ด ์ต์ข
๊ฒฐ์ ์์ฒญ ์คํ.
- ์ฐจ์ด ๊ฒฐ์ ํด๋ง ์ฌ๋ถ ํ์ธ
// ์ฐจ์ด ๊ฒฐ์ ์ํ์ฒดํฌ ํด๋ง ์ฌ๋ถ๋ฅผ ํ์ธํ์ค ์ ์์ต๋๋ค.
Iamport.isPolling()?.observe(this, EventObserver {
i("์ฐจ์ด ํด๋ง? :: $it")
})
// ๋๋, ํด๋ง ์ํ๋ฅผ ๋ณด๊ณ ์ถ์๋ ๋ช
์์ ์ผ๋ก ํธ์ถ
i("isPolling? ${Iamport.isPollingValue()}")
- ์ฐจ์ด ๊ฒฐ์ ํด๋ง ์ค์๋ ํฌ๊ทธ๋ผ์ด๋ ์๋น์ค๊ฐ ์๋์ ๋จ๊ฒ ๋ฉ๋๋ค.
enableService = true ๋ผ๋ฉด, ํด๋ง์ค ํฌ๊ทธ๋ผ์ด๋ ์๋น์ค๋ฅผ ๋ณด์ฌ์ค๋๋ค.
enableFailStopButton = true ๋ผ๋ฉด, ํฌ๊ทธ๋ผ์ด๋ ์๋น์ค์์ ์ค์ง ๋ฒํผ ์์ฑํฉ๋๋ค.
(ํด๋น enableChaiPollingForegroundService(false, false) ๋ฅผ Iamport.payment(๊ฒฐ์ ํจ์) ์ ์ ํธ์ถํด์ฃผ์๋ฉด ํฌ๊ทธ๋ผ์ด๋ ์๋น์ค๋ฅผ ๋ฑ๋กํ์ง ์์ต๋๋ค)
Iamport.enableChaiPollingForegroundService(enableService = true, enableFailStopButton = true)
- ํฌ๊ทธ๋ผ์ด๋ ์๋น์ค ์๋ ๋ฐ ์ค์ง ๋ฒํผ ํด๋ฆญ์ ๋์์
์๋ ๊ฐ์ ๋ธ๋ก๋ ์บ์คํธ ๋ฆฌ์๋ฒ๋ฅผ ํตํด ์บ์นํ ์ ์์ต๋๋ค.
์ํ์ฑ์ ์์ MerchantReceiver.kt
const val BROADCAST_FOREGROUND_SERVICE = "com.iamport.sdk.broadcast.fgservice"
const val BROADCAST_FOREGROUND_SERVICE_STOP = "com.iamport.sdk.broadcast.fgservice.stop"
- (ํฌ๊ทธ๋ผ์ด๋ ์๋น์ค ์ง์ ๊ตฌํ์์๋ enableService = false ๋ก ์ค์ ํ๊ณ ,
Iamport.isPolling()?.observe ์์ true ์ ๋ฌ ๋ฐ์ ์์ ์, ์ง์ ํฌ๊ทธ๋ผ์ด๋ ์๋น์ค ๋ง๋ค์ด ๋์ฐ์๋ฉด ๋ฉ๋๋ค.)
ํผ์ณ๋ณด๊ธฐ
์๋ฐ ํ๋ก์ ํธ์์ app build.gradle ์์ kotin-stblib ์ถ๊ฐ๊ฐ ํ์ํฉ๋๋ค $์ฝํ๋ฆฐ-๋ฒ์
implementation "org.jetbrains.kotlin:kotlin-stdlib:$์ฝํ๋ฆฐ-๋ฒ์ "
ํ์๊ตฌํ ์ฌํญ. SDK ์ ๊ณต api ๋ณ ์ค๋ช ์ ์์ KOTLIN usage ๋ฅผ ์ฐธ๊ณ ํ์ธ์.
// ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ
// ์ฌ์ฉํ์๋ ์๋๋ก์ด๋ ์ดํ๋ฆฌ์ผ์ด์
ํด๋์ค์ ์ถ๊ฐํ์ธ์
public class BaseApplication extends Application {
@Override
public void onCreate() {
..
Iamport.INSTANCE.create(this, null);
}
}
// DI ๋ก koin ์ ์ฌ์ฉํ์๋ ๊ฒฝ์ฐ
// ์์ฑ๋ koinApplication ์ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ฃผ์
์ผ ํฉ๋๋ค
public class BaseApplication extends Application {
@Override
public void onCreate() {
..
KoinApplication koinApp = ..
Iamport.INSTANCE.create(this, koinApp);
}
}
@Override
public void onCreate() {
Iamport.INSTANCE.init(this);
..
}
@Override
public void onDeatroy() {
..
Iamport.INSTANCE.close();
}
IamPortRequest request
= IamPortRequest.builder()
.pg("chai")
.pay_method(PayMethod.trans)
.name("์ฌ๊ธฐ์ฃผ๋ฌธ์ด์")
.merchant_uid("mid_123456")
.amount("3000")
.buyer_name("ํ๊ธธ๋").build();
Iamport.INSTANCE.payment("imp123456", request,
iamPortApprove -> {
// (Optional) ์ฐจ์ด ์ต์ข
๊ฒฐ์ ์ ์ฝ๋ฐฑ ํจ์.
return Unit.INSTANCE;
}, iamPortResponse -> {
// ์ต์ข
๊ฒฐ์ ํ ์ฝ๋ฐฑํจ์
return Unit.INSTANCE;
});
- ์ฐจ์ด ๊ฒฐ์ ์์ approveCallback ์ด ์์ ๋ (์ต์ข ๊ฒฐ์ ์ ์ฌ๊ณ ํ์ธ ๋ฑ์ด ํ์ํ ๋)
Iamport.INSTANCE.chaiPayment(iamPortApprove) // ์ฌ๊ณ ๋ฑ ํ์ธ ํ, ์ฐจ์ด ์ต์ข
๊ฒฐ์ ์์ฒญ ์คํ.
- ์ฐจ์ด ๊ฒฐ์ ํด๋ง ์ฌ๋ถ ํ์ธ
Iamport.INSTANCE.isPolling().observe(this, EventObserver -> {
i("์ฐจ์ด ํด๋ง? :: " + it)
});
i("isPolling? " + Iamport.INSTANCE.isPollingValue())
- ์ฐจ์ด ๊ฒฐ์ ํด๋ง ์ค์๋ ํฌ๊ทธ๋ผ์ด๋ ์๋น์ค๊ฐ ์๋์ ๋จ๊ฒ ๋ฉ๋๋ค.
Iamport.INSTANCE.enableChaiPollingForegroundService(true, true)
- ํฌ๊ทธ๋ผ์ด๋ ์๋น์ค ์๋ ๋ฐ ์ค์ง ๋ฒํผ ํด๋ฆญ์ ๋์์ ์๋ ๊ฐ์ ๋ธ๋ก๋ ์บ์คํธ ๋ฆฌ์๋ฒ๋ฅผ ํตํด ์บ์นํ ์ ์์ต๋๋ค.
const val BROADCAST_FOREGROUND_SERVICE = "com.iamport.sdk.broadcast.fgservice"
const val BROADCAST_FOREGROUND_SERVICE_STOP = "com.iamport.sdk.broadcast.fgservice.stop"
- git clone
- Android Studio project open
- build app
BaseApplication.kt (SDK ์์ฑ)
override fun onCreate() {
super.onCreate()
Iamport.create(this)
/**
* DI ๋ก KOIN ์ฌ์ฉ์ ์๋์ ๊ฐ์ด ์ฌ์ฉ
val koinApp = startKoin {
logger(AndroidLogger(Level.DEBUG))
androidContext(this@BaseApplication)
}
Iamport.create(this, koinApp)
*/
}
PaymentFragment.kt (๊ฒฐ์ ํ๋ฉด)
// ์ด๊ธฐํ ์ฒ๋ฆฌ
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Iamport.init(this) // fragment
}
// ํฌ๊ทธ๋ผ์ด๋ ์๋น์ค ์ฒ๋ฆฌ์ฉ ๋ธ๋ก๋ ์บ์คํธ ๋ฆฌ์๋ฒ ๋ฑ๋ก
override fun onAttach(context: Context) {
super.onAttach(context)
registForegroundServiceReceiver(context)
..
}
// ์ข
๋ฃ ์ฒ๋ฆฌ
override fun onDestroy() {
super.onDestroy()
Iamport.close()
..
}
// ๊ฒฐ์ ๋ฒํผ ํด๋ฆญ
private fun onClickPayment() {
..
val request = IamPortRequest(
pg = pg.getPgSting(storeId = ""), // PG ์ฌ
pay_method = payMethod, // ๊ฒฐ์ ์๋จ
name = paymentName, // ์ฃผ๋ฌธ๋ช
merchant_uid = merchantUid, // ์ฃผ๋ฌธ๋ฒํธ
amount = amount, // ๊ฒฐ์ ๊ธ์ก
buyer_name = "๋จ๊ถ์๋
"
)
// ๊ฒฐ์ ํธ์ถ
Iamport.payment(userCode, request,
approveCallback = { approveCallback(it) },
paymentResultCallback = { callBackListener.result(it) })
}
// ์ฐจ์ด ๊ฒฐ์ ์ ์ฝ๋ฐฑ ๋ฐ ์ต์ข
๊ฒฐ์ ์์ฒญ ์ฒ๋ฆฌ
private fun approveCallback(iamPortApprove: IamPortApprove) {
val secUnit = 1000L
val sec = 1
GlobalScope.launch {
delay(sec * secUnit) // sec ์ด๊ฐ ์ฌ๊ณ ํ์ธ ํ๋ก์ธ์ค๋ฅผ ๊ฐ์ ํฉ๋๋ค
Iamport.chaiPayment(iamPortApprove) // TODO: ์ํ ํ์ธ ํ SDK ์ ์ต์ข
๊ฒฐ์ ์์ฒญ
}
}
// fragment ์์ ๋ช
์์ ์ธ ์ข
๋ฃํ ๋ ์ฒ๋ฆฌ Iamport.close()
private val backPressCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
Builder(view?.context)
.setPositiveButton(android.R.string.ok) { _, _ ->
Iamport.close() // TODO ๋ช
์์ ์ธ SDK ์ข
๋ฃ
requireActivity().finish()
}
..
}
}