Skip to content

CyberSource ​

CyberSource Secure Acceptance is a hosted checkout for card payments, in MMK or any other currency.

CallWhat it doesReturns
cyberSource.Initiate(data)Signed form posted to the hosted checkout*FormPayment
cyberSource.HandleCallback(request)Verify the result post*PaymentCallback

cyberSource is the *cybersource.Gateway that paymentsfacades.MyanmarPayments().CyberSource() returns. CyberSource has no status API in this package: the callback is the only payment result.

Responses shows what CyberSource puts in each result.

How it works ​

CyberSource posts the result twice, to your backoffice URL and through the browser to your receipt page, and both are verified the same way.

CyberSource: signed form, hosted checkout, two result postsCustomerYour appCyberSourceCheck outRedirect to autoSubmitUrlcyberSource.Initiate(data), payments.AutoSubmitURL(form)Post to the hosted checkoutPOST /pay, then the card formBackoffice postoverride_backoffice_post_urlVerified callback is proofcyberSource.HandleCallback(request)Browser posts the receiptoverride_custom_receipt_pageSame signature checkcyberSource.HandleCallback(request)Show the receipt
CyberSource: signed form, hosted checkout, two result posts

Initiating a Payment ​

go
import (
	"fmt"

	"github.com/goravel/framework/contracts/http"
	myanmarpayments "github.com/laranex/go-myanmar-payments/v4"
	"github.com/laranex/go-myanmar-payments/v4/cybersource"
	payments "github.com/laranex/goravel-myanmar-payments/v4"
	paymentsfacades "github.com/laranex/goravel-myanmar-payments/v4/facades"
)

func (r *CheckoutController) Card(ctx http.Context) http.Response {
	order := findOrder(ctx) // your own order lookup

	cyberSource, err := paymentsfacades.MyanmarPayments().CyberSource()
	if err != nil {
		return ctx.Response().String(http.StatusInternalServerError, "%s", err)
	}
	data := cybersource.PaymentData{
		OrderID:         fmt.Sprintf("ORDER_%d", order.ID),
		Amount:          myanmarpayments.Kyat(10000),
		CallbackURL:     "https://shop.test/payments/cybersource/callback",
		Currency:        "MMK",
		TransactionType: cybersource.Sale,
		Locale:          "en-us",
		ReturnURL:       "https://shop.test/payments/cybersource/receipt",
		CancelURL:       "https://shop.test/checkout",
	}

	form, err := cyberSource.Initiate(data)
	if err != nil {
		return ctx.Response().String(http.StatusUnprocessableEntity, "%s", err)
	}
	link, err := payments.AutoSubmitURL(form)
	if err != nil {
		return ctx.Response().String(http.StatusInternalServerError, "%s", err)
	}

	return ctx.Response().Redirect(http.StatusFound, link)
}

cybersource.PaymentData ​

FieldTypeRequiredRules
OrderIDstringYesAt most 50 characters, sent as reference_number
Amountmyanmarpayments.AmountYesOrder total in Currency, 0 or more, any number of decimals, at most 15 characters, e.g. Kyat(10000) or MustParseAmount("10.50")
CallbackURLstringYesAbsolute http or https URL CyberSource posts the result to. At most 255 characters; CyberSource may require HTTPS in production
CurrencystringYesAny three-letter uppercase ISO 4217 code, e.g. MMK
TransactionTypecybersource.TransactionTypeYescybersource.Sale ("sale"), Authorization ("authorization"), SaleAndCreateToken ("sale,create_payment_token") or AuthorizationAndCreateToken ("authorization,create_payment_token")
LocalestringYesHosted page language as a CyberSource locale code, e.g. en-us
ReturnURLstringNoReceipt page for the customer (absolute http or https URL). At most 255 characters
CancelURLstringNoPage shown when the customer cancels (absolute http or https URL). At most 255 characters

Amounts and Currencies ​

CyberSource is multi-currency and accepts decimals. For another currency, pass an Amount with the currency: Amount: myanmarpayments.MustParseAmount("10.50"), Currency: "USD".

Form Encoding ​

CyberSource expects the form as application/x-www-form-urlencoded. form.Enctype carries it; use it if you render the form yourself.

Handling Callbacks ​

CyberSource posts a form to CallbackURL. The same check works for the browser post to your receipt page.

go
import (
	"github.com/goravel/framework/contracts/http"
	payments "github.com/laranex/goravel-myanmar-payments/v4"
	paymentsfacades "github.com/laranex/goravel-myanmar-payments/v4/facades"

	"yourapp/app/facades"
)

facades.Route().Post("/payments/cybersource/callback", func(
	ctx http.Context,
) http.Response {
	request, err := payments.CallbackRequestFromContext(ctx)
	if err != nil {
		return ctx.Response().String(http.StatusBadRequest, "bad request")
	}
	cyberSource, err := paymentsfacades.MyanmarPayments().CyberSource()
	if err != nil {
		return ctx.Response().String(http.StatusInternalServerError, "%s", err)
	}
	callback, err := cyberSource.HandleCallback(request)
	if err != nil { // *myanmarpayments.SignatureVerificationError
		return ctx.Response().String(http.StatusBadRequest, "invalid")
	}

	if callback.IsSuccessful() {
		// callback.OrderID is your req_reference_number
		// callback.GatewayReference is CyberSource's transaction_id
	}

	return payments.Acknowledge(ctx, callback)
})

Only signed fields are trusted: decision and req_reference_number must be listed in signed_field_names, transaction_id and the amount are read only when they are signed, and Raw keeps only the signed fields plus signature. An unsigned extra field, such as decision=ACCEPT added to a re-posted checkout form, can't change the result.

Responses ​

What CyberSource puts in each field. See Results and PaymentCallback & Status for the full types. CyberSource posts form fields, so every Raw value is a string, exactly as sent.

Initiate() → *FormPayment ​

Field / MethodCyberSource value
OrderIDYour OrderID
Action{base_url}/pay, e.g. https://testsecureacceptance.cybersource.com/pay
FieldsThe signed fields below, in this order. Post them unchanged
Enctypeapplication/x-www-form-urlencoded
HTML()A full HTML page that posts Fields to Action on load

payments.AutoSubmitURL(form) returns the encrypted link to the myanmar-payments.form route, e.g. https://shop.test/myanmar-payments/form?payload=…. It expires after form_route.ttl_minutes. With form_route.enabled set to false it returns payments.ErrFormRouteDisabled.

Fields, all signed, in this order:

Form fieldValue
access_keyYour configured access key
profile_idYour configured profile ID
transaction_uuidA random ID, new for every call
signed_field_namesThe field names in this table except signature, comma-separated
signed_date_timeUTC time, e.g. 2026-10-08T09:30:00Z
localeYour Locale, e.g. en-us
transaction_typeYour TransactionType, e.g. sale
reference_numberYour OrderID
amountYour Amount, e.g. 10000
currencyYour Currency, e.g. MMK
override_custom_receipt_pageYour ReturnURL, "" when unset
override_backoffice_post_urlYour CallbackURL
override_custom_cancel_pageYour CancelURL, "" when unset
signatureBase64 HMAC-SHA256 of the signed fields

Initiate() makes no HTTP call. FormPayment has no Raw: nothing is sent to CyberSource until the customer's browser posts the form.

HandleCallback() → *PaymentCallback ​

FieldCyberSource value
OrderIDCyberSource req_reference_number (your OrderID)
Statusdecision mapped, see Statuses
GatewayStatusCyberSource decision, trimmed and uppercased, e.g. ACCEPT
GatewayReferenceCyberSource transaction_id. Empty when it is not signed
AmountCyberSource auth_amount, falling back to req_amount when it is missing or empty, e.g. 10000. Signed values only
RawThe signed fields of the verified post plus signature, e.g. decision, reason_code, message, transaction_id, auth_amount, auth_code, req_reference_number, req_amount, req_currency, req_transaction_uuid, signed_field_names, signed_date_time. Unsigned fields are left out
AcknowledgementHTTP 200, empty body, Content-Type: text/plain

payments.Acknowledge(ctx, callback) writes Acknowledgement as the Goravel response. HandleCallback() takes the *myanmarpayments.CallbackRequest that payments.CallbackRequestFromContext(ctx) builds.

Statuses ​

CyberSource decisionPaymentStatus
ACCEPTStatusSuccessful
REVIEWStatusPending
DECLINE, ERRORStatusFailed
CANCELStatusCanceled
anything elseStatusUnknown

Errors ​

CallReturnsWhen
Initiate()*InvalidPaymentDataErrorA value breaks the rules above. Nothing is signed
HandleCallback()*SignatureVerificationErrorsignature doesn't match, a field listed in signed_field_names is missing, or decision or req_reference_number isn't signed

CyberSource makes no HTTP calls, so nothing returns an *APIError.

Released under the MIT License, except where a package says otherwise.