Skip to content

Latest commit

ย 

History

History
476 lines (352 loc) ยท 14.3 KB

README.md

File metadata and controls

476 lines (352 loc) ยท 14.3 KB

๐ŸŒฑ I'mport Android SDK ๐ŸŒฑ

๐Ÿ“– ์„ค๋ช…

์•ˆ๋“œ๋กœ์ด๋“œ ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ์—์„œ ๊ฒฐ์ œ ๊ฐœ๋ฐœ์„ ๊ฐ„ํŽธํ•˜๊ฒŒ ๋„์™€์ฃผ๋Š” ์•„์ž„ํฌํŠธ SDK ์ž…๋‹ˆ๋‹ค.

  • PG ๋“ค์€ WebView ๊ธฐ๋ฐ˜์œผ๋กœ ์—ฐ๋™๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ถ”ํ›„ ์ˆœ์ฐจ์ ์œผ๋กœ ํƒ€ ๊ฐ„ํŽธ๊ฒฐ์ œ๋“ค๋„ ๋„ค์ดํ‹ฐ๋ธŒ ์—ฐ๋™ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.


๐Ÿ”ฅ ์‚ฌ์šฉ๋ฐฉ๋ฒ•

Gradle implementation

project build.gradle

  maven {
    url 'https://jitpack.io'
  }

app build.gradle

์ตœ์‹  ๋ฒ„์ „ ํ™•์ธ

  implementation 'com.github.iamport:iamport-android:vX.Y.Z'

Kotlin usage

ํ•„์ˆ˜๊ตฌํ˜„ ์‚ฌํ•ญ

// ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ
// ์‚ฌ์šฉํ•˜์‹œ๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ Application ํด๋ž˜์Šค์— ์ถ”๊ฐ€ํ•˜์„ธ์š”
class BaseApplication : Application() {
    override fun onCreate() {
        ..
        Iamport.create(this)
    }
}

// DI ๋กœ koin ์„ ์‚ฌ์šฉํ•˜์‹œ๋Š” ๊ฒฝ์šฐ 
// ์ƒ์„ฑ๋œ koinApplication ์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ์ฃผ์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค
// ์ฐธ๊ณ  : ์ฝ”ํ‹€๋ฆฐ 1.5.0 ์ด์ƒ ๋ฐ Koin 2.2.2 ๋ฅผ ์‚ฌ์šฉํ•˜์‹œ๋Š” ๋ถ„๋“ค์€ 2.2.3 ์œผ๋กœ ์—…๋ฐ์ดํŠธ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.
// ์ฐธ๊ณ  : v1.2.0 ๋ถ€ํ„ฐ koin 3.1.2 ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
class BaseApplication : Application() {
    override fun onCreate() {
        ..
        val koinApp = startKoin { .. }
        Iamport.createWithKoin(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 ์ข…๋ฃŒ
// ๋ช…์‹œ์ ์œผ๋กœ ํ™”๋ฉด์„ ๋‚˜๊ฐ€๋Š” ์‹œ์ , ๊บผ์ง€๋Š” ์‹œ์  ๋“ฑ์— ์ถ”๊ฐ€
Iamport.close()


// SDK ์— ๊ฒฐ์ œ ์š”์ฒญํ•  ๋ฐ์ดํ„ฐ ๊ตฌ์„ฑ
val request = IamPortRequest(
    pg = "chai",                                 // PG ์‚ฌ
    pay_method = PayMethod.trans.name,          // ๊ฒฐ์ œ์ˆ˜๋‹จ
    name = "์—ฌ๊ธฐ์ฃผ๋ฌธ์ด์š”",                         // ์ฃผ๋ฌธ๋ช…
    merchant_uid = "mid_123456",               // ์ฃผ๋ฌธ๋ฒˆํ˜ธ
    amount = "3000",                           // ๊ฒฐ์ œ๊ธˆ์•ก
    buyer_name = "ํ™๊ธธ๋™"
)


// ๊ฒฐ์ œ์š”์ฒญ
Iamport.payment("imp123456", request,
    approveCallback = { /* (Optional) CHAI ์ตœ์ข… ๊ฒฐ์ œ์ „ ์ฝœ๋ฐฑ ํ•จ์ˆ˜. */ },
    paymentResultCallback = { /* ์ตœ์ข… ๊ฒฐ์ œ๊ฒฐ๊ณผ ์ฝœ๋ฐฑ ํ•จ์ˆ˜. */ })

Optional ๊ตฌํ˜„์‚ฌํ•ญ : WebView Mode ์™€ MobileWeb Mode

ํŽผ์ณ๋ณด๊ธฐ

๋ณธ sdk ์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฒฐ์ œ์—ฐ๋™์˜ ํŽธ์˜๋ฅผ ์ œ๊ณตํ•˜๊ณ ์ž
Iamport.payment ๋ฅผ ํ†ตํ•ด ๊ฒฐ์ œ ์š”์ฒญ์‹œ ์ƒˆ๋กœ์šด Activity ๊ฐ€ ์—ด๋ฆฌ๊ณ ,
๋‚ด๋ถ€์ ์œผ๋กœ WebView ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ „๋‹ฌํ•ด์ฃผ์‹  parameters ๋ฅผ ํ†ตํ•ด ๊ฒฐ์ œ์ฐฝ์„ ์—ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์š”์ฒญ์— ๋”ฐ๋ผ ๊ฐœ๋ฐœ์˜ ์ž์œ ๋„๋ฅผ ๋“œ๋ฆฌ๊ธฐ ์œ„ํ•ด WebView Mode, MobileWeb Mode ๋‘๊ฐ€์ง€๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ( <= 1.0.0-dev05 )

1. WebView Mode

์„ค๋ช… : ๊ฒฐ์ œํŽ˜์ด์ง€๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜์‹œ๊ณ  iamport-sdk ์— webview ๋ฅผ ๋„˜๊ฒจ ๊ฒฐ์ œ๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
ex) ๊ฒฐ์ œ Activity(or Fragment) ๋ฅผ ํ†ตํ•ด ์ง์ ‘ ๊ฒฐ์ œํŽ˜์ด์ง€๋ฅผ ๊พธ๋ฏธ๊ธฐ ์›ํ•˜๋Š” ๋ถ„.

๋ฐ˜์˜๋ฐฉ๋ฒ• : ๊ธฐ์กด ํ•„์ˆ˜๊ตฌํ˜„ ์‚ฌํ•ญ ๊ณผ ๊ฐ™์ด iamport-sdk ์„ธํŒ…์„ ํ•ฉ๋‹ˆ๋‹ค.
Iamport.payment ํ˜ธ์ถœ ํŒŒ๋ผ๋ฏธํ„ฐ ์ค‘ webviewMode ์— webview ๋ฅผ ๋„ฃ์–ด์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๊ทธ ์™ธ๋Š” ๊ธฐ์กด์˜ ๋™์ž‘๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ƒ˜ํ”Œ์•ฑ์˜ ์˜ˆ์‹œ WebViewModeFragment.kt

Iamport.payment(๊ฐ€๋งน์ ์‹๋ณ„์ฝ”๋“œ, webviewMode = webview, ๊ธฐํƒ€ params, ์ฝœ๋ฐฑ)

2. MobileWeb Mode

์„ค๋ช… : ์•„์ž„ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Mobile ์›นํŽ˜์ด์ง€๊ฐ€ load ๋œ webview ๋ฅผ ๋„˜๊ฒจ ๊ฒฐ์ œ ์ง„ํ–‰์„ ์„œํฌํŠธ ํ•ฉ๋‹ˆ๋‹ค.
ex) ์ด๋ฏธ ์›น์‚ฌ์ดํŠธ์—์„œ ์•„์ž„ํฌํŠธ js sdk ๋ฅผ ์ด์šฉํ•˜๊ณ  ์žˆ๊ณ , ๋ณธ์ธ ์„œ๋น„์Šค๋ฅผ app ์œผ๋กœ๋งŒ ๊ฐ์‹ธ์„œ ์ถœ์‹œ ํ•˜๊ณ ์ž ํ•˜์‹œ๋Š” ๋ถ„.

๋ฐ˜์˜๋ฐฉ๋ฒ• : ๊ธฐ์กด ํ•„์ˆ˜๊ตฌํ˜„ ์‚ฌํ•ญ ๊ณผ ๊ฐ™์ด iamport-sdk ์„ธํŒ…์„ ํ•ฉ๋‹ˆ๋‹ค.
์ถ”๊ฐ€๋กœ Iamport.pluginMobileWebSupporter(webview) ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ webview ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
์‹ค์ œ ๊ฒฐ์ œ ์ง„ํ–‰์€ ๊ณ ๊ฐ๋‹˜์˜ ์›น์‚ฌ์ดํŠธ ๋‚ด์—์„œ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.

์ƒ˜ํ”Œ์•ฑ์˜ ์˜ˆ์‹œ mobileweb.html (์˜ˆ์‹œ์ด๋ฉฐ ์‹ค์ œ๋กœ๋Š” ๊ณ ๊ฐ๋‹˜์˜ Front-End ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.)
์ƒ˜ํ”Œ์•ฑ์˜ ์˜ˆ์‹œ MobileWebViewModeFragment.kt

Iamport.pluginMobileWebSupporter(webview)
  • Custom WebViewClient ์˜ ์‚ฌ์šฉ

์ƒ˜ํ”Œ์•ฑ์˜ ์˜ˆ์‹œ MyWebViewClient class

/**
 webview url ์„ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง์ด ์žˆ์„ ๊ฒฝ์šฐ์— 
 [IamPortMobileModeWebViewClient] ์ƒ์†ํ•˜์—ฌ ์‚ฌ์šฉ ํ•˜์‹œ๊ฑฐ๋‚˜,
 [Iamport.mobileWebModeShouldOverrideUrlLoading] ์˜ observe ์„ ํ†ตํ•ด ๋ณ€๊ฒฝ๋˜๋Š” url ์„ ์ฒดํฌ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
 */
// CASE 1 : IamPortMobileModeWebViewClient ์ƒ์†
open class MyWebViewClient : IamPortMobileModeWebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
        Log.i("MyWebViewClient", "updated webview url ${view?.url}")
        return super.shouldOverrideUrlLoading(view, request)
    }
}

class MobileWebViewModeFragment : Fragment() {
    override fun setupWebView() {
        // IamPortMobileModeWebViewClient ์‚ฌ์šฉ
        binding?.webview?.webViewClient = MyWebViewClient()

        // CASE 2 : Iamport.mobileWebModeShouldOverrideUrlLoading ์‚ฌ์šฉ
        // oreo ๋ฏธ๋งŒ์—์„œ url ๋ณ€๊ฒฝ๋งŒ ๋ณด๊ณ  ์‹ถ์€๊ฒฝ์šฐ (oreo ์ด์ƒ๋ถ€ํ„ฐ getWebViewClient ๊ฐ€ ์ง€์›๋˜๋ฏ€๋กœ)
        Iamport.mobileWebModeShouldOverrideUrlLoading()?.observe(this, EventObserver { uri ->
            Log.i("SAMPLE", "changed url :: $uri")
        })
    }
}
  • Custom WebChromeClient ์˜ ์‚ฌ์šฉ

์ƒ˜ํ”Œ์•ฑ์˜ ์˜ˆ์‹œ MyWebViewChromeClient class

/**
 [IamportWebChromeClient] ์ƒ์†ํ•˜์—ฌ ์‚ฌ์šฉ
 */
// CASE 1 : IamportWebChromeClient ์ƒ์†
open class MyWebViewChromeClient : IamportWebChromeClient() {
    override fun onJsConfirm(view: WebView, url: String, message: String, result: JsResult): Boolean {
        Log.i("MyWebViewChromeClient", "called this function")
        return super.onJsConfirm(view, url, message, result)
    }
}

class MobileWebViewModeFragment : Fragment() {
    override fun setupWebView() {
        // IamportWebChromeClient ์‚ฌ์šฉ
        it.webChromeClient = MyWebViewChromeClient()
        // ..
    }
}

Optional ๊ตฌํ˜„์‚ฌํ•ญ : ๊ฒฐ์ œ ํ›„ ๋‚˜์˜ ์•ฑ์œผ๋กœ์˜ ๋ณต๊ท€(app_scheme ํŒŒ๋ผ๋ฏธํ„ฐ) ์— ๋Œ€ํ•˜์—ฌ

ํŽผ์ณ๋ณด๊ธฐ

์•ˆ๋“œ๋กœ์ด๋“œ ์‹œ์Šคํ…œ์ƒ ์ƒˆ๋กœ ์•ฑ์„ ๋„์šฐ๊ณ  ์ข…๋ฃŒ๊ฐ€ ๋˜๋ฉด ์ž๋™์œผ๋กœ ํ˜ธ์ถœํ–ˆ๋˜ ์•ฑ์œผ๋กœ ๋Œ์•„์˜ค๊ฒŒ ๋˜์–ด ์žˆ๊ธฐ์—
๊ธฐ๋ณธ์ ์œผ๋กœ app_scheme ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์‚ฌ์šฉํ•˜์‹ค ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. (iOS ์˜ ๊ฒฝ์šฐ ํ•ด๋‹น ๊ธฐ๋Šฅ์ด ์—†๊ธฐ์— ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.)

๊ทธ๋Ÿผ์—๋„ ์‚ฌ์šฉ์„ ์›ํ•˜์‹ ๋‹ค๋ฉด, ๊ฒฐ์ œ ์š”์ฒญ์‹œ ๊ตฌ์„ฑํ•˜๋Š” IamPortRequest class ์— app_scheme ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ด ๋ฐ์ดํ„ฐ๋Š” ์„œ๋“œํŒŒํ‹ฐ ๊ฒฐ์ œ ์•ฑ(ํŽ˜์ด๋ถ, ๋ฑ…ํฌํŽ˜์ด, toss ๋“ฑ)์—์„œ ๊ฒฐ์ œ์ธ์ฆ์ด ์™„๋ฃŒ๋œ ํ›„, ํ˜ธ์ถœํ•œ ๋‚˜์˜ ์•ฑ์„ ์‹คํ–‰์‹œํ‚ค๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

๋ณธ SDK ์˜ WebView Mode / MobileWeb Mode ์—์„œ๋งŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ,
activity ์˜ launchMode ๋ฅผ singleInstance ๋กœ ๊ตฌ์„ฑํ•˜์‹œ๊ณ ,
์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด manifest ์—์„œ intent-filter scheme ์„ ์„ค์ •ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.
(PG ์ด๋‹ˆ์‹œ์Šค์˜ ๊ฒฝ์šฐ scheme ์— . ๋ฅผ ํฌํ•จํ•˜๋ฉด ๊ฒฐ์ œ ์‹คํŒจ ์ฒ˜๋ฆฌ๋˜๋ฏ€๋กœ ์ฃผ์˜ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.)

  <activity
      android:launchMode="singleInstance"
      ..
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="mycustomappscheme" />
  </intent-filter>
val request = IamPortRequest(
  app_scheme = "mycustomappscheme"
  ..

์ผ๋ฐ˜ ๊ฒฐ์ œ ๋ชจ๋“œ์˜ ๊ฒฝ์šฐ ์ƒˆ๋กœ์šด activity ๋ฅผ ๋„์›Œ ๊ฒฐ์ œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ app_scheme ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.


JAVA ํ”„๋กœ์ ํŠธ๋Š” ์•„๋ž˜ [ํŽผ์ณ๋ณด๊ธฐ] ๋ฅผ ์ฐธ์กฐํ•ด์ฃผ์„ธ์š”

ํŽผ์ณ๋ณด๊ธฐ

JAVA usage

์ž๋ฐ” ํ”„๋กœ์ ํŠธ์—์„  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 ์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ์ฃผ์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค
   // ์ฐธ๊ณ  : ์ฝ”ํ‹€๋ฆฐ 1.5.0 ์ด์ƒ ๋ฐ Koin 2.2.2 ๋ฅผ ์‚ฌ์šฉํ•˜์‹œ๋Š” ๋ถ„๋“ค์€ 2.2.3 ์œผ๋กœ ์—…๋ฐ์ดํŠธ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.
    public class BaseApplication extends Application {
        @Override
        public void onCreate() {
            ..
            KoinApplication koinApp = ..
            Iamport.INSTANCE.createWithKoin(this, koinApp);
        }
    }
  @Override
  public void onCreate() {
    Iamport.INSTANCE.init(this);
    ..
  }
  

  // SDK ์ข…๋ฃŒ
  // ๋ช…์‹œ์ ์œผ๋กœ ํ™”๋ฉด์„ ๋‚˜๊ฐ€๋Š” ์‹œ์ , ๊บผ์ง€๋Š” ์‹œ์  ๋“ฑ์— ์ถ”๊ฐ€
  Iamport.INSTANCE.close();


  IamPortRequest request
          = IamPortRequest.builder()
          .pg("chai")
          .pay_method(PayMethod.trans.name)
          .name("์—ฌ๊ธฐ์ฃผ๋ฌธ์ด์š”")
          .merchant_uid("mid_123456")
          .amount("3000")
          .buyer_name("ํ™๊ธธ๋™").build();


  Iamport.INSTANCE.payment("imp123456", request, 
    iamPortApprove -> {
      // (Optional) CHAI ์ตœ์ข… ๊ฒฐ์ œ์ „ ์ฝœ๋ฐฑ ํ•จ์ˆ˜.
      return Unit.INSTANCE;
  }, iamPortResponse -> {
      // ์ตœ์ข… ๊ฒฐ์ œ๊ฒฐ๊ณผ ์ฝœ๋ฐฑ ํ•จ์ˆ˜.
      return Unit.INSTANCE;
  });

Optional ๊ตฌํ˜„์‚ฌํ•ญ for CHAI ๊ฒฐ์ œ

  • ์ฐจ์ด ๊ฒฐ์ œ์—์„œ 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"

๐Ÿ’ก ์ƒ˜ํ”Œ์•ฑ

์•ฑ ์†Œ์Šค ํ™•์ธ ๊ฒฝ๋กœ

  1. git clone
  2. Android Studio project open
  3. build app

BaseApplication.kt (SDK ์ƒ์„ฑ)

    override fun onCreate() {
        super.onCreate()
        Iamport.create(this)

        /**
         * DI ๋กœ KOIN ์‚ฌ์šฉ์‹œ ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉ
        val koinApp = startKoin {
            logger(AndroidLogger())
            androidContext(this@BaseApplication)
        }
        Iamport.create(this, koinApp)
         */
    }

MainActivity.kt

    // ์ดˆ๊ธฐํ™” ์ฒ˜๋ฆฌ
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
        Iamport.init(this)
        ..
    }

PaymentFragment.kt (๊ฒฐ์ œ ํ™”๋ฉด)

// ํฌ๊ทธ๋ผ์šด๋“œ ์„œ๋น„์Šค ์ฒ˜๋ฆฌ์šฉ ๋ธŒ๋กœ๋“œ ์บ์ŠคํŠธ ๋ฆฌ์‹œ๋ฒ„ ๋“ฑ๋ก
override fun onAttach(context: Context) {
    super.onAttach(context)
    registForegroundServiceReceiver(context)
    ..
}


// ๊ฒฐ์ œ๋ฒ„ํŠผ ํด๋ฆญ
private fun onClickPayment() {
    ..
    val request = IamPortRequest(
        pg = pg.getPgSting(pgId = ""),              // 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()
            }
        ..
    }
}