Currency Exchange Rate with below code is working sometimes and not working sometimes and not at all reliable. Is there any better way to get Currency Exchange Rate in PHP?
public function getJPYtoUSDExchangeRate(){
$from = 'JPY';
$to = 'USD';
$amount = 1;
$data = file_get_contents("https://finance.google.com/finance/converter?a=$amount&from=$from&to=$to");
preg_match("/<span class=bld>(.*)<\/span>/",$data, $converted);
$converted = preg_replace("/[^0-9.]/", "", $converted[1][0]);
return number_format(round($converted, 3),2);
}
You have several issues:
You're not calling an actual API, you're scraping a web page, which means that:
you're most likely violating Google's TOS
you're more likely to get rate-limited (or be detected as abuse and blacklisted) at some point if you're fetching this page too often
you're dependent on any change made in the HTML structure of the web page
You're scraping the page every single time you need to convert an amount to another currency, which means that any failure makes your currency conversion fail.
What you should do:
load exchange rates from a legitimate feed or API
load them on a regular basis (via a cron job for example) and save them to a local database, that will be used to perform currency conversions
This way, even if an API call fails, you still have access to a slightly outdated exchange rate, which is better than a failure in most cases.
Where do you find a trustable exchange rate feed?
There are plenty of APIs, free or not, that offer this service.
A good source I know of is the European Central Bank, who provides an XML feed that's been there for years and provides exchange rates for 32 currencies relative to EUR.
OpenExchangeRates also offers a free plan with a limit of 1,000 requests per month, which is enough to refresh rates every hour. It provides exchange rates for 170 currencies, relative to USD.
How do you store the values in your database?
Whichever feed you choose, you need to parse it (if XML) or json_decode() it (if JSON) and store the values in your database. Ideally, set up a cron job to run your import script daily or even hourly.
The actual parsing and importing steps are outside the scope of this question, but let's assume a simple MySQL table that holds the records:
CREATE TABLE exchange_rate(
target_currency CHAR(3) COLLATE ascii_bin NOT NULL PRIMARY KEY,
exchange_rate DOUBLE NOT NULL
);
How to properly handle currency conversions based on rates relative to a single currency?
This is a question I've answered recently. The feeds above give you rates to convert the base currency (EUR or USD) to another currency, but do not give you a clue on how to convert between two arbitrary currencies. I would suggest you use a proper library that handles these conversions for you, such as brick/money - disclaimer: I'm the author.
Here is how you would configure it to load your exchange rates from the table above:
use Brick\Money\CurrencyConverter;
use Brick\Money\ExchangeRateProvider\PDOProvider;
use Brick\Money\ExchangeRateProvider\PDOProviderConfiguration;
use Brick\Money\ExchangeRateProvider\BaseCurrencyProvider;
// set to whatever your rates are relative to
$baseCurrency = 'USD';
// use your own credentials, or re-use your existing PDO connection
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$configuration = new PDOProviderConfiguration();
$configuration->tableName = 'exchange_rate';
$configuration->exchangeRateColumnName = 'exchange_rate';
$configuration->targetCurrencyColumnName = 'target_currency';
$configuration->sourceCurrencyCode = $baseCurrency;
// this provider loads exchange rates from your database
$provider = new PDOProvider($pdo, $configuration);
// this provider calculates exchange rates relative to the base currency
$provider = new BaseCurrencyProvider($provider, $baseCurrency);
// this currency converter can now handle any currency pair
$converter = new CurrencyConverter($provider);
And how you would use it:
use Brick\Math\RoundingMode;
use Brick\Money\Money;
$money = Money::of(10, 'EUR'); // EUR 10.00
$converter->convert($money, 'CAD', RoundingMode::DOWN); // CAD 15.27
CurrencyFreaks API provides trusty exchange rates for 179 currencies worldwide in JSON and XML formats compatible with multiple programming languages. By using CurrencyFreaks API, you can also change the 'base' currency and can get exchange rates for specific currencies.
Here is a simple currency exchange rate endpoint by using PHP:
setUrl('https://api.currencyfreaks.com/latest
?apikey=YOUR_APIKEY
&base=GBP');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
'follow_redirects' => TRUE
));
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
The JSON response will be:
{
"date": "2020-10-06 11:22:00+00",
"base": "GBP",
"rates": {
"FJD": "2.737385252915371",
"MXN": "27.74546375788785",
"STD": "27185.017172962733",
"LVL": "0.8482572402792966",
"SCR": "23.257414775003944",
"CDF": "2535.4260357935937",
"BBD": "2.585121591194042",
"GTQ": "10.055244048403818",
"CLP": "1031.8523300993463",
"HNL": "31.82062875327341",
"UGX": "4769.159332676713",
"ZAR": "21.445845580346873",
"TND": "3.542262860333636",
"CUC": "1.2926654930214643",
"BSD": "1.292560795597021",
"SLL": "12676.789824444395",
"SDG": "71.5109260164052",
"IQD": "1542.8992384231794",
"GMD": "66.89002117214584",
"CUP": "34.25286108332106",
"TWD": "37.17921872455271",
"RSD": "128.99756740058268",
"DOP": "75.46618143934401",
"KMF": "540.1610026652604",
.
.
.
[179 Currencies]
}
}
I hope it works.
The bank of Canada provides RSS feed for these currencies :
AUD, BRL, CNY, EUR, HKD, INR, IDR, JPY, MXN, NZD, NOK, PEN, RUB, SAR, SGD, ZAR, KRW, SEK, CHF, TWD, TRY, GBP, USD
Here is a way of getting currency conversions without API or 3rd party service:
<?php
class EXCHANGE {
public $Rates;
public $Rate;
public function __construct(){
$this->Rates = $this->fetchAllRates();
foreach($this->Rates as $currency => $rate){
$this->Rate[$currency] = $rate['latest'];
}
}
public function fetchAllRates(){
$currencies = ["AUD","BRL","CNY","EUR","HKD","INR","IDR","JPY","MXN","NZD","NOK","PEN","RUB","SAR","SGD","ZAR","KRW","SEK","CHF","TWD","TRY","GBP","USD"];
$cURL = curl_init();
curl_setopt($cURL, CURLOPT_URL, "https://www.bankofcanada.ca/valet/observations/group/FX_RATES_DAILY/json?start_date=2010-01-01");
curl_setopt($cURL, CURLOPT_RETURNTRANSFER, 1);
$rates = curl_exec($cURL);
curl_close($cURL);
$rates = json_decode($rates,true)['observations'];
foreach($currencies as $currency){
foreach($rates as $rate){
$AllRates[$currency][$rate['d']] = $rate['FX'.$currency.'CAD']['v'];
$AllRates[$currency]['latest'] = $rate['FX'.$currency.'CAD']['v'];
}
}
return $AllRates;
}
public function convert($value,$from,$to){
if($to == "CAD"){ return $value*$this->Rate[$from]; }
else { return ($value*$this->Rate[$from])/$this->Rate[$to]; }
}
}
$Exchange = new EXCHANGE();
foreach($Exchange->Rate as $currency => $rate){
echo $currency.': '.$rate."<br>\n"; // Listing all the exchange rates
}
echo "Converting 2.00 USD to CAD : ".$Exchange->convert(2,"USD","CAD")."\n"; //2022-02-23 = 2.5486
echo "Converting 2.00 USD to AUD : ".$Exchange->convert(2,"USD","AUD")."\n"; //2022-02-23 = 2.7708197434225
Update:
I had initially forgot to put the convert method.
Information:
This class is using the RSS feed of the Bank of Canada. It is not the most accurate data, because it is only updated once per business day. The $Rate property contains the exchange rates for CAD currency. Thus to convert other currencies, it first converts the initial currency to CAD and then to the new currency. So in the example provided above, 2.00 USD is converted to 2.5486 CAD. Then divided by the exchange rate of AUD resulting in 2.7708197434225 AUD.
I am using a function I created that I have tried creating customers from, and creating charges from. For whatever reason it seems to be double charging in test mode (Not bringing into live mode under these conditions) and I'm trying to understand why. I had it going through a few functions so I made it all happen in one function to make sure that it had nothing to do with what I had made. I'm lost on why this is happening. I try to make charges from token, doubles in less than a second. I try to create a customer from token, doubles in less than a second. I am using Stripes latest stripe-php library.
public function invoice($invoice = null) {
//Provides billing info for invoice.ctp
$this->loadModel('Invoice');
$billingi = $this->Invoice->get($invoice, [
'contain' => ['Items'],
]);
$dollars = 0;
foreach ($billingi->items as $item) {
$dollars += $item->price;
}
$cents = bcmul($dollars, 100);
$price = floatval($cents);
if ($this->request->is('post')) {
$stripeToken = $this->request->data('stripeToken');
//Sets stripe API
\Stripe\Stripe::setApiKey("sk_test_QVYouMViTf1k3zfVu2VAyZge");
//Retrieves stripe token from stripe API
//$response = \Stripe\Token::retrieve($stripeToken);
\Stripe\Customer::create(array(
"description" => "Test customer",
"source" => $stripeToken // obtained with Stripe.js
));
$this->Flash->success(__('Thank you for your payment!'));
return $this->redirect(['action' => 'approved', $invoice]);
}
/*
if ($response && $this->checkExists($response->card->cvc_check, $response->card->address_zip_check) == true) {
$this->insertCharge($invoice, $response, $price);
} else {
//Throw error because cvc_check or zip came back null (doesn't exist)
}
}
*/
$this->set('billingi', $billingi);
$this->set('_serialize', ['billing']);
}
The reason why there are things commented out is because I wanted to test the function without it, but adding it back later when I understand what the issue is.
In your code, the only API request sent to Stripe is a customer creation request (\Stripe\Customer::create(...)).
This doesn't charge the user -- it merely validates the card from the token in the source parameter, and creates a persistent customer object that you can in turn use to create actual charges. This tutorial explains this flow.
There's nothing in your code that would cause the API request to be sent twice. It's very unlikely the issue is on Stripe's end. More likely, your code is being called twice for some reason that's not related to Stripe. You'd need to add traces to your code to figure out what exactly is being called in what order.
I have a feature in my website that a user can change/update/add a credit card in his/her Paypal recurring payment profile. But while updating the profile nothing happens. Please help.
Code is as below:
require_once("paypal_pro.inc.php");
$paypalPro = new paypal_pro('xxxxxxxxxxxxxxxxxxxxx.gmail.com', 'xxxxxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxxxxxxxx', '', '', FALSE, FALSE );
$paymentAction = urlencode("Sale");
$methodToCall = 'UpdateRecurringPaymentsProfile';
$padDateMonth = str_pad(4, 2, '0', STR_PAD_LEFT);
$expDateYear =urlencode( 2018);
$expDate = $padDateMonth.$expDateYear;
$nvpstr='&PAYMENTACTION='.$paymentAction.'&METHOD=UpdateRecurringPaymentsProfile&PROFILEID=I-NGYJW5L1TLNV&CREDITCARDTYPE=VISA&ACCT=4111111111111111&CVV2=123&EXPDATE='.$expDate;
$resArray = $paypalPro->hash_call($methodToCall,$nvpstr);
echo '<pre>';
print_r($resArray);
I am trying this with a sandbox account.
First of all you need to tell where are you writing this code. Don't mind but your code looks like not as it should be:
1- Which version are you using (Yii1 | Yii2)? I guess Yii1
if you are using yii1 and you want to perform this stuff under profile update Action.
so lets consider "profile/update" Action. so there will be some thing like below under "ProfileController".
public function actionUpdate(){
//some thing will be placed here....
}
There are 2 ways to do it. one just do it along with the controller or user Hooks (recommended) so it will be under "Model afterSave" hook. some thing like that. you can use any extension / component / widget.
Paypal Extension can tell you how you can do it .
Does anyone know how to fetch all facebook ads statistics and display on webpage using Facebook Ads Api-PHP SDK. I am using this API and I am getting campaign details like name of campaign, id, status. but not able to get impressions,clicks, spent.
What I am doing let me share with you:
1) I am getting access token by authorizing user
2) After getting access token, I am using below code
$account = new AdAccount('act_XXXXXXXXXXXXXXX');
$account->read();
$fields = array(
AdCampaignFields::ID,
AdCampaignFields::NAME,
AdCampaignFields::OBJECTIVE,
);
$params = array(AdCampaignFields::STATUS => array(AdCampaign::STATUS_ACTIVE,AdCampaign::STATUS_PAUSED,),);
$campaigns = $account->getAdCampaigns($fields, $params);
/* Added By Jigar */
$campaign = new AdCampaign('XXXXXXXXXXXXXXXX');
$compainDetails = $campaign->read($fields);
3) then printing the array
echo "<pre>";
print_r($compainDetails);
exit;
If anyone know any suggestion in above code, please share. All code is in PHP. Dose anyone have any tutorial that fetch all above required data then share it
You could try to use the facebook insights api instead of $campaign->read. Here's an example:
https://developers.facebook.com/docs/marketing-api/insights/v2.5#create-async-jobs
What you have to do to get impressions, click and spent is to add these fields to the $fields param. In your case, the complete code should look like the following:
use FacebookAds\Object\Campaign;
use FacebookAds\Object\Values\InsightsLevels;
use FacebookAds\Object\Values\InsightsFields;
$campaign = new Campaign();
$fields = array(
InsightsFields::IMPRESSIONS,
InsightsFields::UNIQUE_CLICKS,
InsightsFields::CALL_TO_ACTION_CLICKS,
InsightsFields::INLINE_LINK_CLICKS,
InsightsFields::SOCIAL_CLICKS,
InsightsFields::UNIQUE_SOCIAL_CLICKS,
InsightsFields::SPEND,
);
$params = array(
'level' => InsightsLevels::CAMPAIGN,
);
$async_job = $campaign->getInsightsAsync($fields, $params);
$async_job->read();
I don't know what exactly the "click" param means for you, but if you take a look at all these click params, I'm sure you'll find it or you'll know how to calculate it.
For a complete list of fields available on insights objects, have a look at: https://github.com/facebook/facebook-php-ads-sdk/blob/master/src/FacebookAds/Object/Fields/InsightsFields.php
Hope that helps.
Regards, Benjamin
I use Payum stable version 0.13 and Zend framework v2 for make payments via AuthorizeNet.
My code for test:
$storage = $this->getServiceLocator()
->get('payum')
->getStorage('LowbiddoPayment\Entity\AgreementDetails');
$details = $storage->create();
$details['currency'] = 'USD';
$details['amount'] = 100;
$details['card_num'] = new SensitiveValue('4111111111111111');
$details['exp_date'] = new SensitiveValue('10/16');
$details['description'] = 'Test';
$storage->update($details);
$this->getServiceLocator()
->get('payum.security.token_factory')
->setUrlPlugin($this->url());
$doneUrl = $this->url()->fromRoute('payment_done', array('id' => $orderId), array('force_canonical' => true));
$captureToken = $this->getServiceLocator()
->get('payum.security.token_factory')
->createCaptureToken('authorize-net-aim', $details, $doneUrl);
I have this error
/vendor/payum/payum/src/Payum/AuthorizeNet/Aim/Action/CaptureAction.php:58
Credit card details has to be set explicitly or there has to be an action that supports ObtainCreditCard request.
How can I fix it?
Thanks!
PayumModule does not provide (yet) a built-in ObtainCreditCardAction. So there are two ways to go.
You can ask for credit card information yourself. Like create a form than render it. User fills it and submit. You get that info and pass it to Payum with the rest of information. Authorize.Net AIM asks for 'card_num', 'exp_date' fields.
The other way is to create a zend specific ObtainCreditCardAction and add it to Payment object using addAction method. Here's an example of ObtainCreditCardAction for Symfony: https://github.com/Payum/Payum/blob/master/src/Payum/Core/Bridge/Symfony/Action/ObtainCreditCardAction.php