Documentation ¶
Overview ¶
Package payments implements Payments API.
Documentation: https://dev.vk.com/ru/api/payments/getting-started
With Payments API applications can sell virtual products to users or provide them with services using VK internal currency — votes.
Processing payment notifications ¶
Documentation: https://dev.vk.com/ru/api/payments/notifications/overview
Notifications are sent by the payment system server to the callback URL indicated in app settings, according to HTTP or HTTPS protocol, depending on the protocol specified in the callback URL with the POST method in UTF-8 encoding.
To avoid the possible forgery, notifications are signed with a secret key known only to the app and payment system owner.
The app developer must process notifications and return either the processing result if successful or an error description if unsuccessful. The response must be sent in 10 seconds, or else the connection will be lost and the attempt to send the notification will happen once more after some time.
cb := payments.NewCallback(secret) cb.OnGetItem(func(e payments.GetItemRequest) (*payments.GetItemResponse, *payments.Error) { // ... }) cb.OnOrderStatusChange(func(e payments.OrderStatusChangeRequest) ( *payments.OrderStatusChangeResponse, *payments.Error, ) { // ... }) cb.OnGetSubscription(func(e payments.GetSubscriptionRequest) ( *payments.GetSubscriptionResponse, *payments.Error, ) { // ... }) cb.OnSubscriptionStatusChange(func(e payments.SubscriptionStatusChangeRequest) ( *payments.SubscriptionStatusChangeResponse, *payments.Error, ) { // ... }) http.HandleFunc("/payments", cb.HandleFunc) http.ListenAndServe(":8080", nil)
Test Mode ¶
Documentation: https://dev.vk.com/ru/api/payments/getting-started
Test mode allows for testing an app's functionality for buying goods and transferring votes without a real transfer of votes.
While your app has not been checked by the VK administration, test mode is necessary to use. Payments are completed in "combat" mode immediately after the app verification procedure has been completed.
To make payments in test mode, add all users who will make test payments to the special list in app settings (the "Payments tester" field).
In test mode, the suffix '_test' is added to the NotificationType parameter.
cb.OnGetItemTest(func(e payments.GetItemRequest) (*payments.GetItemResponse, *payments.Error) { // ... }) cb.OnOrderStatusChangeTest(func(e payments.OrderStatusChangeRequest) ( *payments.OrderStatusChangeResponse, *payments.Error, ) { // ... }) cb.OnGetSubscriptionTest(func(e payments.GetSubscriptionRequest) ( *payments.GetSubscriptionResponse, *payments.Error, ) { // ... }) cb.OnSubscriptionStatusChangeTest(func(e payments.SubscriptionStatusChangeRequest) ( *payments.SubscriptionStatusChangeResponse, *payments.Error, ) { // ... })
The order IDs in test mode (i.e. the notification parameter OrderID) can overlap with the order IDs in operating mode.
Index ¶
- Constants
- type Callback
- func (cb *Callback) HandleFunc(w http.ResponseWriter, r *http.Request)
- func (cb *Callback) OnGetItem(f func(e GetItemRequest) (*GetItemResponse, *Error))
- func (cb *Callback) OnGetItemTest(f func(e GetItemRequest) (*GetItemResponse, *Error))
- func (cb *Callback) OnGetSubscription(f func(e GetSubscriptionRequest) (*GetSubscriptionResponse, *Error))
- func (cb *Callback) OnGetSubscriptionTest(f func(e GetSubscriptionRequest) (*GetSubscriptionResponse, *Error))
- func (cb *Callback) OnOrderStatusChange(f func(e OrderStatusChangeRequest) (*OrderStatusChangeResponse, *Error))
- func (cb *Callback) OnOrderStatusChangeTest(f func(e OrderStatusChangeRequest) (*OrderStatusChangeResponse, *Error))
- func (cb *Callback) OnSubscriptionStatusChange(...)
- func (cb *Callback) OnSubscriptionStatusChangeTest(...)
- func (cb *Callback) Sign(values url.Values) string
- type Error
- type GetItemRequest
- type GetItemResponse
- type GetSubscriptionRequest
- type GetSubscriptionResponse
- type Notification
- type NotificationType
- type OrderStatusChangeRequest
- type OrderStatusChangeResponse
- type Reason
- type Status
- type SubscriptionStatusChangeRequest
- type SubscriptionStatusChangeResponse
Constants ¶
const ( LangRussian = "ru_RU" // Russian LangUkrainian = "uk_UA" // Ukrainian LangBelarusian = "be_BY" // Belarusian LangEnglish = "en_US" // English )
User language as language_country.
const ( // Common error. // // Severity: true/false. CommonError = 1 // Temporary database error. // // Severity: false. TemporaryDatabaseError = 2 // The calculated and sent signatures do not match. // // Severity: true. BadSignatures = 10 // Request parameters do not comply with the specification. // No required fields in the request. // Other request integrity errors. // // Severity: true. BadRequest = 11 // Product does not exist. // // Severity: true. ProductNotExist = 20 // Product is out of stock. // // Severity: true. ProductOutOfStock = 21 // User does not exist. // // Severity: true. UserNotExist = 22 )
Numerical code error.
Errors 100-999 are specified by the app. Such errors always include an error description.
See https://dev.vk.com/ru/api/payments/notifications/overview
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Callback ¶
type Callback struct { Secret string // contains filtered or unexported fields }
Callback struct.
func (*Callback) HandleFunc ¶
func (cb *Callback) HandleFunc(w http.ResponseWriter, r *http.Request)
HandleFunc a request handler that process notifications and return either the processing result if successful or an error description if unsuccessful.
func (*Callback) OnGetItem ¶
func (cb *Callback) OnGetItem(f func(e GetItemRequest) (*GetItemResponse, *Error))
OnGetItem notification is sent when the product purchase dialog box is opened in the application. Then, obtained information about the product is shown in the purchase dialog box.
With item specifying the product name received in the notification, the developer shall return actual information about such product. When there is no product available, reply with Error 20 "Product does not exist".
&payments.Error{ Code: payments.ProductNotExist, Msg: "Product does not exist", Critical: true, }
Please note! As item is passed at the client side, user can change this parameters.
Please note! We recommend you to use product caching for all products, this will decrease the number of calls to the application server and users will not wait when information about them is retrieved.
In case information about the product with item ID was cached for expiration period, following requests for such product will not be run within the given time.
See https://dev.vk.com/ru/api/payments/notifications/get-item
func (*Callback) OnGetItemTest ¶
func (cb *Callback) OnGetItemTest(f func(e GetItemRequest) (*GetItemResponse, *Error))
OnGetItemTest OnGetItem for test.
func (*Callback) OnGetSubscription ¶
func (cb *Callback) OnGetSubscription(f func(e GetSubscriptionRequest) (*GetSubscriptionResponse, *Error))
OnGetSubscription is sent when a subscription dialog window is opened via application.
See https://dev.vk.com/ru/api/payments/notifications/get-subscription
func (*Callback) OnGetSubscriptionTest ¶
func (cb *Callback) OnGetSubscriptionTest(f func(e GetSubscriptionRequest) (*GetSubscriptionResponse, *Error))
OnGetSubscriptionTest OnGetSubscription for test.
func (*Callback) OnOrderStatusChange ¶
func (cb *Callback) OnOrderStatusChange(f func(e OrderStatusChangeRequest) (*OrderStatusChangeResponse, *Error))
OnOrderStatusChange is sent when order status changes.
Please note! In case of repeated notification of Changing order status type (with the same order_id), the reply shall be the exact copy of the reply for initial notification.
For example, if such notification was sent and positive reply was received but it was not received by VK, or for any temporary reason the blocked funds could not be charged to the application account immediately after reply, such notification will be resent. And there is no need to place a new order, you just send the same reply as before (by keeping order_id and checking whether such notification was received).
See https://dev.vk.com/ru/payments/notifications/order-status-change
func (*Callback) OnOrderStatusChangeTest ¶
func (cb *Callback) OnOrderStatusChangeTest(f func(e OrderStatusChangeRequest) (*OrderStatusChangeResponse, *Error))
OnOrderStatusChangeTest OnOrderStatusChange for test.
func (*Callback) OnSubscriptionStatusChange ¶
func (cb *Callback) OnSubscriptionStatusChange(f func(e SubscriptionStatusChangeRequest) ( *SubscriptionStatusChangeResponse, *Error, ), )
OnSubscriptionStatusChange is sent the moment the subscription status changes. Please note that the subscription status doesn’t change after renewal (withdrawal of a new payment from a user). You won’t receive a payment notification about subscription renewal. It’s sent only if a user decides to not renew and thus cancels the subscription. Warning! If the notification of Change in subscription status type (with the same subscription_id) occurs repeatedly, the response should be identical to the response of the initial notification.
For example, if this notification was sent and a positive response was received, but it didn’t reach VK servers or for some temporary reasons transferring frozen funds to the application’s account failed right after receiving the response, the same notification will be sent again. There is no need to issue a new order. It is necessary to send the same response as the previous time (having saved the subscription_id and verified through it as if the same notification had already been received).
Note that if the subscription was canceled due to lack of funds on a user’s account, it can be renewed within five days (provided that the user replenishes their account balance within these five days). In this case, the existing subscription is the one renewed, and there is no need to create a new one.
See https://dev.vk.com/ru/api/payments/notifications/subscription-status-change
func (*Callback) OnSubscriptionStatusChangeTest ¶
func (cb *Callback) OnSubscriptionStatusChangeTest(f func(e SubscriptionStatusChangeRequest) ( *SubscriptionStatusChangeResponse, *Error, ), )
OnSubscriptionStatusChangeTest OnSubscriptionStatusChange for test.
type Error ¶
type Error struct { // Numerical code error Code int `json:"error_code"` // Error description in easy-to-read format // (required for error_code >= 100). Msg string `json:"error_msg,omitempty"` // Error severity. Possible values are: // // true — if a notification with identical parameters is passed // repeatedly, the same error will occur. For example, the indicated // product does not exist. The notification will not be resent as the user // will receive an error. // // false — if the error is temporary, a notification may be processed // later. For example, a temporary error in posting to the database. // The notification will be sent after some time and the user will wait // for the response. Critical bool `json:"critical"` }
Error struct.
When critical errors occur, the order cancels and the app event onOrderFail is sent. If the error is temporary, a notification will be resent after some time and the user will wait for the process is completed.
See https://dev.vk.com/ru/api/payments/notifications/overview
type GetItemRequest ¶
type GetItemRequest struct { Notification // The recipient’s ID. ReceiverID int `schema:"receiver_id,required"` // The ID of the order. OrderID int `schema:"order_id,required"` // User language as language_country. Lang string `schema:"lang,required"` // Product name passed to the purchase dialog box. Item string `schema:"item,required"` }
GetItemRequest notification parameters.
type GetItemResponse ¶
type GetItemResponse struct { // product name, max 48 characters // // Required parameter Title string `json:"title"` // URL of product image on the developer's server PhotoURL string `json:"photo_url,omitempty"` // product price, in votes // // Required parameter Price int `json:"price"` // the size of the discount on the goods in the votes. Should be within // 1 to 1000 votes and less than the price of goods. Discount int `json:"discount,omitempty"` // product ID in the application ItemID string `json:"item_id,omitempty"` // allows product caching for {Expiration} seconds. Allowed // range from 600 to 604800 seconds. // // Warning! In the absence of the parameter is possible to cache the goods // for 3600 seconds with a large number of consecutive identical // responses. For cancellation of caching it is necessary to pass 0 as // value of parameter. Expiration int `json:"expiration,omitempty"` }
GetItemResponse reply parameters.
type GetSubscriptionRequest ¶
type GetSubscriptionRequest struct { Notification // The recipient’s ID. ReceiverID int `schema:"receiver_id,required"` // Order identifier in the VK payment system. OrderID int `schema:"order_id,required"` // User language in the language_country format. // // ru_RU — Russian // // uk_UA — Ukrainian // // be_BY — Belarusian // // en_US — English Lang string `schema:"lang,required"` // Product name passed to the subscription dialog window. Item string `schema:"item,required"` }
GetSubscriptionRequest notification parameters.
type GetSubscriptionResponse ¶
type GetSubscriptionResponse struct { // Product identifier in the application. ItemID int `json:"item_id,omitempty"` // Subscription name. Title string `json:"title"` // Image URL on the developer’s server for the subscription. PhotoURL string `json:"photo_url,omitempty"` // Subscription price shown in votes. Price int `json:"price"` // Subscription period duration in days. Possible values: 3, 7, 30. Period int `json:"period"` // Trial period duration in days. Possible values: 3, 7, 30. TrialDuration int `json:"trial_duration,omitempty"` // Allows product caching for {expiration} seconds. Permitted range is // from 600 to 604,800 seconds. // // Warning! Without the parameter, caching of the product is possible for // 3,600 seconds if many identical consecutive responses occur. To disable // caching, it is necessary to pass 0 as the parameter value. Expiration int `json:"expiration,omitempty"` }
GetSubscriptionResponse reply parameters.
Using the item identifier received in the notification, developers should return current information about it. If there is no product, error 20 “Subscription does not exist” should be returned in the response.
&payments.Error{ Code: payments.ProductNotExist, Msg: "Subscription does not exist", Critical: true, }
Warning! Due to the item being sent on the client-side, this parameter can be changed by users.
type Notification ¶
type Notification struct { // The type of notification. Type NotificationType `schema:"notification_type,required"` // The app’s ID. AppID int `schema:"app_id,required"` // The ID of the user who made the order. UserID int `schema:"user_id,required"` // The notification signature. Sig string `schema:"sig,required"` }
Notification structures.
The selection of fields depends on the type of notification. However all types of notifications contain the following fields.
type NotificationType ¶
type NotificationType string
NotificationType type of notification.
const ( // For acquiring product information. // // https://dev.vk.com/ru/api/payments/notifications/get-item GetItem NotificationType = "get_item" // For changing the order’s status. // // https://dev.vk.com/ru/payments/notifications/order-status-change OrderStatusChange NotificationType = "order_status_change" // For receiving subscription information. // // https://dev.vk.com/ru/api/payments/notifications/get-subscription GetSubscription NotificationType = "get_subscription" // For changing a subscription’s status. // // https://dev.vk.com/ru/api/payments/notifications/subscription-status-change SubscriptionStatusChange NotificationType = "subscription_status_change" )
List type of notification.
func (NotificationType) Test ¶
func (t NotificationType) Test() NotificationType
Test return NotificationType for test mode.
In test mode, the suffix '_test' is added to the notification_type parameter.
type OrderStatusChangeRequest ¶
type OrderStatusChangeRequest struct { Notification // The recipient’s ID. ReceiverID int `schema:"receiver_id,required"` // Order ID in VK payment system. OrderID int `schema:"order_id,required"` // Date when the order was created (as "unix timestamp"). Date int `schema:"date,required"` // New status of the order. // // chargeable - order ready for payment. User shall complete the order // in the application. In case of successful reply the payment system will // charge votes to the application account. In case of error message the // order will be canceled. // // refunded - Available as of API version 5.132. Order cancelled. It is necessary // to pick up game values given to the user for payments. Status Status `schema:"status,required"` // Product name passed to the purchase dialog box. // // For special offer (call of the payment dialog box with type=offers), Item // parameter will include "offer_{offer_id}", item_price parameter is the // number of votes charged for such special offer. Item string `schema:"item,required"` // Product ID in the application. ItemID string `schema:"item_id"` // Product name. ItemTitle string `schema:"item_title,required"` // Product image. ItemPhotoURL string `schema:"item_photo_url"` // Product price. ItemPrice string `schema:"item_price,required"` // Cost in application currency. // // See https://dev.vk.com/ru/api/payments/getting-started ItemCurrencyAmount string `schema:"item_currency_amount"` // Product discount. ItemDiscount string `schema:"item_discount"` }
OrderStatusChangeRequest notification parameters.
func (OrderStatusChangeRequest) OfferID ¶
func (r OrderStatusChangeRequest) OfferID() int
OfferID returns a offer_id.
type OrderStatusChangeResponse ¶
type OrderStatusChangeResponse struct { // order ID in VK payment system OrderID int `json:"order_id"` // ID of the order in the application. Shall be unique for each order AppOrderID int `json:"app_order_id,omitempty"` }
OrderStatusChangeResponse reply parameters.
type Reason ¶
type Reason string
Reason type.
const ( // Subscription canceled by the user. UserDecision Reason = "user_decision" // Subscription canceled by the application (orders.cancelSubscription). AppDecision Reason = "app_decision" // Subscription canceled due to a failed payment. PaymentFail Reason = "payment_fail" // Subscription canceled for a different reason. Unknown Reason = "unknown" )
Reason for cancellation.
type Status ¶
type Status string
Status type.
const ( // Subscription is ready for payments. An order for the user // needs to be processed within the application. If the response is // successful, the payment system credits votes to the application // balance. If the response is a failure, the order is canceled. Chargeable Status = "chargeable" // Available as of API version 5.132. Order cancelled. It is necessary // to pick up game values given to the user for payments. Refunded Status = "refunded" // Subscription is active. Active Status = "active" // Subscription is canceled. Cancelled Status = "cancelled" )
Subscription status.
type SubscriptionStatusChangeRequest ¶
type SubscriptionStatusChangeRequest struct { Notification // Reason for cancellation. CancelReason Reason `schema:"cancel_reason"` // Product identifier in the application. ItemID string `schema:"item_id,required"` // Product price. ItemPrice string `schema:"item_price,required"` // New subscription status. Possible values: // // chargeable — subscription is ready for payments. An order for the user // needs to be processed within the application. If the response is // successful, the payment system credits votes to the application // balance. If the response is a failure, the order is canceled. // // active — subscription is active; // // cancelled — subscription is canceled. Status Status `schema:"status,required"` // Subscription is active until the end of the paid period (status = active). // // integer, [1] PendingCancel int `schema:"pending_cancel"` // Subscription identifier. SubscriptionID int `schema:"subscription_id,required"` // Subscription next bill time NextBillTime int `schema:"next_bill_time"` }
SubscriptionStatusChangeRequest notification parameters.
type SubscriptionStatusChangeResponse ¶
type SubscriptionStatusChangeResponse struct { // Global subscription identifier. SubscriptionID int `json:"subscription_id"` // Order identifier within the app. Must be unique for each order. AppOrderID int `json:"app_order_id,omitempty"` }
SubscriptionStatusChangeResponse reply parameters.