Uh oh! We couldn’t find any match.

Please try other search keywords.

Bixby Developer Center

Guides

Supporting Payments

To allow users to pay for purchases, Bixby provides native integration of Samsung Payment Services (SPS). If your region does not currently support Spreedly, you can use different payment gateways.

Note

Support for Samsung Payment is currently limited to specific developers. If you are interested in integrating Samsung Payment in your capsule, reach out to the Samsung Developer Relations team for more information.

Configuring Endpoints for Payments

In order to implement SPS, you need to configure your endpoints file either with local endpoints or remote endpoints.

SPS Payments Using Local Endpoints

To process payments through SPS using local endpoints, invoke the payment by calling http.spsProxyPost in the JavaScript file, passing headers and a body in the following manner:

  var options = {}
options.headers = {"Content-Type" : "application/json", "User" : "blah"}
options.body = "\"{ \"product_id\": \"916598\", \"card_number\": \"{{credit_card_number}}\" }\"";
The options can also include the url of the merchant api the payment should be delivered too.
options.url = "https://transfer-money-to-account"
var wev = http.spsProxyPost(options)

Notice that you can also pass to options a URL of the merchant API that the payment should be delivered to.

Within your *.endpoints.bxb file, add a payment-methods block that includes details of the SPS payment, including:

  • merchant ID
  • merchant URL
  • supported cards
  • whether CVV verification is required
  • payment details such as amount, currency, and itemized details

Here is an example of how a local endpoint could look with SPS information:

...
action-endpoints{
action-endpoint(paymentAction){
payment-methods{
sps{
merchant{
name(transfer-money-to-account)
url{
template (https://transfer-money-to-account.com/purchase/post)
}
spreedly-receiver-type (test)
test-api-hostname (https://transfer-money-to-account.com/) //optional, but required if testing in Simulator
supported-card(VISA)
supported-card(MASTER)
cvv-verification (false)
}
payment{
amount (SomeStruct.amount) // must evaluate to a numeric type (decimal/integer)
currency (SomeStruct.currency) // must evaluate to a String type (text/name) and be a valid ISO 4217 currency code
items(payInfo.items){
where-each (item){
item{
name(item.name) // must evaluate to a String type (text/name)
amount(item.amount) // must evaluate to a numeric type (decimal/integer)
count(item.count) // must evaluate to a integer
}
}
}
}
}
}
}
}
...
Note

The url child key of merchant-api is optional. If it is not specified, you need to add it to the options in your javascript: options.url = "https://transfer-money-to-account".

SPS Payments Using Remote Endpoints

With remote endpoints, you provide the payments details as you do with local endpoints. However, you also provide headers and body details using variables and functions in the remote-endpoint block of your *.endpoints.bxb file:

...
action-endpoints {
action-endpoint (paymentAction) {
payment-methods {
sps {
merchant {
name (transfer-money-to-alex-account)
url {
template (http://ptsv2.com/t/vivspstest/post)
}
spreedly-receiver-type (test)
//test-api-hostname (http://ptsv2.com/) //required if testing in Simulator
supported-card(VISA)
supported-card(MASTER)
cvv-verification (false)
}
payment {
amount (payInfo.amount)
currency (payInfo.currency)
// Both 'items' and 'item' are optional, but at least one needs to be present.
// It is possible to have multiple 'items' and 'item's and a combination of both.
items (payInfo.items) {
where-each (item) {
item {
name("#{value(item.name)}")
amount(item.amount)
//count(item.count) // Optional. Should be specified when it applies.
}
}
}
}
}
}
remote-endpoint (https://transfer-money-to-alex-acount.com) {
headers {
header (some-merchant-api-header:some-header-value)
}
body {
template ("{ \"product_id\": \"916598\", \"card_number\": \"{{credit_card_number}}\" }\"")
}
method (POST)
}
}
}
...

For more information on SPS payments, read about related keys in the Reference Guide.

SPS Payment Variables and Functions

As part of the body or headers, you can include a number of credit card variables:

VariableDescription
credit_card_tokenThe Spreedly payment method token
credit_card_numberThe full credit card number of the payment method
credit_card_verification_valueThe CVV of the credit card
credit_card_first_nameThe card holder’s first name
credit_card_last_nameThe card holder’s last name
credit_card_monthThe numerical month of the credit card’s expiration date (example: 4 for April)
credit_card_yearThe four digit year of the credit card’s expiration date (example: 2015)
credit_card_expiration_dateThe credit card’s expiration date (example: 2020-04-01)
credit_card_created_atThe credit card’s created_at date (example: 2016-07-13 14:14:03 UTC)
credit_card_updated_atThe credit card’s updated_at date (example: 2016-07-13 14:14:03 UTC)
credit_card_typeThe type, or brand, of the card. Allowable values are: visa, master, american_express, discover, jcb, diners_club, dankort, maestro, carnet
credit_card_emailThe card holder’s email address
credit_card_address1The card holder’s billing address line 1
credit_card_address2The card holder’s billing address line 2
credit_card_cityThe card holder’s billing city
credit_card_stateThe card holder’s billing state
credit_card_zipThe card holder’s billing zip
credit_card_countryThe card holder’s billing country
credit_card_phone_numberThe card holder’s phone number

Additionally, you can use the following functions in requests:

FunctionDescription
aesEncrypt contents using the Advanced Encryption Standard (AES) symmetric encryption algorithm.
base64Base 64 encode contents.
Example: {{#base64}}contents to encode{{/base64}}
binary_security_tokenFor receivers that require an x509 certificate (for example: Mastercard), the binary_security_token inserts the Base64 encoded certificate.
bytes_hexTakes a hex string and turns it into raw bytes. This function is rarely useful by itself, but can be helpful when paired with functions such as aes.<
Example: {{#bytes_hex}}hexadecimal string to decode{{/bytes_hex}}
card_type_mappingOutput a custom card brand.
Example: {{#card_type_mapping}}brand:output,brand:output{{/card_type_mapping}}
Any card types whose value is not mapped in the function body will have the default credit_card_type value used. For example, if Diners Club card type is not specified the default diners_club would be output.
credit_card?If the payment method is a credit card payment method, evaluates to true. You can use this to conditionally evaluate a section.
Example: {{#credit_card?}}I'm a credit card payment method{{/credit_card?}}
digestDigests contents using the specified digest algorithm. The digest algorithm can be one of sha512 or sha256. Because the raw output is in binary form you will often use the digest function embedded within another encoding function, such as base64, to produce web-safe output.
Example: {{#base64}}{{#digest}}sha512,{{ credit_card_number }}{{/digest}}{{/base64}}
format_dateParse a date value to a specific string format.
Example: {{#format_date}}%m%y,{{credit_card_expiration_date}}{{/format_date}}
Parse a date value to a specific string format. The format specifier syntax is based on the posix date format.
gpgFor some SFTP endpoints (batch export), the receiver requires the uploaded file to be encrypted using GnuPG and their public key.
Example: {{#gpg}}full pem,recipient identity,file template to encrypt{{/gpg}}
The gpg function takes the public key in PEM form as the first argument, the target identity as the second (email address of the recipient), and the content to encrypt as the third. The third argument will be your entire templated export which can include other receiver functions are variables.
hex_bytesTakes a byte string and turns it into a hex string.
Example: {{#hex_bytes}}delimiter,byte string to encode{{/hex_bytes}}
hex_digestComputes the HMAC of a given payload. The payload is returned as a hexadecimal string. The digest algorithm can be any of SHA1, SHA256, or SHA512.
Example: {{#hmac}}digest algorithm,secret key,payload whose digest is desired{{/hmac}}
lastGet the last characters of a value.
Example: {{#last}}num,contents{{/last}}
md5Calculate the MD5 digest of the contents.
Example: {{#md5}}value to digest{{/md5}}
replaceReplaces every instance of a given pattern with a new value in the content. Neither the pattern nor replacement can themselves contain commas.
Example: {{#replace}}pattern,replacement,content{{/replace}}
rsaEncrypts contents using RSA public key cryptography. The certificate value must be in PEM format. The currently available padding schemes include: pkcs1 or oaep. Because the raw output is in binary form you will often use the rsa function embedded within another encoding function, such as base64, to produce web-safe output.
Example: {{#rsa}}certificate-pem,padding-scheme,contents to encrypt{{/rsa}}
rsa_signSigns (and base64 encodes) contents using the private key configured for the receiver. Requires a receiver pre-configured with an encryption certificate. The digest algorithm can be sha512 or sha256.
Example: {{#rsa_sign}}digest-algorithm,contents to sign{{/rsa_sign}}
triple_desEncrypt contents using the Triple DES (3DES) symmetric encryption algorithm. The encryption mode can be CBC, CFB, OFB, or CTR. Because the raw output is in binary form you will often use the triple_des function embedded within another encoding function, such as base64, to produce web-safe output. Note that 3DES encryption is not generally acceptable for use in a PCI-compliant context, as 3DES encryption can be broken in a trivial amount of time on normal desktop computers and cell phones. You should instead use alternative mechanisms, such as AES encryption, in most contexts.
Example: {{#triple_des}}mode,initialization vector as byte array,encryption key,data{{/triple_des}}
truncateTruncate a value to a given size.
Example: {{#truncate}}length,contents{{/truncate}}
utc_timestampInserts an ISO 8601 formatted timestamp at the time of export.
Example: {{#utc_timestamp}}{{/utc_timestamp}}
xml_dsigGenerate the WS-Security XML digital signature for a given SOAP envelope. Requires a receiver pre-configured with an encryption certificate.
Example: {{#xml_dsig}}full XML body{{/xml_dsig}}

Gateway Payments

If your country or region does not support Spreedly, you can opt to use your own payment gateway. Within local and remote endpoints, you can include a gateway block within payment-methods.

Here's an example for a fictional gateway:

...
action-endpoint (ProcessedPayment){
accepted-inputs (order,$vivContext,$payment)
local-endpoint (ProcessedPayment.js)
payment-methods {
gateway (samsung_pay_simple) {
label {
template (SamsungPay)
}
url {
template ("#{value(order.webViewUrl)}")
}
method (GET)
callback (bixby://payResult)
}
}
}
...

The specific parameters within the gateway block will depend on the specific gateway you are using, but they can include information such as the URL, body, and header parameters. For more information, refer to gateway in the Reference Guide.

After the payment is processed, the result is passed back in a $payment parameter as shown in this example:

$payment: {
id: "simple_pay"
response: {...}
}

The id is the ID of the gateway that is invoked, while the response is the response that is sent back from the gateway.

Gateway Payments using SamsungPay (Korea)

Here is an example that uses SamsungPay with Starbucks:

action-endpoint (starbucks.FinalizeOrder) {
accepted-inputs (order,... , $payment)
remote-endpoint ("{main.url}/starbucks/place_order") {
method (POST)
}

payment-methods {
gateway (starbucks_gw) {
label {
template (Pay via Starbucks)
}
url {
template ("https://msr.istarbucks.co.kr:9443/appif/xo/paymentPg.do?orderNo=#{value(order.orderNo)}")
}
method (GET)
body {
template ("{'app': {'orderNo':#{value(order.orderNo)}}}")
}
header-params {
param (appid) {
literal (...)
}
param (session_id) {
literal (...)
}
}
callback (starbucks://payResult)
}

gateway (samsung_pay_simple) {
label {
template (SamsungPay)
}
...
}
}
}

Once confirmed, the user gets to choose between "Pay via Starbucks" and "Use SamsungPay", which invokes the corresponding gateway. The response is, as mentioned before, placed in $payment endpoint parameter:

$payment: {
id: "starbucks_gw" // or "samsung_pay_simple"
response: {...} // opaque blob, format agreed upon by both gateway and action endpoint
}

For more information on gateway payments, read about related keys in the Reference Guide.

Passing a User's Non-Sensitive Card Information

You can add a special $paymentCard input to your accepted inputs if you need to access non-sensitive information about the card confirmed by the user.

Note

This parameter is only available in actions that specify sps as their payment-methods in your action-endpoints.

accepted-inputs (payInfo, taxInfo, shipInfo, $vivContext, $paymentCard)

Here is the following information that you can access via the $paymentCard parameter:

  • last4 : The last four digits of the credit card. Example: 9999
  • address1 : The first line of the billing address. Example: 1445 Norwood Ave
  • address1 : The second line of the billing address, if needed. This is typically used for apartment or unit numbers. Example Building 5
  • city : The city of the billing address. Example: Itasca
  • state : The state of the billing address. Example: IL
  • zip: The zip code of the billing address. Example: 60143
  • country: The country of the billing address. Example: US
  • phone: The phone number of the customer, if provided. Example: 18885551212

Here is an example of using $paymentCard to get the billing address information.

First, create an action model:

action (AccessPaymentCard) {
type(Commit)
collect {
input (dummyInput) {
type (viv.core.Integer)
}
}
output (viv.core.Text)
}

In your corresponding JavaScript file, access the $paymentCard.%information% parameter to return the billing address information.

//AccessPaymentCard.js
module.exports.function = function paymentAction (dummyInput, $vivContext, $paymentCard) {
if ($paymentCard) {
console.log("$paymentCard.last4: " + $paymentCard.last4)
console.log("$paymentCard.address1: " + $paymentCard.address1)
console.log("$paymentCard.address2: " + $paymentCard.address2)
console.log("$paymentCard.city: " + $paymentCard.city)
console.log("$paymentCard.state: " + $paymentCard.state)
console.log("$paymentCard.zip: " + $paymentCard.zip)
console.log("$paymentCard.country: " + $paymentCard.country)
console.log("$paymentCard.phone: " + $paymentCard.phone)
} else {
console.log("$paymentCard is null")
}
...

You would then need to configure your endpoints for this action like below, including making sure that you set up the proper accepted-inputs for your endpoint:

action-endpoint (AccessPaymentCard) {
accepted-inputs (dummyInput, $vivContext, $paymentCard)
local-endpoint ("AccessPaymentCard.js")
}