PHP code example of coretrekas / vipps

1. Go to this page and download the library: Download coretrekas/vipps library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

coretrekas / vipps example snippets


use Coretrek\Vipps\VippsClient;

$client = new VippsClient(
    clientId: 'your-client-id',
    clientSecret: 'your-client-secret',
    subscriptionKey: 'your-subscription-key',
    merchantSerialNumber: 'your-msn',
    testMode: true // Set to false for production
);

$client = new VippsClient(
    clientId: 'your-client-id',
    clientSecret: 'your-client-secret',
    subscriptionKey: 'your-subscription-key',
    merchantSerialNumber: 'your-msn',
    testMode: true,
    options: [
        'systemName' => 'MyEcommercePlatform',
        'systemVersion' => '2.1.0',
        'pluginName' => 'VippsPaymentPlugin',
        'pluginVersion' => '1.5.3',
    ]
);

// Or set it later
$client->setSystemInfo(
    systemName: 'MyEcommercePlatform',
    systemVersion: '2.1.0',
    pluginName: 'VippsPaymentPlugin',
    pluginVersion: '1.5.3'
);

// Simple payment creation
$payment = $client->epayment()->createSimplePayment(
    reference: 'order-12345',
    amount: 10000, // Amount in minor units (100.00 NOK)
    currency: 'NOK',
    userFlow: 'WEB_REDIRECT',
    options: [
        'returnUrl' => 'https://example.com/order/12345/complete',
        'paymentDescription' => 'Order #12345',
    ]
);

// Redirect user to payment page
header('Location: ' . $payment['redirectUrl']);

$payment = $client->epayment()
    ->buildPayment()
    ->amount(10000, 'NOK')
    ->reference('order-12345')
    ->userFlow('WEB_REDIRECT')
    ->returnUrl('https://example.com/order/12345/complete')
    ->paymentDescription('Order #12345')
    ->paymentMethod('WALLET')
    ->customerInteraction('CUSTOMER_NOT_PRESENT')
    ->idempotencyKey('payment-order-12345')
    ->systemInfo('my-shop', '1.0.0', 'vipps-plugin', '1.0.0')
    ->create();

echo "Payment URL: " . $payment['redirectUrl'];

$orderLines = [
    [
        'name' => 'Premium Socks',
        'id' => 'SOCK-001',
        'totalAmount' => 5000,
        'totalAmountExcludingTax' => 4000,
        'totalTaxAmount' => 1000,
        'unitInfo' => [
            'unitPrice' => 2500,
            'quantity' => '2',
            'quantityUnit' => 'PCS',
        ],
    ],
];

$bottomLine = [
    'currency' => 'NOK',
    'receiptNumber' => 'order-12345',
];

$payment = $client->epayment()
    ->buildPayment()
    ->amount(5000, 'NOK')
    ->reference('order-12345')
    ->userFlow('WEB_REDIRECT')
    ->returnUrl('https://example.com/order/12345/complete')
    ->paymentDescription('Order with receipt')
    ->paymentMethod('WALLET')
    ->receipt($orderLines, $bottomLine)
    ->metadata(['orderId' => 'order-12345', 'customerId' => 'CUST-123'])
    ->create();

$payment = $client->epayment()->getPayment('order-12345');

echo "Payment State: " . $payment['state'];
echo "Amount: " . $payment['amount']['value'] . ' ' . $payment['amount']['currency'];
echo "Authorized: " . $payment['aggregate']['authorizedAmount']['value'];
echo "Captured: " . $payment['aggregate']['capturedAmount']['value'];

// Capture full amount
$result = $client->epayment()->captureAmount(
    reference: 'order-12345',
    amount: 10000,
    currency: 'NOK',
    headers: ['Idempotency-Key' => 'capture-order-12345']
);

// Or use the detailed method
$result = $client->epayment()->capturePayment('order-12345', [
    'modificationAmount' => [
        'value' => 10000,
        'currency' => 'NOK',
    ],
]);

// Refund partial amount
$result = $client->epayment()->refundAmount(
    reference: 'order-12345',
    amount: 5000,
    currency: 'NOK',
    headers: ['Idempotency-Key' => 'refund-order-12345']
);

// Or use the detailed method
$result = $client->epayment()->refundPayment('order-12345', [
    'modificationAmount' => [
        'value' => 5000,
        'currency' => 'NOK',
    ],
]);

$result = $client->epayment()->cancelPayment('order-12345');

echo "Payment State: " . $result['state']; // TERMINATED

$events = $client->epayment()->getPaymentEventLog('order-12345');

foreach ($events as $event) {
    echo $event['name'] . ' at ' . $event['timestamp'] . "\n";
}

$payment = $client->epayment()
    ->buildPayment()
    ->amount(5000, 'NOK')
    ->reference('order-12345')
    ->userFlow('QR')
    ->qrFormat('IMAGE/SVG+XML')
    ->paymentDescription('QR payment')
    ->paymentMethod('WALLET')
    ->create();

echo "QR Code URL: " . $payment['redirectUrl'];

$payment = $client->epayment()
    ->buildPayment()
    ->amount(7500, 'NOK')
    ->reference('order-12345')
    ->userFlow('PUSH_MESSAGE')
    ->customerPhoneNumber('4712345678')
    ->paymentDescription('Push message payment')
    ->paymentMethod('WALLET')
    ->create();

$payment = $client->epayment()
    ->buildPayment()
    ->amount(15000, 'NOK')
    ->reference('order-12345')
    ->userFlow('WEB_REDIRECT')
    ->returnUrl('https://example.com/order/12345/complete')
    ->paymentDescription('Order with shipping')
    ->paymentMethod('WALLET')
    ->fixedShipping([
        [
            'type' => 'HOME_DELIVERY',
            'brand' => 'POSTEN',
            'options' => [
                [
                    'id' => 'posten-standard',
                    'name' => 'Standard Delivery',
                    'amount' => ['value' => 9900, 'currency' => 'NOK'],
                    'estimatedDelivery' => '2-3 days',
                ],
                [
                    'id' => 'posten-express',
                    'name' => 'Express Delivery',
                    'amount' => ['value' => 19900, 'currency' => 'NOK'],
                    'estimatedDelivery' => 'Next day',
                ],
            ],
        ],
    ])
    ->profileScope('name email phoneNumber address')
    ->create();

// Simple payment session
$session = $client->checkout()->createPaymentSession(
    reference: 'order-12345',
    amount: 10000, // Amount in minor units (100.00 NOK)
    currency: 'NOK',
    options: [
        'paymentDescription' => 'Order #12345',
        'merchantInfo' => [
            'callbackUrl' => 'https://example.com/vipps/callback',
            'returnUrl' => 'https://example.com/order/12345/complete',
            'termsAndConditionsUrl' => 'https://example.com/terms',
        ],
    ]
);

// Redirect user to checkout
header('Location: ' . $session['checkoutFrontendUrl']);

$session = $client->checkout()
    ->buildPaymentSession()
    ->reference('order-12345')
    ->transaction(10000, 'NOK', 'order-12345', 'Order #12345')
    ->merchantInfo(
        callbackUrl: 'https://example.com/vipps/callback',
        returnUrl: 'https://example.com/order/12345/complete',
        termsAndConditionsUrl: 'https://example.com/terms',
        callbackAuthorizationToken: 'your-secret-token'
    )
    ->prefillCustomer([
        'firstName' => 'John',
        'lastName' => 'Doe',
        'email' => '[email protected]',
        'phoneNumber' => '+4712345678',
    ])
    ->customerInteraction('CUSTOMER_NOT_PRESENT')
    ->elements('Full')
    ->countries(['NO', 'SE', 'DK'])
    ->idempotencyKey('unique-key-' . time())
    ->systemInfo('my-ecommerce', '1.0.0', 'vipps-plugin', '2.0.0')
    ->create();

echo "Checkout URL: " . $session['checkoutFrontendUrl'];

$sessionInfo = $client->checkout()->getSession('order-12345');

echo "Session State: " . $sessionInfo['sessionState'];
echo "Payment Method: " . $sessionInfo['paymentMethod'];

$agreement = $client->recurring()
    ->buildAgreement()
    ->legacyPricing(2500, 'NOK') // 25.00 NOK per interval
    ->interval('MONTH', 1)
    ->product('Premium Subscription', 'Access to premium features')
    ->merchantUrls(
        redirectUrl: 'https://example.com/subscription/complete',
        agreementUrl: 'https://example.com/my-subscriptions'
    )
    ->phoneNumber('4712345678')
    ->initialCharge(100, 'NOK', 'Activation fee', 'DIRECT_CAPTURE')
    ->idempotencyKey('agreement-' . time())
    ->create();

// Redirect user to accept agreement
header('Location: ' . $agreement['vippsConfirmationUrl']);

$agreements = $client->recurring()->listAgreements([
    'status' => 'ACTIVE',
    'pageNumber' => 1,
    'pageSize' => 50,
]);

foreach ($agreements as $agreement) {
    echo "Agreement ID: " . $agreement['id'] . "\n";
    echo "Product: " . $agreement['productName'] . "\n";
    echo "Status: " . $agreement['status'] . "\n";
}

$charge = $client->recurring()->createCharge(
    agreementId: 'agr_5kSeqz',
    chargeData: [
        'amount' => 2500,
        'transactionType' => 'DIRECT_CAPTURE',
        'description' => 'Monthly subscription - January 2024',
        'due' => '2024-01-01',
        'retryDays' => 5,
        'type' => 'RECURRING',
    ],
    headers: ['Idempotency-Key' => 'charge-jan-2024']
);

echo "Charge ID: " . $charge['chargeId'];

$client->recurring()->captureCharge(
    agreementId: 'agr_5kSeqz',
    chargeId: 'chr_123',
    captureData: [
        'amount' => 2500,
        'description' => 'Capture for January',
    ]
);

$client->recurring()->refundCharge(
    agreementId: 'agr_5kSeqz',
    chargeId: 'chr_123',
    refundData: [
        'amount' => 2500,
        'description' => 'Customer requested refund',
    ]
);

use GuzzleHttp\Client;

$httpClient = new Client([
    'timeout' => 60,
    'verify' => true,
]);

$client = new VippsClient(
    clientId: 'your-client-id',
    clientSecret: 'your-client-secret',
    subscriptionKey: 'your-subscription-key',
    merchantSerialNumber: 'your-msn',
    testMode: true,
    options: ['http_client' => $httpClient]
);

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$logger = new Logger('vipps');
$logger->pushHandler(new StreamHandler('path/to/vipps.log', Logger::DEBUG));

$client = new VippsClient(
    clientId: 'your-client-id',
    clientSecret: 'your-client-secret',
    subscriptionKey: 'your-subscription-key',
    merchantSerialNumber: 'your-msn',
    testMode: true,
    options: ['logger' => $logger]
);

use Coretrek\Vipps\Exceptions\VippsException;

try {
    $session = $client->checkout()->createPaymentSession(
        reference: 'order-12345',
        amount: 10000,
        currency: 'NOK'
    );
} catch (VippsException $e) {
    echo "Error: " . $e->getMessage() . "\n";
    echo "Status Code: " . $e->getCode() . "\n";
    
    // Check error type
    if ($e->isValidationError()) {
        echo "Validation error occurred\n";
        print_r($e->getErrorDetails());
    }
    
    if ($e->isAuthenticationError()) {
        echo "Authentication failed - check your credentials\n";
    }
    
    if ($e->isNotFoundError()) {
        echo "Resource not found\n";
    }
}

$session = $client->checkout()
    ->buildPaymentSession()
    ->reference('order-12345')
    ->transaction(10000, 'NOK', 'order-12345', 'Order with shipping')
    ->merchantInfo(
        'https://example.com/callback',
        'https://example.com/return',
        'https://example.com/terms'
    )
    ->logistics([
        'fixedOptions' => [
            [
                'brand' => 'POSTEN',
                'amount' => ['value' => 300, 'currency' => 'NOK'],
                'id' => 'posten-home',
                'priority' => 1,
                'isDefault' => true,
                'description' => 'Home delivery',
            ],
            [
                'brand' => 'POSTEN',
                'amount' => ['value' => 200, 'currency' => 'NOK'],
                'type' => 'PICKUP_POINT',
                'id' => 'posten-pickup',
                'priority' => 2,
                'isDefault' => false,
                'description' => 'Pickup point',
            ],
        ],
    ])
    ->create();

$session = $client->checkout()
    ->buildSubscriptionSession()
    ->reference('sub-12345')
    ->transaction(100, 'NOK', 'sub-12345', 'Initial charge')
    ->subscription([
        'productName' => 'Premium Membership',
        'amount' => ['value' => 2500, 'currency' => 'NOK'],
        'interval' => ['unit' => 'MONTH', 'count' => 1],
        'merchantAgreementUrl' => 'https://example.com/my-subscriptions',
        'productDescription' => 'Monthly premium membership',
    ])
    ->merchantInfo(
        'https://example.com/callback',
        'https://example.com/return',
        'https://example.com/terms'
    )
    ->create();

// Price campaign - reduced price until a date
$agreement = $client->recurring()
    ->buildAgreement()
    ->legacyPricing(3900, 'NOK')
    ->interval('MONTH', 1)
    ->product('News Subscription')
    ->merchantUrls('https://example.com/redirect', 'https://example.com/manage')
    ->phoneNumber('4712345678')
    ->priceCampaign(100, '2024-12-31T23:59:59Z') // 1 NOK until end of year
    ->create();

// Period campaign - fixed price for a period
$agreement = $client->recurring()
    ->buildAgreement()
    ->legacyPricing(3900, 'NOK')
    ->interval('MONTH', 1)
    ->product('News Subscription')
    ->merchantUrls('https://example.com/redirect', 'https://example.com/manage')
    ->phoneNumber('4712345678')
    ->periodCampaign(100, 'WEEK', 4) // 1 NOK for 4 weeks
    ->initialCharge(100, 'NOK', 'Campaign activation', 'DIRECT_CAPTURE')
    ->create();

$agreement = $client->recurring()
    ->buildAgreement()
    ->variablePricing(5000, 'NOK') // User can be charged up to 50 NOK
    ->interval('MONTH', 1)
    ->product('Usage-based Service')
    ->merchantUrls('https://example.com/redirect', 'https://example.com/manage')
    ->phoneNumber('4712345678')
    ->create();

$charges = [
    [
        'agreementId' => 'agr_123',
        'amount' => 2500,
        'transactionType' => 'DIRECT_CAPTURE',
        'description' => 'January charge',
        'due' => '2024-01-01',
        'retryDays' => 5,
        'type' => 'RECURRING',
    ],
    [
        'agreementId' => 'agr_456',
        'amount' => 2500,
        'transactionType' => 'DIRECT_CAPTURE',
        'description' => 'January charge',
        'due' => '2024-01-01',
        'retryDays' => 5,
        'type' => 'RECURRING',
    ],
];

$result = $client->recurring()->createChargesAsync($charges);

use Coretrek\Vipps\Login\AuthorizationUrlBuilder;

// Generate secure random values
$state = AuthorizationUrlBuilder::generateState();
$nonce = AuthorizationUrlBuilder::generateNonce();
$codeVerifier = AuthorizationUrlBuilder::generateCodeVerifier();

// Build authorization URL
$authUrl = $client->login()
    ->buildAuthorizationUrl()
    ->clientId('your-client-id')
    ->redirectUri('https://example.com/vipps/callback')
    ->scope(['openid', 'name', 'email', 'phoneNumber', 'address'])
    ->state($state)
    ->nonce($nonce)
    ->pkce($codeVerifier, 'S256')
    ->build();

// Store state, nonce, and code_verifier in session
$_SESSION['oauth_state'] = $state;
$_SESSION['oauth_nonce'] = $nonce;
$_SESSION['oauth_code_verifier'] = $codeVerifier;

// Redirect user to Vipps login
header('Location: ' . $authUrl);

use Coretrek\Vipps\Login\AuthorizationUrlBuilder;

// Generate secure random values
$state = AuthorizationUrlBuilder::generateState();
$nonce = AuthorizationUrlBuilder::generateNonce();
$codeVerifier = AuthorizationUrlBuilder::generateCodeVerifier();

// Build authorization URL with app-to-app flow
$authUrl = $client->login()
    ->buildAuthorizationUrl()
    ->clientId('your-client-id')
    ->redirectUri('https://example.com/vipps/callback')
    ->scope(['openid', 'name', 'email', 'phoneNumber'])
    ->state($state)
    ->nonce($nonce)
    ->pkce($codeVerifier, 'S256')
    ->requestedFlow('app_to_app')
    ->appCallbackUri('myapp://oauth/callback/vipps')
    ->build();

// Store state, nonce, and code_verifier securely
// Then open the auth URL in the device browser or use a deep link

// In your callback handler
$code = $_GET['code'];
$returnedState = $_GET['state'];

// Verify state to prevent CSRF
if ($returnedState !== $_SESSION['oauth_state']) {
    throw new Exception('Invalid state');
}

// Exchange code for tokens
$tokens = $client->login()->exchangeCodeForTokens(
    code: $code,
    redirectUri: 'https://example.com/vipps/callback',
    options: [
        'code_verifier' => $_SESSION['oauth_code_verifier'],
    ]
);

// Get user information
$userInfo = $client->login()->getUserInfo($tokens['access_token']);

echo "Welcome, " . $userInfo['name'];
echo "Email: " . $userInfo['email'];
echo "Phone: " . $userInfo['phone_number'];

// Check if user exists
$userExists = $client->login()->checkUserExists('4712345678');

if ($userExists['exists']) {
    // Initiate authentication
    $auth = $client->login()->initiateCibaAuth(
        loginHint: '4712345678',
        options: [
            'scope' => 'openid name email',
            'bindingMessage' => 'Login to Example App',
            'requested_expiry' => 300,
        ]
    );

    // Poll for token (with proper interval)
    $interval = $auth['interval'];
    $authReqId = $auth['auth_req_id'];

    while (true) {
        sleep($interval);

        try {
            $tokens = $client->login()->pollCibaToken($authReqId);
            // User has authenticated
            break;
        } catch (VippsException $e) {
            // Still waiting for user to approve
            continue;
        }
    }

    $userInfo = $client->login()->getUserInfo($tokens['access_token']);
}

// Get OpenID Connect discovery document
$config = $client->login()->getOpenIdConfiguration();

echo "Issuer: " . $config['issuer'];
echo "Authorization Endpoint: " . $config['authorization_endpoint'];
echo "Supported Scopes: " . implode(', ', $config['scopes_supported']);

// Get JWKS for token verification
$jwks = $client->login()->getJwks();