0

I am creating a bot (Python, aiogram) with a paid subscription using the Fondy payment gateway. I am using the principle of checking the payment status, but after sending the request, I receive the following error:

{'response': {'error_code': 1014, 'error_message': 'Invalid signature signature: 8dccc7a9e053c3cdc1efddb13f906bc866239ae6; response_signature_string: **********|1396424|85cceedc-e54a-43f5-a9fd-e39dc6f15c1a', 'request_id': 'ZKIukrDkwZDz9', 'response_status': 'failure'}} 

Even though the order_id (85cceedc-e54a-43f5-a9fd-e39dc6f15c1a) is displayed correctly, the signature is still incorrect. Please help me find the error. Here is the payment code.

@dp.message_handler(commands ='FONDY')
async def order_fondy(message: types.Message):
    people_id = message.chat.id
    base = sqlite3.connect('users.db')
    cursor = base.cursor()

    order_id = str(uuid.uuid4())
    print(order_id)
    cursor.execute(f"UPDATE users_id SET  order_id == ? WHERE user_id == ?",
                   (order_id, people_id))
    base.commit()

    def generate_signature( order_id):
        params1 = {

            'merchant_id': '1396424',
            'order_desc': 'demo order',
            'currency': 'USD',
            'amount': '125',
            'order_id': f'{order_id}'
        }
        password = 'test'

        # Generating a list of values sorted by key
        values = []
        for key in sorted(params1.keys()):
            value = params1[key]
            # Skipping empty values
            if value:
                values.append(str(value))

        # Adding a parameter named "password" with the value 'test' to the beginning of the list of values
        values.insert(0, password)

        # Generating a string of values separated by a delimiter "|"
        signature_string = "|".join(values)
        print(signature_string)
        # Applying the SHA1 function to a string and returning the result in the format of a hexadecimal string
        signature = hashlib.sha1(signature_string.encode('utf-8')).hexdigest()

        return signature

    signature = generate_signature(order_id)
    print(signature)  # Displaying the signature

    api = Api(merchant_id=1396424,
              secret_key='test')
    checkout = Checkout(api=api)
    data = {
        'order_desc': 'demo order',
        'currency': 'USD',
        'amount': '125',
        'order_id': f'{order_id}'
    }

    payment_url = checkout.url(data).get('checkout_url')

    # Sending payment links to the user
    await message.reply(f"To make a payment, please follow the link: {payment_url}")

# Checking the payment status
@dp.callback_query_handler(text='check')
async def check_payment_status(call: CallbackQuery):
    people_id = call.message.chat.id
    connect = sqlite3.connect('users.db')
    cursor = connect.cursor()
    cursor.execute(f"SELECT order_id FROM users_id WHERE user_id = {people_id}")
    result_1 = cursor.fetchone()
    order_id = str(result_1[0])
    print(order_id)
    cursor.execute(f"SELECT payment_id FROM users_id WHERE user_id = {people_id}")
    result_2 = cursor.fetchone()
    signature = str(result_2[0])
    print(signature)
    url = 'https://pay.fondy.eu/api/status/order_id'
    headers = {'Content-Type': 'application/json'}
    data = {
        "request": {
            'currency': 'USD',
            'amount': '125',
            'order_id': f'{order_id}',
            'merchant_id': '1396424',
            'signature': f'{signature}',
            'order_desc': 'demo order',
            "response_url": "https://pay.fondy.eu/responsepage/"
                }
            }

    async with aiohttp.ClientSession() as session:
        async with session.post(url, headers=headers, data=json.dumps(data)) as response:
            response_data = await response.json()
            print(response_data)


            if response.status == 200:
            # Handling a successful response

I tried adding parameters and removing the "data" and "params1" parameters, but it didn't lead to any results.

1 Answers1

0

This is my js function for signature generation

getSignature(merchant_id, PaymentKey, params: any) {
        params.merchant_id = merchant_id;
        
        const sortedKeys = Object.keys(params).sort();

        params.PaymentKey = PaymentKey;
        sortedKeys.unshift('PaymentKey')

        const concatenatedParams = sortedKeys.map(key => params[key]).join('|');

        return sha1(concatenatedParams);
    }

You need to sort the keys alphabetically and set the payment key on the first place.

In case of failure you can see the right order of params in the response from fondly.

Like this:

Invalid signature signature: 72b7eb21125dff8d394c3f8535fed43e45c29c9b; response_signature_string: `**********|1000|USD|1530334|Testpayment|23u23823r22d2322d23|Y|https://your.domain/callback

toyota Supra
  • 3,181
  • 4
  • 15
  • 19