Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
xu42 committed Nov 25, 2017
1 parent 7d5dc70 commit 039a439
Show file tree
Hide file tree
Showing 9 changed files with 303 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
vendor
.idea
composer.lock
public/yz.log
20 changes: 20 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "xu42/pay",
"type": "project",
"license": "MIT",
"authors": [
{
"name": "xu42",
"email": "xu42.cn@gmail.com"
}
],
"autoload": {
"psr-4": {
"Pay\\": "src/"
}
},
"require": {
"xu42/open-sdk": "^1.0",
"workerman/workerman": "^3.5"
}
}
66 changes: 66 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<html lang="zh_CN" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>在线收款 - 个人开发者的福音 - 基于有赞云</title>
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
<style>
body{text-align:center;background-color:#e0e0e0}#app{margin:0 auto}#app h2{padding-top:3%}#intro{padding-top:2%;text-align:center}#app img{padding-top:3%;width:280px}#app input{margin:1%}
</style>
</head>
<body>
<div id="app">
<h2>在线收款Demo</h2>
<div id="intro">
1. 支持支付宝、微信、信用卡,扫码付款<br>
2. 无需公司资质、无需接入支付宝、微信<br>
3. 基于有赞云可信赖,费率低每笔交易1%<br>
</div>
<img v-bind:src="qrcode">
<div id="input_price">
<input v-model="price" placeholder="输入金额(单位: 分)">
<button v-on:click="generate">点此生成支付二维码</button>
</div>
</div>


<a href="https://github.com/xu42/pay"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"></a></body>


<script src="//cdn.staticfile.org/vue/2.2.6/vue.min.js"></script>
<script>
var clientId = '';
var ws = new WebSocket('ws://127.0.0.1:11942');
var app = new Vue({
el: '#app',
data: {
qrcode: 'https://img.yzcdn.cn/upload_files/2017/11/25/FlaMfOlko4gdrls7LmdfHDtoACxK.jpg',
price: 10
},
methods: {
generate: function () {
clientId = Math.random().toString(36).substr(2);
ws.send(clientId + ',' + app.price);
}
}
});

ws.onmessage = function (response) {

var responseObj = JSON.parse(response.data);

if (responseObj.code !== 200) {
alert(responseObj.msg);
return;
}

if (responseObj.event === 'pay') {
if (responseObj.data === 'WAIT_BUYER_PAY') app.qrcode = 'https://img.yzcdn.cn/upload_files/2017/11/25/FqZjK96_t4g3PYC7m58RHXQ4PCRm.png';
if (responseObj.data === 'TRADE_SUCCESS') app.qrcode = 'https://img.yzcdn.cn/upload_files/2017/11/25/FnFa-_giR389G_rtBBWspFw8esc7.png';
}

if (responseObj.event === 'create') {
app.qrcode = responseObj.data.qr;
}
};
</script>
</html>
26 changes: 26 additions & 0 deletions public/listening.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

require_once __DIR__ . '/../src/Service/TradeService.php';

$request = $GLOBALS['HTTP_RAW_POST_DATA'];

echo json_encode(['code' => 0, 'msg' => 'success']);

file_put_contents('yz.log', $request . PHP_EOL, FILE_APPEND);

$request = json_decode($request, true);

if (empty($request) || !isset($request['kdt_id']) || !isset($request['id']) || !isset($request['status'])) {
return;
}


$QRId = (new Service\TradeService)->getQRId($request['id']);
if (empty($QRId)) return "send QRId is empty";

$client = stream_socket_client('tcp://127.0.0.1:11900');
$data = array('qrId' => $QRId, 'msg' => $request['status']);
fwrite($client, json_encode($data) . "\n");
$res = fread($client, 8192);

file_put_contents('yz.log', 'QRID:' . (string)$QRId . '--' . 'pushRes:' . $res . PHP_EOL, FILE_APPEND);
31 changes: 31 additions & 0 deletions src/Service/InnerTextServer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Service;

class InnerTextServer
{
/**
* @param \Workerman\Connection\TcpConnection $connection
* @param string $message
*/
public static function onMessage($connection, $message)
{
$data = json_decode($message, true);
$json = json_encode(['code' => 200, 'msg' => 'success', 'event' => 'pay', 'data' => $data['msg']]);
$sendRes = self::sendMessageByQRId($data['qrId'], $json);
$connection->send($sendRes ? 'success' : 'error');
}

private static function sendMessageByQRId($QRId, $message)
{
global $webSocketServer;

if (!isset($webSocketServer->userQRs[$QRId])) return false;
$userId = $webSocketServer->userQRs[$QRId];

if (!isset($webSocketServer->userConnections[$userId])) return false;
/** @var \Workerman\Connection\TcpConnection $connection $connection */
$connection = $webSocketServer->userConnections[$userId];
return $connection->send($message);
}
}
45 changes: 45 additions & 0 deletions src/Service/PayService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Service;

use Exception;
use Youzan\Open\Client;

class PayService extends YouzanYunService
{

/**
* @param \Workerman\Connection\TcpConnection $connection
* @param $price
*/
public function create($connection, $price)
{
global $webSocketServer;
$price = abs(intval($price)) != 0 ? abs(intval($price)) : 10;

try {
$response = $this->createPayQRCode($this->getAccessToken(), $price);
$connection->send(json_encode(['code' => 200, 'msg' => 'success', 'event' => 'create', 'data' => ['qr' => $response['qr_code']]]));
$webSocketServer->userQRs[$response['qr_id']] = $connection->userId;
} catch (Exception $e) {
$connection->send(json_encode(['code' => 1000, 'msg' => $e->getMessage(), 'event' => 'create', 'data' => []]));
}
}


private function createPayQRCode($accessToken, $price = 1)
{
$apiVersion = $this->config['api']['version'];
$createPayQRCode = $this->config['api']['createPayQRCode'];

$params = [
'qr_price' => abs(intval($price)),
'qr_name' => 'Demo By Xu42',
'qr_type' => 'QR_TYPE_DYNAMIC',
];

$response = (new Client($accessToken))->get($createPayQRCode, $apiVersion, $params);
if (!isset($response['response']['qr_code'])) throw new Exception('wrong create pay qrcode');
return $response['response'];
}
}
38 changes: 38 additions & 0 deletions src/Service/TradeService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace Service;

require_once 'YouzanYunService.php';

use Exception;
use Youzan\Open\Client;

class TradeService extends YouzanYunService
{
public function getQRId($orderNo)
{
try {
$tradeInfo = $this->getSingleTrade($orderNo);
return $tradeInfo['trade']['qr_id'];
} catch (Exception $e) {
return 0;
}
}

public function getSingleTrade($orderNo)
{
$apiVersion = $this->config['api']['version'];
$getTrade = $this->config['api']['getTrade'];

$params = [
'tid' => $orderNo,
'with_childs' => false,
'fields' => 'qr_id'
];

$response = (new Client($this->getAccessToken()))->get($getTrade, $apiVersion, $params);
var_dump($response);
if (!isset($response['response'])) throw new Exception('wrong getTrade');
return $response['response'];
}
}
40 changes: 40 additions & 0 deletions src/Service/YouzanYunService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Service;

use Exception;
use Youzan\Open\Token;

class YouzanYunService
{
protected $config = [];

public function __construct()
{
$this->config = [
'type' => 'self',
'kdtId' => '0000',
'clientId' => '00000',
'clientSecret' => '0000',
'api' => [
'version' => '3.0.0',
'getTrade' => 'youzan.trade.get',
'createPayQRCode' => 'youzan.pay.qrcode.create',
],
];
}

protected function getAccessToken()
{
$clientId = $this->config['clientId'];
$clientSecret = $this->config['clientSecret'];
$type = $this->config['type'];
$keys = [
'kdt_id' => $this->config['kdtId']
];

$accessToken = (new Token($clientId, $clientSecret))->getToken($type, $keys);
if (!isset($accessToken['access_token'])) throw new Exception('wrong server pay config');
return $accessToken['access_token'];
}
}
33 changes: 33 additions & 0 deletions src/start.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

require_once __DIR__ . '/../vendor/autoload.php';

use Service\PayService;
use Workerman\WebServer;
use Workerman\Worker;


$webServer = new WebServer('http://127.0.0.1:8083');
$webServer->addRoot('localhost:8083', __DIR__ . '/../public/');
$webServer->count = 3;

$webSocketServer = new Worker('websocket://127.0.0.1:11942');
$webSocketServer->count = 1;
$webSocketServer->userConnections = [];
$webSocketServer->userQRs = [];
$webSocketServer->onWorkerStart = function () use ($webSocketServer) {
$textWorker = new Worker('Text://127.0.0.1:11900');
$textWorker->onMessage = 'Service\\InnerTextServer::onMessage';
$textWorker->listen();
};
$webSocketServer->onMessage = function ($connection, $message) use ($webSocketServer) {
$arr = explode(',', $message);
if (!isset($connection->userId)) {
$connection->userId = $arr[0];
$webSocketServer->userConnections[$connection->userId] = $connection;
}
(new PayService)->create($connection, $arr[1]);
};


Worker::runAll();

0 comments on commit 039a439

Please sign in to comment.