Exemple #1
0
def _transaction_action(transaction: Transaction, amount: int,
                        action: TransactionAction) -> Tuple[bool, str]:
    version = '2.0'
    shop_id = resolve(settings.WS_PAY_SHOP_ID)
    secret_key = resolve(settings.WS_PAY_SECRET_KEY)

    signature = generate_signature([
        shop_id, transaction.ws_pay_order_id, secret_key, transaction.stan,
        secret_key, transaction.approval_code, secret_key,
        str(amount), secret_key, transaction.ws_pay_order_id
    ])

    data = {
        'Version': version,
        'WsPayOrderId': transaction.ws_pay_order_id,
        'ShopID': shop_id,
        'ApprovalCode': transaction.approval_code,
        'STAN': transaction.stan,
        'Amount': amount,
        'Signature': signature
    }
    r = requests.post(f'{get_services_endpoint()}/{action.value}', data=data)
    response_data = r.json()

    expected_signature = generate_signature([
        shop_id,
        secret_key,
        response_data['STAN'],
        response_data['ActionSuccess'],
        secret_key,
        response_data['ApprovalCode'],
        response_data['WsPayOrderId'],
    ])

    if response_data['Signature'] != expected_signature:
        raise ValidationError('Bad signature')

    # Per WSPay docs update approval_code in case it was changed
    new_approval_code = response_data['ApprovalCode']
    if transaction.approval_code != new_approval_code:
        transaction.approval_code = new_approval_code
        transaction.save()

    success = bool(int(response_data['ActionSuccess']))
    error_message = response_data.get('ErrorMessage', '')
    return success, error_message
Exemple #2
0
def test_wspay_encode():
    """Test the processing function which prepares the data for WSPay."""
    shop_id = resolve(settings.WS_PAY_SHOP_ID)
    secret_key = resolve(settings.WS_PAY_SECRET_KEY)
    assert shop_id == 'MojShop'
    assert secret_key == '3DfEO2B5Jjm4VC1Q3vEh'

    return_data = {
        'ShopID': shop_id,
        'Version': resolve(settings.WS_PAY_VERSION),
        'TotalAmount': '10,00',
        'ReturnURL': (
            'http://testserver' + reverse('wspay:process-response', kwargs={'status': 'success'})
        ),
        'CancelURL': (
            'http://testserver' + reverse('wspay:process-response', kwargs={'status': 'cancel'})
        ),
        'ReturnErrorURL': (
            'http://testserver' + reverse('wspay:process-response', kwargs={'status': 'error'})
        ),
        'ReturnMethod': 'POST',
    }

    incoming_form = UnprocessedPaymentForm({'cart_id': 1, 'price': 10})
    if (incoming_form.is_valid()):
        form_data = generate_wspay_form_data(
            incoming_form.cleaned_data.copy(), RequestFactory().get('/')
        )

    req = WSPayRequest.objects.get()
    return_data['ShoppingCartID'] = str(req.request_uuid)
    return_data['Signature'] = generate_signature([
        shop_id,
        secret_key,
        str(req.request_uuid),
        secret_key,
        '1000',
        secret_key,
    ])

    assert return_data == form_data
Exemple #3
0
def status_check(request_uuid):
    """Check status of a transaction."""
    version = '2.0'
    shop_id = resolve(settings.WS_PAY_SHOP_ID)
    secret_key = resolve(settings.WS_PAY_SECRET_KEY)
    shopping_cart_id = str(request_uuid)
    signature = generate_signature([
        shop_id, secret_key, shopping_cart_id, secret_key, shop_id,
        shopping_cart_id
    ])

    data = {
        'Version': version,
        'ShopId': shop_id,
        'ShoppingCartId': shopping_cart_id,
        'Signature': signature
    }

    r = requests.post(f'{get_services_endpoint()}/statusCheck', data=data)
    return process_transaction_report(
        verify_transaction_report(WSPayTransactionReportForm, r.json()))
Exemple #4
0
def verify_transaction_report(form_class, data):
    """Verify validity and authenticity of wspay transaction report."""
    form = form_class(data=data)
    if form.is_valid():
        signature = form.cleaned_data['Signature']
        shop_id = resolve(settings.WS_PAY_SHOP_ID)
        secret_key = resolve(settings.WS_PAY_SECRET_KEY)
        param_list = [
            shop_id,
            secret_key,
            form.cleaned_data['ActionSuccess'],
            form.cleaned_data['ApprovalCode'],
            secret_key,
            shop_id,
            form.cleaned_data['ApprovalCode'],
            form.cleaned_data['WsPayOrderId'],
        ]
        expected_signature = generate_signature(param_list)
        if signature != expected_signature:
            raise ValidationError('Bad signature')

        return form.cleaned_data

    raise ValidationError('Form is not valid')
Exemple #5
0
def verify_response(form_class, data):
    """Verify validity and authenticity of wspay response."""
    form = form_class(data=data)
    if form.is_valid():
        signature = form.cleaned_data['Signature']
        shop_id = resolve(settings.WS_PAY_SHOP_ID)
        secret_key = resolve(settings.WS_PAY_SECRET_KEY)
        param_list = [
            shop_id,
            secret_key,
            data['ShoppingCartID'],
            secret_key,
            data['Success'],
            secret_key,
            data['ApprovalCode'],
            secret_key,
        ]
        expected_signature = generate_signature(param_list)
        if signature != expected_signature:
            raise ValidationError('Bad signature')

        return form.cleaned_data

    raise ValidationError('Form is not valid')
Exemple #6
0
    def dispatch(self, request, *args, **kwargs):
        form_class, request_status, redirect_setting = self._unpack_response_status(
            kwargs['status']
        )

        data = request.POST if request.method == 'POST' else request.GET
        wspay_request = process_response_data(
            verify_response(form_class, data),
            request_status
        )

        kwargs = {
            'cart_id': wspay_request.cart_id,
            'request_uuid': wspay_request.request_uuid,
        }
        redirect_url = resolve(
            redirect_setting, **kwargs)

        process_response_pre_redirect.send_robust(
            self.__class__,
            wspay_request=wspay_request, http_request=request, redirect_url=redirect_url,
        )

        return redirect(redirect_url)
Exemple #7
0
def generate_wspay_form_data(input_data, request, additional_data=''):
    """Process incoming data and prepare for POST to WSPay."""
    wspay_request = WSPayRequest.objects.create(
        cart_id=input_data['cart_id'],
        additional_data=additional_data,
    )
    # Send a signal
    pay_request_created.send_robust(WSPayRequest, instance=wspay_request)

    input_data['cart_id'] = str(wspay_request.request_uuid)

    price = input_data['price']
    assert price > 0, 'Price must be greater than 0'
    total_for_sign, total = build_price(price)

    shop_id = resolve(settings.WS_PAY_SHOP_ID)
    secret_key = resolve(settings.WS_PAY_SECRET_KEY)
    signature = generate_signature([
        shop_id,
        secret_key,
        input_data['cart_id'],
        secret_key,
        total_for_sign,
        secret_key,
    ])

    return_data = {
        'ShopID':
        shop_id,
        'ShoppingCartID':
        input_data['cart_id'],
        'Version':
        resolve(settings.WS_PAY_VERSION),
        'TotalAmount':
        total,
        'Signature':
        signature,
        'ReturnURL':
        request.build_absolute_uri(
            reverse('wspay:process-response', kwargs={'status': 'success'})),
        'CancelURL':
        request.build_absolute_uri(
            reverse('wspay:process-response', kwargs={'status': 'cancel'})),
        'ReturnErrorURL':
        request.build_absolute_uri(
            reverse('wspay:process-response', kwargs={'status': 'error'})),
        'ReturnMethod':
        'POST',
    }
    if input_data.get('first_name'):
        return_data['CustomerFirstName'] = input_data['first_name']
    if input_data.get('last_name'):
        return_data['CustomerLastName'] = input_data['last_name']
    if input_data.get('address'):
        return_data['CustomerAddress'] = input_data['address']
    if input_data.get('city'):
        return_data['CustomerCity'] = input_data['city']
    if input_data.get('zip_code'):
        return_data['CustomerZIP'] = input_data['zip_code']
    if input_data.get('country'):
        return_data['CustomerCountry'] = input_data['country']
    if input_data.get('email'):
        return_data['CustomerEmail'] = input_data['email']
    if input_data.get('phone'):
        return_data['CustomerPhone'] = input_data['phone']

    return return_data
Exemple #8
0
def get_services_endpoint():
    """Return production or dev services endpoint based on DEVELOPMENT setting."""
    development = resolve(settings.WS_PAY_DEVELOPMENT)
    if development:
        return 'https://test.wspay.biz/api/services'
    return 'https://secure.wspay.biz/api/services'
Exemple #9
0
def get_form_endpoint():
    """Return production or dev endpoint based on DEVELOPMENT setting."""
    development = resolve(settings.WS_PAY_DEVELOPMENT)
    if development:
        return 'https://formtest.wspay.biz/authorization.aspx'
    return 'https://form.wspay.biz/authorization.aspx'
Exemple #10
0
def test_conf_resolver():
    """Test conf resolver when settings are callables or dotted path to a callable."""
    assert resolve(settings.WS_PAY_SHOP_ID) == 'MojShop'
    assert resolve(settings.WS_PAY_SECRET_KEY) == '3DfEO2B5Jjm4VC1Q3vEh'