Skip to content

Commit

Permalink
update payment gateway
Browse files Browse the repository at this point in the history
  • Loading branch information
兩足大貓貓 committed Jun 5, 2021
1 parent c13847f commit 6dae8b3
Show file tree
Hide file tree
Showing 15 changed files with 864 additions and 491 deletions.
1 change: 1 addition & 0 deletions app/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
$this->post('/notify', App\Services\Payment::class . ':notify');
$this->post('/notify/{type}', App\Services\Payment::class . ':notify');
$this->post('/status', App\Services\Payment::class . ':getStatus');
$this->post('/coinpay/notify', App\Services\CoinPayment::class. ':notify');
});

// Auth
Expand Down
25 changes: 13 additions & 12 deletions config/.config.example.php
Original file line number Diff line number Diff line change
Expand Up @@ -285,37 +285,32 @@


//支付系统设置----------------------------------------------------------------------------------------
#取值 none | codepay | f2fpay | paymentwall | spay | payjs | yftpay | bitpayx | theadpay
#取值 none | f2fpay | paymentwall | spay | payjs | bitpayx | theadpay | coinpay
$_ENV['payment_system'] = 'none';

#yft支付设置
$_ENV['yft_secret'] = '';
$_ENV['yft_accesskey'] = '';

#codepay码支付
#wiki地址:https://goo.gl/dRwRDi http://t.cn/RnsWjtB
# codepay码支付
$_ENV['codepay_id'] = ''; //码支付ID
$_ENV['codepay_key'] = ''; //码支付通信密钥

#alipay,f2fpay
# alipay,f2fpay
$_ENV['f2fpay_app_id'] = '';
$_ENV['f2fpay_p_id'] = '';
$_ENV['alipay_public_key'] = '';
$_ENV['merchant_private_key'] = '';
$_ENV['f2fNotifyUrl'] = null; //自定义当面付回调地址

#PaymentWall
# PaymentWall
$_ENV['pmw_publickey'] = '';
$_ENV['pmw_privatekey'] = '';
$_ENV['pmw_widget'] = 'm2_1';
$_ENV['pmw_height'] = '350px';

#alipay,spay
# alipay,spay
$_ENV['alipay_id'] = '';
$_ENV['alipay_key'] = '';
$_ENV['amount'] = [2, 23, 233, 2333, 23333]; //充值金额选项设定

#alipay,zfbjk.com
# alipay,zfbjk.com
$_ENV['zfbjk_pid'] = '';
$_ENV['zfbjk_key'] = '';
$_ENV['zfbjk_qrcodeurl'] = '';
Expand All @@ -325,7 +320,7 @@
# 客服和技术 24x7 在线支持: https://t.me/mugglepay
$_ENV['bitpay_secret'] = '';

#PayJs
# PayJs
$_ENV['payjs_mchid'] = '';
$_ENV['payjs_key'] = '';

Expand All @@ -334,6 +329,12 @@
$_ENV['theadpay_mchid'] = '';
$_ENV['theadpay_key'] = '';

# CoinPay
$_ENV['coinpay_appid'] =''; // CoinPay 应用ID (*)
$_ENV['coinpay_secret'] =''; // CoinPay 验证密钥 (*)
$_ENV['coinpay_notify'] =''; // 异步回调URL
$_ENV['coinpay_return'] =''; // 同步返回URL

#后台商品列表 销量统计
$_ENV['sales_period'] = 30; //统计指定周期内的销量,值为【expire/任意大于0的整数】

Expand Down
43 changes: 43 additions & 0 deletions src/Services/CoinPayment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace App\Services;

use App\Services\Gateway\CoinPay;

class CoinPayment
{
public static function getClient()
{
return new CoinPay(Config::get('coinpay_secret'), Config::get('coinpay_appid'));
}

public static function notify($request, $response, $args)
{
return self::getClient()->notify($request, $response, $args);
}

public static function returnHTML($request, $response, $args)
{
return self::getClient()->getReturnHTML($request, $response, $args);
}

public static function purchaseHTML()
{
$coinpay_secret = Config::get('coinpay_secret');
if (self::getClient() != null && $coinpay_secret != '') {
return self::getClient()->getPurchaseHTML();
}

return '';
}

public static function getStatus($request, $response, $args)
{
return self::getClient()->getStatus($request, $response, $args);
}

public static function purchase($request, $response, $args)
{
return self::getClient()->purchase($request, $response, $args);
}
}
187 changes: 187 additions & 0 deletions src/Services/Gateway/CoinPay.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
<?php


namespace App\Services\Gateway;


use App\Models\Paylist;
use App\Services\Auth;
use App\Services\Config;
use App\Services\Gateway\CoinPay\CoinPayApi;
use App\Services\Gateway\CoinPay\CoinPayConfig;
use App\Services\Gateway\CoinPay\CoinPayException;
use App\Services\Gateway\CoinPay\CoinPayUnifiedOrder;

class CoinPay extends AbstractPayment
{
private $coinPaySecret;
private $coinPayGatewayUrl;
private $coinPayAppId;


public function __construct($coinPaySecret, $coinPayAppId)
{
$this->coinPaySecret = $coinPaySecret;
$this->coinPayAppId = $coinPayAppId;
$this->coinPayGatewayUrl = "https://openapi.coinpay.la/"; // 网关地址
}


public function purchase($request, $response, $args)
{
// set timezone
date_default_timezone_set('Asia/Hong_Kong');
/**************************请求参数**************************/
$amount = $request->getParam('price');
//var_dump($request->getParam("price"));die();
$user = Auth::getUser();
$pl = new Paylist();
$pl->userid = $user->id;
$pl->total = $amount;
$pl->tradeno = self::generateGuid();
$pl->save();
//商户订单号,商户网站订单系统中唯一订单号,必填
$out_trade_no = $pl->tradeno;
//订单名称,必填
$subject = $pl->id . 'UID:' . $user->id . ' 充值' . $amount . '元';
//付款金额,必填
$total_fee = (float)$amount;
/************************************************************/
$report_data = new CoinPayUnifiedOrder();
$report_data->SetSubject($subject);
$report_data->SetOut_trade_no($out_trade_no);
$report_data->SetTotal_amount($total_fee);
$report_data->SetTimestamp(date('Y-m-d H:i:s', time()));
$report_data->SetReturn_url(Config::get('baseUrl') . '/user/code');
$report_data->SetNotify_url(Config::get('baseUrl') . '/payment/coinpay/notify');
// $report_data->SetBody(json_encode($pl));
// $report_data->SetTransCurrency("CNY");
// $report_data->SetAttach("");
$config = new CoinPayConfig();
try {
$url = CoinPayApi::unifiedOrder($config, $report_data);
return json_encode(['code' => 0, 'url' => $this->coinPayGatewayUrl . 'api/gateway?' . $url]);
} catch (CoinPayException $exception) {
print_r($exception->getMessage());
die();
}
}

private function Sign($value, $secret)
{
ksort($value);
reset($value);
$sign_param = implode('&', $value);
$signature = hash_hmac('sha256', $sign_param, $secret, true);
return base64_encode($signature);
}

/**
* @param $data
* @param $sign
* @return bool
*/
public function verify($data, $sign)
{
$payConfig = new CoinPayConfig();
if ($sign === self::Sign($data, $payConfig->GetSecret())) {
return true;
}
return false;
}

/**
* 异步通知
* @param \Slim\Http\Request $request
* @param \Slim\Http\Response $response
* @param array $args
*/
public function notify($request, $response, $args)
{
$raw = file_get_contents("php://input");
file_put_contents(BASE_PATH . '/coinpay_purchase.log', $raw . "\r\n", FILE_APPEND);
$data = json_decode($raw, true);
if (empty($data)) {
file_put_contents(BASE_PATH . '/coinpay_purchase.log', "返回数据异常\r\n", FILE_APPEND);
echo "fail";
die();
}
// 签名验证
$sign = $data['sign'];
unset($data['sign']);
$resultVerify = self::verify($data, $sign);
$isPaid = $data !== null && $data['trade_status'] !== null && $data['trade_status'] === 'TRADE_SUCCESS';
if ($resultVerify) {
if ($isPaid) {
$this->postPayment($data['out_trade_no'], 'CoinPay');
echo "success";
file_put_contents(BASE_PATH . '/coinpay_purchase.log', "订单{$data['out_trade_no']}支付成功\r\n" . json_encode($data) . "\r\n", FILE_APPEND);
} else {
echo "success";
file_put_contents(BASE_PATH . '/coinpay_purchase.log', "订单{$data['out_trade_no']}未支付自动关闭成功\r\n" . json_encode($data) . "\r\n", FILE_APPEND);
}
} else {
echo "fail";
file_put_contents(BASE_PATH . '/coinpay_purchase.log', "订单{$data['out_trade_no']}签名验证失败或者订单未支付成功\r\n" . json_encode($data) . "\r\n", FILE_APPEND);
}
die();
}

public function getReturnHTML($request, $response, $args)
{
// TODO: Implement getStatus() method.
}

public function getStatus($request, $response, $args)
{
// TODO: Implement getStatus() method.
}

public function getPurchaseHTML()
{
return '<div class="card-inner">
<div class="form-group pull-left">
<p class="modal-title">CoinPay 支持BTC、ETH、USDT等数十种数字货币</p>
<div class="form-group form-group-label">
<label class="floating-label" for="price">充值金额</label>
<input id="type" class="form-control maxwidth-edit" name="amount" />
</div>
<a class="btn btn-flat waves-attach" id="submitSpay" style="padding: 8px 24px;color: #fff;background: #1890ff;"><span class="icon">check</span>&nbsp;充&nbsp;值&nbsp;</a>
</div>
</div>
<script>
window.onload = function(){
$("#submitSpay").click(function() {
var price = parseFloat($("#type").val());
if (isNaN(price)) {
$("#result").modal();
$("#msg").html("非法的金额!");
return false;
}
$(\'#readytopay\').modal();
$("#readytopay").on(\'shown.bs.modal\', function () {
$.ajax({
\'url\': "/user/payment/purchase",
\'data\': {
\'price\': price,
},
\'dataType\': \'json\',
\'type\': "POST",
success: (data) => {
if (data.code == 0) {
$("#result").modal();
$("#msg").html("正在跳转CoinPay支付网关...");
window.location.href = data.url;
} else {
$("#result").modal();
$$.getElementById(\'msg\').innerHTML = data.msg;
console.log(data);
}
}
});
});
});
};</script>
';
}
}
67 changes: 67 additions & 0 deletions src/Services/Gateway/CoinPay/CoinPayApi.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace App\Services\Gateway\CoinPay;

class CoinPayApi
{
/**
* 统一下单,CoinPayUnifiedOrder、total_amount、必填
* @param CoinPayConfigInterface $config "配置对象"
* @param CoinPayUnifiedOrder $inputObj
* @param int $timeOut
* @return string
* @throws CoinPayException
*/
public static function unifiedOrder($config, $inputObj, $timeOut = 6)
{
if (!$inputObj->IsSubjectSet()) {
throw new CoinPayException("缺少统一支付接口必填参数subject!");
} else if (!$inputObj->IsTimestampSet()) {
throw new CoinPayException("缺少统一支付接口必填参数timestamp!");
} else if (!$inputObj->IsOut_trade_noSet()) {
throw new CoinPayException("缺少统一支付接口必填参数out_trade_no!");
} else if (!$inputObj->IsTotal_amountSet()) {
throw new CoinPayException("缺少统一支付接口必填参数total_amount!");
}

//异步通知url未设置,则使用配置文件中的url
if (!$inputObj->IsNotify_urlSet() && $config->GetNotifyUrl() != "") {
$inputObj->SetNotify_url($config->GetNotifyUrl());
}
if (!$inputObj->IsReturn_urlSet() && $config->GetReturnUrl() != "") {
$inputObj->SetReturn_url($config->GetReturnUrl());
}
if (!$inputObj->IsAttachSet() && $config->GetAttach() != "") {
$inputObj->SetAttach($config->GetAttach());
}
if (!$inputObj->IsBodySet() && $config->GetBody() != "") {
$inputObj->SetBody($config->GetBody());
}
if (!$inputObj->IsTransCurrencySet() && $config->GetTransCurrency() != "") {
$inputObj->SetTransCurrency($config->GetTransCurrency());
}

// 设置AppID于随机字符串
$inputObj->SetAppid($config->GetAppId());
$inputObj->SetNonce_str(self::getNonceStr());

//签名
$inputObj->SetSign($config->GetSecret());
return http_build_query($inputObj->ReturnArray());
}

/**
* 返回随机字符串
* @param int $length
* @return string
*/
public static function getNonceStr($length = 32)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
}
Loading

0 comments on commit 6dae8b3

Please sign in to comment.