Credit Card

Cowpay service to charge customers using their credit cards

How it works

The V1 of card payments API now applies 3d-secure measures to detect fraud charge attempts. If your customer enabled any 3d-secure measures on his card the payment won't be processed on the same request, but you the payment will require an OTP entered from the customers in order to verify the payment operation. More details are below

Initiating the charge request

Initiate a POST by following the below instructions

Request Endpoints

https://cowpay.me/api/v1/charge/card
https://staging.cowpay.me/api/v1/charge/card
Make sure to send all the listed below headers and keys with the proper values

Headers

HeaderValue
AuthorizationBearer [you token]
Content-Typeapplication/json
Acceptapplication/json

Keys

FieldRequiredTypeDescription
merchant_reference_idyesstringUnique alphanumeric value required as identifier for the charge request
customer_merchant_profile_idyesstringID of the customer being charged on your system
amountyesstringtwo decimal value like: "15.60"
customer_nameyesstringcustomer name being charged
customer_mobileyesstringinternationally formatted customer mobile
customer_emailyesstringcustomer valid email
card_numberyesstring16 digits customer card
cvvyesstring3 digits of customer security code
expiry_yearyesstring2 digits like: 24
expiry_monthyesstring2 digits like: 05
descriptionyesstringcharge request description that reserve the payment name
signatureyesstringsha-256 hash for the following concatenated params: merchant_code + merchant_reference_id + customer_merchant_profile_id + amount + hash_key
Both merchant_code and hash_key are being found in your API settings page in your cowpay dashboard
You can generate signatures while testing here

Testing Credit Card

The below credit card details are only accepted on staging environment

KeyValue
Card Number5123456789012346
CVV123
Expiry Month05
Expiry Year21

Request Payload Example

{
    "merchant_reference_id": "mc-12545",
    "customer_merchant_profile_id": "253",
    "card_number": "5123456789012346",
    "cvv": "123",
    "expiry_month": "05",
    "expiry_year": "21",
    "customer_name": "John Doe",
    "customer_email": "example@gmail.com",
    "customer_mobile": "+201xxxxxxxxx",
    "amount": "10.00",
    "signature": "6fec70795ae74b15f43fd645d85e2b03c86f8a08c2c671ab345914c0eae4f7da",
    "description": "Charge request description"
}

non 3d-secure response

In case of the charge attempt succeeded, and the card has no 3d-secure measures enabled you will get the below response which includes the payment_gateway_reference_id and the customer will be charged directly

{
    "success": true,
    "status_code": 200,
    "status_description": "Operation done successfully",
    "type": "Credit Card Charge Request",
    "cowpay_reference_id": 60245,
    "payment_gateway_reference_id": "95648547",
    "merchant_reference_id": "mc-12545",
}

3d-secure response

In case of the card has any 3d-secure measures you won't receive the payment_gateway_reference_id directly but instead the response will contain the key three_d_secured which means the payment operation requires an OTP from the customer

{
    "success": true,
    "status_code": 200,
    "status_description": "Operation done successfully",
    "type": "Credit Card Charge Request",
    "three_d_secured": true,
    "cowpay_reference_id": 1000165
}

Handling the OTP step using cowpay plugin

To use cowpay OTP plugin you need to load the below script on your page
The plugin requires a div with id cowpay-otp-container element to be mounted on.

If you are testing on staging please replace cowpay.me with staging.cowpay.me to load the relevant script file.
<script src="https://cowpay.me/js/plugins/OTPPaymentPlugin.js"></script>

After embedding the plugin on your page it creates a global object called COWPAYOTPDIALOG which anables you to initiate and load the payment dialog by calling the following two functions

Don't forget to replace cowpay_reference_id parameter with the actual value you received from the charge response
<script>
    COWPAYOTPDIALOG.init()
    COWPAYOTPDIALOG.load(cowpay_reference_id) // the key from the charge request response
</script>

Payment Processed In Browser Notification

When the customer enters the OTP code and payment being processed the plugin popup will close itself and post a message in the browser using JavaScript postMessage API that contains the bellow content

Beside the browser callback you will also get a server callback in order to take an action on your backend
{
    callback_type: "order_status_update",
    cowpay_reference_id: "1000242",
    message_source: "cowpay",
    message_type: "cowpay_browser_callback",
    payment_gateway_reference_id: "971498564",
    payment_status: "PAID" // or "FAILED"
}

And you can handle that message using the below code:

<script>
    window.addEventListener('message', function (e) {
        if (e.data && e.data.message_source === 'cowpay') {
            let paymentStatus = e.data.payment_status,
                cowpayReferenceId = e.data.cowpay_reference_id,
                gatewayReferenceId = e.data.payment_gateway_reference_id;
            
            // take an action based on the values 
        }
    
    }, false);
</script>

Code Examples

POST /api/v1/charge/card HTTP/1.1
Host: cowpay.me
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjA4YzExYWRkOTgxYmEyMTAxMjBiNDU4NjU0YzJhNmFkYjdhYjRkNTg0M2UxYTFkMzVlMDM2MDdlNmY2ODMyN2QwZTA1ZmVhY2ExOWExYWIxIn0.eyJhdWQiOiIzIiwianRpIjoiMDhjMTFhZGQ5ODFiYTIxMDEyMGI0NTg2NTRjMmE2YWRiN2FiNGQ1ODQzZTFhMWQzNWUwMzYwN2U2ZjY4MzI3ZDBlMDVmZWFjYTE5YTFhYjEiLCJpYXQiOjE2MDAwODMwNjgsIm5iZiI6MTYwMDA4MzA2OCwiZXhwIjoxNjMxNjE5MDY4LCJzdWIiOiIxNyIsInNjb3BlcyI6W119.f--W72hdY9ABlepGkzFubQx4PNNbxiYJZj8hPfXC2EwsUhPwWYGOL3rTSFnhYTuubJcEXLKnncoXInhBf9Ho2g
Content-Type: application/json

{
    "merchant_reference_id": "mc-12545",
    "customer_merchant_profile_id": "253",
    "card_number": "4005550000000001",
    "cvv": "123",
    "expiry_month": "05",
    "expiry_year": "21",
    "customer_name": "Testing",
    "customer_email": "dev@cowpay.me",
    "customer_mobile": "+201096545211",
    "amount": "10.00",
    "signature": "ca2f64dc29dc89aa24aecc664a5791ad35b244c4fe47ddb93520fa96f9593ec8",
    "description": "Charge request description"
}
let axios = require('axios');

let data = {
    "merchant_reference_id": "mc-12545",
    "customer_merchant_profile_id": "253",
    "card_number": "4005550000000001",
    "cvv": "123",
    "expiry_month": "05",
    "expiry_year": "21",
    "customer_name": "Testing",
    "customer_email": "dev@cowpay.me",
    "customer_mobile": "+201096545211",
    "amount": "10.00",
    "signature": "ca2f64dc29dc89aa24aecc664a5791ad35b244c4fe47ddb93520fa96f9593ec8",
    "description": "Charge request description"
}

let axiosConfig = {
    method: 'post',
    baseURL: 'https://cowpay.me/api/v1/', // or https://staging.cowpay.me/api/v1/,
    url: 'charge/card',
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjA4YzExYWRkOTgxYmEyMTAxMjBiNDU4NjU0YzJhNmFkYjdhYjRkNTg0M2UxYTFkMzVlMDM2MDdlNmY2ODMyN2QwZTA1ZmVhY2ExOWExYWIxIn0.eyJhdWQiOiIzIiwianRpIjoiMDhjMTFhZGQ5ODFiYTIxMDEyMGI0NTg2NTRjMmE2YWRiN2FiNGQ1ODQzZTFhMWQzNWUwMzYwN2U2ZjY4MzI3ZDBlMDVmZWFjYTE5YTFhYjEiLCJpYXQiOjE2MDAwODMwNjgsIm5iZiI6MTYwMDA4MzA2OCwiZXhwIjoxNjMxNjE5MDY4LCJzdWIiOiIxNyIsInNjb3BlcyI6W119.f--W72hdY9ABlepGkzFubQx4PNNbxiYJZj8hPfXC2EwsUhPwWYGOL3rTSFnhYTuubJcEXLKnncoXInhBf9Ho2g'
    },
    data: data
}

axios(axiosConfig)
    .then(response => {
        console.log(response.data)
    })
    .catch(error => {
        console.log(error.response.data)
    })
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://cowpay.me/api/v1/', // or https://staging.cowpay.me/api/v1
    'headers' => [
        'Content-Type' => 'application/json',
        'Accept' => 'application/json',
        'Authorization' => 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjA4YzExYWRkOTgxYmEyMTAxMjBiNDU4NjU0YzJhNmFkYjdhYjRkNTg0M2UxYTFkMzVlMDM2MDdlNmY2ODMyN2QwZTA1ZmVhY2ExOWExYWIxIn0.eyJhdWQiOiIzIiwianRpIjoiMDhjMTFhZGQ5ODFiYTIxMDEyMGI0NTg2NTRjMmE2YWRiN2FiNGQ1ODQzZTFhMWQzNWUwMzYwN2U2ZjY4MzI3ZDBlMDVmZWFjYTE5YTFhYjEiLCJpYXQiOjE2MDAwODMwNjgsIm5iZiI6MTYwMDA4MzA2OCwiZXhwIjoxNjMxNjE5MDY4LCJzdWIiOiIxNyIsInNjb3BlcyI6W119.f--W72hdY9ABlepGkzFubQx4PNNbxiYJZj8hPfXC2EwsUhPwWYGOL3rTSFnhYTuubJcEXLKnncoXInhBf9Ho2g'
    ]
]);

try {
    $response = $client->request('POST', 'charge/card', [
        'json' => [
            'merchant_reference_id' => 'mc-12549',
            'customer_merchant_profile_id' => '253',
            'card_number' => '4005550000000001',
            'cvv' => '123',
            'expiry_month' => '05',
            'expiry_year' => '21',
            'customer_name' => 'Testing',
            'customer_email' => 'dev@cowpay.me',
            'customer_mobile' => '+201096545211',
            'amount' => '10.00',
            'signature' => 'c73771a1f07bdef54ffc5f4da265909e8b5febb9ca3720a3d10ba9ace06c8080',
            'description' => 'Charge request description'
        ]
    ]);

    $result = json_decode($response->getBody()->getContents(), true);

    if (isset($result['three_d_secured']) && $result['three_d_secured'] == true) {
        // go on and handle the OTP step 
        
    } else {
        // payment processed directly
    }

} catch (\GuzzleHttp\Exception\RequestException $exception) {

    $response = json_decode($exception->getResponse()->getBody()->getContents(), true);

    if ($response['status_code'] == 422) { 

        $errors = $response['errors']; // check invalid data messages

    }
}