Skip to content
This repository has been archived by the owner on Aug 28, 2024. It is now read-only.

Commit

Permalink
Repaired posData lookup
Browse files Browse the repository at this point in the history
- callback was not parsing the post data returned from the validation response correctly
- added a validator to ensure the response is likely to contain correct data
  • Loading branch information
Chris Kleeschulte committed Jun 23, 2016
1 parent 993116c commit ef264be
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 49 deletions.
72 changes: 34 additions & 38 deletions bitpay/bp_lib.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
<?php
/**
* The MIT License (MIT)
*
*
* Copyright (c) 2011-2015 BitPay
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Expand All @@ -26,17 +26,17 @@
require_once 'bp_options.php';

function bpCurl($url, $apiKey, $post = false) {
global $bpOptions;
global $bpOptions;

$curl = curl_init($url);
$length = 0;
if ($post)
{
{
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
$length = strlen($post);
}

$uname = base64_encode($apiKey);
$header = array(
'Content-Type: application/json',
Expand All @@ -54,9 +54,9 @@ function bpCurl($url, $apiKey, $post = false) {
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);

$responseString = curl_exec($curl);

if($responseString == false) {
$response = curl_error($curl);
} else {
Expand All @@ -65,43 +65,43 @@ function bpCurl($url, $apiKey, $post = false) {
curl_close($curl);
return $response;
}
// $orderId: Used to display an orderID to the buyer. In the account summary view, this value is used to
// $orderId: Used to display an orderID to the buyer. In the account summary view, this value is used to
// identify a ledger entry if present.
//
// $price: by default, $price is expressed in the currency you set in bp_options.php. The currency can be
// $price: by default, $price is expressed in the currency you set in bp_options.php. The currency can be
// changed in $options.
//
// $posData: this field is included in status updates or requests to get an invoice. It is intended to be used by
// the merchant to uniquely identify an order associated with an invoice in their system. Aside from that, Bit-Pay does
// not use the data in this field. The data in this field can be anything that is meaningful to the merchant.
//
// $options keys can include any of:
// $options keys can include any of:
// ('itemDesc', 'itemCode', 'notificationEmail', 'notificationURL', 'redirectURL', 'apiKey'
// 'currency', 'physical', 'fullNotifications', 'transactionSpeed', 'buyerName',
// 'currency', 'physical', 'fullNotifications', 'transactionSpeed', 'buyerName',
// 'buyerAddress1', 'buyerAddress2', 'buyerCity', 'buyerState', 'buyerZip', 'buyerEmail', 'buyerPhone')
// If a given option is not provided here, the value of that option will default to what is found in bp_options.php
// (see api documentation for information on these options).
function bpCreateInvoice($orderId, $price, $posData, $options = array()) {
global $bpOptions;
function bpCreateInvoice($orderId, $price, $posData, $options = array()) {
global $bpOptions;

$options = array_merge($bpOptions, $options); // $options override any options found in bp_options.php

$options['posData'] = '{"posData": "' . $posData . '"';
if ($bpOptions['verifyPos']) // if desired, a hash of the POS data is included to verify source in the callback
$options['posData'].= ', "hash": "' . crypt($posData, $options['apiKey']).'"';
$options['posData'].= '}';
$options['posData'].= '}';

$options['orderID'] = $orderId;
$options['price'] = $price;
$postOptions = array('orderID', 'itemDesc', 'itemCode', 'notificationEmail', 'notificationURL', 'redirectURL',
'posData', 'price', 'currency', 'physical', 'fullNotifications', 'transactionSpeed', 'buyerName',

$postOptions = array('orderID', 'itemDesc', 'itemCode', 'notificationEmail', 'notificationURL', 'redirectURL',
'posData', 'price', 'currency', 'physical', 'fullNotifications', 'transactionSpeed', 'buyerName',
'buyerAddress1', 'buyerAddress2', 'buyerCity', 'buyerState', 'buyerZip', 'buyerEmail', 'buyerPhone');
foreach($postOptions as $o)
if (array_key_exists($o, $options))
$post[$o] = $options[$o];
$post = json_encode($post);

$response = bpCurl('https://bitpay.com/api/invoice/', $options['apiKey'], $post);

return $response;
Expand All @@ -111,25 +111,25 @@ function bpCreateInvoice($orderId, $price, $posData, $options = array()) {
function bpVerifyNotification($apiKey = false) {
global $bpOptions;
if (!$apiKey)
$apiKey = $bpOptions['apiKey'];
$apiKey = $bpOptions['apiKey'];

$post = file_get_contents("php://input");
if (!$post)
return 'No post data';

$json = json_decode($post, true);

if (is_string($json))
return $json; // error

if (!array_key_exists('posData', $json))
if (!array_key_exists('posData', $json))
return 'no posData';

$posData = json_decode($json['posData'], true);
if($bpOptions['verifyPos'] and $posData['hash'] != crypt($posData['posData'], $apiKey))
if($bpOptions['verifyPos'] and $posData['hash'] != crypt($posData['posData'], $apiKey))
return 'authentication failed (bad hash)';
$json['posData'] = $posData['posData'];

if (!array_key_exists('id', $json))
{
return 'Cannot find invoice ID';
Expand All @@ -142,17 +142,13 @@ function bpVerifyNotification($apiKey = false) {
function bpGetInvoice($invoiceId, $apiKey=false) {
global $bpOptions;
if (!$apiKey)
$apiKey = $bpOptions['apiKey'];
$apiKey = $bpOptions['apiKey'];

$response = bpCurl('https://bitpay.com/api/invoice/'.$invoiceId, $apiKey);
if (is_string($response))
return $response; // error
$response['posData'] = json_decode($response['posData'], true);
if($bpOptions['verifyPos'])
{
$response['posData'] = $response['posData']['posData'];
}
return $response;
return $response;
}

?>
34 changes: 23 additions & 11 deletions bitpay_callback.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

/**
* The MIT License (MIT)
*
*
* Copyright (c) 2011-2015 BitPay
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Expand All @@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

require 'bitpay/bp_lib.php';
require 'includes/application_top.php';

Expand All @@ -37,18 +37,30 @@ function bplog($contents) {
}
}

function validateResponse($response, $keys) {
if (is_array($response) &&
array_key_exists($keys[0], $response) &&
array_key_exists($keys[0], $response[$keys[0]]) &&
preg_match('/^\d+$/', $response[$keys[0]][$keys[0]]) &&
array_key_exists($keys[1], $response)) {
return true;
}
return false;
}

$response = bpVerifyNotification(MODULE_PAYMENT_BITPAY_APIKEY);
$keys = array('posData', 'status');

if (true === is_string($response)) {
if (!validateResponse($response, $keys)) {
bplog(date('H:i') . " bitpay callback error: " . $response . "\n");
} else {
global $db;
$order_id = $response['posData'];

switch ($response['status']) {
case 'confirmed':
$order_id = $response[$keys[0]][$keys[0]];
$status = $response[$keys[1]];
switch ($status) {
case 'confirmed':
case 'complete':
$db->Execute("update ". TABLE_ORDERS. " set orders_status = " . MODULE_PAYMENT_BITPAY_PAID_STATUS_ID . " where orders_id = ". intval($order_id));
$db->Execute("update ". TABLE_ORDERS. " set orders_status = " . MODULE_PAYMENT_BITPAY_PAID_STATUS_ID . " where orders_id = ". intval($order_id));
break;
case 'expired':
if (true === function_exists('zen_remove_order')) {
Expand Down

0 comments on commit ef264be

Please sign in to comment.