Initial commit

This commit is contained in:
xboard
2023-11-17 14:44:01 +08:00
commit 65fe7682ff
460 changed files with 63554 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
<?php
/**
* 自己写别抄,抄NMB抄
*/
namespace App\Payments;
class AlipayF2F {
public function __construct($config)
{
$this->config = $config;
}
public function form()
{
return [
'app_id' => [
'label' => '支付宝APPID',
'description' => '',
'type' => 'input',
],
'private_key' => [
'label' => '支付宝私钥',
'description' => '',
'type' => 'input',
],
'public_key' => [
'label' => '支付宝公钥',
'description' => '',
'type' => 'input',
],
'product_name' => [
'label' => '自定义商品名称',
'description' => '将会体现在支付宝账单中',
'type' => 'input'
]
];
}
public function pay($order)
{
try {
$gateway = new \Library\AlipayF2F();
$gateway->setMethod('alipay.trade.precreate');
$gateway->setAppId($this->config['app_id']);
$gateway->setPrivateKey($this->config['private_key']); // 可以是路径,也可以是密钥内容
$gateway->setAlipayPublicKey($this->config['public_key']); // 可以是路径,也可以是密钥内容
$gateway->setNotifyUrl($order['notify_url']);
$gateway->setBizContent([
'subject' => $this->config['product_name'] ?? (admin_setting('app_name', 'XBoard') . ' - 订阅'),
'out_trade_no' => $order['trade_no'],
'total_amount' => $order['total_amount'] / 100
]);
$gateway->send();
return [
'type' => 0, // 0:qrcode 1:url
'data' => $gateway->getQrCodeUrl()
];
} catch (\Exception $e) {
abort(500, $e->getMessage());
}
}
public function notify($params)
{
if ($params['trade_status'] !== 'TRADE_SUCCESS') return false;
$gateway = new \Library\AlipayF2F();
$gateway->setAppId($this->config['app_id']);
$gateway->setPrivateKey($this->config['private_key']); // 可以是路径,也可以是密钥内容
$gateway->setAlipayPublicKey($this->config['public_key']); // 可以是路径,也可以是密钥内容
try {
if ($gateway->verify($params)) {
/**
* Payment is successful
*/
return [
'trade_no' => $params['out_trade_no'],
'callback_no' => $params['trade_no']
];
} else {
/**
* Payment is not successful
*/
return false;
}
} catch (\Exception $e) {
/**
* Payment is not successful
*/
return false;
}
}
}
+148
View File
@@ -0,0 +1,148 @@
<?php
namespace App\Payments;
class BTCPay {
public function __construct($config) {
$this->config = $config;
}
public function form()
{
return [
'btcpay_url' => [
'label' => 'API接口所在网址(包含最后的斜杠)',
'description' => '',
'type' => 'input',
],
'btcpay_storeId' => [
'label' => 'storeId',
'description' => '',
'type' => 'input',
],
'btcpay_api_key' => [
'label' => 'API KEY',
'description' => '个人设置中的API KEY(非商店设置中的)',
'type' => 'input',
],
'btcpay_webhook_key' => [
'label' => 'WEBHOOK KEY',
'description' => '',
'type' => 'input',
],
];
}
public function pay($order) {
$params = [
'jsonResponse' => true,
'amount' => sprintf('%.2f', $order['total_amount'] / 100),
'currency' => 'CNY',
'metadata' => [
'orderId' => $order['trade_no']
]
];
$params_string = @json_encode($params);
$ret_raw = self::_curlPost($this->config['btcpay_url'] . 'api/v1/stores/' . $this->config['btcpay_storeId'] . '/invoices', $params_string);
$ret = @json_decode($ret_raw, true);
if(empty($ret['checkoutLink'])) {
abort(500, "error!");
}
return [
'type' => 1, // Redirect to url
'data' => $ret['checkoutLink'],
];
}
public function notify($params) {
$payload = trim(get_request_content());
$headers = getallheaders();
//IS Btcpay-Sig
//NOT BTCPay-Sig
//API doc is WRONG!
$headerName = 'Btcpay-Sig';
$signraturHeader = isset($headers[$headerName]) ? $headers[$headerName] : '';
$json_param = json_decode($payload, true);
$computedSignature = "sha256=" . \hash_hmac('sha256', $payload, $this->config['btcpay_webhook_key']);
if (!self::hashEqual($signraturHeader, $computedSignature)) {
abort(400, 'HMAC signature does not match');
return false;
}
//get order id store in metadata
$context = stream_context_create(array(
'http' => array(
'method' => 'GET',
'header' => "Authorization:" . "token " . $this->config['btcpay_api_key'] . "\r\n"
)
));
$invoiceDetail = file_get_contents($this->config['btcpay_url'] . 'api/v1/stores/' . $this->config['btcpay_storeId'] . '/invoices/' . $json_param['invoiceId'], false, $context);
$invoiceDetail = json_decode($invoiceDetail, true);
$out_trade_no = $invoiceDetail['metadata']["orderId"];
$pay_trade_no=$json_param['invoiceId'];
return [
'trade_no' => $out_trade_no,
'callback_no' => $pay_trade_no
];
return response('success', 200);
}
private function _curlPost($url,$params=false){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 300);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt(
$ch, CURLOPT_HTTPHEADER, array('Authorization:' .'token '.$this->config['btcpay_api_key'], 'Content-Type: application/json')
);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
/**
* @param string $str1
* @param string $str2
* @return bool
*/
private function hashEqual($str1, $str2)
{
if (function_exists('hash_equals')) {
return \hash_equals($str1, $str2);
}
if (strlen($str1) != strlen($str2)) {
return false;
} else {
$res = $str1 ^ $str2;
$ret = 0;
for ($i = strlen($res) - 1; $i >= 0; $i--) {
$ret |= ord($res[$i]);
}
return !$ret;
}
}
}
+104
View File
@@ -0,0 +1,104 @@
<?php
namespace App\Payments;
class CoinPayments {
public function __construct($config) {
$this->config = $config;
}
public function form()
{
return [
'coinpayments_merchant_id' => [
'label' => 'Merchant ID',
'description' => '商户 ID,填写您在 Account Settings 中得到的 ID',
'type' => 'input',
],
'coinpayments_ipn_secret' => [
'label' => 'IPN Secret',
'description' => '通知密钥,填写您在 Merchant Settings 中自行设置的值',
'type' => 'input',
],
'coinpayments_currency' => [
'label' => '货币代码',
'description' => '填写您的货币代码(大写),建议与 Merchant Settings 中的值相同',
'type' => 'input',
]
];
}
public function pay($order)
{
// IPN notifications are slow, when the transaction is successful, we should return to the user center to avoid user confusion
$parseUrl = parse_url($order['return_url']);
$port = isset($parseUrl['port']) ? ":{$parseUrl['port']}" : '';
$successUrl = "{$parseUrl['scheme']}://{$parseUrl['host']}{$port}";
$params = [
'cmd' => '_pay_simple',
'reset' => 1,
'merchant' => $this->config['coinpayments_merchant_id'],
'item_name' => $order['trade_no'],
'item_number' => $order['trade_no'],
'want_shipping' => 0,
'currency' => $this->config['coinpayments_currency'],
'amountf' => sprintf('%.2f', $order['total_amount'] / 100),
'success_url' => $successUrl,
'cancel_url' => $order['return_url'],
'ipn_url' => $order['notify_url']
];
$params_string = http_build_query($params);
return [
'type' => 1, // Redirect to url
'data' => 'https://www.coinpayments.net/index.php?' . $params_string
];
}
public function notify($params)
{
if (!isset($params['merchant']) || $params['merchant'] != trim($this->config['coinpayments_merchant_id'])) {
abort(500, 'No or incorrect Merchant ID passed');
}
$headers = getallheaders();
ksort($params);
reset($params);
$request = stripslashes(http_build_query($params));
$headerName = 'Hmac';
$signHeader = isset($headers[$headerName]) ? $headers[$headerName] : '';
$hmac = hash_hmac("sha512", $request, trim($this->config['coinpayments_ipn_secret']));
// if ($hmac != $signHeader) { <-- Use this if you are running a version of PHP below 5.6.0 without the hash_equals function
// abort(400, 'HMAC signature does not match');
// }
if (!hash_equals($hmac, $signHeader)) {
abort(400, 'HMAC signature does not match');
}
// HMAC Signature verified at this point, load some variables.
$status = $params['status'];
if ($status >= 100 || $status == 2) {
// payment is complete or queued for nightly payout, success
return [
'trade_no' => $params['item_number'],
'callback_no' => $params['txn_id'],
'custom_result' => 'IPN OK'
];
} else if ($status < 0) {
//payment error, this is usually final but payments will sometimes be reopened if there was no exchange rate conversion or with seller consent
abort(500, 'Payment Timed Out or Error');
} else {
//payment is pending, you can optionally add a note to the order page
return('IPN OK: pending');
}
}
}
+129
View File
@@ -0,0 +1,129 @@
<?php
namespace App\Payments;
class Coinbase {
public function __construct($config) {
$this->config = $config;
}
public function form()
{
return [
'coinbase_url' => [
'label' => '接口地址',
'description' => '',
'type' => 'input',
],
'coinbase_api_key' => [
'label' => 'API KEY',
'description' => '',
'type' => 'input',
],
'coinbase_webhook_key' => [
'label' => 'WEBHOOK KEY',
'description' => '',
'type' => 'input',
],
];
}
public function pay($order) {
$params = [
'name' => '订阅套餐',
'description' => '订单号 ' . $order['trade_no'],
'pricing_type' => 'fixed_price',
'local_price' => [
'amount' => sprintf('%.2f', $order['total_amount'] / 100),
'currency' => 'CNY'
],
'metadata' => [
"outTradeNo" => $order['trade_no'],
],
];
$params_string = http_build_query($params);
$ret_raw = self::_curlPost($this->config['coinbase_url'], $params_string);
$ret = @json_decode($ret_raw, true);
if(empty($ret['data']['hosted_url'])) {
abort(500, "error!");
}
return [
'type' => 1,
'data' => $ret['data']['hosted_url'],
];
}
public function notify($params) {
$payload = trim(get_request_content());
$json_param = json_decode($payload, true);
$headerName = 'X-Cc-Webhook-Signature';
$headers = getallheaders();
$signatureHeader = isset($headers[$headerName]) ? $headers[$headerName] : '';
$computedSignature = \hash_hmac('sha256', $payload, $this->config['coinbase_webhook_key']);
if (!self::hashEqual($signatureHeader, $computedSignature)) {
abort(400, 'HMAC signature does not match');
}
$out_trade_no = $json_param['event']['data']['metadata']['outTradeNo'];
$pay_trade_no=$json_param['event']['id'];
return [
'trade_no' => $out_trade_no,
'callback_no' => $pay_trade_no
];
return response('success', 200);
}
private function _curlPost($url,$params=false){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 300);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt(
$ch, CURLOPT_HTTPHEADER, array('X-CC-Api-Key:' .$this->config['coinbase_api_key'], 'X-CC-Version: 2018-03-22')
);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
/**
* @param string $str1
* @param string $str2
* @return bool
*/
public function hashEqual($str1, $str2)
{
if (function_exists('hash_equals')) {
return \hash_equals($str1, $str2);
}
if (strlen($str1) != strlen($str2)) {
return false;
} else {
$res = $str1 ^ $str2;
$ret = 0;
for ($i = strlen($res) - 1; $i >= 0; $i--) {
$ret |= ord($res[$i]);
}
return !$ret;
}
}
}
+69
View File
@@ -0,0 +1,69 @@
<?php
namespace App\Payments;
class EPay {
public function __construct($config)
{
$this->config = $config;
}
public function form()
{
return [
'url' => [
'label' => 'URL',
'description' => '',
'type' => 'input',
],
'pid' => [
'label' => 'PID',
'description' => '',
'type' => 'input',
],
'key' => [
'label' => 'KEY',
'description' => '',
'type' => 'input',
]
];
}
public function pay($order)
{
$params = [
'money' => $order['total_amount'] / 100,
'name' => $order['trade_no'],
'notify_url' => $order['notify_url'],
'return_url' => $order['return_url'],
'out_trade_no' => $order['trade_no'],
'pid' => $this->config['pid']
];
ksort($params);
reset($params);
$str = stripslashes(urldecode(http_build_query($params))) . $this->config['key'];
$params['sign'] = md5($str);
$params['sign_type'] = 'MD5';
return [
'type' => 1, // 0:qrcode 1:url
'data' => $this->config['url'] . '/submit.php?' . http_build_query($params)
];
}
public function notify($params)
{
$sign = $params['sign'];
unset($params['sign']);
unset($params['sign_type']);
ksort($params);
reset($params);
$str = stripslashes(urldecode(http_build_query($params))) . $this->config['key'];
if ($sign !== md5($str)) {
return false;
}
return [
'trade_no' => $params['out_trade_no'],
'callback_no' => $params['trade_no']
];
}
}
+102
View File
@@ -0,0 +1,102 @@
<?php
/**
* 自己写别抄,抄NMB抄
*/
namespace App\Payments;
use \Curl\Curl;
class MGate {
private $config;
public function __construct($config)
{
$this->config = $config;
}
public function form()
{
return [
'mgate_url' => [
'label' => 'API地址',
'description' => '',
'type' => 'input',
],
'mgate_app_id' => [
'label' => 'APPID',
'description' => '',
'type' => 'input',
],
'mgate_app_secret' => [
'label' => 'AppSecret',
'description' => '',
'type' => 'input',
],
'mgate_source_currency' => [
'label' => '源货币',
'description' => '默认CNY',
'type' => 'input'
]
];
}
public function pay($order)
{
$params = [
'out_trade_no' => $order['trade_no'],
'total_amount' => $order['total_amount'],
'notify_url' => $order['notify_url'],
'return_url' => $order['return_url']
];
if (isset($this->config['mgate_source_currency'])) {
$params['source_currency'] = $this->config['mgate_source_currency'];
}
$params['app_id'] = $this->config['mgate_app_id'];
ksort($params);
$str = http_build_query($params) . $this->config['mgate_app_secret'];
$params['sign'] = md5($str);
$curl = new Curl();
$curl->setUserAgent('MGate');
$curl->setOpt(CURLOPT_SSL_VERIFYPEER, 0);
$curl->post($this->config['mgate_url'] . '/v1/gateway/fetch', http_build_query($params));
$result = $curl->response;
if (!$result) {
abort(500, '网络异常');
}
if ($curl->error) {
if (isset($result->errors)) {
$errors = (array)$result->errors;
abort(500, $errors[array_keys($errors)[0]][0]);
}
if (isset($result->message)) {
abort(500, $result->message);
}
abort(500, '未知错误');
}
$curl->close();
if (!isset($result->data->trade_no)) {
abort(500, '接口请求失败');
}
return [
'type' => 1, // 0:qrcode 1:url
'data' => $result->data->pay_url
];
}
public function notify($params)
{
$sign = $params['sign'];
unset($params['sign']);
ksort($params);
reset($params);
$str = http_build_query($params) . $this->config['mgate_app_secret'];
if ($sign !== md5($str)) {
return false;
}
return [
'trade_no' => $params['out_trade_no'],
'callback_no' => $params['trade_no']
];
}
}
+117
View File
@@ -0,0 +1,117 @@
<?php
/**
* 自己写别抄,抄NMB抄
*/
namespace App\Payments;
use Stripe\Source;
use Stripe\Stripe;
class StripeAlipay {
public function __construct($config)
{
$this->config = $config;
}
public function form()
{
return [
'currency' => [
'label' => '货币单位',
'description' => '',
'type' => 'input',
],
'stripe_sk_live' => [
'label' => 'SK_LIVE',
'description' => '',
'type' => 'input',
],
'stripe_webhook_key' => [
'label' => 'WebHook密钥签名',
'description' => '',
'type' => 'input',
]
];
}
public function pay($order)
{
$currency = $this->config['currency'];
$exchange = $this->exchange('CNY', strtoupper($currency));
if (!$exchange) {
abort(500, __('Currency conversion has timed out, please try again later'));
}
Stripe::setApiKey($this->config['stripe_sk_live']);
$source = Source::create([
'amount' => floor($order['total_amount'] * $exchange),
'currency' => $currency,
'type' => 'alipay',
'statement_descriptor' => $order['trade_no'],
'metadata' => [
'user_id' => $order['user_id'],
'out_trade_no' => $order['trade_no'],
'identifier' => ''
],
'redirect' => [
'return_url' => $order['return_url']
]
]);
if (!$source['redirect']['url']) {
abort(500, __('Payment gateway request failed'));
}
return [
'type' => 1,
'data' => $source['redirect']['url']
];
}
public function notify($params)
{
\Stripe\Stripe::setApiKey($this->config['stripe_sk_live']);
try {
$event = \Stripe\Webhook::constructEvent(
get_request_content(),
request()->header('HTTP_STRIPE_SIGNATURE'),
$this->config['stripe_webhook_key']
);
} catch (\Stripe\Error\SignatureVerification $e) {
abort(400);
}
switch ($event->type) {
case 'source.chargeable':
$object = $event->data->object;
\Stripe\Charge::create([
'amount' => $object->amount,
'currency' => $object->currency,
'source' => $object->id,
'metadata' => json_decode($object->metadata, true)
]);
break;
case 'charge.succeeded':
$object = $event->data->object;
if ($object->status === 'succeeded') {
if (!isset($object->metadata->out_trade_no) && !isset($object->source->metadata)) {
return('order error');
}
$metaData = isset($object->metadata->out_trade_no) ? $object->metadata : $object->source->metadata;
$tradeNo = $metaData->out_trade_no;
return [
'trade_no' => $tradeNo,
'callback_no' => $object->id
];
}
break;
default:
abort(500, 'event is not support');
}
return('success');
}
private function exchange($from, $to)
{
$result = file_get_contents('https://api.exchangerate.host/latest?symbols=' . $to . '&base=' . $from);
$result = json_decode($result, true);
return $result['rates'][$to];
}
}
+139
View File
@@ -0,0 +1,139 @@
<?php
namespace App\Payments;
use Stripe\Stripe;
use Stripe\Checkout\Session;
class StripeCheckout {
public function __construct($config)
{
$this->config = $config;
}
public function form()
{
return [
'currency' => [
'label' => '货币单位',
'description' => '',
'type' => 'input',
],
'stripe_sk_live' => [
'label' => 'SK_LIVE',
'description' => 'API 密钥',
'type' => 'input',
],
'stripe_pk_live' => [
'label' => 'PK_LIVE',
'description' => 'API 公钥',
'type' => 'input',
],
'stripe_webhook_key' => [
'label' => 'WebHook 密钥签名',
'description' => '',
'type' => 'input',
],
'stripe_custom_field_name' => [
'label' => '自定义字段名称',
'description' => '例如可设置为“联系方式”,以便及时与客户取得联系',
'type' => 'input',
]
];
}
public function pay($order)
{
$currency = $this->config['currency'];
$exchange = $this->exchange('CNY', strtoupper($currency));
if (!$exchange) {
abort(500, __('Currency conversion has timed out, please try again later'));
}
$customFieldName = isset($this->config['stripe_custom_field_name']) ? $this->config['stripe_custom_field_name'] : 'Contact Infomation';
$params = [
'success_url' => $order['return_url'],
'cancel_url' => $order['return_url'],
'client_reference_id' => $order['trade_no'],
'line_items' => [
[
'price_data' => [
'currency' => $currency,
'product_data' => [
'name' => $order['trade_no']
],
'unit_amount' => floor($order['total_amount'] * $exchange)
],
'quantity' => 1
]
],
'mode' => 'payment',
'invoice_creation' => ['enabled' => true],
'phone_number_collection' => ['enabled' => true],
'custom_fields' => [
[
'key' => 'contactinfo',
'label' => ['type' => 'custom', 'custom' => $customFieldName],
'type' => 'text',
],
],
// 'customer_email' => $user['email'] not support
];
Stripe::setApiKey($this->config['stripe_sk_live']);
try {
$session = Session::create($params);
} catch (\Exception $e) {
info($e);
abort(500, "Failed to create order. Error: {$e->getMessage}");
}
return [
'type' => 1, // 0:qrcode 1:url
'data' => $session->url
];
}
public function notify($params)
{
\Stripe\Stripe::setApiKey($this->config['stripe_sk_live']);
try {
$event = \Stripe\Webhook::constructEvent(
get_request_content(),
request()->header('HTTP_STRIPE_SIGNATURE'),
$this->config['stripe_webhook_key']
);
} catch (\Stripe\Error\SignatureVerification $e) {
abort(400);
}
switch ($event->type) {
case 'checkout.session.completed':
$object = $event->data->object;
if ($object->payment_status === 'paid') {
return [
'trade_no' => $object->client_reference_id,
'callback_no' => $object->payment_intent
];
}
break;
case 'checkout.session.async_payment_succeeded':
$object = $event->data->object;
return [
'trade_no' => $object->client_reference_id,
'callback_no' => $object->payment_intent
];
break;
default:
abort(500, 'event is not support');
}
return('success');
}
private function exchange($from, $to)
{
$result = file_get_contents('https://api.exchangerate.host/latest?symbols=' . $to . '&base=' . $from);
$result = json_decode($result, true);
return $result['rates'][$to];
}
}
+124
View File
@@ -0,0 +1,124 @@
<?php
/**
* 自己写别抄,抄NMB抄
*/
namespace App\Payments;
use Stripe\Source;
use Stripe\Stripe;
class StripeCredit {
public function __construct($config)
{
$this->config = $config;
}
public function form()
{
return [
'currency' => [
'label' => '货币单位',
'description' => '',
'type' => 'input',
],
'stripe_sk_live' => [
'label' => 'SK_LIVE',
'description' => '',
'type' => 'input',
],
'stripe_pk_live' => [
'label' => 'PK_LIVE',
'description' => '',
'type' => 'input',
],
'stripe_webhook_key' => [
'label' => 'WebHook密钥签名',
'description' => '',
'type' => 'input',
]
];
}
public function pay($order)
{
info($order);
$currency = $this->config['currency'];
$exchange = $this->exchange('CNY', strtoupper($currency));
if (!$exchange) {
abort(500, __('Currency conversion has timed out, please try again later'));
}
Stripe::setApiKey($this->config['stripe_sk_live']);
try {
$charge = \Stripe\Charge::create([
'amount' => floor($order['total_amount'] * $exchange),
'currency' => $currency,
'source' => $order['stripe_token'],
'metadata' => [
'user_id' => $order['user_id'],
'out_trade_no' => $order['trade_no'],
'identifier' => ''
]
]);
} catch (\Exception $e) {
info($e);
abort(500, __('Payment failed. Please check your credit card information'));
}
if (!$charge->paid) {
abort(500, __('Payment failed. Please check your credit card information'));
}
return [
'type' => 2,
'data' => $charge->paid
];
}
public function notify($params)
{
\Stripe\Stripe::setApiKey($this->config['stripe_sk_live']);
try {
$event = \Stripe\Webhook::constructEvent(
get_request_content(),
request()->header('HTTP_STRIPE_SIGNATURE'),
$this->config['stripe_webhook_key']
);
} catch (\Stripe\Error\SignatureVerification $e) {
abort(400);
}
switch ($event->type) {
case 'source.chargeable':
$object = $event->data->object;
\Stripe\Charge::create([
'amount' => $object->amount,
'currency' => $object->currency,
'source' => $object->id,
'metadata' => json_decode($object->metadata, true)
]);
break;
case 'charge.succeeded':
$object = $event->data->object;
if ($object->status === 'succeeded') {
if (!isset($object->metadata->out_trade_no) && !isset($object->source->metadata)) {
return('order error');
}
$metaData = isset($object->metadata->out_trade_no) ? $object->metadata : $object->source->metadata;
$tradeNo = $metaData->out_trade_no;
return [
'trade_no' => $tradeNo,
'callback_no' => $object->id
];
}
break;
default:
abort(500, 'event is not support');
}
return('success');
}
private function exchange($from, $to)
{
$result = file_get_contents('https://api.exchangerate.host/latest?symbols=' . $to . '&base=' . $from);
$result = json_decode($result, true);
return $result['rates'][$to];
}
}
+117
View File
@@ -0,0 +1,117 @@
<?php
/**
* 自己写别抄,抄NMB抄
*/
namespace App\Payments;
use Stripe\Source;
use Stripe\Stripe;
class StripeWepay {
public function __construct($config)
{
$this->config = $config;
}
public function form()
{
return [
'currency' => [
'label' => '货币单位',
'description' => '',
'type' => 'input',
],
'stripe_sk_live' => [
'label' => 'SK_LIVE',
'description' => '',
'type' => 'input',
],
'stripe_webhook_key' => [
'label' => 'WebHook密钥签名',
'description' => '',
'type' => 'input',
]
];
}
public function pay($order)
{
$currency = $this->config['currency'];
$exchange = $this->exchange('CNY', strtoupper($currency));
if (!$exchange) {
abort(500, __('Currency conversion has timed out, please try again later'));
}
Stripe::setApiKey($this->config['stripe_sk_live']);
$source = Source::create([
'amount' => floor($order['total_amount'] * $exchange),
'currency' => $currency,
'type' => 'wechat',
'statement_descriptor' => $order['trade_no'],
'metadata' => [
'user_id' => $order['user_id'],
'out_trade_no' => $order['trade_no'],
'identifier' => ''
],
'redirect' => [
'return_url' => $order['return_url']
]
]);
if (!$source['wechat']['qr_code_url']) {
abort(500, __('Payment gateway request failed'));
}
return [
'type' => 0,
'data' => $source['wechat']['qr_code_url']
];
}
public function notify($params)
{
\Stripe\Stripe::setApiKey($this->config['stripe_sk_live']);
try {
$event = \Stripe\Webhook::constructEvent(
get_request_content(),
request()->header('HTTP_STRIPE_SIGNATURE'),
$this->config['stripe_webhook_key']
);
} catch (\Stripe\Error\SignatureVerification $e) {
abort(400);
}
switch ($event->type) {
case 'source.chargeable':
$object = $event->data->object;
\Stripe\Charge::create([
'amount' => $object->amount,
'currency' => $object->currency,
'source' => $object->id,
'metadata' => json_decode($object->metadata, true)
]);
break;
case 'charge.succeeded':
$object = $event->data->object;
if ($object->status === 'succeeded') {
if (!isset($object->metadata->out_trade_no) && !isset($object->source->metadata)) {
return('order error');
}
$metaData = isset($object->metadata->out_trade_no) ? $object->metadata : $object->source->metadata;
$tradeNo = $metaData->out_trade_no;
return [
'trade_no' => $tradeNo,
'callback_no' => $object->id
];
}
break;
default:
abort(500, 'event is not support');
}
return('success');
}
private function exchange($from, $to)
{
$result = file_get_contents('https://api.exchangerate.host/latest?symbols=' . $to . '&base=' . $from);
$result = json_decode($result, true);
return $result['rates'][$to];
}
}
+84
View File
@@ -0,0 +1,84 @@
<?php
namespace App\Payments;
use Omnipay\Omnipay;
use Omnipay\WechatPay\Helper;
class WechatPayNative {
public function __construct($config)
{
$this->config = $config;
}
public function form()
{
return [
'app_id' => [
'label' => 'APPID',
'description' => '绑定微信支付商户的APPID',
'type' => 'input',
],
'mch_id' => [
'label' => '商户号',
'description' => '微信支付商户号',
'type' => 'input',
],
'api_key' => [
'label' => 'APIKEY(v1)',
'description' => '',
'type' => 'input',
]
];
}
public function pay($order)
{
$gateway = Omnipay::create('WechatPay_Native');
$gateway->setAppId($this->config['app_id']);
$gateway->setMchId($this->config['mch_id']);
$gateway->setApiKey($this->config['api_key']);
$gateway->setNotifyUrl($order['notify_url']);
$params = [
'body' => $order['trade_no'],
'out_trade_no' => $order['trade_no'],
'total_fee' => $order['total_amount'],
'spbill_create_ip' => '0.0.0.0',
'fee_type' => 'CNY'
];
$request = $gateway->purchase($params);
$response = $request->send();
$response = $response->getData();
if ($response['return_code'] !== 'SUCCESS') {
abort(500, $response['return_msg']);
}
return [
'type' => 0,
'data' => $response['code_url'],
'custom_result' => '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'
];
}
public function notify($params)
{
$data = Helper::xml2array(get_request_content());
$gateway = Omnipay::create('WechatPay');
$gateway->setAppId($this->config['app_id']);
$gateway->setMchId($this->config['mch_id']);
$gateway->setApiKey($this->config['api_key']);
$response = $gateway->completePurchase([
'request_params' => get_request_content()
])->send();
if (!$response->isPaid()) {
return('FAIL');
}
return [
'trade_no' => $data['out_trade_no'],
'callback_no' => $data['transaction_id']
];
}
}