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

Commit ef264be

Browse files
author
Chris Kleeschulte
committed
Repaired posData lookup
- 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
1 parent 993116c commit ef264be

File tree

2 files changed

+57
-49
lines changed

2 files changed

+57
-49
lines changed

bitpay/bp_lib.php

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
<?php
22
/**
33
* The MIT License (MIT)
4-
*
4+
*
55
* Copyright (c) 2011-2015 BitPay
6-
*
6+
*
77
* Permission is hereby granted, free of charge, to any person obtaining a copy
88
* of this software and associated documentation files (the "Software"), to deal
99
* in the Software without restriction, including without limitation the rights
1010
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1111
* copies of the Software, and to permit persons to whom the Software is
1212
* furnished to do so, subject to the following conditions:
13-
*
13+
*
1414
* The above copyright notice and this permission notice shall be included in
1515
* all copies or substantial portions of the Software.
16-
*
16+
*
1717
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1818
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1919
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -26,17 +26,17 @@
2626
require_once 'bp_options.php';
2727

2828
function bpCurl($url, $apiKey, $post = false) {
29-
global $bpOptions;
30-
29+
global $bpOptions;
30+
3131
$curl = curl_init($url);
3232
$length = 0;
3333
if ($post)
34-
{
34+
{
3535
curl_setopt($curl, CURLOPT_POST, 1);
3636
curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
3737
$length = strlen($post);
3838
}
39-
39+
4040
$uname = base64_encode($apiKey);
4141
$header = array(
4242
'Content-Type: application/json',
@@ -54,9 +54,9 @@ function bpCurl($url, $apiKey, $post = false) {
5454
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
5555
curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
5656
curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
57-
57+
5858
$responseString = curl_exec($curl);
59-
59+
6060
if($responseString == false) {
6161
$response = curl_error($curl);
6262
} else {
@@ -65,43 +65,43 @@ function bpCurl($url, $apiKey, $post = false) {
6565
curl_close($curl);
6666
return $response;
6767
}
68-
// $orderId: Used to display an orderID to the buyer. In the account summary view, this value is used to
68+
// $orderId: Used to display an orderID to the buyer. In the account summary view, this value is used to
6969
// identify a ledger entry if present.
7070
//
71-
// $price: by default, $price is expressed in the currency you set in bp_options.php. The currency can be
71+
// $price: by default, $price is expressed in the currency you set in bp_options.php. The currency can be
7272
// changed in $options.
7373
//
7474
// $posData: this field is included in status updates or requests to get an invoice. It is intended to be used by
7575
// the merchant to uniquely identify an order associated with an invoice in their system. Aside from that, Bit-Pay does
7676
// not use the data in this field. The data in this field can be anything that is meaningful to the merchant.
7777
//
78-
// $options keys can include any of:
78+
// $options keys can include any of:
7979
// ('itemDesc', 'itemCode', 'notificationEmail', 'notificationURL', 'redirectURL', 'apiKey'
80-
// 'currency', 'physical', 'fullNotifications', 'transactionSpeed', 'buyerName',
80+
// 'currency', 'physical', 'fullNotifications', 'transactionSpeed', 'buyerName',
8181
// 'buyerAddress1', 'buyerAddress2', 'buyerCity', 'buyerState', 'buyerZip', 'buyerEmail', 'buyerPhone')
8282
// If a given option is not provided here, the value of that option will default to what is found in bp_options.php
8383
// (see api documentation for information on these options).
84-
function bpCreateInvoice($orderId, $price, $posData, $options = array()) {
85-
global $bpOptions;
86-
84+
function bpCreateInvoice($orderId, $price, $posData, $options = array()) {
85+
global $bpOptions;
86+
8787
$options = array_merge($bpOptions, $options); // $options override any options found in bp_options.php
88-
88+
8989
$options['posData'] = '{"posData": "' . $posData . '"';
9090
if ($bpOptions['verifyPos']) // if desired, a hash of the POS data is included to verify source in the callback
9191
$options['posData'].= ', "hash": "' . crypt($posData, $options['apiKey']).'"';
92-
$options['posData'].= '}';
93-
92+
$options['posData'].= '}';
93+
9494
$options['orderID'] = $orderId;
9595
$options['price'] = $price;
96-
97-
$postOptions = array('orderID', 'itemDesc', 'itemCode', 'notificationEmail', 'notificationURL', 'redirectURL',
98-
'posData', 'price', 'currency', 'physical', 'fullNotifications', 'transactionSpeed', 'buyerName',
96+
97+
$postOptions = array('orderID', 'itemDesc', 'itemCode', 'notificationEmail', 'notificationURL', 'redirectURL',
98+
'posData', 'price', 'currency', 'physical', 'fullNotifications', 'transactionSpeed', 'buyerName',
9999
'buyerAddress1', 'buyerAddress2', 'buyerCity', 'buyerState', 'buyerZip', 'buyerEmail', 'buyerPhone');
100100
foreach($postOptions as $o)
101101
if (array_key_exists($o, $options))
102102
$post[$o] = $options[$o];
103103
$post = json_encode($post);
104-
104+
105105
$response = bpCurl('https://bitpay.com/api/invoice/', $options['apiKey'], $post);
106106

107107
return $response;
@@ -111,25 +111,25 @@ function bpCreateInvoice($orderId, $price, $posData, $options = array()) {
111111
function bpVerifyNotification($apiKey = false) {
112112
global $bpOptions;
113113
if (!$apiKey)
114-
$apiKey = $bpOptions['apiKey'];
115-
114+
$apiKey = $bpOptions['apiKey'];
115+
116116
$post = file_get_contents("php://input");
117117
if (!$post)
118118
return 'No post data';
119-
119+
120120
$json = json_decode($post, true);
121-
121+
122122
if (is_string($json))
123123
return $json; // error
124124

125-
if (!array_key_exists('posData', $json))
125+
if (!array_key_exists('posData', $json))
126126
return 'no posData';
127-
127+
128128
$posData = json_decode($json['posData'], true);
129-
if($bpOptions['verifyPos'] and $posData['hash'] != crypt($posData['posData'], $apiKey))
129+
if($bpOptions['verifyPos'] and $posData['hash'] != crypt($posData['posData'], $apiKey))
130130
return 'authentication failed (bad hash)';
131131
$json['posData'] = $posData['posData'];
132-
132+
133133
if (!array_key_exists('id', $json))
134134
{
135135
return 'Cannot find invoice ID';
@@ -142,17 +142,13 @@ function bpVerifyNotification($apiKey = false) {
142142
function bpGetInvoice($invoiceId, $apiKey=false) {
143143
global $bpOptions;
144144
if (!$apiKey)
145-
$apiKey = $bpOptions['apiKey'];
145+
$apiKey = $bpOptions['apiKey'];
146146

147147
$response = bpCurl('https://bitpay.com/api/invoice/'.$invoiceId, $apiKey);
148148
if (is_string($response))
149149
return $response; // error
150150
$response['posData'] = json_decode($response['posData'], true);
151-
if($bpOptions['verifyPos'])
152-
{
153-
$response['posData'] = $response['posData']['posData'];
154-
}
155-
return $response;
151+
return $response;
156152
}
157153

158154
?>

bitpay_callback.php

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
/**
44
* The MIT License (MIT)
5-
*
5+
*
66
* Copyright (c) 2011-2015 BitPay
7-
*
7+
*
88
* Permission is hereby granted, free of charge, to any person obtaining a copy
99
* of this software and associated documentation files (the "Software"), to deal
1010
* in the Software without restriction, including without limitation the rights
1111
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1212
* copies of the Software, and to permit persons to whom the Software is
1313
* furnished to do so, subject to the following conditions:
14-
*
14+
*
1515
* The above copyright notice and this permission notice shall be included in
1616
* all copies or substantial portions of the Software.
17-
*
17+
*
1818
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1919
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2020
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,7 +23,7 @@
2323
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2424
* THE SOFTWARE.
2525
*/
26-
26+
2727
require 'bitpay/bp_lib.php';
2828
require 'includes/application_top.php';
2929

@@ -37,18 +37,30 @@ function bplog($contents) {
3737
}
3838
}
3939

40+
function validateResponse($response, $keys) {
41+
if (is_array($response) &&
42+
array_key_exists($keys[0], $response) &&
43+
array_key_exists($keys[0], $response[$keys[0]]) &&
44+
preg_match('/^\d+$/', $response[$keys[0]][$keys[0]]) &&
45+
array_key_exists($keys[1], $response)) {
46+
return true;
47+
}
48+
return false;
49+
}
50+
4051
$response = bpVerifyNotification(MODULE_PAYMENT_BITPAY_APIKEY);
52+
$keys = array('posData', 'status');
4153

42-
if (true === is_string($response)) {
54+
if (!validateResponse($response, $keys)) {
4355
bplog(date('H:i') . " bitpay callback error: " . $response . "\n");
4456
} else {
4557
global $db;
46-
$order_id = $response['posData'];
47-
48-
switch ($response['status']) {
49-
case 'confirmed':
58+
$order_id = $response[$keys[0]][$keys[0]];
59+
$status = $response[$keys[1]];
60+
switch ($status) {
61+
case 'confirmed':
5062
case 'complete':
51-
$db->Execute("update ". TABLE_ORDERS. " set orders_status = " . MODULE_PAYMENT_BITPAY_PAID_STATUS_ID . " where orders_id = ". intval($order_id));
63+
$db->Execute("update ". TABLE_ORDERS. " set orders_status = " . MODULE_PAYMENT_BITPAY_PAID_STATUS_ID . " where orders_id = ". intval($order_id));
5264
break;
5365
case 'expired':
5466
if (true === function_exists('zen_remove_order')) {

0 commit comments

Comments
 (0)