integrate in-app payment with merchant apps objective learn how to integrate in-app payment with your merchant apps using samsung pay sdk. partnership request to use the samsung pay sdk, you must become an official samsung partner. once done, you can fully utilize this code lab. you can learn more about the partnership process by visiting samsung pay page, here in samsung developers. notein accordance with the applicable samsung partner agreements, this code lab covers setup and use of the samsung pay sdk for purposes of integrating the samsung pay app with partner apps. the use cases and corresponding code samples included are representative examples only and should not be construed as either recommended or required. overview the samsung pay sdk is an application framework for integrating selected samsung pay features with android-based partner apps on samsung devices. in-app payment, which allows customers to pay for products and services with samsung pay, is one of the operations supported alongside push provisioning and open favorite cards. partner apps can leverage the samsung pay sdk to perform different operations ― push provisioning and open favorite cards for issuers; in-app payment for merchants. key components include: partner app: app developed by merchant or issuer for making online or offline payments and provisioning payment cards through samsung pay samsung pay sdk: sdk integrated into the partner app for direct communication with samsung pay samsung pay app: pay app with which the samsung pay sdk communicates financial network: comprises the payment gateways, acquirers, card associations, and issuers that participate in transaction processing under agreement with the merchant most common use case for in-app payment: the merchant app allows the user to make payments with samsung pay. upon user selection of the samsung pay option, the merchant app calls the apis included in the samsung pay sdk to initiate a transaction with the samsung pay app. the samsung pay app responds with the tokenized payment information necessary to complete the transaction. the merchant app forwards this payment information to the designated payment gateway (pg), either directly through the merchant's web server or indirectly via the samsung-pg interface server for standard transaction processing. for more detailed information, see the official samsung pay sdk programming guide. set up your environment you will need the following: samsung wallet or samsung pay app (depending on the country) a compatible mobile device with android marshmallow 6.0 or android api level 23 (or later android os versions) samsung pay sdk android studio (latest version recommended) java se development kit (jdk) 11 or later sample code here is a sample code for you to start coding in this code lab. download it and start your learning experience! in-app payment sample code (162.23 kb) integrate the samsung pay sdk with your app the following steps comprise the general process for integrating the samsung pay sdk with your app: sign up for the samsung pay developers portal by clicking sign up and register your samsung account (or create it if you don't already have one), then sign in. follow the on-screen instructions for adding your app and creating a new service to generate the service id you'll need to use in your project, along with a debug-api-key (see understanding the debug api key and api level) download the samsung pay sdk by going to resources > sdk download. add the samsung pay sdk jar file (samsungpay.jar) to your android project using android studio or file explorer. develop your partner app with the required api calls and callbacks for samsung pay integration. upload a release version of your app to the samsung pay developers portal for approval. upon samsung approval, publish your partner app to the google play store and samsung galaxy apps. notethe service id is already provided in the sample code for this code lab. however, this service id is for test purposes only and cannot be used for an actual application or service. using the provided test service id enforces your app to use the fixed properties below: service id: 0915499788d6493aa3a038 package name: com.test.beta.pay app version: 1.0/ 1 (or higher) start your project after downloading the sample code containing the project files, in android studio click open to open existing project. locate the downloaded android project (sampleonlinepay) from the directory and click ok. add the samsungpaysdk_2.18.00_release.jar file from the sdk's libs folder to your android project's libs folder. go to gradle scripts > build.gradle (module: sampleonlinepay.app) and enter the following to the dependencies block: implementation files('libs/samsungpaysdk_2.18.00_release.jar') if the target sdk version is 30 (android 11 or the r-os), you must include the following <queries> element in androidmanifest.xml. <queries> <package android:name="com.samsung.android.spay" /> </queries> configure the api level and enable release mode as of sdk version 1.4, enhanced version control management has been introduced to improve backward compatibility and handle api dependency from country and service type. for example, if a partner integrates the latest sdk—for instance, api level 2.18—but continues to use apis based on level 1.4, the partner app remains compatible with samsung pay apps supporting api level 1.4 without upgrading the samsung pay app. implement the following in application tag of androidmanifest.xml: <meta-data android:name="spay_sdk_api_level" android:value="2.17" /> // most recent sdk version is recommended to leverage the latest apis apps configured for debug or release mode can be registered on the samsung pay developers site to integrate samsung pay functionalities. debug mode – for testing and qa; requires spay_debug_api_key and allowed samsung account(s) in build to test. release mode – for market release to end users; does not need a debug key or an allowed list of samsung accounts in a samsung-approved build to run. for this code lab, enable release mode. <meta-data android:name="debug_mode" android:value="n" /> <!--set to y if debug mode--> <!-- uncomment if debug mode--> <!-- <meta-data android:name="spay_debug_api_key" android:value="" /> --> tipif you want to learn more about these two modes, see configuring debug mode. add an xml layout and modify the activity next, replace the xml layout in res > layout > activity_main.xml. this layout shows the sample item information such as image, name, and price. <?xml version="1.0" encoding="utf-8"?> <layout xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"> <androidx.constraintlayout.widget.constraintlayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".mainactivity"> <imageview android:id="@+id/imageview" android:layout_width="350dp" android:layout_height="184dp" android:layout_margintop="100dp" app:layout_constraintend_toendof="parent" app:layout_constraintstart_tostartof="parent" app:layout_constrainttop_totopof="parent" android:src="@drawable/galaxy_z_flip4_image"/> <imageview android:id="@+id/samsung_pay_button" android:layout_width="wrap_content" android:layout_height="75dp" app:layout_constraintbottom_tobottomof="parent" app:layout_constraintend_toendof="parent" app:layout_constraintstart_tostartof="parent" android:src="@drawable/pay_rectangular_full_screen_black" android:visibility="invisible"/> <textview android:id="@+id/textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="10dp" android:text="galaxy z flip4" android:textsize="16sp" android:textstyle="bold" app:layout_constraintend_toendof="parent" app:layout_constraintstart_tostartof="parent" app:layout_constrainttop_tobottomof="@+id/imageview" /> <textview android:id="@+id/textview2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="5dp" android:text="$990.99" android:textsize="14sp" app:layout_constraintend_toendof="parent" app:layout_constrainthorizontal_bias="0.517" app:layout_constraintstart_tostartof="parent" app:layout_constrainttop_tobottomof="@+id/textview" /> </androidx.constraintlayout.widget.constraintlayout> </layout> since you added a data binding layout, you need to inflate the xml file differently. go to java > com > test > beta > pay > mainactivity.kt, and declare the databinding variable in the mainactivity class. private lateinit var databinding: activitymainbinding replace the standard setcontentview declaration with the data binding version inside the oncreate method. databinding = databindingutil.setcontentview(this, r.layout.activity_main) check samsung pay status in the mainactivity, create the samsungpay instance. to determine if the device supports samsung pay and if the samsung pay button can be displayed as the user's payment option, check the samsung pay status. samsungpay() requires a valid partnerinfo from the merchant app, which consists of service id and service type. during onboarding, the samsung pay developers portal assigns the service id and service type. in the mainactivity, declare the partnerinfo variable. private lateinit var partnerinfo: partnerinfo then, set the partnerinfo in the oncreate method. val bundle = bundle() bundle.putstring(spaysdk.partner_service_type, spaysdk.servicetype.inapp_payment.tostring()) partnerinfo = partnerinfo(service_id, bundle) after setting partnerinfo, call the getsamsungpaystatus method via updatesamsungpaybutton function inside the oncreate method. updatesamsungpaybutton() the getsamsungpaystatus method of the samsungpay class must be called before using any other feature in the samsung pay sdk. write the updatesamsungpaybutton function as follows: private fun updatesamsungpaybutton() { val samsungpay = samsungpay(this, partnerinfo) samsungpay.getsamsungpaystatus(object : statuslistener { override fun onsuccess(status: int, bundle: bundle) { when (status) { spaysdk.spay_ready -> { databinding.samsungpaybutton.visibility = view.visible // perform your operation. } spaysdk.spay_not_ready -> { // samsung pay is supported but not fully ready. // if extra_error_reason is error_spay_app_need_to_update, // call gotoupdatepage(). // if extra_error_reason is error_spay_setup_not_completed, // call activatesamsungpay(). databinding.samsungpaybutton.visibility = view.invisible } spaysdk.spay_not_allowed_temporally -> { // if extra_error_reason is error_spay_connected_with_external_display, // guide user to disconnect it. databinding.samsungpaybutton.visibility = view.invisible } spaysdk.spay_not_supported -> { databinding.samsungpaybutton.visibility = view.invisible } else -> databinding.samsungpaybutton.visibility = view.invisible } } override fun onfail(errorcode: int, bundle: bundle) { databinding.samsungpaybutton.visibility = view.invisible toast.maketext(applicationcontext, "getsamsungpaystatus fail", toast.length_short).show() } }) } tipfor the list and detailed definition of status codes such as spay_ready, refer to checking samsung pay status. noteas of sdk version 1.5, if the device has android lollipop 5.1 (android api level 22) or earlier versions, the getsamsungpaystatus() api method returns a spay_not supported status code. merchant apps using sdk 1.4 or earlier must check their app's android version. activate the samsung pay app the samsungpay class provides an api method called activatesamsungpay() to activate the samsung pay app on the same device where the partner app is running. if the getsamsungpaystatus() returns spay_not_ready and the extra_error_reason is error_spay_setup_not_complete, the partner app needs to display an appropriate message to the user. then, call activatesamsungpay() to launch samsung pay app and request the user to sign in. in updatesamsungpaybutton function, add the code to call activatesamsungpay method via doactivatesamsungpay function when the status is spay_not_ready: // if extra_error_reason is error_spay_setup_not_completed, // call activatesamsungpay(). val extraerror = bundle.getint(samsungpay.extra_error_reason) if (extraerror == samsungpay.error_spay_setup_not_completed) { doactivatesamsungpay(spaysdk.servicetype.inapp_payment.tostring()) } create the doactivatesamsungpay function as below: private fun doactivatesamsungpay(servicetype: string) { val bundle = bundle() bundle.putstring(samsungpay.partner_service_type, servicetype) val partnerinfo = partnerinfo(service_id, bundle) val samsungpay = samsungpay(this, partnerinfo) samsungpay.activatesamsungpay() } create a transaction request upon successfully initializing the samsungpay class, the merchant app should create a transaction request with payment information. samsung pay offers two types of online payment sheet―normal and custom. the normal payment sheet has fixed display items ― items, tax, and shipping. the custom payment sheet offers more dynamic controls for customizing the ui, together with additional customer order and payment data. for this code lab, use the custom payment sheet and populate the fields in customsheetpaymentinfo to initiate a payment transaction. /* * make user's transaction details. * the merchant app should send paymentinfo to samsung pay via the applicable samsung pay sdk api method for the operation * being invoked. * upon successful user authentication, samsung pay returns the "payment info" structure and the result string. * the result string is forwarded to the pg for transaction completion and will vary based on the requirements of the pg used. * the code example below illustrates how to populate payment information in each field of the paymentinfo class. */ private fun maketransactiondetailswithsheet(): customsheetpaymentinfo? { val brandlist = brandlist val extrapaymentinfo = bundle() val customsheet = customsheet() customsheet.addcontrol(makeamountcontrol()) return customsheetpaymentinfo.builder() .setmerchantid("123456") .setmerchantname("sample merchant") .setordernumber("amz007mar") // if you want to enter address, please refer to the javadoc : // reference/com/samsung/android/sdk/samsungpay/v2/payment/sheet/addresscontrol.html .setaddressinpaymentsheet(customsheetpaymentinfo.addressinpaymentsheet.do_not_show) .setallowedcardbrands(brandlist) .setcardholdernameenabled(true) .setrecurringenabled(false) .setcustomsheet(customsheet) .setextrapaymentinfo(extrapaymentinfo) .build() } private fun makeamountcontrol(): amountboxcontrol { val amountboxcontrol = amountboxcontrol(amount_control_id, "usd") amountboxcontrol.additem(product_item_id, "item", 990.99, "") amountboxcontrol.additem(product_tax_id, "tax", 5.0, "") amountboxcontrol.additem(product_shipping_id, "shipping", 1.0, "") amountboxcontrol.setamounttotal(996.99, amountconstants.format_total_price_only) return amountboxcontrol } private val brandlist: arraylist<spaysdk.brand> get() { val brandlist = arraylist<spaysdk.brand>() brandlist.add(spaysdk.brand.visa) brandlist.add(spaysdk.brand.mastercard) brandlist.add(spaysdk.brand.americanexpress) brandlist.add(spaysdk.brand.discover) return brandlist } request payment with a custom payment sheet the startinapppaywithcustomsheet() method of the paymentmanager class is applied to request payment using a custom payment sheet in samsung pay. when you call the startinapppaywithcustomsheet() method, a custom payment sheet is displayed on the merchant app screen. from there, the user can select a registered card for payment and change the billing and shipping addresses as necessary. the payment sheet lasts for 5 minutes after calling the api. if the time limit expires, the transaction fails. in the mainactivity class, declare the paymentmanager variable. private lateinit var paymentmanager: paymentmanager then, in oncreate(), set an onclicklistener method before calling the updatesamsungpaybutton function to trigger the startinapppaywithcustomsheet function when the samsungpaybutton is clicked. databinding.samsungpaybutton.setonclicklistener { startinapppaywithcustomsheet() } lastly, create a function to call startinapppaywithcustomsheet() method of the paymentmanager class. /* * paymentmanager.startinapppaywithcustomsheet is a method to request online(in-app) payment with samsung pay. * partner app can use this method to make in-app purchase using samsung pay from their * application with custom payment sheet. */ private fun startinapppaywithcustomsheet() { paymentmanager = paymentmanager(applicationcontext, partnerinfo) paymentmanager.startinapppaywithcustomsheet( maketransactiondetailswithsheet(), transactioninfolistener ) } /* * customsheettransactioninfolistener is for listening callback events of online (in-app) custom sheet payment. * this is invoked when card is changed by the user on the custom payment sheet, * and also with the success or failure of online (in-app) payment. */ private val transactioninfolistener: paymentmanager.customsheettransactioninfolistener = object : paymentmanager.customsheettransactioninfolistener { // this callback is received when the user changes card on the custom payment sheet in samsung pay. override fun oncardinfoupdated(selectedcardinfo: cardinfo, customsheet: customsheet) { /* * called when the user changes card in samsung pay. * newly selected cardinfo is passed and partner app can update transaction amount based on new card (if needed). * call updatesheet() method. this is mandatory. */ paymentmanager.updatesheet(customsheet) } override fun onsuccess( response: customsheetpaymentinfo, paymentcredential: string, extrapaymentdata: bundle ) { /* * you will receive the payloads shown below in paymentcredential parameter * the output paymentcredential structure varies depending on the pg you're using and the integration model (direct, indirect) with samsung. */ toast.maketext(applicationcontext, "onsuccess() ", toast.length_short).show() } // this callback is received when the online payment transaction has failed. override fun onfailure(errorcode: int, errordata: bundle?) { toast.maketext(applicationcontext, "onfailure() ", toast.length_short).show() } } run the app after building the apk, you can run the sample merchant app and see how it connects to samsung pay upon clicking the button at the bottom of the screen. to thoroughly test the sample app, you must add at least one card to the samsung pay app. you're done! congratulations! you have successfully achieved the goal of this code lab. now, you can integrate in-app payment with your app by yourself! if you're having trouble, you may download this file: in-app payment complete code (525.20 kb) to learn more about developing apps for samsung pay devices, visit: developer.samsung.com/pay