My website currently has a weird bug that only shows itself on the live version, but not on my local setup.
Essentially, in this scenario, a user is trying to ask an artist (another type of user) for a quote, hence the requestQuote function.
public function requestQuote(Request $request, AppMailer $mailer) {
$reciUsername = $request->input('recipient');
$recipientID = User::where('username', $reciUsername)->value('id');
$recipient = User::where('username', $reciUsername)->first();
$active_commissions_count = Commission::where('artist_id', $recipientID)
->where('complete', 0)
->where('stripe_charge_id', '!=', "")
->where('stripe_charge_id', '!=', null)
->count();
$this->validate($request, [
'message' => 'required|max:5000|min:10',
]);
$message = Auth::user()->messages()->create([
'body' => $request->input('message'),
'subject' => 'Status: Commission requested!',
'recipient_id' => $recipientID,
'sender_read' => 1,
'is_quote' => 1,
'quote_expires' => Carbon\Carbon::now()->addWeeks(1),
]);
$from = Auth::user()->username;
$mailer->sendQuoteRequestEmailTo($recipient, $from);
Auth::user()->update([
'timeout' => Carbon\Carbon::now(),
]);
dd("Message ID: " . $message->id . " - Message User ID: " . $message->user_id);
return redirect()->back()->with('info', 'Quote sent.');
}
This creates a message which the artist can then read. In this scenario, the recipient_id user is the artist, and the user_id user is the one who made the original quote. This is not supposed to change at any point during this transaction.
You'll notice there's a diedump at the end there.
In this scenario, the dd returns
"QUOTE REQUEST - Message ID: 30 - Message User ID: 2 - Recipient ID: 21"
Great. Everything works well so far, and the correct message is sent through, with the correct user being shown as having sent the quote.
The problem happens when the artist replies to the quote.
public function quoteReply(Request $request, $messageId, AppMailer $mailer) {
$this->validate($request, [
"reply-{$messageId}" => 'max:5000',
"price" => 'required|min:10|max:9999|numeric',
"date" => 'required|date',
], [
'max' => 'The text body has a maximum of 5000 characters.',
'price.max' => 'Commissions have a maximum of 9999 US dollars.',
'price.min' => 'Commissions have a minimum of 10 US dollars.',
]);
$message = Message::notReply()->find($messageId);
if (!$message) {
return redirect()->route('home')->with('info', 'Something went wrong.');
}
$date = $request->input('date');
$date2 = DateTime::createFromFormat('m/d/Y', $date);
$date3 = $date2->format("Y-m-d");
$reply = message::create([
'body' => $request->input("reply-{$messageId}"),
'sender_read' => 3,
'reci_read' => 3,
])->user()->associate(Auth::user());
Message::where('id', $messageId)->update([
'updated_at' => Carbon\Carbon::now(),
'subject' => 'Status: Price quote delivered.',
'quoted' => 1,
'price' => $request->input('price'),
'estimated_date' => $date3,
'quote_expires' => Carbon\Carbon::now()->addWeeks(1),
]);
$userID = $message->value('user_id');
$recipientID = $message->value('recipient_id');
$user = User::where('id', $userID)->first();
if (Auth::user()->id == $userID) {
Message::where('id', $messageId)->update(['reci_read' => 0]);
}
if (Auth::user()->id == $recipientID) {
Message::where('id', $messageId)->update(['sender_read' => 0]);
}
$message->replies()->save($reply);
$from = Auth::user()->username;
$mailer->sendQuoteReplyEmailTo($user, $from);
dd("QUOTE REPLY - Message ID: " . $message->id . " - Message User ID: " . $message->user_id . " - Message Recipient ID: " . $message->recipient_id . " - User ID: " . $user->id );
return redirect()->back()->with('info', 'Price quote delivered.');
}
This will return:
"QUOTE REPLY - Message ID: 30 - Message User ID: 2 - Message Recipient
ID: 21 - User ID: 3"
I first noticed this problem when the wrong user was receiving email. In fact it's ALWAYS the same user getting the email. User 3. If I use a different user for the artist, and a different user for the person requesting the quote, $user always becomes user 3.
Despite this, the correct users are still getting correct messages. At the moment this is only affecting who's getting the correct email in the quoteReply function.
What could be causing this?
Switching
$userID = $message->value('user_id');
to
$userID = $message->user_id;
Fixed my problem.
Related
I made a simple telegram bot with PHP to copy and send any messages that receives to another group
but how can I give the option to user in the bot to choose different groups to send
for example to group A or B
$msgID = $updates["message"]["message_id"];
file_get_contents($link."/copyMessage?chat_id=GroupA&from_chat_id=999999&message_id=$msgID&disable_notification=true");
file_get_contents($link."/copyMessage?chat_id=GroupB&from_chat_id=999999&message_id=$msgID&disable_notification=true");
I think sending message with buttons it's better way to that.
It'll be like this:
User sends /start command
User sends any message
Bot reply user's message with buttons
User chooses a button
Bot copies message to selected chat
Bot answers user with success or fail
Use this code:
# Configuration that you need to fill
# Bot token obtained from #BotFather
define('BOT_TOKEN', 'Put your bot token here');
# Chat IDs Or Usernames that messages will be copied to
$chats =
[
# Username/ID => 'Chat title'
'#MyOwnGroup' => 'The bot creator group',
'1265170068' => 'My own account'
];
# Function to call any Bot API method
function bot(string $method, array $data = [])
{
$api_url = 'https://api.telegram.org/bot' . BOT_TOKEN . "/$method";
if (count(data) > 0)
{
$api_url .= '?'.http_build_url($data, '', '&');
}
return file_get_contents($api_url);
}
# The update data, Received from Telegram
$update = json_decode(file_get_contents('php://input'));
# Handle if new message received
if (property_exists($update, 'message') && $update->message->text !== '/start')
{
$message = $update->message;
$buttons = ['inline_keyboard' => []];
foreach ($chats as $chat_id => $chat_title)
{
array_push($buttons['inline_keyboard'], [['text' => $chat_title, 'callback_query' => $chat_id]]);
}
# Sending message with buttons to get which group the user wants
bot('sendMessage', [
'chat_id' => $message->chat->id,
'text' => 'Select which group you want to send the message..',
'reply_to_message_id' => $message->message_id,
'reply_markup' => json_encode($buttons)
]);
}
# Handle if one of buttons was pressed
if (property_exists($update, 'callback_query'))
{
$callback_query = $update->callback_query;
# Copy the message
$result = bot('copyMessage', [
'from_chat_id' => $callback_query->message->chat->id,
'message_id' => $callback_query->message->message_id,
'chat_id' => $callback_query->data
]);
if ($result->ok == true)
{
bot('answerCallbackQuery', [
'callback_query_id' => $callback_query->id,
'text' => 'Message was sent successfully!'
]);
}
else
{
bot('answerCallbackQuery', [
'callback_query_id' => $callback_query->id,
'text' => 'Message sending failed!',
'show_alert' => true
]);
}
}
I'm trying to create a customer before i charge them. on my charge.php file i have this.
if (isset($_POST['stripeToken'])) {
\Stripe\Stripe::setApiKey('___stripe_secret_key_____');
$api_error = false;
$token = $_POST['stripeToken'];
try {
$customer = \Stripe\Customer::create(array(
"name" => $name,
"email" => $email,
"source" => $token,
"metadata" => ['id' => $uid]
));
$stripe_id = $customer->id;
//update stripe ID to DB
User::model()->updateByPk($uid, array('stripe_id' => $stripe_id));
} catch(Exception $e) {
$api_error = $e->getMessage();
}
if(empty($api_error) && $stripe_id) {
try {
$charge = \Stripe\Charge::create(
array(
'customer' => $stripe_id, //customer id
'amount' => $_POST['stripe-amount'],
'currency' => strtolower($_POST['stripe-currency']),
'description' => 'US Report',
'metadata' => [
'Currency' => $_POST['stripe-currency'],
'Invoice' => $_POST['ref_id'],
],
'receipt_email' => $email,
), array (
'idempotency_key' => preg_replace('/[^a-z\d]/im', '', $_POST['idempotency']),
)
);
} catch(\Stripe\Exception\CardException $e) {
// Since it's a decline, \Stripe\Exception\CardException will be caught
$api_error = 'Status is:' . $e->getHttpStatus() . '<br />';
$api_error .= 'Type is:' . $e->getError()->type . '<br />';
$api_error .= 'Code is:' . $e->getError()->code . '<br />';
// param is '' in this case
$api_error .= 'Param is:' . $e->getError()->param . '<br />';
$api_error .= 'Message is:' . $e->getError()->message . '<br />';
}
I'm using my own HTML form for the credit card , expiry and ccv. and included https://js.stripe.com/v3/ in my page.
When i submit my payment i get this error
Charge creation failed! Status is:402
Type is:card_error
Code is:missing
Param is:card
Message is:Cannot charge a customer that has no active card
Any idea what i'm missing here?
The only path that I see here that would cause that error is if $_POST['stripeToken'] is blank or null. I don't see that you're checking for that. If you look in your Stripe Dashboard logs, you should be able to see the exact parameters sent by your script to the "create customer" endpoint.
Beyond that, if you're still stuck I'd send the request ID (req_xxx) to Stripe Support along with your example code so that someone can take a closer look.
Try to pass Stripe token in source parameter when creating the charge as well.
$charge = \Stripe\Charge::create(
array(
'customer' => $stripe_id, //customer id
'source' => $token,
'amount' => $_POST['stripe-amount'],
'currency' => strtolower($_POST['stripe-currency']),
'description' => 'US Report',
'metadata' => [
'Currency' => $_POST['stripe-currency'],
'Invoice' => $_POST['ref_id'],
],
'receipt_email' => $email,
), array (
'idempotency_key' => preg_replace('/[^a-z\d]/im', '', $_POST['idempotency']),
)
);
Didn't need this before, but I added it and now my code works again.
No idea why :p
\Stripe\Customer::createSource(
$stripe_id,
array('source' => $token)
);
Added this before my $charge = \Stripe\Charge::create()
Let's start with example.
if I have fixed form parameter (name , email , phone) then Guzzle Post method code would be like this :
public function test(Request $request){
$client = new \GuzzleHttp\Client();
$url = www.example.com
$res = $client->post($url.'/article',[
'headers' => ['Content-Type' => 'multipart/form-data'],
'body' => json_encode([
'name' => $request['name'],
'email' => $request['email'],
'write_article' => $request['article'],
'phone' => $request['phone'],
])
]);
}
Above code is working perfectly.
But when don't have fix form parameter then How to send data using Guzzle ?
Foe example first time when I have submited form I have name , email , phone field. next time may be fields would be name , email , phone , father_name , mother_name, interest , etc.. . next time may be it would be name , email , father name
So How to work with this dynamic form field situation ?
Try this:
public function test(Request $request)
{
$client = new \GuzzleHttp\Client();
$url = 'www.example.com';
$body = [];
// exceptions, for when you want to rename something
$exceptions = [
'article' => 'write_article',
];
foreach ($request as $key => $value) {
if (isset($exceptions[$key])) {
$body[$exceptions[$key]] = $value;
} else {
$body[$key] = $value;
}
}
$res = $client->post($url.'/article',[
'headers' => ['Content-Type' => 'multipart/form-data'],
'body' => json_encode($body)
]);
}
I am running Active Collab 5.8.7 with PHP 5.6. I am using the API to create an invoice. I am following the API per this documentation. My issue is that the post requires an invoice number and I have no way of telling what the next invoice number should be.
I would like to know if there is a way to use the API to get the next invoice number inline or to add an invoice and let the system pick an invoice number for you.
Currently, I am using a random sequence of characters when I create an invoice through the API and then when we try to manually add an invoice, the invoice number field is blank. There has to be an easier and more consistent way to handle invoice numbers.
Thanks,
Larry
I figured this out on my own and wanted to post it here in case someone else needs it:
//get next invoice number
function get_next_ac_invoice_number($client) {
//get all invoices
$result = $client->get('/reports/run?type=InvoicesFilter')->getJson();
$invoices = $result['all']['invoices'];
usort($invoices,'sortbyInvoiceId');
$next_invoice_id = strval(intval(explode('-',$invoices[0]['number'])[0]) + 1) . '-' . date("Y");
return $next_invoice_id;
}
function sortbyInvoiceId($a,$b){
if ($a == $b) {
return 0;
}
return ($b < $a) ? -1 : 1;
}
EDIT FEB 22 '17
There is a bunch of cruft in here for Braintree but you should be able to get the gist of it. One thing I would make sure you consider is that you clear out AC's trash before posting since the next invoice id function will not return trashed invoices and will cause a duplicate invoice id error.
//get next invoice number
function get_next_ac_invoice_number($client) {
#get all invoices
$trashit = $client->delete('/trash');
$result = $client->get('/reports/run?type=InvoicesFilter')->getJson();
$invoices = $result['all']['invoices'];
usort($invoices,'sortbyInvoiceId');
$next_invoice_id = strval(intval(explode('-',$invoices[0]['number'])[0]) + 1) . '-' . date("Y");
return $next_invoice_id;
}
//creates an invoice in active collab
function create_ac_invoice($customer, $subscription, $transaction, $client) {
//get the next invoice ID
get_next_ac_invoice_number($client);
$plans = Braintree_Plan::all();
$plan;
foreach ($plans AS $myplan) {
if (strtolower($myplan->id) == strtolower($subscription->planId)) {
$plan = $myplan;
}
}
if (isset($transaction->discounts[0])) {
$result = $client->post('invoices', [
'company_id' => $customer['company_id'],
'number' => get_next_ac_invoice_number($client),
'items' => [
[
'description' => $plan->name . " - " . $plan->description,
'quantity' => 1,
'unit_cost' => $subscription->price
],
[
'description' => 'Promo Code Discount - ' . $transaction->discounts[0]->name,
'quantity' => 1,
'unit_cost' => (float) $transaction->discounts[0]->amount * -1
]
],
'private_note' => 'Auto-generated by Braintree'
]);
} else {
$result = $client->post('invoices', [
'company_id' => $customer['company_id'],
'number' => get_next_ac_invoice_number($client),
'items' => [
[
'description' => $plan->name . " - " . $plan->description,
'quantity' => 1,
'unit_cost' => $subscription->price
]
],
'private_note' => 'Auto-generated by Braintree'
]);
}
$invoice = $result->getJson();
if (isset($invoice['message'])) {
//we have an error, let's log and send email
$dump = print_r($invoice, true) . print_r($customer, true) . print_r($subscription, true);
logit('ERROR', $dump);
sendEmail($dump, 'Braintree Webhook Error Creating AC Invoice');
}
//mark the invoice as paid
$result = $client->post('payments', [
'parent_type' => 'Invoice',
'parent_id' => $invoice['single']['id'],
'amount' => getTotalCost($subscription, $transaction),
'comment' => 'Paid in full'
]);
$result = $result->getJson();
if (isset($result['message'])) {
//we have an error, let's log and send email
$dump = print_r($invoice, true) . print_r($customer, true) . print_r($subscription, true);
logit('ERROR', $dump);
sendEmail($dump, 'Braintree Webhook Error Creating AC Payment');
}
//send the invoice
$result = $client->put('invoices/' . $invoice['single']['id'] . '/send', [
'recipients' => [
$customer['email']
],
'subject' => "New Invoice",
'message' => "Thanks!",
'allow_payments' => 2
]);
$result = $result->getJson();
if (isset($result['message'])) {
//we have an error, let's log and send email
$dump = print_r($invoice, true) . print_r($customer, true) . print_r($subscription, true);
logit('ERROR', $dump);
sendEmail($dump, 'Braintree Webhook Error Sending AC Invoice Email');
}
return $invoice;
}
I realize it is not possible to use a Bot to receive a sender's phone number.
I do, however, need to implement a bot-like client, that responds to anyone who is messaging it. I am using PHP on apache.
It is not a Bot, as it does not take commands, but rather responds to sent text from anyone who has that phone number. So you add the user as a contact (using a phone number), and then send text to it.
My goal is to realise the sender's phone number as I receive it, I saw on the Telegram API that there's a peer ID, but I can't find how to get the phone number if that's even possible...
try this lib from github https://github.com/irazasyed/telegram-bot-sdk
and code to create 'visit card' button in private chat:
$keyboard = array(
array(
array(
'text'=>"Send your visit card",
'request_contact'=>true
)
)
); //user button under keyboard.
$reply_markup = $telegram->replyKeyboardMarkup([ 'keyboard' => $auth_keyboard, 'resize_keyboard' => true, 'one_time_keyboard' => false ]);
$telegram->sendMessage([ 'chat_id' => $chat_id, 'text' => $reply, 'reply_markup' => $reply_markup ]);
and code to get unic user phone from 'visit card' after user push the button
$user_phone = $result["message"]["contact"]["phone_number"];
if ($user_phone) {
$reply = $user_phone;
$telegram->sendMessage([ 'chat_id' => $chat_id, 'text' => $reply, 'reply_markup' => $reply_markup ]);
}
finally i found how to get the phone number.
I use package https://github.com/irazasyed/telegram-bot-sdk for Laravel 8.
The code below is command to send button and when user press the button, it'll catch the phone number from user after the user click on "share".
PhoneNumberCommand.php
public function handle()
{
$response = $this->getUpdate();
$chat_id = $response->getChat()->getId();
$btn = Keyboard::button([
'text' => 'Varify',
'request_contact' => true,
]);
$keyboard = Keyboard::make([
'keyboard' => [[$btn]],
'resize_keyboard' => true,
'one_time_keyboard' => true
]);
return $this->telegram->sendMessage([
'chat_id' => $chat_id,
'text' => 'Please click on Verify and Share.',
'reply_markup' => $keyboard
]);
}
ControllerWebhook.php
public function commandHandlerWebHook()
{
$updates = Telegram::commandsHandler(true);
$chat_id = $updates->getChat()->getId();
// Catch Phone Number
$user_phone = array_key_exists('contact', $updates['message']) ?
$updates['message']['contact']['phone_number'] : null;
$text = 'Phone number : ' . $user_phone;
if($user_phone) return Telegram::sendMessage(['chat_id' => $chat_id, 'text' => $text]);
return 'ok';
}
It's work for me! hope you can implement too.