A thin PHP wrapper for BitcoinPostage.info – a website/API which sells USPS, UPS and FedEx postage and accepts Bitcoin and Monero for payment.
composer require brianhenryie/bh-php-bitcoinpostageinfo
See:
- API Documentation (shows example cURL requests for each endpoint)
- Register
- Create an API key
Create an instance of the API class with a PSR HTTP implementation. Guzzle is the most popular.
$httpFactory = new \GuzzleHttp\Psr7\HttpFactory();
$client = new \GuzzleHttp\Client();
$bitcoinPostageInfo = new \BrianHenryIE\BitcoinPostageInfo\BitcoinPostageInfoAPI(
requestFactory: $httpFactory,
streamFactory: $httpFactory,
client: $client,
);
All API calls require authentication:
$credentials = new \BrianHenryIE\BitcoinPostageInfo\Model\Request\Credentials(
key: $_ENV[ 'BITCOINPOSTAGEINFO_API_KEY' ],
secret: $_ENV[ 'BITCOINPOSTAGEINFO_API_SECRET' ],
);
Add credit to your account:
$chargeCreditsRequest = new \BrianHenryIE\BitcoinPostageInfo\Model\Request\ChargeCreditsRequest(
credentials: $credentials,
amount: '10.00'
);
/** @var \BrianHenryIE\BitcoinPostageInfo\Model\Response\ChargeCredits $chargeCreditsResponse */
$chargeCreditsResponse = $api->chargeCredits($chargeCreditsRequest);
$bitcoinAddressHref = 'bitcoin:' . $chargeCreditsResponse->address . '?amount=' . $chargeCreditsResponse->amount;
$bitcoinQrCode = 'https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl=' . $bitcoinAddressHref . '&choe=UTF-8';
printf(
'<a href="%s" target="_blank"><img src="%s"/><br/>Pay BitcoinPostage.info for $%s credits.</a>',
$bitcoinAddressHref,
$bitcoinQrCode,
$chargeCreditsResponse->credits
);
Check your account balance:
$credits = $api->getCredits($credentials);
echo $credits->credits;
You'll need your from and to addresses and the package dimensions to get rates and to purchase labels:
$fromAddress = new \BrianHenryIE\BitcoinPostageInfo\Model\Address(
name: 'Brian Henry',
street: '800 N St.',
street2: null,
city: 'Sacramento',
state: 'CA',
zip: '95814',
country: 'US',
phone: null,
);
$toAddress = new \BrianHenryIE\BitcoinPostageInfo\Model\Address(
name: 'Brian Henry',
street: '1 Palace St',
street2: 'Apartment 3',
city: 'Dublin',
state: 'Dublin',
zip: 'D02 XR57',
country: 'IE',
phone: null,
);
$dimensions = new \BrianHenryIE\BitcoinPostageInfo\Model\Dimensions(
weightLbs: 0,
weightOz: 1.5,
heightInches: 1.0,
widthInches: 2.0,
depthInches: 3.0,
);
Query for rates:
$ratesRequest = new \BrianHenryIE\BitcoinPostageInfo\Model\Request\GetRatesRequest(
credentials: $credentials,
fromAddress: $fromAddress,
toAddress: $toAddress,
service: new \BrianHenryIE\BitcoinPostageInfo\Model\Service(
packageType: UspsPackage::FLAT_RATE_ENVELOPE,
),
dimensions: $dimensions,
);
/** @var \BrianHenryIE\BitcoinPostageInfo\Model\Response\Rate[] $ratesResponse */
$ratesResponse = $api->getRates($ratesRequest);
$cheapest_rate = array_reduce(
$ratesResponse,
function (\BrianHenryIE\BitcoinPostageInfo\Model\Response\Rate $carry, \BrianHenryIE\BitcoinPostageInfo\Model\Response\Rate $rate) {
return is_null($carry) || $rate->rate < $carry->rate ? $rate : $carry;
},
null
);
echo "{$cheapest_rate->currency} {$cheapest_rate->rate}";
echo $cheapest_rate->service;
International shipments require customs information:
$customs = new Customs(
type: CustomsContentsType::GIFT,
signer: 'Brian Henry',
customs: [
new \BrianHenryIE\BitcoinPostageInfo\Model\CustomsItem(
quantity: 1,
description: 'T-shirt',
totalValue: '10.00',
totalWeightOz: 20.5,
countryCodeOfOrigin: 'US',
hsTariffNumber: '610910',
)
],
);
Purchase a label:
$createPurchaseRequest = new \BrianHenryIE\BitcoinPostageInfo\Model\Request\CreatePurchaseRequest(
credentials: $credentials,
fromAddress: $fromAddress,
toAddress: $toAddress,
service: new \BrianHenryIE\BitcoinPostageInfo\Model\Service(
packageType: UspsPackage::FLAT_RATE_ENVELOPE,
service: 'usps_intl_first_class_package',
),
dimensions: $dimensions,
customs: $customs,
testMode: true,
);
/** @var \BrianHenryIE\BitcoinPostageInfo\Model\Response\Purchase $purchaseResponse */
$purchaseResponse = $api->createPurchase($createPurchaseRequest);
/** @var \BrianHenryIE\BitcoinPostageInfo\Model\Response\PurchaseItem $purchasedLabel */
$purchasedLabel = $purchaseResponse->items[0];
echo $purchasedLabel->price;
echo $purchasedLabel->filename;
echo $purchasedLabel->trackingNo;
- Currency amounts are strings and other numbers are floats, except for
weightLbs
which is an int - A good PHP library for generating QR codes is chillerlan/php-qrcode (for the
::chargeCredits()
payment address) - Guzzle is a great PSR HTTP library but consider Art4/WP-Requests-PSR18-Adapter if you are developing for WordPress
- USPS will send you free flat rate envelopes and boxes. Order them online or pick them up at your local post office.
PhpDoc is incomplete. I'm not sure the correct way to document PHP 8.0 constructor property promotion properties.
What's a better coding standard to use?
No testing has been done for UPS / FedEx.
The BitcoinPostage.info support was very quick to reply to emails and update documentation as requested.