SDK Programming Guide
  • 3.3.5 Creating a transaction request
  • Partner apps: Merchant

    Upon successful initialization of the SamsungPay class, the merchant app should create a transaction request with payment information. Samsung Pay offers two types of online payment sheet―a normal and custom.

    The normal payment sheet has fixed display items ― “Items”, “Tax”, and “Shipping”. If these items are not applicable for your merchant needs, you should use the custom payment sheet. The custom payment sheet offers more dynamic controls for tailoring the UI look and feel with additional customer order and payment data.

    • Note
    • SDK v1.8.00 does not currently support In-App payments using Discover card. Support for Discover will be included in a subsequent SDK release. In all cases, merchant app developers will need to update their apps with the latest version of the SDK to respond to Samsung Pay callbacks to avoid timing out using an earlier version of the SDK.
  • Using a normal payment sheet
  • When initiating a payment transaction, the merchant app should populate the following mandatory fields in payment information:
    • Merchant Name - as it will appear on the Payment Sheet of Samsung Pay and the user's card account statement
    • Amount - the constituent transaction properties (currency, item price, shipping price, tax, total price) which together determine the total amount the user is agreeing to pay the merchant
      • Caution
      • Not populating the mandatory fields will throw an IllegalArgumentException.

      Optionally, the following fields can be added to the payment information:

    • Merchant ID - can be used for the merchant’s own designated purpose at its discretion unless merchant uses an Indirect Payment Gateway like Stripe. If an indirect PG is used, this field must be set to the merchant’s Payment Gateway ID fetched from the Samsung Pay Developers portal upon product creation.
    • Order Number - usually created by the merchant app via interaction with a PG. This number is required for refunds and chargebacks. In the case of VISA cards, this value is mandatory. The allowed characters are [A-Z][a-z][0-9,-] and the length of the value can be up to 36 characters.
    • Payment Protocol - specified based on the PG used by the merchant. The Samsung Pay SDK currently supports 3D Secure only.
    • Shipping Address - shipping destination given to Samsung Pay; related to delivery address.
    • Address on the Payment Sheet - one of six “Address on the Payment Sheet” options regarding billing and/or shipping address (see Address in Payment Sheet for details). The “Shipping Address” field is mandatory if SEND_SHIPPING or NEED_BILLING_AND_SEND_SHIPPING is set for the “Address on the Payment Sheet” option.
    • Allowed Card Brands - specifies the merchant-supported card brand. If the supported card brand is not specified, all card brands in Samsung Pay can be listed on the Payment Sheet (see Configuring the Payment Sheet UI for details).
    • Recurring - depending on the PG and merchant app, recurring payment can be support; merchant app can set the “Recurring” billing option for cardholder selection and agreement.
      • Caution
      • Only one billingAddress is allowed in Samsung Pay 2.5.1.
    • The snippet below demonstrates the “Payment Info” structure of the PaymentInfo class, which includes each of the fields above.
  • public class PaymentInfo implements Parcelable { 
    		private String version; 
    		private Amount amount;
    		private Address shippingAddress; 
    		private Address billingAddress;  
    		private String merchantId;
    		private String merchantName;
    		private String orderNumber;
    		private PaymentProtocol paymentProtocol;
    		private AddressInPaymentSheet addressInPaymentSheet = AddressInPaymentSheet.DO_NOT_SHOW;
    		private List<Brand> allowedCardBrand;
    		private boolean isCardHolderNameRequired = false;
    		private boolean isRecurring = false;
    		private String merchantCountryCode;
    		private Bundle extraPaymentInfo;
    }
    
  • 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 PaymentInfo makeTransactionDetails() {
    	ArrayList<PaymentManager.Brand> brandList = new ArrayList<>();
    	// If the supported brand is not specified, all card brands in Samsung Pay are listed 
             // in the Payment Sheet.
    
    	brandList.add(PaymentManager.Brand.MASTERCARD);
    	brandList.add(PaymentManager.Brand.VISA);
    	brandList.add(PaymentManager.Brand.AMERICANEXPRESS);
    	PaymentInfo.Address shippingAddress = new PaymentInfo.Address.Builder()
    				.setAddressee("name")
    				.setAddressLine1("addLine1")
    				.setAddressLine2("addLine2")
    				.setCity("city")
    				.setState("state")
    				.setCountryCode("United States")
    				.setPostalCode("zip")
    				.build();
    	PaymentInfo.Amount amount = new PaymentInfo.Amount.Builder()
    				.setCurrencyCode("USD")
    				.setItemTotalPrice("1000")
    				.setShippingPrice("10")
    				.setTax("50")
    				.setTotalPrice("1060")
    				.build();
    			   PaymentInfo.Builder paymentInfoBuilder = new PaymentInfo.Builder();
    			   PaymentInfo paymentInfo = PaymentInfo.Builder()
    				.setMerchantId("123456")
    				.setMerchantName("Sample Merchant")
    				.setOrderNumber("AMZ007MAR")
    				.setPaymentProtocol(PaymentInfo.PaymentProtocol.PROTOCOL_3DS)
    							// Merchant requires billing address from Samsung Pay and 
    							// sends the shipping address to Samsung Pay.
    							// Option shows both billing and shipping address on the payment sheet.
    							.setAddressInPaymentSheet(PaymentInfo.AddressInPaymentSheet.
    NEED_BILLING_SEND_SHIPPING)
    				.setShippingAddress(shippingAddress)
    				.setAllowedCardBrands(brandList)
    				.setCardHolderNameEnabled(true)
    				.setRecurringEnabled(false)
    				.setAmount(amount)
    				.build();
    		 return paymentInfo;
    }
    
  • Requesting Payment with normal payment sheet
  • The startInAppPay() method of the PaymentManager class is used to request payment with Samsung Pay, although the merchant app must first pass a valid PartnerInfo to PaymentManager for caller verification. The PaymentManager class furnishes the following API methods for transacting payments:
    • startInAppPay() - initiates payment request with Samsung Pay.
    • updateAmount() - updates the transaction amount if shipping address/card information is changed by Samsung Pay.
    • updateAmountFailed() - returns an error code when the new amount cannot be updated due to a wrong address.
  • To request payment, call the startInAppPay() method with the following data:
    • PaymentInfo - Payment Info structure containing the constituent payment information.
    • TransactionInfoListener - result of payment request is delivered here; this listener should be registered before calling startInAppPay().
      When the startInAppPay() method is called, the online payment sheet of the Samsung Pay app displays on the merchant app screen. The user can choose a card for payment from the list of registered cards in Samsung Pay and change the billing and shipping addresses as necessary.

      The result is delivered to TransactionInfoListener, which provides one of the following events:

      • onSuccess() - called when Samsung Pay confirms payment. It provides the PaymentInfo object and the paymentCredential JSON string.
        PaymentInfo is payment information used for the current transaction containing amount, shippingAddress, merchantId, merchantName, orderNumber, and paymentProtocol. API methods exclusively available in the onSuccess() callback comprise:
        • isFastCheckout() - returns whether or not the Fast Checkout option was executed for the transaction
        • getPaymentCardLast4DPAN() - returns the last 4 digits of the user's digitized personal identification numbers (DPAN)
        • getPaymentCardLast4FPAN() - returns the last digits of the user's funding personal identification number (FPAN)
        • getPaymentCardBrand() - returns the brand of the card used for the transaction
        • getPaymentCurrencyCode() - returns the ISO currency code governing the transaction
        • getPaymentShippingAddress() - returns the shipping/delivery address for the transaction
          For merchants using PGs participating under the direct model, paymentCredential is a JSON object containing an encrypted cryptogram, which can be passed to the PG. For PGs participating under the indirect model, the JSON object contains a reference (card reference, a token ID generated by the PG) and status (AUTHORIZED, PENDING, CHARGED, or REFUNDED). See Sample paymentCredential for additional details.
      • onFailure() - called when a transaction fails; returns the error code and errorData bundle for the failure
  • The following example demonstrates how to call the startInAppPay() method of the PaymentManager class.
  • private void startInAppPay() {
    	// PaymentManager.startInAppPay method to show normal payment sheet
    	try {
    		Bundle bundle = new Bundle();
    		bundle.putString(SamsungPay.PARTNER_SERVICE_TYPE, SamsungPay.ServiceType.INAPP_PAYMENT.toString());
    		PartnerInfo partnerInfo = new PartnerInfo(serviceId, bundle);
    		paymentManager = new PaymentManager(context, partnerInfo);
    
    	    /*
    		* PaymentManager.startInAppPay is a method to request online (In-App) payment 
    		* with Samsung Pay.
    		* Merchant app can use this method to make In-App purchase using Samsung Pay from their
    		* application with normal payment sheet.
    		*/
    		paymentManager.startInAppPay(makeTransactionDetails(), transactionListener);
    	         } catch (NullPointerException e) {
    		     Toast.makeText(context, "All mandatory fields cannot be null.", Toast.LENGTH_LONG).show();
    		     e.printStackTrace();
    	         } catch (IllegalStateException e) {
    		     Toast.makeText(context, "IllegalStateException", Toast.LENGTH_LONG).show();
    		     e.printStackTrace();
    	         } catch (NumberFormatException e) {
    		     Toast.makeText(context, "Amount values is not valid", Toast.LENGTH_LONG).show();
    		     e.printStackTrace();
    	         } catch (IllegalArgumentException e) {
    		     Toast.makeText(context, "PaymentInfo values are not valid or all mandatory fields are not set.", Toast.LENGTH_LONG).show();
    		     e.printStackTrace();
    	         }
              } 
    
    /*
     * TransactionInfoListener is for listening callback events of online (In-App)
     * payment. This is invoked when card or address is changed by the user on the 
     * payment sheet, and also with the success or failure of online (In-App) payment.
     */
    private PaymentManager.TransactionInfoListener transactionListener = new PaymentManager.TransactionInfoListener() {
    	// This callback is received when the user modifies or selects a new address
        // on the payment sheet.
    	@Override
    	public void onAddressUpdated(PaymentInfo paymentInfo) {
    		try {
    			// Do address verification by merchant app
    			/* setAddressInPaymentSheet(PaymentInfo.AddressInPaymentSheet.
    			* NEED_BILLING_SEND_SHIPPING)
    			* If you set NEED_BILLING_SEND_SHIPPING or NEED_BILLING_SPAY with
    			* like upper codes,
    			* you can get Billing Address with getBillingAddress().
    			* If you set NEED_BILLING_AND_SHIPPING or NEED_SHIPPING_SPAY,
    			* you can get Shipping Address with getShippingAddress().
    			 */
    
    			PaymentInfo.Address billing_address = paymentInfo.getBillingAddress();
    			int billing_errorCode = validateBillingAddress(billing_address);
    			// Call updateAmount() or updateAmountFailed() method. This is mandatory.
    			if (billing_errorCode != PaymentManager.ERROR_NONE)
    				paymentManager.updateAmountFailed(billing_errorCode);
    			else {
    				PaymentInfo.Amount amount = new PaymentInfo.Amount.Builder()
    			          .setCurrencyCode("USD")
    				     .setItemTotalPrice("1000.00")
    				     .setShippingPrice("10.00")
    				     .setTax("50.00")
    				     .setTotalPrice("1060.00")
    				     .build();
    				paymentManager.updateAmount(amount);
    			}
    		} catch (IllegalStateException | NullPointerException e){
    			e.printStackTrace();
    		}
    	}
    
    	//This callback is received when the user changes card on the payment sheet in Samsung Pay
    	@Override
    	public void onCardInfoUpdated(CardInfo selectedCardInfo) {
    		/*
    		 * Called when the user changes card in Samsung Pay.
    		 * Newly selected cardInfo is passed and merchant app can update transaction
                       * amount based on new card (if needed).
    		 */
    		try {
    			PaymentInfo.Amount amount = new PaymentInfo.Amount.Builder()
    					.setCurrencyCode("USD")
    					.setItemTotalPrice("1000.00")
    					.setShippingPrice("10.00")
    					.setTax("50.00")
    					.setTotalPrice("1060.00")
    					.build();
    
    			// Call updateAmount() method. This is mandatory.
    			paymentManager.updateAmount(amount);
    		} catch (IllegalStateException | NullPointerException e){
    			e.printStackTrace();
    		}
    	}
    
    	/*
    	 * This callback is received when the online (In-App) payment transaction is approved by
    	 * user and able to successfully generate In-App payload.
    	 * The payload could be an encrypted cryptogram (direct In-App payment)
    	 * or Payment Gateway's token reference ID (indirect In-App payment).
    	 */
    	@Override
    	public void onSuccess(PaymentInfo response, String paymentCredential, Bundle extraPaymentData) {
    		Toast.makeText(context, "Transaction : onSuccess", Toast.LENGTH_LONG).show();
    		// You can use PaymentInfo, paymentCredential and extraPaymentData.
    	}
    
    	// This callback is received when the online payment transaction has failed.
    	@Override
    	public void onFailure(int errorCode, Bundle errorData) {
    		Toast.makeText(context, "Transaction : onFailure : "+ errorCode, Toast.LENGTH_LONG).show();
    	}
    };
    
  • Call the updateAmountFailed() API method if the address provided by Samsung Pay is invalid, out of delivery, or does not exist; For example:
    • Merchant does not support the product delivery to the designated location
    • Billing address from Samsung Pay is invalid for tax recalculation.
  • In such cases, the merchant app should call the updateAmountFailed() with one of the following error codes:
    • ERROR_SHIPPING_ADDRESS_INVALID
    • ERROR_SHIPPING_ADDRESS_UNABLE_TO_SHIP
    • ERROR_SHIPPING_ADDRESS_NOT_EXIST
    • ERROR_BILLING_ADDRESS_INVALID
    • ERROR_BILLING_ADDRESS_NOT_EXIST
  • The code example below demonstrates the use of the updateAmountFailed() method in the merchant app.
  • // This callback is received when the user modifies or selects a new address on the payment sheet.
    @Override
    public void onAddressUpdated(PaymentInfo paymentInfo) {
    	try {
    		// Do address verification by merchant app
    
    		/* setAddressInPaymentSheet(PaymentInfo.AddressInPaymentSheet.NEED_BILLING_SEND_SHIPPING)
    		* If you set NEED_BILLING_SEND_SHIPPING or NEED_BILLING_SPAY with like upper codes,
    		* you can get Billing Address with getBillingAddress().
    		* If you set NEED_BILLING_AND_SHIPPING or NEED_SHIPPING_SPAY,
    		* you can get Shipping Address with getShippingAddress().
    		*/
    		PaymentInfo.Address billing_address = paymentInfo.getBillingAddress();
    		int billing_errorCode = validateBillingAddress(billing_address);
    
    		if (billing_errorCode != PaymentManager.ERROR_NONE)
    			paymentManager.updateAmountFailed(billing_errorCode);
    		else {
    			PaymentInfo.Amount amount = new PaymentInfo.Amount.Builder()
    			     .setCurrencyCode("USD")
    			     .setItemTotalPrice("1000.00")
    			     .setShippingPrice("10.00")
    			     .setTax("50.00")
    			     .setTotalPrice("1060.00")
    			     .build();
    
    			// Call updateAmount() method. This is mandatory.
    			paymentManager.updateAmount(amount);
    		}
    		} catch (IllegalStateException | NullPointerException e){
    		     e.printStackTrace();
         	      }
    }
    
    • Note
    • The onAddressUpdated() callback is available for the normal payment sheet only. It is unavailable for custom payment sheet. Refer to sheetUpdatedListener for custom payment sheet.
  • Using a custom payment sheet
  • To initiate a payment transaction with custom payment sheet, the merchant app should populate the following fields in CustomSheetPaymentInfo. Many of the same PaymentInfo fields used for the normal payment sheet are used for custom payment sheets. See Using a normal payment sheet above for descriptions of the common fields. The essential difference in the CustomSheetPaymentInfo class is that CustomSheet is added in place of Amount and Address.
    • Note
    • Developers should modify their merchant app codes in accordance with this guide when using the Samsung Pay’s custom payment sheet, even if they worked with earlier versions of the SDK.
  • The following example shows the CustomSheetPaymentInfo structure.
  • public class CustomSheetPaymentInfo implements Parcelable {
    		private String version;
    		private String merchantId;
    		private String merchantName;
    		private String orderNumber;
    		private PaymentProtocol paymentProtocol;
    		private AddressInPaymentSheet addressInPaymentSheet = AddressInPaymentSheet.DO_NOT_SHOW;
    		private List allowedCardBrand;
    		private CardInfo cardInfo;
    		private boolean isCardHolderNameRequired = false;
    		private boolean isRecurring = false;
    		private String merchantCountryCode;
    		private CustomSheet customSheet;
    		private Bundle extraPaymentInfo;
    }
    
  • The merchant app sends this CustomSheetPaymentInfo to Samsung Pay via the applicable Samsung Pay SDK API methods. Upon successful user authentication, Samsung Pay returns the "Payment Info" structure and the result string. The result string is forwarded to the PG to complete the transaction and can vary based on the PG used.
  • The following example demonstrates how to populate customSheet in the CustomSheetPaymentInfo class. See Sample merchant app using custom payment sheet below for each CustomSheet control.
  • /*
    * Make user's transaction details.
    * The merchant app should send CustomSheetPaymentInfo to Samsung Pay via 
    * the applicable Samsung Pay SDK API method for the operation being invoked.
    */
    private CustomSheetPaymentInfo makeCustomSheetPaymentInfo() {
    		ArrayList bList = new ArrayList<>();
    		// If the supported brand is not specified, all card brands in Samsung Pay are 
    		// listed in the Payment Sheet.
    		brandList.add(PaymentManager.Brand.VISA);
    		brandList.add(PaymentManager.Brand.MASTERCARD);
    		brandList.add(PaymentManager.Brand.AMERICANEXPRESS);
    
    		/*
    		* Make SheetControls you want and add to custom sheet.
    		* Each SheetControl is located in sequence.
    		* There must be a AmountBoxControl and it must be located on last.
    		*/
    		CustomSheet customSheet = new CustomSheet();
    		customSheet.addControl(makeBillingAddressControl());
    		customSheet.addControl(makeShippingAddressControl());
    		customSheet.addControl(makePlainTextControl());
    		customSheet.addControl(makeShippingMethodSpinnerControl());
    		// customSheet.addControl(makeInstallmentSpinnerControl());
    		customSheet.addControl(makeAmountControl());
    
    		CustomSheetPaymentInfo customSheetPaymentInfo = new CustomSheetPaymentInfo.Builder()
    				.setMerchantId("123456")
    				.setMerchantName("Sample Merchant")
    				.setOrderNumber("AMZ007MAR")
    				.setPaymentProtocol(CustomSheetPaymentInfo.PaymentProtocol.PROTOCOL_3DS)
    				// Merchant requires billing address from Samsung Pay and 
    				//sends the shipping address to Samsung Pay.
    				// Show both billing and shipping address on the payment sheet.
    				.setAddressInPaymentSheet(CustomSheetPaymentInfo.AddressInPaymentSheet.
    NEED_BILLING_SEND_SHIPPING)
    				.setAllowedCardBrands(bList)
    				.setCardHolderNameEnabled(true)
    				.setRecurringEnabled(false)
    				.setCustomSheet(customSheet)
    				.build();
    		return customSheetPaymentInfo;
    } 
    
  • Requesting payment with custom payment sheet
  • The startInAppPayWithCustomSheet() method of the PaymentManager class is applied to request payment using a custom payment sheet in Samsung Pay. PaymentManager also provides an updating method. The two methods are defined as follows:
    • startInAppPayWithCustomSheet() - initiates the payment request with a custom payment sheet. After the API is called, the payment sheet persists for 5 minutes. If the timer is expires, the transaction fails.
    • updateSheet() - updates the custom payment sheet if any values on the sheet are changed. As of API level 1.5, a merchant app can update the custom sheet with a custom error message. Refer to Updating sheet with custom error message.
      When you call the startInAppPayWithCustomSheet() method, a custom payment sheet is displayed on the merchant app screen. From it, the user can select a registered card for payment and change the billing and shipping addresses, as necessary.

      The result is delivered to CustomSheetTransactionInfoListener, which provides the following events:

      • onCardInfoUpdated() - called when the user changes the payment card. In this callback, updateSheet() method must be called to update current payment sheet.
      • onSuccess() - called when Samsung Pay confirms payment. It provides the CustomSheetPaymentInfo object and the paymentCredential JSON string.

        The CustomSheetPaymentInfo is payment information used for the current transaction containing amount, shippingAddress, merchantId, merchantName, orderNumber, and paymentProtocol. API methods exclusively available in the onSuccess() callback comprise:

          • isFastCheckout() - returns whether or not the Fast Checkout option was executed for the transaction
          • getPaymentCardLast4DPAN() - returns the last 4 digits of the user's digitized personal/primary identification number (DPAN)
          • getPaymentCardLast4FPAN() - returns the last 4 digits of the user's funding personal/primary identification number (FPAN)
          • getPaymentCardBrand() - returns the brand of the card used for the transaction
          • getPaymentCurrencyCode() - returns the ISO currency code in which the transaction is valued
          • getPaymentShippingAddress() - returns the shipping/delivery address for the transaction
          • getPaymentShippingMethod() - returns the shipping method for the transaction.

        For the Payment Gateway using direct model, the paymentCredential is a JSON object containing encrypted cryptogram which can be passed to the PG. For the Payment Gateway using indirect model like Stripe, it is a JSON object containing reference (card reference – a token ID generated by the PG) and status (AUTHORIZED, PENDING, CHARGED, or REFUNDED). Refer to Sample paymentCredential for details.

      • onFailure() - called when the transaction fails; returns the error code and errorData bundle for the failure.
      • The following example demonstrates how to call the startInAppPayWithCustomSheet()method of the PaymentManager class.
      • /*
         * 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 PaymentManager.CustomSheetTransactionInfoListener transactionListener
        		= new PaymentManager.CustomSheetTransactionInfoListener() {
        		// This callback is received when the user changes card on the custom payment sheet 
        		// in Samsung Pay.
        		@Override
        	public void onCardInfoUpdated(CardInfo selectedCardInfo, CustomSheet customSheet) {
        		/* 
        		* Called when the user changes card in Samsung Pay.
        		* Newly selected cardInfo is passed and merchant app can update transaction amount
        		* based on new card (if needed).
        		*/
        
        		AmountBoxControl amountBoxControl = (AmountBoxControl)
                customSheet.getSheetControl(AMOUNT_CONTROL_ID);
                 
        		// You can set discount rate. Set discount rate for each card 
        		// brand(optional).
        		amountBoxControl.updateValue(PRODUCT_ITEM_ID, 1000);
        		amountBoxControl.updateValue(PRODUCT_TAX_ID, 50);
        		amountBoxControl.updateValue(PRODUCT_SHIPPING_ID, 10);
        		amountBoxControl.updateValue(PRODUCT_FUEL_ID, 0, "Pending");
        		amountBoxControl.setAmountTotal(1060, AmountConstants.FORMAT_TOTAL_PRICE_ONLY);
        		customSheet.updateControl(amountBoxControl);
        		// Call updateSheet() method. This is mandatory.
        		try { 
        			     paymentManager.updateSheet(customSheet);
        		} catch (IllegalStateException | NullPointerException e) {
        				   e.printStackTrace();
        		 }
        	}
        
        	/*
        	* This callback is received when the online (In-App) payment transaction is
        	* approved by the user and successfully generates the In-App payload. The
        	* payload can be an encrypted cryptogram (direct In-App payment) or the PG's
        	* token reference ID (indirect In-App payment).
        	*/
        	@Override
        	public void onSuccess(CustomSheetPaymentInfo response, String paymentCredential, Bundle extraPaymentData) {
        	 /*
        	  * Called when Samsung Pay successfully creates the In-App cryptogram; Merchant app sends 
        	  * this cryptogram to the merchant server or PG to complete In-App payment
        	  */
           try {
        		String DPAN = response.getCardInfo().getCardMetaData().getString(SpaySdk.EXTRA_LAST4_DPAN, "Null");
        		String FPAN = response.getCardInfo().getCardMetaData().getString(SpaySdk.EXTRA_LAST4_FPAN, "Null");
        		Snackbar.make(fragmentView, " DPAN: " + DPAN + " FPAN: " + FPAN, Snackbar.LENGTH_LONG).setAction(getString(R.string.ok), 
        		new View.OnClickListener() {
        				@Override
        				public void onClick(View v) {
        				}
        		}).show();
        	} catch (NullPointerException e) {
        	  e.printStackTrace();
        	}
        
        			Toast.makeText(context, "Transaction : onSuccess", Toast.LENGTH_LONG).show();
        			// You can use PaymentInfo, paymentCredential and extraPaymentData.
        	}
        
        	// This callback is received when the online payment transaction has failed.
        	@Override
        	public void onFailure(int errorCode, Bundle errorData) {
        			// Called when some error occurred during In-App cryptogram generation.
        			Toast.makeText(context, "Transaction : onFailure : "+ errorCode, Toast.LENGTH_LONG).show();
        	}
        }; 
        
        private void startInAppPayWithCustomSheet() {
        	// PaymentManager.startInAppPayWithCustomSheet to show custom payment sheet.
        
        	try {
        			Bundle bundle = new Bundle();
        			bundle.putString(SamsungPay.PARTNER_SERVICE_TYPE, SamsungPay.ServiceType.INAPP_PAYMENT.toString());
        			final PartnerInfo partnerInfo = new PartnerInfo(serviceId, bundle);
        			paymentManager = new PaymentManager(context, partnerInfo);
        
        		/*
        		* PaymentManager.startInAppPayWithCustomSheet is Method to request online(In-App) 
        		* payment with Samsung Pay.
        		* Merchant app can use this Method to make In-App purchase using Samsung Pay from their
        		* application with custom payment sheet.
        		*/
        	   paymentManager.startInAppPayWithCustomSheet(makeCustomSheetPaymentInfo(), 
        transactionListener);
        
        	} catch (NullPointerException e) {
        			Toast.makeText(context, SHORTTAG + "All mandatory fields cannot be null.", Toast.LENGTH_LONG).show();
        			e.printStackTrace();
        	} catch (IllegalStateException e) {
        			Toast.makeText(context, SHORTTAG + "IllegalStateException", Toast.LENGTH_LONG).show();
        			e.printStackTrace();
        	} catch (NumberFormatException e) {
        			Toast.makeText(context, SHORTTAG + "Amount values are not valid", Toast.LENGTH_LONG).show();
        			e.printStackTrace();
        	} catch (IllegalArgumentException e) {
        			Toast.makeText(context, SHORTTAG + "PaymentInfo values are not valid or all mandatory fields are not set.", 
        			Toast.LENGTH_LONG).show();
        			e.printStackTrace();
        	}
        }
        
    • Use the updateSheet() method when the address is updated on the custom payment sheet. errorCode should be set if the address provided by Samsung Pay app is invalid, out of delivery, or does not exist. For example:
      • Merchant does not support the product delivery to the designated location
      • Billing address from Samsung Pay is not valid for tax recalculation

        For such cases, the merchant app should call updateSheet() with one of the following error codes:

        • ERROR_SHIPPING_ADDRESS_INVALID
        • ERROR_SHIPPING_ADDRESS_UNABLE_TO_SHIP
        • ERROR_SHIPPING_ADDRESS_NOT_EXIST
        • ERROR_BILLING_ADDRESS_INVALID
        • ERROR_BILLING_ADDRESS_NOT_EXIST
    • The sample code in Applying the Address Control illustrates how to use the updateSheet() method for addressesControl in a custom payment sheet.