Currently I'm using PayPal buttons for receiving payments from users. I have a website that automatically calculates postage cost for a particular item, and I want to update the cost on the PayPal page to reflect the shipping costs. How do I accomplish this?
I'm thinking there should be a way to dynamically create an encrypted PayPal "Buy Now" button in PayPal, then display that form to the user, but the documentation on how to do this is scattered.
If possible I want to avoid recording transactions in a database and verifying. I just want a PayPal button that I can securely change the shipping cost of, disallowing users from setting the cost manually.
Create PayPal certificates following instructions: https://developer.paypal.com/docs/classic/paypal-payments-standard/integration-guide/encryptedwebpayments/#id08A3I0P20E9
In PHP:
define('OPENSSL', '/usr/bin/openssl');
class PayPal {
public function __construct() {
$this->key_file = 'my-prvkey.pem';
$this->cert_file = 'my?pubcert.pem';
$this->paypal_key = 'paypal_cert.pem';
$this->button = array(
'cert_id' => 'YOUR CERT ID',
'cmd' => '_xclick',
'business' => 'YOUR PAYPAL EMAIL',
'lc' => 'US',
'item_name' => 'ITEM NAME',
'amount' => 'X',
'currency_code' => 'USD',
'button_subtype' => 'services',
'no_note' => '0',
'bn' => 'PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest'
);
}
public function create_form($shipping) {
$this->button['shipping'] = $shipping;
return '<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top"><input name="cmd" type="hidden" value="_s-xclick" />
<input name="encrypted" type="hidden" value="'.$this->encrypt().'" />
<input type="image" src="https://www.paypalobjects.com/en_AU/i/btn/btn_buynow_LG.gif" border="0" name="submit" alt="PayPal — The safer, easier way to pay online.">
<img src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" alt="" width="1" height="1" border="0" /></form>';
}
private function encrypt() {
$data = '';
foreach ($this->button as $key => $value) {
if ($value) $data .= "$key=$value\n";
}
$cmd = '('.OPENSSL." smime -sign -signer {$this->cert_file} -inkey {$this->key_file} " .
"-outform der -nodetach -binary <<_EOF_\n{$data}\n_EOF_\n) | " .
OPENSSL." smime -encrypt -des3 -binary -outform pem {$this->paypal_key}";
exec($cmd, $output, $error);
return implode("\n", $output);
}
}
Then to output the dynamic PayPal form:
$paypal = new Paypal();
echo $paypal->create_form(20);
Consider using braintree which was acquired by PayPal for a more simplified PayPal implementation.
To answer your question, you should have the postage calculation occur before sending the purchase data to PayPal so that the user confirms the final amount.
I'm unfamiliar with the buttons but their implementation needs to allow for shipping costs to fluctuate.
Obviously PayPal will not allow a price change after the user has confirmed a lower/different price.
Related
My question is a little complicated so I would rather to go for some explanations before asking the main questions.
I'm making a Content Management System for managing my Telegram Bot and get the latest updates by that.
Basically what I have done till now, is getting the updates with Telegram Bot API and show them in a little Chat Box like this:
For example as you can see in this pic, a user called Pouya has sent a message to the Bot that I'm working with.
Now in order to reply and send message to this, I coded this:
if (session_status() == PHP_SESSION_NONE) {
session_start();
$_SESSION['messages'] = array();
}
$request_params = array();
if (isset($_POST['send'])){
$pm = $_POST['message'];
array_push($_SESSION['messages'], $pm);
$request_params = [
'chat_id' => $id,
'text' => $_SESSION['messages']
];
$request_url = 'https://api.telegram.org/bot' . $botToken . '/sendMessage?' . http_build_query($request_params);
file_get_contents($request_url);
print_r($request_params);
}
<div class="box-footer">
<form action="" method="post">
<div class="input-group">
<input type="text" name="message" placeholder="Write your direct message" class="form-control">
<span class="input-group-btn">
<input name="send" type="submit" class="btn btn-danger btn-flat"/>
</span>
</div>
</form>
</div>
As you can see I have saved the $pm into a session called $_SESSION['messages']. So by this way I can call it again in the Chat Box and there would be no need of using Database & etc:
$num3 = count($request_params["text"]);
for($z=0;$z<$num3;$z++){
echo '<div class="direct-chat-text">';
echo $request_params["text"][$z];
echo '</div>';
}
So everything looks nice and clean but there are two problems with this code:
1- The reply message does not sent into Telegram account
(However if I change this:
$request_params = [
'chat_id' => $id,
'text' => $_SESSION['messages']
];
to this:
$request_params = [
'chat_id' => $id,
'text' => $pm
];
it will send message correctly).
2- And second problem is that the message does not even shown in the Chat Box after submitting the form.
I guess the main thing that cause these problems is that the $_SESSION['messages'] does not contain any value at all and its empty!
So what is your idea about this... Please share your suggestions about this. Thanks :)
UPDATE 1:
file_get_contents($request_url); contains this as example:
https://api.telegram.org/bot423495534:asdsadsadsad/sendmessage?chat_id=108132368&text=hi
$_SESSION['messages'] is an array and won’t convert to a string, likely erroring.
Try using implode implode(" ", $_SESSION['messages']) to add a space between each message, or anything you’d prefer.
$request_params = [
'chat_id' => $id,
'text' => implode(" ", $_SESSION['messages'])
];
I'm using coinpayment gateway api (cmd=create_transfer).
I generated qr code and address those are successfully scanned from app but after payment I want to redirect success_url and other information submitted into database.
<?php
/*
CoinPayments.net API Example
Copyright 2016 CoinPayments.net. All rights reserved.
License: GPLv2 - http://www.gnu.org/licenses/gpl-2.0.txt
*/
require('./coinpayments.inc.php');
$cps = new CoinPaymentsAPI();
$public_key = "xxx";
$private_key = "xxx";
$cps->Setup($private_key, $public_key);
$req = array(
'amount' => $_POST['amount'],
'currency1' => "USD",
'currency2' => "BTC",
'address' => '', // leave blank send to follow your settings on the Coin Settings page
// 'item_name' => $_POST['item_name']
print 'ipn_url' => $_POST['ipn_url'],
print 'txn_id' => $_POST['txn_id'],
print 'status' => intval($_POST['status']),
print 'status_text' => $_POST['status_text']
);
// See https://www.coinpayments.net/apidoc-create-transaction for all of the available fields
$result = $cps->CreateTransaction($req);
if ($result['error'] == 'ok') {
$le = php_sapi_name() == 'cli' ? "\n" : '<br />';
?>
<div class="col-4">
<h2><?php print 'Buyer should send ' . sprintf('%.08f', $result['result']['amount']) . ' BTC' . $le; ?></h2>
<img width="220" height="220" alt="" src="https://blockchain.info/qr?data=bitcoin:<?php echo $result['result']['address']; ?>?amount=<?php echo $result['result']['amount']; ?>%26label=example%2520label">
<?php
} else {
print 'Error: ' . $result['error'] . "\n";
}
?>
Please refer here :- https://www.coinpayments.net/apidoc-get-tx-info. To make use of this api, just add this function in coinpayments.inc.php
}
public function GetTransactionInformation($txId) {
$req = array(
'txid' => $txId,
);
return $this->api_call('get_tx_info', $req);
}
Add this in you's script before printing tx id
$txid = strip_tags($_POST['txn_id'])
And for results
$cps = new CoinPaymentsAPI();
$cps->Setup('Your_Private_Key', 'Your_Public_Key');
$result = $cps->GetTransactionInformation('$txid');
//get the array info of transaction
if ($result['error'] == 'ok') {
print_r ($result);
} else {
print 'Error: '.$result['error']."\n";
}
You should get result in Array. For getting in Json output just replace.
print_r ($result);
With
print $result['result']['status']
Replace status with other arrays and modify your page accordingly.
Status has following numericals:-
<0 Error, 0-99 Pending, 100 Completed/Paid
If you are wanting offsite checkout you'd want to be using the Simple or Advanced buttons, the 'create_transaction' API is for making your own custom checkout pages.
Please check this link for the Simple or Advanced buttons:
Coinpayments Simple and Advanced buttons link.
I'm using the following PHP code to encrypt the billing details I'm passing to PayPal:
<?php
$MY_KEY_FILE = "my-prvkey.pem";
$MY_CERT_FILE = "my-pubcert.pem";
$PAYPAL_CERT_FILE = "paypal_cert.pem";
$OPENSSL = "/usr/bin/openssl";
$form = array(
'cmd' => '_xclick',
'cert_id' => 'HSFU5KJLFS8JD',
'business' => 'example#icloud.com',
'currency_code' => 'EUR',
'no_shipping' => '1',
'charset' => 'utf-8',
'lc' => 'DE',
'item_name' => 'Test',
'amount' => '4.20',
'return' => 'http://www.example.com/success.php',
'cancel_return' => 'http://www.example.com/error.php',
);
$encrypted = paypal_encrypt($form);
function paypal_encrypt($hash)
{
global $MY_KEY_FILE;
global $MY_CERT_FILE;
global $PAYPAL_CERT_FILE;
global $OPENSSL;
if (!file_exists($MY_KEY_FILE)) {
echo "ERROR: MY_KEY_FILE $MY_KEY_FILE not found\n";
}
if (!file_exists($MY_CERT_FILE)) {
echo "ERROR: MY_CERT_FILE $MY_CERT_FILE not found\n";
}
if (!file_exists($PAYPAL_CERT_FILE)) {
echo "ERROR: PAYPAL_CERT_FILE $PAYPAL_CERT_FILE not found\n";
}
$data = "";
foreach ($hash as $key => $value) {
if ($value != "") {
$data .= "$key=$value\n";
}
}
$openssl_cmd = "($OPENSSL smime -sign -signer $MY_CERT_FILE -inkey $MY_KEY_FILE "."-outform der -nodetach -binary <<_EOF_\n$data\n_EOF_\n) | "."$OPENSSL smime -encrypt -des3 -binary -outform pem $PAYPAL_CERT_FILE";
exec($openssl_cmd, $output, $error);
if (!$error) {
return implode("\n",$output);
} else {
return "ERROR: encryption failed";
}
};
?>
<!DOCTYPE html>
<html>
<body>
<form action="https://www.paypal.com/cgi-bin/webscr" method="get">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="encrypted" value=" <?php echo $encrypted;?>">
<input type="submit">
</form>
</body>
</html>
When clicking on the submit button I'll get redirected to PayPal and can make the payment.
I can either send the form data with method="post" or method="get".
If I'm using my code with method="post" I'm getting redirected to a page looking like this:
When using exactly the same code but changing method="post" to method="get" I'm getting redirected to a page looking like this:
This doesn't really look beautiful. I prefer the first one and I think my customers will do so, too.
Does anybody know how I can fix that? What am I doing wrong?
I have seen your question on Freelancer website as well. For your requirement of HTTP GET:
PayPal is discontinuing use of HTTP GET from June 2017.
https://www.paypal.com/au/webapps/mpp/discontinuation-get-method
I think I asked this twice already and no one even bothered to view this. please help me out and try to at least think about it before forgetting the question.
So I am following this tutorial : http://www.stellarwebsolutions.com/en/articles/paypal_button_encryption_php.php and when I used their code and inserted all the things that were different with me I ran the code and got the error message from paypal 'Unable to decrypt certificate id'. After a little of research I found that the function in the code returned 'ERROR: Encryption failed.' I think the error was caused by the following piece of code:
$openssl_cmd = "($OPENSSL smime -sign -signer $MY_CERT_FILE -inkey $MY_KEY_FILE " .
"-outform der -nodetach -binary < \"_EOF_\n$data\n_EOF_\n\") | " .
"$OPENSSL smime -encrypt -des3 -binary -outform pem $PAYPAL_CERT_FILE";
exec($openssl_cmd, $output, $error);
if (!$error) {
return implode("\n",$output);
} else {
return "ERROR: encryption failed";
}
Is there any possible way of converting this openssl command to a openssl_something(); call? I would greatly appreciate any help. Here is the full code and another note: PLEASE don't make stupid comments on themes such as the questions is bad, e.t.c. :
<?php
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);
?>
<HTML>
<?php
//Sample PayPal Button Encryption: Copyright 2006-2010 StellarWebSolutions.com
//Not for resale - license agreement at
//http://www.stellarwebsolutions.com/en/eula.php
//Updated: 2010 02 01
# private key file to use
$MY_KEY_FILE = "my-prvkey.pem";
# public certificate file to use
$MY_CERT_FILE = "my-pubcert.pem";
# Paypal's public certificate
$PAYPAL_CERT_FILE = "paypal_cert_pem.txt";
# path to the openssl binary
$OPENSSL = "/usr/bin/openssl";
$form = array('cmd' => '_xclick',
'business' => 'naclo3samuel#gmail.com',
'cert_id' => 'PRIVACY?',
'lc' => 'RU',
'custom' => 'test',
'invoice' => '',
'currency_code' => 'USD',
'no_shipping' => '1',
'item_name' => 'Donation',
'item_number' => '1',
'amount' => '10'
);
$encrypted = paypal_encrypt($form);
function paypal_encrypt($hash)
{
//Sample PayPal Button Encryption: Copyright 2006-2010 StellarWebSolutions.com
//Not for resale - license agreement at
//http://www.stellarwebsolutions.com/en/eula.php
global $MY_KEY_FILE;
global $MY_CERT_FILE;
global $PAYPAL_CERT_FILE;
global $OPENSSL;
if (!file_exists($MY_KEY_FILE)) {
echo "ERROR: MY_KEY_FILE $MY_KEY_FILE not found\n";
}
if (!file_exists($MY_CERT_FILE)) {
echo "ERROR: MY_CERT_FILE $MY_CERT_FILE not found\n";
}
if (!file_exists($PAYPAL_CERT_FILE)) {
echo "ERROR: PAYPAL_CERT_FILE $PAYPAL_CERT_FILE not found\n";
}
//Assign Build Notation for PayPal Support
$hash['bn']= 'StellarWebSolutions.PHP_EWP2';
$data = "";
foreach ($hash as $key => $value) {
if ($value != "") {
//echo "Adding to blob: $key=$value\n";
$data .= "$key=$value\n";
}
}
$openssl_cmd = "($OPENSSL smime -sign -signer $MY_CERT_FILE -inkey $MY_KEY_FILE " .
"-outform der -nodetach -binary < \"_EOF_\n$data\n_EOF_\n\") | " .
"$OPENSSL smime -encrypt -des3 -binary -outform pem $PAYPAL_CERT_FILE";
exec($openssl_cmd, $output, $error);
if (!$error) {
return implode("\n",$output);
} else {
return "ERROR: encryption failed";
}
};
?>
<HEAD>
<LINK REL=stylesheet HREF="/styles/stellar.css" TYPE="text/css">
<TITLE>PHP Sample Donation using PayPal Encrypted Buttons</TITLE>
</HEAD>
<BODY bgcolor=white>
<TABLE border=0>
<TR><TD align=center>
<h1>Sample Donation Page</h1>
<P>This page uses encrypted PayPal buttons for your security.</P>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target=_blank>
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="encrypted" value="
<?PHP echo $encrypted; ?>">
<input type="submit" value="Donate $10">
</form>
<P><SMALL>(PayPal will open in a new window for demonstration purposes.)</SMALL></P>
</TD></TR></TABLE>
</BODY>
</HTML>
Well, then here is my answer ;) You might have a problem with safe_mode which prevents your code from executing the openssl binary.
Can any body help me about how to integrate migs (MasterCard Virtual Payment Client) in a php website !
I have read the reference guide but it's unhelpful!
//This value submited to the MIGS PAYMENT GATEWAY
$SECURE_SECRET = $signature; //value from migs payment gateway
$accessCode = $accesscode;//value from migs payment gateway
$merchantId = $merchantid;//value from migs payment gateway
$paymentdata = array(
"vpc_AccessCode" => $accessCode,
"vpc_Amount" => ($amount*100),//our product price , must multipy by 100
"vpc_Command" => 'pay',
"vpc_Locale" => 'en',// order id
"vpc_MerchTxnRef" => random_unique_value(like session),
"vpc_Merchant" => $merchantId,
"vpc_OrderInfo" => "Some Comment",
"vpc_ReturnURL" => "htps://yoursite.com/returnpoint",//here code for db updation, return variable here
"vpc_Version" => '1'
);
$actionurl = 'https://migs.mastercard.com.au/vpcpay' . "?";
$HashData = $SECURE_SECRET;
$str = 0;
foreach ($paymentdata as $key => $value) {
// create the md5 input and URL
if (strlen($value) > 0) {
// this ensures the first paramter of the URL is preceded by the '?' char
if ($appendAmp == 0) {
$actionurl .= urlencode($key) . '=' . urlencode($value);
$str = 1;
} else {
$actionurl .= '&' . urlencode($key) . "=" . urlencode($value);
}
$HashData .= $value;
}
}
if (strlen($SECURE_SECRET) > 0){$actionurl .= "&vpc_SecureHash=" . strtoupper(md5($HashData));}
header("Location: " . $actionurl);
}
/////////////////////RETURN VALUE/////////////////////////////////
the return url will be like
https://yoursite.com/returnpoint?vpc_TransactionNo="migs_transaction_number"&vpc_MerchTxnRef="random_unique_value(we post to migs)"&vpc_TxnResponseCode=value&vpc_Message="value"
if vpc_TxnResponseCode = 0 -- success ,vpc_Message = approved -- paymet is success , All other unsuccessfull payment
You could use the Omnipay PHP Library which has support for the MIGS gateway.
An example of the off-site payment processing (3-Party) looks like this:
use Omnipay\Omnipay;
$gateway = Omnipay::create('Migs_ThreeParty');
$gateway->setMerchantId('foo');
$gateway->setMerchantAccessCode('foo');
$gateway->setSecureHash('foo');
$response = $gateway->purchase(array('amount' => '10.00', 'currency' => 'AUD'))->send();
if ($response->isRedirect()) {
// redirect to offsite payment gateway
$response->redirect();
} else {
// payment failed: display message to customer
echo $response->getMessage();
}
implementing migs payment gateway in which we need to post some details to the
https://migs.mastercard.com.au/vpcpay? this url with the below datas
/*"vpc_AccessCode" the accesscode given by Migs
"vpc_Amount" Amount that is multiplied by 100
"vpc_Command" ='pay',default pay
"vpc_Locale" = 'en' // language
"vpc_MerchTxnRef" orderId // Should be Unique for each payment
"vpc_Merchant" // merchant ID
"vpc_OrderInfo" // Desc or and details of Product
"vpc_ReturnURL" // SuccessUrl
"vpc_Version" = '1'
&vpc_SecureHash = // create MD5 of all the values that are passed */
Creating Url
$SECURE_SECRET = "YEOCOEN29B0785F1FF1E3C0FA8A3FUJK";
$accessCode = '546484645';
$merchantId = '5465465288';
if($migs_testmode ==1) {
$SECURE_SECRET = "YEOCOEN29B0785F1FF1E3C0FA8A3FUJK";
$accessCode = '98989645';
$merchantId = '56456456489';
}
$amount ='10.00';
$unique_id = rand(999999,8988888888);//this is a sample random no
$postdata = array(
"vpc_AccessCode" => $accessCode,
"vpc_Amount" => ($amount*100),
"vpc_Command" => 'pay',
"vpc_Locale" => 'en',
"vpc_MerchTxnRef" => $unique_id,
"vpc_Merchant" => $merchantId,
"vpc_OrderInfo" => 'this is a product',
"vpc_ReturnURL" => "https://mywebsite.com/success.php",
"vpc_Version" => '1');
$vpcURL = 'https://migs.mastercard.com.au/vpcpay?';
$md5Hash = $SECURE_SECRET;
$appendAmp = 0;
foreach ($wpay_postdata as $key => $value) {
if (strlen($value) > 0) {
if ($appendAmp == 0) {
$vpcURL .= urlencode($key) . '=' . urlencode($value);
$appendAmp = 1;
} else {
$vpcURL .= '&' . urlencode($key) . "=" . urlencode($value);
}
$md5Hash .= $value;
}
}
if (strlen($SECURE_SECRET) > 0) {
$vpcURL .= "&vpc_SecureHash=" . strtoupper(md5($md5Hash));
}
header("Location: " . $vpcURL)
for detailed result is available here
I tried MIGS mastercard intergration in python django. I went through lot of problems. Here is my experience with integrating MIGS with My web application. I was using VPC Integration reference 3.1.21.1
While implementing Mode1 VPC: I got 400 Bad request. Which is due to Secure hash code for my case. This error occurs if user is sending wrong fields names or non sorted order.
Once I resolved Mode1 error, I used external payment selection(EPS), Where I send VPC_card and VPC_gateway additional field with Mode1 VPC parameters. I got 400 Bad request. So after long discussion with MIGS support team. We resolve it by changing vpc_card to vpc_Card and vpc_Gateway. Which was document error.
Once I able to bypass card type page. I tried to complete Mode 2 VPC implementation.So, In this case I added vpc_CardNum,vpc_vpc_CardExp,vpc_CardSecurityCode additional fields with above point request. I send GET request. It didnot work. For card details or Mode2 we have to use POST request.
For mode2 VPC, we should use POST request with HTTPS not HTTP. Self-signed certificate will be fine. So, I send HTTPS POST request with additional parameter, But It still didnot work, I got 403 forbidden error. Because, Content-type is application/json for my ajax call. So after using default POST content-type. It worked fine.
Sample code for python developer: Here in migs.config.app I am adding system variable which nothing to do with Migs. So User can ignore it.
import hashlib
import urllib, urllib2
from migs.config.app_config import *
'''
This method is for sorting the fields and creating an MD5 secure hash.
#param fields is a map of all the incoming hey-value pairs from the VPC
#param buf is the hash being returned for comparison to the incoming hash
'''
class MigsClient(object):
def __init__(self, secure_token, vpc_url, server_name):
self.secure_secret = secure_token
self.vpcURL = vpc_url
self.server_name = server_name
def hash_all_fields(self,fields):
buf = ""
# create a list and sort it
fieldNames = fields.keys();
fieldNames.sort()
# create a buffer for the md5 input and add the secure secret first
buf = buf + self.secure_secret
for key in fieldNames:
print key,fields[key]
buf = buf + fields[key]
# iterate through the list and add the remaining field values
# create the md5 hash and UTF-8 encode it
try:
m = hashlib.md5()
m.update(buf)
ba = m.hexdigest()
ba = ba.upper()
return ba
except Exception,e:
import traceback
traceback.print_exc()
def setup(self, fields,additional_fields=None):
#The Page does a redirect to the Virtual Payment Client
#retrieve all the parameters into a hash map
# no need to send the vpc url, EnableAVSdata and submit button to the vpc
'''
Retrieve the order page URL from the incoming order page and add it to
the hash map. This is only here to give the user the easy ability to go
back to the Order page. This would not be required in a production system
NB. Other merchant application fields can be added in the same manner
'''
'''
Create MD5 secure hash and insert it into the hash map if it was created
created. Remember if self.secure_secret = "" it will not be created
'''
if self.secure_secret:
secureHash = self.hash_all_fields(fields);
fields["vpc_SecureHash"] = secureHash;
# Create a redirection URL
buf = self.vpcURL+'?';
if not additional_fields:
buf = buf + urllib.urlencode(fields)
else:
buf = buf + urllib.urlencode(fields)+"&"+urllib.urlencode(additional_fields)
return buf
#return fields["vpc_ReturnURL"], buf
def post_setup(self,fields, additional_fields=None):
try:
if self.secure_secret:
secureHash = self.hash_all_fields(fields);
fields["vpc_SecureHash"] = secureHash;
return self.vpcURL,fields
except:
import traceback
traceback.print_exc()
Above is sample code which user can use to sort and create Get request and POST request and post dictionary.