or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advertising-monetization.mdapplication-lifecycle.mdauthentication.mdcore-bridge.mddevice-features.mdgeolocation.mdindex.mdlaunch-parameters.mdmiddleware.mdpayments-commerce.mdqr-barcode-scanning.mdsocial-features.mdstorage-data.mdui-display.mduser-data.md

payments-commerce.mddocs/

0

# Payments & Commerce

1

2

Payment processing and e-commerce functionality for monetizing VK Mini Apps through VK Pay integration.

3

4

## Capabilities

5

6

### Payment Processing

7

8

Process payments through VK Pay system with support for various payment methods and transaction types.

9

10

```typescript { .api }

11

/**

12

* Open VK Pay payment form

13

* @param props - Payment configuration with action and parameters

14

*/

15

function send(method: 'VKWebAppOpenPayForm', props: VKPayProps<VKPayActionType>): Promise<

16

TransactionResult | { result: TransactionResult }

17

>;

18

19

interface VKPayProps<T extends VKPayActionType> {

20

/** VK application ID */

21

app_id: number;

22

/** Payment action type */

23

action: T;

24

/** Action-specific parameters */

25

params: VKPayActionParamsMap[T];

26

}

27

28

type VKPayActionType = 'pay-to-service' | 'pay-to-user' | 'pay-to-group';

29

30

interface VKPayActionParamsMap {

31

'pay-to-service': {

32

/** Merchant ID */

33

merchant_id: number;

34

/** Payment amount */

35

amount: number;

36

/** Payment description */

37

description: string;

38

/** Unique transaction ID */

39

order_id: string;

40

/** Additional data */

41

data?: string;

42

};

43

'pay-to-user': {

44

/** Recipient user ID */

45

user_id: number;

46

/** Payment amount */

47

amount: number;

48

/** Payment description */

49

description: string;

50

};

51

'pay-to-group': {

52

/** Recipient group ID */

53

group_id: number;

54

/** Payment amount */

55

amount: number;

56

/** Payment description */

57

description: string;

58

};

59

}

60

61

interface TransactionResult {

62

/** Transaction status */

63

status: 'success' | 'cancel' | 'fail';

64

/** Transaction ID */

65

transaction_id?: string;

66

/** Payment amount */

67

amount?: number;

68

/** Additional transaction data */

69

extra?: any;

70

}

71

```

72

73

**Usage Examples:**

74

75

```typescript

76

// Service payment (in-app purchase)

77

const servicePayment = await bridge.send('VKWebAppOpenPayForm', {

78

app_id: 51665960,

79

action: 'pay-to-service',

80

params: {

81

merchant_id: 12345,

82

amount: 100, // Amount in kopecks (1 ruble = 100 kopecks)

83

description: 'Premium features unlock',

84

order_id: `order_${Date.now()}`,

85

data: JSON.stringify({

86

feature: 'premium',

87

duration: '1month'

88

})

89

}

90

});

91

92

if (servicePayment.status === 'success') {

93

console.log('Payment successful:', servicePayment.transaction_id);

94

// Unlock premium features

95

await unlockPremiumFeatures();

96

} else if (servicePayment.status === 'cancel') {

97

console.log('Payment cancelled by user');

98

} else {

99

console.log('Payment failed');

100

}

101

102

// User-to-user payment

103

const userPayment = await bridge.send('VKWebAppOpenPayForm', {

104

app_id: 51665960,

105

action: 'pay-to-user',

106

params: {

107

user_id: 12345,

108

amount: 500, // 5 rubles

109

description: 'Gift from friend'

110

}

111

});

112

113

// Group payment (donation)

114

const groupPayment = await bridge.send('VKWebAppOpenPayForm', {

115

app_id: 51665960,

116

action: 'pay-to-group',

117

params: {

118

group_id: 123456789,

119

amount: 1000, // 10 rubles

120

description: 'Support our community'

121

}

122

});

123

```

124

125

## Payment Flow Patterns

126

127

### In-App Purchases

128

129

```typescript

130

interface Product {

131

id: string;

132

name: string;

133

description: string;

134

price: number; // in kopecks

135

category: 'consumable' | 'non-consumable' | 'subscription';

136

}

137

138

class PaymentManager {

139

private appId: number;

140

private merchantId: number;

141

142

constructor(appId: number, merchantId: number) {

143

this.appId = appId;

144

this.merchantId = merchantId;

145

}

146

147

async purchaseProduct(product: Product, userId: number): Promise<boolean> {

148

try {

149

const result = await bridge.send('VKWebAppOpenPayForm', {

150

app_id: this.appId,

151

action: 'pay-to-service',

152

params: {

153

merchant_id: this.merchantId,

154

amount: product.price,

155

description: product.description,

156

order_id: `${product.id}_${userId}_${Date.now()}`,

157

data: JSON.stringify({

158

product_id: product.id,

159

user_id: userId,

160

category: product.category

161

})

162

}

163

});

164

165

if (result.status === 'success') {

166

// Record successful purchase

167

await this.recordPurchase(product, userId, result.transaction_id!);

168

return true;

169

}

170

171

return false;

172

} catch (error) {

173

console.error('Purchase failed:', error);

174

return false;

175

}

176

}

177

178

private async recordPurchase(product: Product, userId: number, transactionId: string): Promise<void> {

179

// Send purchase info to your server for validation and fulfillment

180

await fetch('/api/purchases', {

181

method: 'POST',

182

headers: { 'Content-Type': 'application/json' },

183

body: JSON.stringify({

184

product_id: product.id,

185

user_id: userId,

186

transaction_id: transactionId,

187

amount: product.price,

188

timestamp: Date.now()

189

})

190

});

191

}

192

}

193

194

// Usage

195

const paymentManager = new PaymentManager(51665960, 12345);

196

197

const premiumProduct: Product = {

198

id: 'premium_month',

199

name: 'Premium Subscription',

200

description: '1 month premium access',

201

price: 29900, // 299 rubles

202

category: 'subscription'

203

};

204

205

const success = await paymentManager.purchaseProduct(premiumProduct, currentUserId);

206

if (success) {

207

console.log('Premium subscription activated!');

208

}

209

```

210

211

### Error Handling

212

213

```typescript

214

async function handlePayment(paymentParams: VKPayProps<VKPayActionType>) {

215

try {

216

const result = await bridge.send('VKWebAppOpenPayForm', paymentParams);

217

218

switch (result.status) {

219

case 'success':

220

console.log('Payment successful');

221

// Process successful payment

222

await processSuccessfulPayment(result);

223

break;

224

225

case 'cancel':

226

console.log('Payment cancelled by user');

227

// Handle cancellation (maybe show retry option)

228

showPaymentCancelledMessage();

229

break;

230

231

case 'fail':

232

console.log('Payment failed');

233

// Handle payment failure

234

showPaymentFailedMessage();

235

break;

236

}

237

238

return result;

239

} catch (error) {

240

console.error('Payment error:', error);

241

242

if (error.error_type === 'client_error') {

243

switch (error.error_data.error_code) {

244

case 1:

245

console.log('Payment method not supported');

246

break;

247

case 2:

248

console.log('Insufficient funds');

249

break;

250

default:

251

console.log('Payment client error:', error.error_data.error_reason);

252

}

253

}

254

255

throw error;

256

}

257

}

258

```

259

260

### Security Considerations

261

262

```typescript

263

// Always validate payments on your server

264

async function validatePayment(transactionId: string, expectedAmount: number): Promise<boolean> {

265

try {

266

const response = await fetch('/api/validate-payment', {

267

method: 'POST',

268

headers: { 'Content-Type': 'application/json' },

269

body: JSON.stringify({

270

transaction_id: transactionId,

271

expected_amount: expectedAmount

272

})

273

});

274

275

const validation = await response.json();

276

return validation.valid === true;

277

} catch (error) {

278

console.error('Payment validation failed:', error);

279

return false;

280

}

281

}

282

283

// Use validation in payment flow

284

const paymentResult = await bridge.send('VKWebAppOpenPayForm', paymentParams);

285

286

if (paymentResult.status === 'success') {

287

const isValid = await validatePayment(

288

paymentResult.transaction_id!,

289

paymentParams.params.amount

290

);

291

292

if (isValid) {

293

// Safe to fulfill the purchase

294

await fulfillPurchase(paymentResult);

295

} else {

296

console.error('Payment validation failed');

297

// Handle invalid payment

298

}

299

}

300

```