Skip to content

Commit

Permalink
Complete Coinbase integration using popup
Browse files Browse the repository at this point in the history
  • Loading branch information
naokipeter committed Aug 28, 2018
1 parent ff4c893 commit 55b5d21
Show file tree
Hide file tree
Showing 11 changed files with 658 additions and 568 deletions.
33 changes: 29 additions & 4 deletions README.md
Expand Up @@ -2,7 +2,7 @@

Free donation plugin for Wordpress. Supports one-time and monthly payments, confirmation and notification-emails, webhooks, a newsletter checkbox, a tax deductibility checkbox, multiple purposes, custom colors, Javascript events, single form inheritance, sandbox mode, centralized settings and translations.

Accept donations via [Stripe](#stripe), [PayPal](#paypal), [GoCardless](#gocardless), [BitPay](#bitpay), [Skrill](#skrill) or [bank transfers](#bank-transfer).
Accept donations via [Stripe](#stripe), [PayPal](#paypal), [GoCardless](#gocardless), [BitPay](#bitpay), [Coinbase](#coinbase), [Skrill](#skrill) or [bank transfers](#bank-transfer).

![Screenshot of Raise - The Free Donation Plugin for WordPress](/assets/images/screenshot.png?raw=true)

Expand Down Expand Up @@ -386,7 +386,7 @@ EOD
#### JsonLogic

The following properties can be specified in an array format that lets you encode `if ... else if ... else` rules:
- `forms > my_form > payment > provider > (banktransfer|stripe|paypal|gocardless|bitpay|skrill)`
- `forms > my_form > payment > provider > (banktransfer|stripe|paypal|gocardless|bitpay|coinbase|skrill)`
- `forms > my_form > payment > form_elements > tax_receipt`
- `forms > my_form > payment > form_elements > share_data`
- `forms > my_form > payment > form_elements > tip`
Expand Down Expand Up @@ -620,16 +620,41 @@ Requires `pairing_code`.
}
```

Bitpay does not support recurring donations.

You can make a sandbox account [here](https://test.bitpay.com/get-started). Go to Payment Tools > Manage API Tokens > Add New Token to generate a pairing code.

Does not support recurring donations. BitPay donations are registered only if the donor clicks continue in the BitPay modal.
**Note:** Donations are registered only if the donor clicks continue in the BitPay modal.

Additional webhook data:
- `vendor_transaction_id`: Invoice ID

![Bitpay flow](/doc/images/bitpay_flow.png?raw=true)


### Coinbase
Requires `api_key`.

```json
"coinbase": {
"account": "Optional identifier for the bank account the donation is eventually transferred to",
"tooltip": "Something you want the donor to know",
"live": {
"api_key": "coinbase_sandbox_api_key"
}
}
```

Coinbase does not support recurring donations. Also, it does not have a sandbox environment for testing.

**Note:** Donations are registered only if the donor waits until the transaction is fully verified without closing the popup.

Additional webhook data:
- `vendor_transaction_id`: Charge code

![Coinbase flow](/doc/images/coinbase_flow.png?raw=true)


### Skrill
Requires `merchant_account`.

Expand Down Expand Up @@ -699,7 +724,7 @@ Send a notification email whenever a donation was completed. Can be a comma-sepa

All keys sent in webhooks can be used as rule conditions. If at least one condition does not match, the notification email is skipped. An empty object will always pass.

Note: The possible `payment_provider` values are `Stripe`, `PayPal`, `GoCardless`, `Skrill`, `BitPay` and `Bank Transfer`
Note: The possible `payment_provider` values are `Stripe`, `PayPal`, `GoCardless`, `Skrill`, `BitPay`, `Coinbase` and `Bank Transfer`


## Webhooks
Expand Down
4 changes: 2 additions & 2 deletions _globals.php
Expand Up @@ -21,8 +21,8 @@
/**
* Coinbase
*/
$GLOBALS['CoinbaseApiEndpoint'] = 'https://api.commerce.coinbase.com';
$GLOBALS['CoinbaseCheckoutEndpoint'] = 'https://commerce.coinbase.com/checkout/';
$GLOBALS['CoinbaseApiEndpoint'] = 'https://api.commerce.coinbase.com';
$GLOBALS['CoinbaseChargeEndpoint'] = 'https://commerce.coinbase.com/charges';

/**
* Supported bank account labels (listed here for automatic detection by Poedit)
Expand Down
4 changes: 4 additions & 0 deletions assets/css/form.css
Expand Up @@ -607,3 +607,7 @@ input[type='number'] {
background-size: 70px;
width: 70px;
}

#CoinbaseModal .coinbase_notice {
margin-bottom: 35px;
}
13 changes: 11 additions & 2 deletions changelog.txt
@@ -1,7 +1,16 @@
= 1.3.1 January 30, 2018
= 1.6 TBD =
* NEW: Coinbase integration

= 1.5 July, 2018 =
* NEW: Tipping feature

= 1.4 June, 2018 =
* NEW: JsonLogic rules

= 1.3.1 January 30, 2018 =
* FIXED: Increased ASSET version number

= 1.3.0 January 29, 2018
= 1.3.0 January 29, 2018 =
* IMPROVED: Replaced PNG by SVG (except flag sprites)
* NEW: Added minimum amounts for recurring donations
* NEW: Custom error messages for minimum amounts
Expand Down
Binary file added doc/images/coinbase_flow.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions form.php
Expand Up @@ -554,10 +554,10 @@ function raise_form($atts, $content = null)
<button class="btn btn-primary" onclick="raisePopup.focus()">OK</button>
</div>
<div class="raise_popup_closed">
<!-- <button id="BitPayPopupButton" class="btn btn-primary"><span class="glyphicon glyphicon-lock" style="margin-right: 5px" aria-hidden="true"></span><?php _e("Pay by Bitcoin", "raise") ?></button> -->
<a class="donate-with-crypto" href="#">
<span><?php _e("Donate with Crypto", "raise") ?></span>
</a>
<p class="coinbase_notice">
<?php _e("<strong>Important:</strong> Do not close the popup window until the transaction has been <strong>verified</strong>. This can take <strong>up to 10 minutes</strong>. Once the transaction is verified, click on <strong>Continue</strong> or wait until the popup is closed automatically.", 'raise'); ?>
</p>
<button id="CoinbasePopupButton" class="btn btn-primary"><span class="glyphicon glyphicon-lock" style="margin-right: 5px" aria-hidden="true"></span><?php _e("Donate with Crypto", "raise") ?></button>
</div>
</div>
</div>
Expand Down
82 changes: 57 additions & 25 deletions functions.php
Expand Up @@ -196,9 +196,6 @@ function ($cur) {
if (in_array('paypal', $enabledProviders)) {
wp_enqueue_script('donation-plugin-paypal');
}
if (in_array('coinbase', $enabledProviders)) {
wp_enqueue_script('donation-plugin-coinbase');
}
wp_enqueue_script('donation-plugin-json-logic');
wp_enqueue_script('donation-plugin-form');
wp_enqueue_script('donation-plugin-combobox');
Expand Down Expand Up @@ -1393,37 +1390,38 @@ function raise_prepare_bitpay_donation(array $donation)
function raise_prepare_coinbase_donation(array $donation)
{
try {
$form = $donation['form'];
$mode = $donation['mode'];
$email = $donation['email'];
$name = $donation['name'];
$amount = $donation['amount'];
$currency = $donation['currency'];
$country = $donation['country'];
$taxReceipt = raise_get($donation['tax_receipt'], false);
$account = raise_get($donation['account']);
$reqId = uniqid(); // Secret request ID. Needed to prevent replay attack
$returnUrl = raise_get_ajax_endpoint() . '?action=coinbase_log&req=' . $reqId;

// Get client
$client = raise_get_coinbase_client($donation);

// Create checkout
$res = $client->request('POST', $GLOBALS['CoinbaseApiEndpoint'] . '/checkouts', [
$res = $client->request('POST', $GLOBALS['CoinbaseApiEndpoint'] . '/charges', [
"json" => [
"name" => "Donation",
"description" => "$name ($email)",
"description" => $donation['name'] . ' (' . $donation['email'] . ')',
"local_price" => [
"amount" => $amount,
"currency" => $currency,
"amount" => $donation['amount'],
"currency" => $donation['currency'],
],
"pricing_type" => "fixed_price",
"redirect_url" => $returnUrl,
],
]);
$checkoutId = $res->getBody()['id'];
$body = json_decode($res->getBody(), true);
$chargeCode = $body['data']['code'];

// Save charge code to session
$_SESSION['raise-vendor-transaction-id'] = $chargeCode;

// Save user data to session
raise_set_donation_data_to_session($donation, $reqId);

// Return URL
return array(
'success' => true,
'url' => $GLOBALS['CoinbaseCheckoutEndpoint'] . $code,
'url' => $GLOBALS['CoinbaseChargeEndpoint'] . '/' . $chargeCode,
);
} catch (\Exception $e) {
return array(
Expand Down Expand Up @@ -1458,7 +1456,7 @@ function raise_get_coinbase_client(array $donation)
*/
function raise_verify_session()
{
if (!isset($_GET['req']) || $_GET['req'] != $_SESSION['raise-req-id']) {
if (!isset($_GET['req']) || $_GET['req'] !== $_SESSION['raise-req-id']) {
throw new \Exception('Invalid request');
}

Expand Down Expand Up @@ -1515,12 +1513,7 @@ function raise_process_bitpay_log()
raise_verify_session();

// Get donation from session
$donation = raise_get_donation_from_session();
$form = $donation['form'];
$mode = $donation['mode'];
$taxReceipt = $donation['tax_receipt'];
$currency = $donation['currency'];
$country = $donation['country'];
$donation = raise_get_donation_from_session();

// Add vendor transaction ID (BitPay invoice ID)
$donation['vendor_transaction_id'] = $_SESSION['raise-vendor-transaction-id'];
Expand Down Expand Up @@ -1549,6 +1542,45 @@ function raise_process_bitpay_log()
<body><script>var mainWindow = (window == top) ? /* mobile */ opener : /* desktop */ parent; mainWindow.showConfirmation("bitpay"); mainWindow.hideModal();</script></body></html>');
}

/**
* AJAX endpoint for handling donation logging for Coinbase.
* Takes user data from session and triggers the web hooks.
*
* @return string HTML with script that terminates the BitPay flow and shows the thank you step
*/
function raise_process_coinbase_log()
{
try {
// Verify session and purge reqId
raise_verify_session();

// Get donation from session
$donation = raise_get_donation_from_session();

// Add vendor transaction ID (Coinbase charge code)
$chargeCode = $_SESSION['raise-vendor-transaction-id'];
$donation['vendor_transaction_id'] = $chargeCode;

// Make sure the payment is paid
$client = raise_get_coinbase_client($donation);
$res = $client->request('GET', $GLOBALS['CoinbaseApiEndpoint'] . '/charges/' . $chargeCode);
$body = json_decode($res->getBody(), true);
$coinfirmedAt = $body['data']['confirmed_at'];
if (!$coinfirmedAt) {
throw new \Exception("Charge isn't confirmed");
}

// Do post donation actions
raise_do_post_donation_actions($donation);
} catch (\Exception $e) {
// No need to say anything. Just show confirmation.
}

die('<!doctype html>
<html lang="en"><head><meta charset="utf-8"><title>Closing flow...</title></head>
<body><script>var mainWindow = (window == top) ? /* mobile */ opener : /* desktop */ parent; mainWindow.showConfirmation("coinbase"); mainWindow.hideModal();</script></body></html>');
}

/**
* Get donation data from session
*
Expand Down
Binary file modified lang/raise-de_DE.mo
Binary file not shown.

0 comments on commit 55b5d21

Please sign in to comment.