├── .gitattributes ├── .gitignore ├── .ide_helper ├── _ide_helper.php ├── _ide_helper_2.php ├── _ide_helper_3.php └── _ide_helper_4.php ├── LICENSE ├── Pay ├── AiMing │ └── Api.php ├── AirPay │ └── Api.php ├── AliAop │ └── Api.php ├── Alidirect │ ├── Api.php │ └── README.md ├── Alipay │ ├── Api.php │ ├── cacert.pem │ └── sdk │ │ ├── alipay_core.function.php │ │ ├── alipay_notify.class.php │ │ └── alipay_submit.class.php ├── ApiInterface.php ├── BTC │ └── Api.php ├── CodePay │ └── Api.php ├── CoinPayments │ └── Api.php ├── Demo │ ├── Api.php │ └── README.md ├── DirectAlipay │ ├── Api.php │ └── README.md ├── DirectWeChat │ ├── Api.php │ └── README.md ├── ECPay │ ├── Api.php │ ├── README.md │ ├── example │ │ ├── sample_ATM_CreateOrder.php │ │ ├── sample_All_CreateOrder.php │ │ ├── sample_AndroidPay_CreateOrder.php │ │ ├── sample_BARCODE_CreateOrder.php │ │ ├── sample_CVS_CreateOrder.php │ │ ├── sample_Credit_CreateOrder.php │ │ ├── sample_FundingReconDetail.php │ │ ├── sample_GooglePay_CreateOrder.php │ │ ├── sample_QueryTradeInfo.php │ │ ├── sample_ServerReplyPaymentStatus.php │ │ ├── sample_TradeNoAio.php │ │ └── sample_WebATM_CreateOrder.php │ └── sdk │ │ └── ECPay.Payment.Integration.php ├── EPay │ └── Api.php ├── EpUSDT │ ├── Api.php │ └── README.md ├── Example │ ├── Api.php │ └── README.md ├── Fakala │ ├── Api.php │ └── sdk.php ├── Fubei │ ├── Api.php │ └── README.md ├── HLPay │ └── Api.php ├── HyuePay │ └── Api.php ├── JCBPay │ └── Api.php ├── JiPays │ ├── Api.php │ └── common.php ├── JinfuPass │ └── Api.php ├── Meeol │ └── Api.php ├── MoTonePay │ └── Api.php ├── MugglePay │ ├── Api.php │ └── README.md ├── Pay.php ├── PayBeaver │ └── Api.php ├── PayPal │ └── Api.php ├── PayPlat │ └── Api.php ├── Payjs │ ├── Api.php │ └── sdk │ │ └── Payjs.php ├── QPay │ ├── Api.php │ └── qpay_mch_sp │ │ ├── qpayMch.config.php │ │ ├── qpayMchAPI.class.php │ │ └── qpayMchUtil.class.php ├── Qf │ └── Api.php ├── QweBank │ └── Api.php ├── ShuYouPay │ └── Api.php ├── Stripe │ └── Api.php ├── SwiftPass │ ├── Api.php │ ├── Utils.class.php │ ├── class │ │ ├── ClientResponseHandler.class.php │ │ ├── PayHttpClient.class.php │ │ └── RequestHandler.class.php │ └── request.php ├── TTPay │ └── Api.php ├── U9Pay │ └── Api.php ├── UigPay │ └── Api.php ├── Unk1Pay │ └── Api.php ├── VPay │ ├── Api.php │ ├── README.md │ ├── example.png │ ├── vpay_alipay.blade.php │ └── vpay_wechat.blade.php ├── WeChat │ ├── Api.php │ ├── PayNotifyCallBack.php │ ├── README.md │ ├── WxLog.php │ ├── WxPay.NativePay.php │ ├── cert │ │ ├── apiclient_cert.pem │ │ └── apiclient_key.pem │ ├── index.php │ ├── lib │ │ ├── WxPay.Api.php │ │ ├── WxPay.Config.php │ │ ├── WxPay.Data.php │ │ ├── WxPay.Exception.php │ │ └── WxPay.Notify.php │ └── logs │ │ └── .gitignore ├── Yeke │ ├── Api.php │ ├── HttpClient.php │ └── yekeApiLib.php ├── Youzan │ ├── Api.php │ └── Open │ │ ├── Client.php │ │ ├── Http.php │ │ ├── Protocol.php │ │ └── Token.php ├── YunCPay │ └── Api.php └── ZhaPay │ └── Api.php └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | *.js linguist-vendored 5 | CHANGELOG.md export-ignore 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /public/hot 3 | /public/storage 4 | /storage/*.key 5 | /vendor 6 | /.idea 7 | /.vs 8 | /.vagrant 9 | Homestead.json 10 | Homestead.yaml 11 | npm-debug.log 12 | yarn-error.log 13 | /.env 14 | -------------------------------------------------------------------------------- /.ide_helper/_ide_helper_2.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 17 | $this->url_return = SYS_URL . '/pay/return/' . $id; 18 | $this->pay_id = $id; 19 | } 20 | 21 | /** 22 | * @param array $config 23 | * @param string $out_trade_no 外部订单号 24 | * @param string $subject 25 | * @param string $body 26 | * @param $amount_cent 27 | * @throws \Exception 28 | * @internal param int $amount 1 = 0.01元 29 | */ 30 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 31 | { 32 | /* By Mr.Point QQ:40386277 www.zfbjk.com */ 33 | 34 | $pid = isset($config['pid']) ? $config['pid'] : ""; 35 | 36 | /** @var \App\Order $result */ 37 | $result = \App\Order::where('order_no', $out_trade_no)->first(); 38 | $payAmount = sprintf('%.2f', $amount_cent / 100); 39 | $title = $result->id; 40 | 41 | switch ($config['payway']) { 42 | case 'alipay': 43 | $paytype = 'alipay'; 44 | break; 45 | case 'weixin': 46 | $paytype = 'weixin'; 47 | break; 48 | default: 49 | throw new \Exception('支付方式填写错误, alipay/weixin'); 50 | } 51 | 52 | // 这里模板文件尽量复用之前的 53 | header("Location: /qrcode/pay/{$out_trade_no}/alidirect_{$paytype}?url={$pid}&title={$title}"); 54 | exit; 55 | } 56 | 57 | function verify($config, $successCallback) 58 | { 59 | $isNotify = isset($config['isNotify']) ? $config['isNotify'] : ""; 60 | 61 | $id = isset($config['id']) ? $config['id'] : ""; 62 | $key = isset($config['key']) ? $config['key'] : ""; 63 | 64 | 65 | if ($isNotify) { 66 | 67 | $tradeNo = isset($_POST['tradeNo']) ? $_POST['tradeNo'] : ''; 68 | $Money = isset($_POST['Money']) ? $_POST['Money'] : 0; 69 | $title = isset($_POST['title']) ? $_POST['title'] : ''; 70 | $memo = isset($_POST['memo']) ? $_POST['memo'] : ''; 71 | $alipay_account = isset($_POST['alipay_account']) ? $_POST['alipay_account'] : ''; 72 | $Gateway = isset($_POST['Gateway']) ? $_POST['Gateway'] : ''; 73 | $Sign = isset($_POST['Sign']) ? $_POST['Sign'] : ''; 74 | $orderid = isset($_POST['orderid']) ? $_POST['orderid'] : ''; 75 | 76 | if ($orderid && is_numeric($orderid)) { 77 | $result = \App\Order::where('id', $orderid)->first(); 78 | if ($result && $result->status == \App\Order::STATUS_SUCCESS) { 79 | exit("success"); 80 | } 81 | exit; 82 | } 83 | if (@strtoupper(md5($id . $key . $tradeNo . $Money . iconv("utf-8", "gb2312", $title) . iconv("utf-8", "gb2312", $memo))) != strtoupper($Sign)) { 84 | exit("Fail"); 85 | } else { 86 | if (!is_numeric($title)) { 87 | exit("FAIL"); 88 | } 89 | 90 | /** @var \App\Order $result */ 91 | $result = \App\Order::where('id', $title)->first(); 92 | if (!$result) { 93 | exit("IncorrectOrder"); 94 | } elseif ($result->paid != $Money * 100) { 95 | exit("fail"); 96 | } 97 | $out_trade_no = $result->order_no; 98 | $total_fee = (int)round($Money * 100); 99 | $trade_no = $tradeNo; 100 | $successCallback($out_trade_no, $total_fee, $trade_no); 101 | 102 | if ($isNotify) { 103 | echo 'success'; 104 | } 105 | return true; 106 | } 107 | } else { 108 | 109 | // 不支持主动查询? 110 | return false; 111 | } 112 | } 113 | 114 | /** 115 | * 退款操作 116 | * @param array $config 支付渠道配置 117 | * @param string $order_no 订单号 118 | * @param string $pay_trade_no 支付渠道流水号 119 | * @param int $amount_cent 金额/分 120 | * @return true|string true 退款成功 string 失败原因 121 | */ 122 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 123 | { 124 | return '此支付渠道不支持发起退款, 请手动操作'; 125 | } 126 | } -------------------------------------------------------------------------------- /Pay/Alidirect/README.md: -------------------------------------------------------------------------------- 1 | 2 | # ZFBJK 支付宝&微信免签约接口 3 | 4 | ## 注册地址 5 | * [支付宝&微信免签约接口](http://www.zfbjk.com/show.asp?g=2&id=37214) 6 | 7 | ## 使用说明 8 | * 驱动 Alidirect 9 | * 方式 alipay / weixin 10 | - alipay 支付宝 11 | - weixin 微信 12 | * 配置 (JSON格式) 13 | 支付宝: 14 | { 15 | "id": "您的商户ID", 16 | "key": "您的商户密钥", 17 | "pid": "您的支付宝PID" 18 | } 19 | 微信: 20 | { 21 | "id": "10001", 22 | "key": "cddc319335122d36ce3ed561fb2c5de2" 23 | } 24 | 25 | ## 说明 26 | zfbjk.com是在线支付行业内首家提供包接口对接的服务商,接口具有即开即用、免签约、免审核、免手续费等特点。 27 | 自2013年从事免签约接口服务以来,八年时间里服务数万用户,为您提供安全可靠的支付宝、微信免签约接口服务。 28 | 29 | -------------------------------------------------------------------------------- /Pay/Alipay/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 17 | $this->url_return = SYS_URL . '/pay/return/' . $id; 18 | $this->pay_id = $id; 19 | } 20 | 21 | /** 22 | * @param array $config 23 | * @param string $out_trade_no 外部订单号 24 | * @param string $subject 25 | * @param string $body 26 | * @param $amount_cent 27 | * @internal param int $amount 1 = 0.01元 28 | */ 29 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 30 | { 31 | $amount = sprintf('%.2f', $amount_cent / 100); //支付宝元为单位 32 | 33 | $alipay_config = $this->buildAliConfig($config); 34 | require_once(__DIR__ . '/sdk/alipay_submit.class.php'); 35 | 36 | // 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数 37 | $alipay_config['notify_url'] = $this->url_notify; 38 | // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数 39 | $alipay_config['return_url'] = $this->url_return . '/' . $out_trade_no; 40 | 41 | // 即时到账: https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.kiX33I&treeId=62&articleId=103740&docType=1 42 | // 手机网站支付: https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.2Z6TSk&treeId=60&articleId=103693&docType=1 43 | $parameter = array( 44 | 'service' => $alipay_config['service'], 45 | 'partner' => $alipay_config['partner'], 46 | 'seller_id' => $alipay_config['seller_id'], 47 | 'payment_type' => $alipay_config['payment_type'], 48 | 'notify_url' => $alipay_config['notify_url'], 49 | 'return_url' => $alipay_config['return_url'], 50 | 'out_trade_no' => $out_trade_no, 51 | 'total_fee' => $amount, 52 | 'subject' => $subject,//商品名称 53 | 'body' => $body,//商品描述 54 | 'show_url' => config('app.url'), // 收银台页面上,商品展示的超链接,必填 55 | 'app_pay' => 'Y',//启用此参数能唤起钱包APP支付宝 56 | '_input_charset' => 'utf-8', 57 | ); 58 | $alipaySubmit = new \AlipaySubmit($alipay_config);//建立请求 59 | $html_text = $alipaySubmit->buildRequestForm($parameter, 'get', '确认'); 60 | echo '正在跳转到支付渠道...

正在跳转到支付渠道...

'; 61 | echo $html_text; 62 | } 63 | 64 | 65 | function verify($config, $successCallback) 66 | { 67 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 68 | $alipay_config = $this->buildAliConfig($config); 69 | 70 | require __DIR__ . '/sdk/alipay_notify.class.php'; 71 | $alipay = new \AlipayNotify($alipay_config); 72 | 73 | if ($isNotify) { 74 | $result = $alipay->verifyNotify(); 75 | } else { 76 | $result = $alipay->verifyReturn(); 77 | } 78 | 79 | if ($result) {//验证成功 80 | $out_trade_no = $_REQUEST['out_trade_no'];//商户订单号 81 | $trade_no = $_REQUEST['trade_no'];//支付宝交易号 82 | $trade_status = $_REQUEST['trade_status'];//交易状态 83 | $total_fee = (int)round($_REQUEST['total_fee'] * 100); 84 | 85 | if ($trade_status == 'TRADE_FINISHED' || $trade_status == 'TRADE_SUCCESS') {//处理 86 | $successCallback($out_trade_no, $total_fee, $trade_no); 87 | } 88 | if ($isNotify) echo 'success'; 89 | return true; 90 | } else { 91 | //验证失败 92 | if ($isNotify) { 93 | echo 'fail'; 94 | $logTag = 'payNotify pay_id: ' . $this->pay_id . ',Alipay'; 95 | } else { 96 | $logTag = 'payReturn pay_id: ' . $this->pay_id . ',Alipay'; 97 | } 98 | \Log::error($logTag . ' Alipay.Api.verify failed'); 99 | return false; 100 | } 101 | } 102 | 103 | private function buildAliConfig($config) 104 | { 105 | return [ 106 | 'partner' => $config['partner'], //合作身份者ID, 107 | 'seller_id' => $config['partner'], //收款支付宝账号 108 | 'key' => $config['key'], //MD5密钥,安全检验码 109 | 'sign_type' => 'MD5', //签名方式 110 | 'input_charset' => 'utf-8', 111 | //ca证书路径地址,用于curl中ssl校验, 请保证cacert.pem文件在当前文件夹目录中 112 | 'cacert' => __DIR__ . DIRECTORY_SEPARATOR . 'cacert.pem', 113 | //访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http 114 | 'transport' => 'https', 115 | 'payment_type' => '1', // 支付类型 ,无需修改 116 | 'service' => $config['payway'] === 'wap' ? 117 | 'alipay.wap.create.direct.pay.by.user' : // 手机网站支付 118 | 'create_direct_pay_by_user', // 即时到账 119 | ]; 120 | } 121 | 122 | /** 123 | * 退款操作 124 | * @param array $config 支付渠道配置 125 | * @param string $order_no 订单号 126 | * @param string $pay_trade_no 支付渠道流水号 127 | * @param int $amount_cent 金额/分 128 | * @return true|string true 退款成功 string 失败原因 129 | */ 130 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 131 | { 132 | return '此支付渠道不支持发起退款, 请手动操作'; 133 | } 134 | } -------------------------------------------------------------------------------- /Pay/Alipay/cacert.pem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tai7sy/card-gateway/c13a0c7201bd1c2f9d4dbe2e996f3225e00e4202/Pay/Alipay/cacert.pem -------------------------------------------------------------------------------- /Pay/Alipay/sdk/alipay_notify.class.php: -------------------------------------------------------------------------------- 1 | alipay_config = $alipay_config; 31 | } 32 | function AlipayNotify($alipay_config) { 33 | $this->__construct($alipay_config); 34 | } 35 | /** 36 | * 针对notify_url验证消息是否是支付宝发出的合法消息 37 | * @return boolean 验证结果 38 | */ 39 | function verifyNotify(){ 40 | if(empty($_POST)) {//判断POST来的数组是否为空 41 | return false; 42 | } 43 | else { 44 | //生成签名结果 45 | $isSign = $this->getSignVeryfy($_POST, $_POST["sign"]); 46 | //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息) 47 | $responseTxt = 'false'; 48 | if (! empty($_POST["notify_id"])) {$responseTxt = $this->getResponse($_POST["notify_id"]);} 49 | 50 | //写日志记录 51 | //if ($isSign) { 52 | // $isSignStr = 'true'; 53 | //} 54 | //else { 55 | // $isSignStr = 'false'; 56 | //} 57 | //$log_text = "responseTxt=".$responseTxt."\n notify_url_log:isSign=".$isSignStr.","; 58 | //$log_text = $log_text.createLinkString($_POST); 59 | //logResult($log_text); 60 | 61 | //验证 62 | //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 63 | //isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 64 | if (preg_match("/true$/i",$responseTxt) && $isSign) { 65 | return true; 66 | } else { 67 | return false; 68 | } 69 | } 70 | } 71 | 72 | /** 73 | * 针对return_url验证消息是否是支付宝发出的合法消息 74 | * @return boolean 验证结果 75 | */ 76 | function verifyReturn(){ 77 | if(empty($_GET)) {//判断POST来的数组是否为空 78 | return false; 79 | } 80 | else { 81 | //生成签名结果 82 | $isSign = $this->getSignVeryfy($_GET, $_GET["sign"]); 83 | //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息) 84 | $responseTxt = 'false'; 85 | if (! empty($_GET["notify_id"])) { 86 | $responseTxt = $this->getResponse($_GET["notify_id"]); 87 | } 88 | 89 | 90 | //写日志记录 91 | //if ($isSign) { 92 | // $isSignStr = 'true'; 93 | //} 94 | //else { 95 | // $isSignStr = 'false'; 96 | //} 97 | //$log_text = "responseTxt=".$responseTxt."\n return_url_log:isSign=".$isSignStr.","; 98 | //$log_text = $log_text.createLinkString($_GET); 99 | //logResult($log_text); 100 | 101 | //验证 102 | //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 103 | //isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 104 | if (preg_match("/true$/i",$responseTxt) && $isSign) { 105 | return true; 106 | } else { 107 | return false; 108 | } 109 | } 110 | } 111 | 112 | /** 113 | * 获取返回时的签名验证结果 114 | * @param array $para_temp 通知返回来的参数数组 115 | * @param string $sign 返回的签名结果 116 | * @return boolean 签名验证结果 117 | */ 118 | function getSignVeryfy($para_temp, $sign) { 119 | //除去待签名参数数组中的空值和签名参数 120 | $para_filter = paraFilter($para_temp); 121 | 122 | //对待签名参数数组排序 123 | $para_sort = argSort($para_filter); 124 | 125 | //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 126 | $prestr = createLinkString($para_sort); 127 | 128 | switch (strtoupper(trim($this->alipay_config['sign_type']))) { 129 | case "MD5" : 130 | $isSgin = md5Verify($prestr, $sign, $this->alipay_config['key']); 131 | break; 132 | default : 133 | $isSgin = false; 134 | } 135 | 136 | return $isSgin; 137 | } 138 | 139 | /** 140 | * 获取远程服务器ATN结果,验证返回URL 141 | * @param string $notify_id 通知校验ID 142 | * @return mixed 服务器ATN结果 143 | * 验证结果集: 144 | * invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空 145 | * true 返回正确信息 146 | * false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟 147 | */ 148 | function getResponse($notify_id) { 149 | $transport = strtolower(trim($this->alipay_config['transport'])); 150 | $partner = trim($this->alipay_config['partner']); 151 | if($transport == 'https') { 152 | $veryfy_url = $this->https_verify_url; 153 | } 154 | else { 155 | $veryfy_url = $this->http_verify_url; 156 | } 157 | $veryfy_url = $veryfy_url."partner=" . $partner . "¬ify_id=" . $notify_id; 158 | // var_dump($veryfy_url); 159 | $responseTxt = getHttpResponseGET($veryfy_url, $this->alipay_config['cacert']); 160 | 161 | 162 | return $responseTxt; 163 | } 164 | } 165 | ?> 166 | -------------------------------------------------------------------------------- /Pay/Alipay/sdk/alipay_submit.class.php: -------------------------------------------------------------------------------- 1 | alipay_config = $alipay_config; 26 | } 27 | 28 | function AlipaySubmit($alipay_config) 29 | { 30 | $this->__construct($alipay_config); 31 | } 32 | 33 | /** 34 | * 生成签名结果 35 | * @param array $para_sort 已排序要签名的数组 36 | * @return string 签名结果字符串 37 | */ 38 | function buildRequestMysign($para_sort) 39 | { 40 | //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 41 | $prestr = createLinkString($para_sort); 42 | 43 | switch (strtoupper(trim($this->alipay_config['sign_type']))) { 44 | case 'MD5' : 45 | $mysign = md5Sign($prestr, $this->alipay_config['key']); 46 | break; 47 | default : 48 | $mysign = ''; 49 | } 50 | 51 | return $mysign; 52 | } 53 | 54 | /** 55 | * 生成要请求给支付宝的参数数组 56 | * @param array $para_temp 请求前的参数数组 57 | * @return array 要请求的参数数组 58 | */ 59 | function buildRequestPara($para_temp) 60 | { 61 | //除去待签名参数数组中的空值和签名参数 62 | $para_filter = paraFilter($para_temp); 63 | 64 | //对待签名参数数组排序 65 | $para_sort = argSort($para_filter); 66 | 67 | //生成签名结果 68 | $mysign = $this->buildRequestMysign($para_sort); 69 | 70 | //签名结果与签名方式加入请求提交参数组中 71 | $para_sort['sign'] = $mysign; 72 | $para_sort['sign_type'] = strtoupper(trim($this->alipay_config['sign_type'])); 73 | 74 | return $para_sort; 75 | } 76 | 77 | /** 78 | * 生成要请求给支付宝的参数数组 79 | * @param array $para_temp 请求前的参数数组 80 | * @return string 要请求的参数数组字符串 81 | */ 82 | function buildRequestParaToString($para_temp) 83 | { 84 | //待请求参数数组 85 | $para = $this->buildRequestPara($para_temp); 86 | 87 | //把参数组中所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串做urlencode编码 88 | $request_data = createLinkStringUrlEncode($para); 89 | 90 | return $request_data; 91 | } 92 | 93 | /** 94 | * 建立请求,以表单HTML形式构造(默认) 95 | * @param array $para_temp 请求参数数组 96 | * @param string $method 提交方式。两个值可选:post、get 97 | * @param string $button_name 确认按钮显示文字 98 | * @return string 提交表单HTML文本 99 | */ 100 | function buildRequestForm($para_temp, $method, $button_name) 101 | { 102 | //待请求参数数组 103 | $para = $this->buildRequestPara($para_temp); 104 | 105 | $sHtml = "
"; 106 | foreach ($para as $key => $val) { 107 | $sHtml .= ""; 108 | } 109 | 110 | //submit按钮控件请不要含有name属性 111 | $sHtml = $sHtml . "
"; 112 | 113 | $sHtml = $sHtml . ""; 114 | 115 | return $sHtml; 116 | } 117 | 118 | 119 | /** 120 | * 用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数 121 | * 注意:该功能PHP5环境及以上支持,因此必须服务器、本地电脑中装有支持DOMDocument、SSL的PHP配置环境。建议本地调试时使用PHP开发软件 122 | * return 时间戳字符串 123 | */ 124 | function query_timestamp() 125 | { 126 | $url = $this->alipay_gateway_new . 'service=query_timestamp&partner=' . trim(strtolower($this->alipay_config['partner'])) . '&_input_charset=' . trim(strtolower($this->alipay_config['input_charset'])); 127 | 128 | $doc = new DOMDocument(); 129 | $doc->load($url); 130 | $itemEncrypt_key = $doc->getElementsByTagName('encrypt_key'); 131 | $encrypt_key = $itemEncrypt_key->item(0)->nodeValue; 132 | 133 | return $encrypt_key; 134 | } 135 | } 136 | 137 | ?> -------------------------------------------------------------------------------- /Pay/ApiInterface.php: -------------------------------------------------------------------------------- 1 | 35 | * $config['isNotify'] = true 则为支付成功后后台通知消息
36 | * $config['out_trade_no'] = 'xx' 则可能为二维码查询页面异步查询
37 | * 其余由情况为 支付成功后前台回调 38 | * @param array $config 支付渠道配置 39 | * @param callable $successCallback 成功回调 (系统单号,交易金额/分,支付渠道单号) 40 | * @return true|string true 验证通过 string 失败原因 41 | */ 42 | function verify($config, $successCallback); 43 | 44 | /** 45 | * 退款操作 46 | * @param array $config 支付渠道配置 47 | * @param string $order_no 订单号 48 | * @param string $pay_trade_no 支付渠道流水号 49 | * @param int $amount_cent 金额/分 50 | * @return true|string true 退款成功 string 失败原因 51 | * @throws \Throwable 52 | */ 53 | function refund($config, $order_no, $pay_trade_no, $amount_cent); 54 | 55 | } -------------------------------------------------------------------------------- /Pay/BTC/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 24 | $this->url_return = SYS_URL . '/pay/return/' . $id; 25 | } 26 | 27 | /** 28 | * @param array $config 29 | * @param string $out_trade_no 30 | * @param string $subject 31 | * @param string $body 32 | * @param int $amount_cent 33 | * @throws \Exception 34 | */ 35 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 36 | { 37 | $amount_btc = CurlRequest::get('https://api.blockchain.info/tobtc?currency=CNY&value=' . 38 | sprintf('%.2f', $amount_cent / 100)); 39 | if (!$amount_btc) { 40 | Log::error('Pay.BTC.goPay, get price error:' . @$amount_btc); 41 | throw new \Exception('获取BTC价格失败,请联系客服'); 42 | } 43 | 44 | $address_raw = CurlRequest::get('https://api.blockchain.info/v2/receive?xpub=' . $config['xpub'] . 45 | '&callback=' . urlencode($this->url_notify . '?secret=' . $config['secret']) . 46 | '&key=' . $config['key']); 47 | $receive = @json_decode($address_raw, true); 48 | if (!$receive || !isset($receive['address'])) { 49 | if($receive['description'] === 'Gap between last used address and next address too large. This might make funds inaccessible.') { 50 | throw new \Exception('钱包地址到达限制, 请等待之前的用户完成付款'); 51 | } 52 | Log::error('Pay.BTC.goPay, get address error:' . @$address_raw); 53 | throw new \Exception('获取BTC地址失败,请联系客服'); 54 | } 55 | 56 | // 小数点后8位 57 | $code_url = 'bitcoin:' . $receive['address'] . '?amount=' . $amount_btc; 58 | 59 | // 这个地址是唯一的 60 | if (\App\Order::wherePayTradeNo($code_url)->exists()) { 61 | throw new \Exception('支付失败, 当前钱包地址重复'); 62 | } 63 | 64 | \App\Order::whereOrderNo($out_trade_no)->update(['pay_trade_no' => $code_url]); 65 | 66 | header('location: /qrcode/pay/' . $out_trade_no . '/btc?url=' . urlencode(json_encode([ 67 | 'address' => $receive['address'], 68 | 'amount' => $amount_btc 69 | ]))); 70 | exit; 71 | } 72 | 73 | /** 74 | * @param $config 75 | * @param callable $successCallback 76 | * @return bool|string 77 | * @throws \Exception 78 | */ 79 | function verify($config, $successCallback) 80 | { 81 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 82 | 83 | if ($isNotify) { 84 | if (@$_GET['secret'] !== $config['secret']) { 85 | echo 'error'; 86 | return false; 87 | } 88 | 89 | if (isset($_GET['confirmations'])) { 90 | $address = $_GET['address']; 91 | $code_url = 'bitcoin:' . $address . '?amount=' . rtrim(rtrim(sprintf('%.8f', $_GET['value'] / 1e8), '0'), '.'); 92 | $order = \App\Order::wherePayTradeNo($code_url)->first(); 93 | if (!$order) { 94 | echo 'error'; 95 | Log::error('Pay.BTC.verify, cannot find order:' . json_encode([ 96 | 'url' => $code_url, 97 | 'params' => $_GET, 98 | ])); 99 | return false; 100 | } 101 | $pay_trade_no = $code_url; //支付地址 作为支付流水号储存 102 | $successCallback($order->order_no, $order->paid, $pay_trade_no); 103 | } 104 | 105 | echo '*ok*'; 106 | return true; 107 | } else { 108 | // 此驱动, 不支持主动查询交易结果 109 | return false; 110 | } 111 | } 112 | 113 | /** 114 | * 退款操作 115 | * @param array $config 支付渠道配置 116 | * @param string $order_no 订单号 117 | * @param string $pay_trade_no 支付渠道流水号 118 | * @param int $amount_cent 金额/分 119 | * @return true|string true 退款成功 string 失败原因 120 | */ 121 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 122 | { 123 | return '此支付渠道不支持发起退款, 请手动操作'; 124 | } 125 | } -------------------------------------------------------------------------------- /Pay/CodePay/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 20 | $this->url_return = SYS_URL . '/pay/return/' . $id; 21 | } 22 | 23 | 24 | // payway: alipay qq weixin 25 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 26 | { 27 | $amount = sprintf('%.2f', $amount_cent / 100); //元为单位 28 | 29 | $codepay_id = $config['id'];//这里改成码支付ID 30 | $codepay_key = $config['key']; //这是您的通讯密钥 31 | 32 | 33 | switch ($config['payway']) { 34 | case 'alipay': 35 | $type = 1; 36 | break; 37 | case 'qq': 38 | $type = 2; 39 | break; 40 | case 'weixin': 41 | $type = 3; 42 | break; 43 | default: 44 | throw new \Exception('支付方式填写错误, alipay/qq/weixin'); 45 | } 46 | 47 | $data = array( 48 | 'id' => $codepay_id,//你的码支付ID 49 | 'pay_id' => $out_trade_no, //唯一标识 可以是用户ID,用户名,session_id(),订单ID,ip 付款后返回 50 | 'type' => $type, //1支付宝支付 3微信支付 2QQ钱包 51 | 'price' => $amount,//金额100元 52 | 'param' => '',//自定义参数 53 | 'notify_url' => $this->url_notify, 54 | 'return_url' => $this->url_return 55 | ); //构造需要传递的参数 56 | 57 | ksort($data); //重新排序$data数组= 58 | 59 | $sign = ''; //初始化需要签名的字符为空 60 | $urls = ''; //初始化URL参数为空 61 | 62 | foreach ($data AS $key => $val) { //遍历需要传递的参数 63 | if ($val == '' || $key == 'sign') continue; //跳过这些不参数签名 64 | if ($sign != '') { //后面追加&拼接URL 65 | $sign .= '&'; 66 | $urls .= '&'; 67 | } 68 | $sign .= "$key=$val"; //拼接为url参数形式 69 | $urls .= "$key=" . urlencode($val); //拼接为url参数形式并URL编码参数值 70 | } 71 | $query = $urls . '&sign=' . md5($sign . $codepay_key); //创建订单所需的参数 72 | 73 | // var_dump("加载中"); 74 | header('Location: http://api3.xiuxiu888.com/creat_order/?' . $query); //跳转到支付页面 75 | exit; 76 | } 77 | 78 | function verify($config, $successCallback) 79 | { 80 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 81 | 82 | $codepay_id = $config['id']; //这里改成码支付ID 83 | $codepay_key = $config['key']; //这是您的通讯密钥 84 | 85 | if (empty($_POST)) { //如果GET访问 86 | $_POST = $_GET; //POST访问 为服务器或软件异步通知 不需要返回HTML 87 | } 88 | ksort($_POST); //排序post参数 89 | reset($_POST); //内部指针指向数组中的第一个元素 90 | 91 | $sign = ''; //加密字符串初始化 92 | 93 | foreach ($_POST AS $key => $val) { 94 | if ($val == '' || $key == 'sign') continue; //跳过这些不签名 95 | if ($sign) $sign .= '&'; //第一个字符串签名不加& 其他加&连接起来参数 96 | $sign .= "$key=$val"; //拼接为url参数形式 97 | } 98 | 99 | // $price = (float)$_POST['price']; //订单的原价 100 | // $param = $_POST['param']; //自定义参数 101 | // $type = (int)$_POST['type']; //支付方式 102 | 103 | if (!isset($_POST['pay_no']) || md5($sign . $codepay_key) != $_POST['sign']) { //不合法的数据 104 | if ($isNotify) echo 'fail'; //返回失败 继续补单 105 | return false; 106 | } else { 107 | if (!isset($_POST['pay_id'])) { 108 | Log::error('Pay.CodePay.verify ERROR: there is no pay_id in $_POST: ' . json_encode($_POST)); 109 | if ($isNotify) echo 'fail'; //返回失败 继续补单 110 | return false; 111 | } 112 | 113 | // price 提交订单的金额 114 | // money 实际付款的金额, 码支付用于区分不同订单而设立的规则 115 | 116 | $out_trade_no = $_POST['pay_id']; //需要充值的ID 或订单号 或用户名 117 | $total_fee = (int)round($_POST['price'] * 100); 118 | $trade_no = $_POST['pay_no']; //流水号 119 | $successCallback($out_trade_no, $total_fee, $trade_no); 120 | 121 | if ($isNotify) echo 'success'; 122 | return true; 123 | } 124 | } 125 | 126 | /** 127 | * 退款操作 128 | * @param array $config 支付渠道配置 129 | * @param string $order_no 订单号 130 | * @param string $pay_trade_no 支付渠道流水号 131 | * @param int $amount_cent 金额/分 132 | * @return true|string true 退款成功 string 失败原因 133 | */ 134 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 135 | { 136 | return '此支付渠道不支持发起退款, 请手动操作'; 137 | } 138 | } -------------------------------------------------------------------------------- /Pay/Demo/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 22 | $this->url_return = SYS_URL . '/pay/return/' . $id; 23 | } 24 | 25 | /** 26 | * @param array $config 27 | * @param string $out_trade_no 28 | * @param string $subject 29 | * @param string $body 30 | * @param int $amount_cent 31 | * @throws \Exception 32 | */ 33 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 34 | { 35 | // 等5秒后直接跳到支付结果页面 36 | sleep(5); 37 | header('Location:' . $this->url_return 38 | . '?out_trade_no=' . $out_trade_no 39 | . '&total_fee=' . sprintf('%.2f', $amount_cent / 100) 40 | . '&transaction_id=' . date('YmdHis') 41 | ); 42 | exit; 43 | } 44 | 45 | /** 46 | * @param $config 47 | * @param callable $successCallback 48 | * @return bool|string 49 | * @throws \Exception 50 | */ 51 | function verify($config, $successCallback) 52 | { 53 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 54 | if ($isNotify) { 55 | // 没有这一步 56 | } else { 57 | // 直接支付成功 58 | 59 | // 用于payReturn支付返回页面第二种情况(传递了out_trade_no), 或者重新发起支付之前检查一下, 或者二维码支付页面主动请求 60 | // 主动查询交易结果 61 | if (!empty($config['out_trade_no'])) { 62 | $order_no = @$config['out_trade_no']; //商户订单号 63 | 64 | // 进行一些查询逻辑 65 | $check_ret = [ 66 | 'code' => 0, 67 | 'total_fee' => sprintf('%.2f', \App\Order::whereOrderNo($order_no)->first()->paid / 100), // 元为单位 68 | 'transaction_id' => date('YmdHis') 69 | ]; 70 | 71 | // 如果检查通过 72 | if (@$check_ret['code'] === 0) { 73 | $total_fee = (int)round((float)$check_ret['total_fee'] * 100); 74 | $pay_trade_no = $check_ret['transaction_id']; //支付流水号 75 | $successCallback($order_no, $total_fee, $pay_trade_no); 76 | return true; 77 | } 78 | return false; 79 | } 80 | 81 | 82 | // 这里可能是payReturn支付返回页面的第一种情况, 支付成功后直接返回, config里面没有out_trade_no 83 | // 这里的URL, $_GET 里面可能有订单参数用于校验订单是否成功(参考支付宝的AliAop逻辑) 84 | if (1) { // 进行一些校验逻辑, 如果检查通过 85 | $order_no = $_REQUEST['out_trade_no']; // 本系统内订单号 86 | $total_fee = (int)round((float)$_REQUEST['total_fee'] * 100); 87 | $pay_trade_no = $_REQUEST['transaction_id']; //支付流水号 88 | $successCallback($order_no, $total_fee, $pay_trade_no); 89 | return true; 90 | } 91 | 92 | return false; 93 | } 94 | return false; 95 | } 96 | 97 | /** 98 | * 退款操作 99 | * @param array $config 支付渠道配置 100 | * @param string $order_no 订单号 101 | * @param string $pay_trade_no 支付渠道流水号 102 | * @param int $amount_cent 金额/分 103 | * @return true|string true 退款成功 string 失败原因 104 | */ 105 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 106 | { 107 | // 直接成功, 用于测试 108 | return true; 109 | } 110 | } -------------------------------------------------------------------------------- /Pay/Demo/README.md: -------------------------------------------------------------------------------- 1 | 2 | 测试用的支付方式, 会直接跳转到支付成功页面 -------------------------------------------------------------------------------- /Pay/DirectAlipay/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## 说明 3 | 4 | 此支付方式采用官方直清方式, 由支付宝/微信直接结算给个人, 订单金额不会计入商户余额, 每个商户需要后台独立进件开户。 5 | 6 | 手续费通过支付宝/微信官方额外的分账接口转到服务商账户中。 7 | 8 | 支付宝需要开通 [直付通](https://opendocs.alipay.com/open/00faww) 9 | 10 | 微信需要开通 [电商收付通](https://pay.weixin.qq.com/wiki/doc/apiv3_partner/open/pay/chapter3_3_0.shtml) 11 | 12 | ## 注意事项 13 | 1. 需要使用异步队列方式, 参考README.md中配置 `QUEUE_DRIVER=database` 或 `QUEUE_DRIVER=redis` 14 | 2. 支付宝直付通 常见问题详细参考: https://opendocs.alipay.com/open/direct-payment/bvxbhg 15 | 2. 微信电商收付通 常见问题详细参考: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/guide/chapter11_2.shtml 16 | 17 | ## 微信配置说明 18 | ### 驱动: DirectAlipay 19 | 20 | ### 支付方式支持 21 | - mobile: 支付宝手机端 (手机网站支付接口 2.0) (本接口PC端支持自动转为支付宝扫码支付) 22 | - pc: 支付宝PC端 23 | 24 | ### 配置JSON: 25 | 26 | 1. 参考 https://opendocs.alipay.com/open/direct-payment/incr1f 27 | 28 | 2. JSON所需参数如下: 29 | - user_id: 平台支付宝账号对应的支付宝唯一用户号,以2088开头的纯16位数字。 30 | - app_id: 后台应用appid 31 | - merchant_private_key: 商户私钥 32 | - alipay_public_key: 支付宝公钥 33 | -------------------------------------------------------------------------------- /Pay/DirectWeChat/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## 说明 3 | 4 | 此支付方式采用官方直清方式, 由支付宝/微信直接结算给个人, 订单金额不会计入商户余额, 每个商户需要后台独立进件开户。 5 | 6 | 手续费通过支付宝/微信官方额外的分账接口转到服务商账户中。 7 | 8 | 支付宝需要开通 [直付通](https://opendocs.alipay.com/open/00faww) 9 | 10 | 微信需要开通 [电商收付通](https://pay.weixin.qq.com/wiki/doc/apiv3_partner/open/pay/chapter3_3_0.shtml) 11 | 12 | ## 注意事项 13 | 1. 需要使用异步队列方式, 参考README.md中配置 `QUEUE_DRIVER=database` 或 `QUEUE_DRIVER=redis` 14 | 2. 支付宝直付通 常见问题详细参考: https://opendocs.alipay.com/open/direct-payment/bvxbhg 15 | 2. 微信电商收付通 常见问题详细参考: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/guide/chapter11_2.shtml 16 | 17 | ## 微信配置说明 18 | ### 驱动: DirectWeChat 19 | 20 | ### 支付方式支持 21 | - NATIVE: 微信Native (网页扫码) 22 | - JSAPI: 微信JSAPI (微信内, 公众号跳转) 23 | > 微信内置浏览器必须使用JSAPI, 扫码无法使用, 因此系统自动适配, 后台只填写NATIVE即可。 24 | > JSAPI方式需要公众号后台配置登录 redirect_uri。 25 | 26 | ### 配置JSON: 27 | 28 | 1. 微信参考 https://pay.weixin.qq.com/wiki/doc/apiv3_partner/open/pay/chapter3_3_1.shtml 29 | 30 | 2. JSON所需参数如下: 31 | - app_id: 服务商申请的公众号appid, 示例值:wx8888888888888888 32 | - app_secret: 服务商申请的公众号secret, 示例值:****** 33 | - merchant_id: 获取微信服务商ID, 示例值:1230000109 34 | - api_key: APIv3 密钥 35 | - cert_serial: 第一步获取的商户API证书序列号 36 | - cert_private_key: 第一步获取的 apiclient_key.pem 用记事本打开删掉第一行和最后一行, 剩余内容删除换行符 37 | -------------------------------------------------------------------------------- /Pay/ECPay/README.md: -------------------------------------------------------------------------------- 1 | ## 綠界科技 全方位(All In One)金流介接 PHP版 2 | 3 | ### 1. 介紹 4 | 5 | * 綠界科技對於有收款需求的會員,提供完整的交易介接API,並有多種收款方式(All In One)可選擇使用。 6 | 本套件為PHP版,可使用作建立訂單,接受付款通知,查詢訂單等金流交易的應用。 7 | * 收款方式清單: 8 | * 信用卡(一次付清、分期付款、定期定額) 9 | * 網路ATM 10 | * ATM櫃員機 11 | * 超商代碼 12 | * 超商條碼 13 | * Google Pay (須特別申請才能使用)(原Android Pay) 14 | 15 | ### 2. 安裝環境 16 | 17 | * PHP 5.3.0 以上 18 | 19 | ### 3. 使用教學 20 | 21 | * 請參考串接文件 https://www.ecpay.com.tw/Service/API_Dwnld 22 | 23 | ### 4. 聯絡我們 24 | 25 | * 綠界科技 技術客服信箱:techsupport@ecpay.com.tw 26 | 27 | 28 | -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_ATM_CreateOrder.php: -------------------------------------------------------------------------------- 1 | ServiceURL = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5"; //服務位置 14 | $obj->HashKey = '5294y06JbISpM5x9' ; //測試用Hashkey,請自行帶入ECPay提供的HashKey 15 | $obj->HashIV = 'v77hoKGq4kWxNNIS' ; //測試用HashIV,請自行帶入ECPay提供的HashIV 16 | $obj->MerchantID = '2000132'; //測試用MerchantID,請自行帶入ECPay提供的MerchantID 17 | $obj->EncryptType = '1'; //CheckMacValue加密類型,請固定填入1,使用SHA256加密 18 | 19 | 20 | //基本參數(請依系統規劃自行調整) 21 | $MerchantTradeNo = "Test".time() ; 22 | $obj->Send['ReturnURL'] = "http://www.ecpay.com.tw/receive.php" ; //付款完成通知回傳的網址 23 | $obj->Send['MerchantTradeNo'] = $MerchantTradeNo; //訂單編號 24 | $obj->Send['MerchantTradeDate'] = date('Y/m/d H:i:s'); //交易時間 25 | $obj->Send['TotalAmount'] = 2000; //交易金額 26 | $obj->Send['TradeDesc'] = "good to drink" ; //交易描述 27 | $obj->Send['ChoosePayment'] = ECPay_PaymentMethod::ATM ; //付款方式:ATM 28 | 29 | //訂單的商品資料 30 | array_push($obj->Send['Items'], array('Name' => "歐付寶黑芝麻豆漿", 'Price' => (int)"2000", 31 | 'Currency' => "元", 'Quantity' => (int) "1", 'URL' => "dedwed")); 32 | 33 | //ATM 延伸參數(可依系統需求選擇是否代入) 34 | $obj->SendExtend['ExpireDate'] = 3 ; //繳費期限 (預設3天,最長60天,最短1天) 35 | $obj->SendExtend['PaymentInfoURL'] = ""; //伺服器端回傳付款相關資訊。 36 | 37 | # 電子發票參數 38 | /* 39 | $obj->Send['InvoiceMark'] = ECPay_InvoiceState::Yes; 40 | $obj->SendExtend['RelateNumber'] = "Test".time(); 41 | $obj->SendExtend['CustomerEmail'] = 'test@ecpay.com.tw'; 42 | $obj->SendExtend['CustomerPhone'] = '0911222333'; 43 | $obj->SendExtend['TaxType'] = ECPay_TaxType::Dutiable; 44 | $obj->SendExtend['CustomerAddr'] = '台北市南港區三重路19-2號5樓D棟'; 45 | $obj->SendExtend['InvoiceItems'] = array(); 46 | // 將商品加入電子發票商品列表陣列 47 | foreach ($obj->Send['Items'] as $info) 48 | { 49 | array_push($obj->SendExtend['InvoiceItems'],array('Name' => $info['Name'],'Count' => 50 | $info['Quantity'],'Word' => '個','Price' => $info['Price'],'TaxType' => ECPay_TaxType::Dutiable)); 51 | } 52 | $obj->SendExtend['InvoiceRemark'] = '測試發票備註'; 53 | $obj->SendExtend['DelayDay'] = '0'; 54 | $obj->SendExtend['InvType'] = ECPay_InvType::General; 55 | */ 56 | 57 | 58 | //產生訂單(auto submit至ECPay) 59 | $html = $obj->CheckOut(); 60 | echo $html; 61 | 62 | } catch (Exception $e) { 63 | echo $e->getMessage(); 64 | } 65 | 66 | 67 | 68 | ?> -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_All_CreateOrder.php: -------------------------------------------------------------------------------- 1 | ServiceURL = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5"; //服務位置 14 | $obj->HashKey = '5294y06JbISpM5x9' ; //測試用Hashkey,請自行帶入ECPay提供的HashKey 15 | $obj->HashIV = 'v77hoKGq4kWxNNIS' ; //測試用HashIV,請自行帶入ECPay提供的HashIV 16 | $obj->MerchantID = '2000132'; //測試用MerchantID,請自行帶入ECPay提供的MerchantID 17 | $obj->EncryptType = '1'; //CheckMacValue加密類型,請固定填入1,使用SHA256加密 18 | 19 | 20 | //基本參數(請依系統規劃自行調整) 21 | $MerchantTradeNo = "Test".time() ; 22 | $obj->Send['ReturnURL'] = "http://www.ecpay.com.tw/receive.php" ; //付款完成通知回傳的網址 23 | $obj->Send['MerchantTradeNo'] = $MerchantTradeNo; //訂單編號 24 | $obj->Send['MerchantTradeDate'] = date('Y/m/d H:i:s'); //交易時間 25 | $obj->Send['TotalAmount'] = 2000; //交易金額 26 | $obj->Send['TradeDesc'] = "good to drink" ; //交易描述 27 | $obj->Send['ChoosePayment'] = ECPay_PaymentMethod::ALL ; //付款方式:全功能 28 | 29 | //訂單的商品資料 30 | array_push($obj->Send['Items'], array('Name' => "歐付寶黑芝麻豆漿", 'Price' => (int)"2000", 31 | 'Currency' => "元", 'Quantity' => (int) "1", 'URL' => "dedwed")); 32 | 33 | # 電子發票參數 34 | /* 35 | $obj->Send['InvoiceMark'] = ECPay_InvoiceState::Yes; 36 | $obj->SendExtend['RelateNumber'] = "Test".time(); 37 | $obj->SendExtend['CustomerEmail'] = 'test@ecpay.com.tw'; 38 | $obj->SendExtend['CustomerPhone'] = '0911222333'; 39 | $obj->SendExtend['TaxType'] = ECPay_TaxType::Dutiable; 40 | $obj->SendExtend['CustomerAddr'] = '台北市南港區三重路19-2號5樓D棟'; 41 | $obj->SendExtend['InvoiceItems'] = array(); 42 | // 將商品加入電子發票商品列表陣列 43 | foreach ($obj->Send['Items'] as $info) 44 | { 45 | array_push($obj->SendExtend['InvoiceItems'],array('Name' => $info['Name'],'Count' => 46 | $info['Quantity'],'Word' => '個','Price' => $info['Price'],'TaxType' => ECPay_TaxType::Dutiable)); 47 | } 48 | $obj->SendExtend['InvoiceRemark'] = '測試發票備註'; 49 | $obj->SendExtend['DelayDay'] = '0'; 50 | $obj->SendExtend['InvType'] = ECPay_InvType::General; 51 | */ 52 | 53 | 54 | //產生訂單(auto submit至ECPay) 55 | $obj->CheckOut(); 56 | 57 | 58 | 59 | } catch (Exception $e) { 60 | echo $e->getMessage(); 61 | } 62 | 63 | 64 | 65 | ?> -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_AndroidPay_CreateOrder.php: -------------------------------------------------------------------------------- 1 | ServiceURL = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5"; //服務位置 14 | $obj->HashKey = '5294y06JbISpM5x9' ; //測試用Hashkey,請自行帶入ECPay提供的HashKey 15 | $obj->HashIV = 'v77hoKGq4kWxNNIS' ; //測試用HashIV,請自行帶入ECPay提供的HashIV 16 | $obj->MerchantID = '2000132'; //測試用MerchantID,請自行帶入ECPay提供的MerchantID 17 | $obj->EncryptType = '1'; //CheckMacValue加密類型,請固定填入1,使用SHA256加密 18 | 19 | 20 | //基本參數(請依系統規劃自行調整) 21 | $MerchantTradeNo = "Test".time() ; 22 | $obj->Send['ReturnURL'] = "http://www.ecpay.com.tw/receive.php" ; //付款完成通知回傳的網址 23 | $obj->Send['MerchantTradeNo'] = $MerchantTradeNo; //訂單編號 24 | $obj->Send['MerchantTradeDate'] = date('Y/m/d H:i:s'); //交易時間 25 | $obj->Send['TotalAmount'] = 2000; //交易金額 26 | $obj->Send['TradeDesc'] = "good to drink" ; //交易描述 27 | $obj->Send['ChoosePayment'] = ECPay_PaymentMethod::AndroidPay ; //付款方式:GooglePay 28 | 29 | //訂單的商品資料 30 | array_push($obj->Send['Items'], array('Name' => "歐付寶黑芝麻豆漿", 'Price' => (int)"2000", 31 | 'Currency' => "元", 'Quantity' => (int) "1", 'URL' => "dedwed")); 32 | 33 | # 電子發票參數 34 | /* 35 | $obj->Send['InvoiceMark'] = ECPay_InvoiceState::Yes; 36 | $obj->SendExtend['RelateNumber'] = "Test".time(); 37 | $obj->SendExtend['CustomerEmail'] = 'test@ecpay.com.tw'; 38 | $obj->SendExtend['CustomerPhone'] = '0911222333'; 39 | $obj->SendExtend['TaxType'] = ECPay_TaxType::Dutiable; 40 | $obj->SendExtend['CustomerAddr'] = '台北市南港區三重路19-2號5樓D棟'; 41 | $obj->SendExtend['InvoiceItems'] = array(); 42 | // 將商品加入電子發票商品列表陣列 43 | foreach ($obj->Send['Items'] as $info) 44 | { 45 | array_push($obj->SendExtend['InvoiceItems'],array('Name' => $info['Name'],'Count' => 46 | $info['Quantity'],'Word' => '個','Price' => $info['Price'],'TaxType' => ECPay_TaxType::Dutiable)); 47 | } 48 | $obj->SendExtend['InvoiceRemark'] = '測試發票備註'; 49 | $obj->SendExtend['DelayDay'] = '0'; 50 | $obj->SendExtend['InvType'] = ECPay_InvType::General; 51 | */ 52 | 53 | 54 | //產生訂單(auto submit至ECPay) 55 | $obj->CheckOut(); 56 | 57 | 58 | 59 | } catch (Exception $e) { 60 | echo $e->getMessage(); 61 | } 62 | 63 | 64 | 65 | ?> -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_BARCODE_CreateOrder.php: -------------------------------------------------------------------------------- 1 | ServiceURL = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5"; //服務位置 14 | $obj->HashKey = '5294y06JbISpM5x9' ; //測試用Hashkey,請自行帶入ECPay提供的HashKey 15 | $obj->HashIV = 'v77hoKGq4kWxNNIS' ; //測試用HashIV,請自行帶入ECPay提供的HashIV 16 | $obj->MerchantID = '2000132'; //測試用MerchantID,請自行帶入ECPay提供的MerchantID 17 | $obj->EncryptType = '1'; //CheckMacValue加密類型,請固定填入1,使用SHA256加密 18 | 19 | 20 | //基本參數(請依系統規劃自行調整) 21 | $MerchantTradeNo = "Test".time() ; 22 | $obj->Send['ReturnURL'] = "http://www.ecpay.com.tw/receive.php" ; //付款完成通知回傳的網址 23 | $obj->Send['MerchantTradeNo'] = $MerchantTradeNo; //訂單編號 24 | $obj->Send['MerchantTradeDate'] = date('Y/m/d H:i:s'); //交易時間 25 | $obj->Send['TotalAmount'] = 2000; //交易金額 26 | $obj->Send['TradeDesc'] = "good to drink" ; //交易描述 27 | $obj->Send['ChoosePayment'] = ECPay_PaymentMethod::BARCODE ; //付款方式:BARCODE超商代碼 28 | 29 | //訂單的商品資料 30 | array_push($obj->Send['Items'], array('Name' => "歐付寶黑芝麻豆漿", 'Price' => (int)"2000", 31 | 'Currency' => "元", 'Quantity' => (int) "1", 'URL' => "dedwed")); 32 | 33 | 34 | //BARCODE超商條碼延伸參數(可依系統需求選擇是否代入) 35 | $obj->SendExtend['Desc_1'] = ''; //交易描述1 會顯示在超商繳費平台的螢幕上。預設空值 36 | $obj->SendExtend['Desc_2'] = ''; //交易描述2 會顯示在超商繳費平台的螢幕上。預設空值 37 | $obj->SendExtend['Desc_3'] = ''; //交易描述3 會顯示在超商繳費平台的螢幕上。預設空值 38 | $obj->SendExtend['Desc_4'] = ''; //交易描述4 會顯示在超商繳費平台的螢幕上。預設空值 39 | $obj->SendExtend['PaymentInfoURL'] = ''; //預設空值 40 | $obj->SendExtend['ClientRedirectURL'] = ''; //預設空值 41 | $obj->SendExtend['StoreExpireDate'] = ''; //預設空值 42 | 43 | # 電子發票參數 44 | /* 45 | $obj->Send['InvoiceMark'] = ECPay_InvoiceState::Yes; 46 | $obj->SendExtend['RelateNumber'] = "Test".time(); 47 | $obj->SendExtend['CustomerEmail'] = 'test@ecpay.com.tw'; 48 | $obj->SendExtend['CustomerPhone'] = '0911222333'; 49 | $obj->SendExtend['TaxType'] = ECPay_TaxType::Dutiable; 50 | $obj->SendExtend['CustomerAddr'] = '台北市南港區三重路19-2號5樓D棟'; 51 | $obj->SendExtend['InvoiceItems'] = array(); 52 | // 將商品加入電子發票商品列表陣列 53 | foreach ($obj->Send['Items'] as $info) 54 | { 55 | array_push($obj->SendExtend['InvoiceItems'],array('Name' => $info['Name'],'Count' => 56 | $info['Quantity'],'Word' => '個','Price' => $info['Price'],'TaxType' => ECPay_TaxType::Dutiable)); 57 | } 58 | $obj->SendExtend['InvoiceRemark'] = '測試發票備註'; 59 | $obj->SendExtend['DelayDay'] = '0'; 60 | $obj->SendExtend['InvType'] = ECPay_InvType::General; 61 | */ 62 | 63 | 64 | //產生訂單(auto submit至ECPay) 65 | $obj->CheckOut(); 66 | 67 | 68 | } catch (Exception $e) { 69 | echo $e->getMessage(); 70 | } 71 | 72 | 73 | 74 | ?> -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_CVS_CreateOrder.php: -------------------------------------------------------------------------------- 1 | ServiceURL = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5"; //服務位置 14 | $obj->HashKey = '5294y06JbISpM5x9' ; //測試用Hashkey,請自行帶入ECPay提供的HashKey 15 | $obj->HashIV = 'v77hoKGq4kWxNNIS' ; //測試用HashIV,請自行帶入ECPay提供的HashIV 16 | $obj->MerchantID = '2000132'; //測試用MerchantID,請自行帶入ECPay提供的MerchantID 17 | $obj->EncryptType = '1'; //CheckMacValue加密類型,請固定填入1,使用SHA256加密 18 | 19 | 20 | //基本參數(請依系統規劃自行調整) 21 | $MerchantTradeNo = "Test".time() ; 22 | $obj->Send['ReturnURL'] = "http://www.ecpay.com.tw/receive.php" ; //付款完成通知回傳的網址 23 | $obj->Send['MerchantTradeNo'] = $MerchantTradeNo; //訂單編號 24 | $obj->Send['MerchantTradeDate'] = date('Y/m/d H:i:s'); //交易時間 25 | $obj->Send['TotalAmount'] = 2000; //交易金額 26 | $obj->Send['TradeDesc'] = "good to drink" ; //交易描述 27 | $obj->Send['ChoosePayment'] = ECPay_PaymentMethod::CVS ; //付款方式:CVS超商代碼 28 | 29 | //訂單的商品資料 30 | array_push($obj->Send['Items'], array('Name' => "歐付寶黑芝麻豆漿", 'Price' => (int)"2000", 31 | 'Currency' => "元", 'Quantity' => (int) "1", 'URL' => "dedwed")); 32 | 33 | 34 | //CVS超商代碼延伸參數(可依系統需求選擇是否代入) 35 | $obj->SendExtend['Desc_1'] = ''; //交易描述1 會顯示在超商繳費平台的螢幕上。預設空值 36 | $obj->SendExtend['Desc_2'] = ''; //交易描述2 會顯示在超商繳費平台的螢幕上。預設空值 37 | $obj->SendExtend['Desc_3'] = ''; //交易描述3 會顯示在超商繳費平台的螢幕上。預設空值 38 | $obj->SendExtend['Desc_4'] = ''; //交易描述4 會顯示在超商繳費平台的螢幕上。預設空值 39 | $obj->SendExtend['PaymentInfoURL'] = ''; //預設空值 40 | $obj->SendExtend['ClientRedirectURL'] = ''; //預設空值 41 | $obj->SendExtend['StoreExpireDate'] = ''; //預設空值 42 | 43 | 44 | # 電子發票參數 45 | /* 46 | $obj->Send['InvoiceMark'] = ECPay_InvoiceState::Yes; 47 | $obj->SendExtend['RelateNumber'] = "Test".time(); 48 | $obj->SendExtend['CustomerEmail'] = 'test@ecpay.com.tw'; 49 | $obj->SendExtend['CustomerPhone'] = '0911222333'; 50 | $obj->SendExtend['TaxType'] = ECPay_TaxType::Dutiable; 51 | $obj->SendExtend['CustomerAddr'] = '台北市南港區三重路19-2號5樓D棟'; 52 | $obj->SendExtend['InvoiceItems'] = array(); 53 | // 將商品加入電子發票商品列表陣列 54 | foreach ($obj->Send['Items'] as $info) 55 | { 56 | array_push($obj->SendExtend['InvoiceItems'],array('Name' => $info['Name'],'Count' => 57 | $info['Quantity'],'Word' => '個','Price' => $info['Price'],'TaxType' => ECPay_TaxType::Dutiable)); 58 | } 59 | $obj->SendExtend['InvoiceRemark'] = '測試發票備註'; 60 | $obj->SendExtend['DelayDay'] = '0'; 61 | $obj->SendExtend['InvType'] = ECPay_InvType::General; 62 | */ 63 | 64 | 65 | //產生訂單(auto submit至ECPay) 66 | $obj->CheckOut(); 67 | 68 | 69 | } catch (Exception $e) { 70 | echo $e->getMessage(); 71 | } 72 | 73 | 74 | 75 | ?> -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_Credit_CreateOrder.php: -------------------------------------------------------------------------------- 1 | ServiceURL = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5"; //服務位置 14 | $obj->HashKey = '5294y06JbISpM5x9' ; //測試用Hashkey,請自行帶入ECPay提供的HashKey 15 | $obj->HashIV = 'v77hoKGq4kWxNNIS' ; //測試用HashIV,請自行帶入ECPay提供的HashIV 16 | $obj->MerchantID = '2000132'; //測試用MerchantID,請自行帶入ECPay提供的MerchantID 17 | $obj->EncryptType = '1'; //CheckMacValue加密類型,請固定填入1,使用SHA256加密 18 | 19 | 20 | //基本參數(請依系統規劃自行調整) 21 | $MerchantTradeNo = "Test".time() ; 22 | $obj->Send['ReturnURL'] = "http://www.ecpay.com.tw/receive.php" ; //付款完成通知回傳的網址 23 | $obj->Send['MerchantTradeNo'] = $MerchantTradeNo; //訂單編號 24 | $obj->Send['MerchantTradeDate'] = date('Y/m/d H:i:s'); //交易時間 25 | $obj->Send['TotalAmount'] = 2000; //交易金額 26 | $obj->Send['TradeDesc'] = "good to drink" ; //交易描述 27 | $obj->Send['ChoosePayment'] = ECPay_PaymentMethod::Credit ; //付款方式:Credit 28 | $obj->Send['IgnorePayment'] = ECPay_PaymentMethod::GooglePay ; //不使用付款方式:GooglePay 29 | 30 | //訂單的商品資料 31 | array_push($obj->Send['Items'], array('Name' => "歐付寶黑芝麻豆漿", 'Price' => (int)"2000", 32 | 'Currency' => "元", 'Quantity' => (int) "1", 'URL' => "dedwed")); 33 | 34 | 35 | //Credit信用卡分期付款延伸參數(可依系統需求選擇是否代入) 36 | //以下參數不可以跟信用卡定期定額參數一起設定 37 | $obj->SendExtend['CreditInstallment'] = '' ; //分期期數,預設0(不分期),信用卡分期可用參數為:3,6,12,18,24 38 | $obj->SendExtend['InstallmentAmount'] = 0 ; //使用刷卡分期的付款金額,預設0(不分期) 39 | $obj->SendExtend['Redeem'] = false ; //是否使用紅利折抵,預設false 40 | $obj->SendExtend['UnionPay'] = false; //是否為聯營卡,預設false; 41 | 42 | //Credit信用卡定期定額付款延伸參數(可依系統需求選擇是否代入) 43 | //以下參數不可以跟信用卡分期付款參數一起設定 44 | // $obj->SendExtend['PeriodAmount'] = '' ; //每次授權金額,預設空字串 45 | // $obj->SendExtend['PeriodType'] = '' ; //週期種類,預設空字串 46 | // $obj->SendExtend['Frequency'] = '' ; //執行頻率,預設空字串 47 | // $obj->SendExtend['ExecTimes'] = '' ; //執行次數,預設空字串 48 | 49 | # 電子發票參數 50 | /* 51 | $obj->Send['InvoiceMark'] = ECPay_InvoiceState::Yes; 52 | $obj->SendExtend['RelateNumber'] = "Test".time(); 53 | $obj->SendExtend['CustomerEmail'] = 'test@ecpay.com.tw'; 54 | $obj->SendExtend['CustomerPhone'] = '0911222333'; 55 | $obj->SendExtend['TaxType'] = ECPay_TaxType::Dutiable; 56 | $obj->SendExtend['CustomerAddr'] = '台北市南港區三重路19-2號5樓D棟'; 57 | $obj->SendExtend['InvoiceItems'] = array(); 58 | // 將商品加入電子發票商品列表陣列 59 | foreach ($obj->Send['Items'] as $info) 60 | { 61 | array_push($obj->SendExtend['InvoiceItems'],array('Name' => $info['Name'],'Count' => 62 | $info['Quantity'],'Word' => '個','Price' => $info['Price'],'TaxType' => ECPay_TaxType::Dutiable)); 63 | } 64 | $obj->SendExtend['InvoiceRemark'] = '測試發票備註'; 65 | $obj->SendExtend['DelayDay'] = '0'; 66 | $obj->SendExtend['InvType'] = ECPay_InvType::General; 67 | */ 68 | 69 | 70 | //產生訂單(auto submit至ECPay) 71 | $obj->CheckOut(); 72 | 73 | 74 | } catch (Exception $e) { 75 | echo $e->getMessage(); 76 | } 77 | 78 | 79 | 80 | ?> -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_FundingReconDetail.php: -------------------------------------------------------------------------------- 1 | ServiceURL = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5"; //服務位置 15 | $obj->HashKey = '5294y06JbISpM5x9' ; //測試用Hashkey,請自行帶入ECPay提供的HashKey 16 | $obj->HashIV = 'v77hoKGq4kWxNNIS' ; //測試用HashIV,請自行帶入ECPay提供的HashIV 17 | $obj->MerchantID = '2000132'; //測試用MerchantID,請自行帶入ECPay提供的MerchantID 18 | $obj->EncryptType = '1'; //CheckMacValue加密類型,請固定填入1,使用SHA256加密 19 | 20 | 21 | //基本參數(請依系統規劃自行調整) 22 | 23 | $obj->Funding['PayDateType'] = 'close'; 24 | $obj->Funding['StartDate'] = '2017-09-01'; 25 | $obj->Funding['EndDate'] = '2017-12-31'; 26 | 27 | $result = $obj->FundingReconDetail(); 28 | echo $result ; 29 | file_put_contents('new.csv', $result); 30 | 31 | } catch (Exception $e) { 32 | echo $e->getMessage(); 33 | } 34 | 35 | ?> -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_GooglePay_CreateOrder.php: -------------------------------------------------------------------------------- 1 | ServiceURL = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5"; //服務位置 14 | $obj->HashKey = '5294y06JbISpM5x9' ; //測試用Hashkey,請自行帶入ECPay提供的HashKey 15 | $obj->HashIV = 'v77hoKGq4kWxNNIS' ; //測試用HashIV,請自行帶入ECPay提供的HashIV 16 | $obj->MerchantID = '2000132'; //測試用MerchantID,請自行帶入ECPay提供的MerchantID 17 | $obj->EncryptType = '1'; //CheckMacValue加密類型,請固定填入1,使用SHA256加密 18 | 19 | 20 | //基本參數(請依系統規劃自行調整) 21 | $MerchantTradeNo = "Test".time() ; 22 | $obj->Send['ReturnURL'] = "http://www.ecpay.com.tw/receive.php" ; //付款完成通知回傳的網址 23 | $obj->Send['MerchantTradeNo'] = $MerchantTradeNo; //訂單編號 24 | $obj->Send['MerchantTradeDate'] = date('Y/m/d H:i:s'); //交易時間 25 | $obj->Send['TotalAmount'] = 2000; //交易金額 26 | $obj->Send['TradeDesc'] = "good to drink" ; //交易描述 27 | $obj->Send['ChoosePayment'] = ECPay_PaymentMethod::GooglePay ; //付款方式:GooglePay 28 | 29 | //訂單的商品資料 30 | array_push($obj->Send['Items'], array('Name' => "歐付寶黑芝麻豆漿", 'Price' => (int)"2000", 31 | 'Currency' => "元", 'Quantity' => (int) "1", 'URL' => "dedwed")); 32 | 33 | # 電子發票參數 34 | /* 35 | $obj->Send['InvoiceMark'] = ECPay_InvoiceState::Yes; 36 | $obj->SendExtend['RelateNumber'] = "Test".time(); 37 | $obj->SendExtend['CustomerEmail'] = 'test@ecpay.com.tw'; 38 | $obj->SendExtend['CustomerPhone'] = '0911222333'; 39 | $obj->SendExtend['TaxType'] = ECPay_TaxType::Dutiable; 40 | $obj->SendExtend['CustomerAddr'] = '台北市南港區三重路19-2號5樓D棟'; 41 | $obj->SendExtend['InvoiceItems'] = array(); 42 | // 將商品加入電子發票商品列表陣列 43 | foreach ($obj->Send['Items'] as $info) 44 | { 45 | array_push($obj->SendExtend['InvoiceItems'],array('Name' => $info['Name'],'Count' => 46 | $info['Quantity'],'Word' => '個','Price' => $info['Price'],'TaxType' => ECPay_TaxType::Dutiable)); 47 | } 48 | $obj->SendExtend['InvoiceRemark'] = '測試發票備註'; 49 | $obj->SendExtend['DelayDay'] = '0'; 50 | $obj->SendExtend['InvType'] = ECPay_InvType::General; 51 | */ 52 | 53 | 54 | //產生訂單(auto submit至ECPay) 55 | $obj->CheckOut(); 56 | 57 | 58 | 59 | } catch (Exception $e) { 60 | echo $e->getMessage(); 61 | } 62 | 63 | 64 | 65 | ?> -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_QueryTradeInfo.php: -------------------------------------------------------------------------------- 1 | ServiceURL = "https://payment-stage.ecpay.com.tw/Cashier/QueryTradeInfo/V5"; //服務位置 14 | $obj->HashKey = '5294y06JbISpM5x9' ; //測試用Hashkey,請自行帶入ECPay提供的HashKey 15 | $obj->HashIV = 'v77hoKGq4kWxNNIS' ; //測試用HashIV,請自行帶入ECPay提供的HashIV 16 | $obj->MerchantID = '2000132'; //測試用MerchantID,請自行帶入ECPay提供的MerchantID 17 | $obj->EncryptType = '1'; //CheckMacValue加密類型,請固定填入1,使用SHA256加密 18 | 19 | //基本參數(請依系統規劃自行調整) 20 | $obj->Query['MerchantTradeNo'] = '2019091711192742'; 21 | $obj->Query['TimeStamp'] = time() ; 22 | 23 | //查詢訂單 24 | $info = $obj->QueryTradeInfo(); 25 | 26 | //顯示訂單資訊 27 | echo "
" . print_r($info, true) . "
"; 28 | 29 | } catch (Exception $e) { 30 | echo $e->getMessage(); 31 | } 32 | 33 | 34 | ?> -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_ServerReplyPaymentStatus.php: -------------------------------------------------------------------------------- 1 | MerchantID = '2000132'; 10 | $AL->HashKey = '5294y06JbISpM5x9'; 11 | $AL->HashIV = 'v77hoKGq4kWxNNIS'; 12 | // $AL->EncryptType = ECPay_EncryptType::ENC_MD5; // MD5 13 | $AL->EncryptType = ECPay_EncryptType::ENC_SHA256; // SHA256 14 | $feedback = $AL->CheckOutFeedback(); 15 | 16 | // 以付款結果訊息進行相對應的處理 17 | /** 18 | 回傳的綠界科技的付款結果訊息如下: 19 | Array 20 | ( 21 | [MerchantID] => 22 | [MerchantTradeNo] => 23 | [StoreID] => 24 | [RtnCode] => 25 | [RtnMsg] => 26 | [TradeNo] => 27 | [TradeAmt] => 28 | [PaymentDate] => 29 | [PaymentType] => 30 | [PaymentTypeChargeFee] => 31 | [TradeDate] => 32 | [SimulatePaid] => 33 | [CustomField1] => 34 | [CustomField2] => 35 | [CustomField3] => 36 | [CustomField4] => 37 | [CheckMacValue] => 38 | ) 39 | */ 40 | 41 | // 在網頁端回應 1|OK 42 | echo '1|OK'; 43 | } catch(Exception $e) { 44 | echo '0|' . $e->getMessage(); 45 | } -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_TradeNoAio.php: -------------------------------------------------------------------------------- 1 | ServiceURL = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5"; //服務位置 14 | $obj->HashKey = '5294y06JbISpM5x9' ; //測試用Hashkey,請自行帶入ECPay提供的HashKey 15 | $obj->HashIV = 'v77hoKGq4kWxNNIS' ; //測試用HashIV,請自行帶入ECPay提供的HashIV 16 | $obj->MerchantID = '2000132'; //測試用MerchantID,請自行帶入ECPay提供的MerchantID 17 | $obj->EncryptType = '1'; //CheckMacValue加密類型,請固定填入1,使用SHA256加密 18 | 19 | 20 | //基本參數(請依系統規劃自行調整) 21 | 22 | $obj->Send['DateType'] = $MerchantTradeNo; 23 | $obj->Send['BeginDate'] = date('Y/m/d H:i:s'); 24 | $obj->Send['EndDate'] = 2000; 25 | $obj->Send['MediaFormated'] = "good to drink" ; 26 | 27 | $obj->TradeNoAio(); 28 | 29 | } catch (Exception $e) { 30 | echo $e->getMessage(); 31 | } 32 | 33 | 34 | 35 | ?> -------------------------------------------------------------------------------- /Pay/ECPay/example/sample_WebATM_CreateOrder.php: -------------------------------------------------------------------------------- 1 | ServiceURL = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5"; //服務位置 14 | $obj->HashKey = '5294y06JbISpM5x9' ; //測試用Hashkey,請自行帶入ECPay提供的HashKey 15 | $obj->HashIV = 'v77hoKGq4kWxNNIS' ; //測試用HashIV,請自行帶入ECPay提供的HashIV 16 | $obj->MerchantID = '2000132'; //測試用MerchantID,請自行帶入ECPay提供的MerchantID 17 | $obj->EncryptType = '1'; //CheckMacValue加密類型,請固定填入1,使用SHA256加密 18 | 19 | 20 | //基本參數(請依系統規劃自行調整) 21 | $MerchantTradeNo = "Test".time() ; 22 | $obj->Send['ReturnURL'] = "http://www.ecpay.com.tw/receive.php" ; //付款完成通知回傳的網址 23 | $obj->Send['MerchantTradeNo'] = $MerchantTradeNo; //訂單編號 24 | $obj->Send['MerchantTradeDate'] = date('Y/m/d H:i:s'); //交易時間 25 | $obj->Send['TotalAmount'] = 2000; //交易金額 26 | $obj->Send['TradeDesc'] = "good to drink" ; //交易描述 27 | $obj->Send['ChoosePayment'] = ECPay_PaymentMethod::WebATM ; //付款方式:WebATM 28 | 29 | //訂單的商品資料 30 | array_push($obj->Send['Items'], array('Name' => "歐付寶黑芝麻豆漿", 'Price' => (int)"2000", 31 | 'Currency' => "元", 'Quantity' => (int) "1", 'URL' => "dedwed")); 32 | 33 | # 電子發票參數 34 | /* 35 | $obj->Send['InvoiceMark'] = ECPay_InvoiceState::Yes; 36 | $obj->SendExtend['RelateNumber'] = "Test".time(); 37 | $obj->SendExtend['CustomerEmail'] = 'test@ecpay.com.tw'; 38 | $obj->SendExtend['CustomerPhone'] = '0911222333'; 39 | $obj->SendExtend['TaxType'] = ECPay_TaxType::Dutiable; 40 | $obj->SendExtend['CustomerAddr'] = '台北市南港區三重路19-2號5樓D棟'; 41 | $obj->SendExtend['InvoiceItems'] = array(); 42 | // 將商品加入電子發票商品列表陣列 43 | foreach ($obj->Send['Items'] as $info) 44 | { 45 | array_push($obj->SendExtend['InvoiceItems'],array('Name' => $info['Name'],'Count' => 46 | $info['Quantity'],'Word' => '個','Price' => $info['Price'],'TaxType' => ECPay_TaxType::Dutiable)); 47 | } 48 | $obj->SendExtend['InvoiceRemark'] = '測試發票備註'; 49 | $obj->SendExtend['DelayDay'] = '0'; 50 | $obj->SendExtend['InvType'] = ECPay_InvType::General; 51 | */ 52 | 53 | //產生訂單(auto submit至ECPay) 54 | //$obj->CheckOut(); 55 | echo $obj->CheckOut(); 56 | 57 | 58 | } catch (Exception $e) { 59 | echo $e->getMessage(); 60 | } 61 | 62 | 63 | 64 | ?> -------------------------------------------------------------------------------- /Pay/EpUSDT/README.md: -------------------------------------------------------------------------------- 1 | # 发卡系统对接 epusdt 类 2 | 3 | 当前版本:`1.0.2` 4 | 5 | 作者:`Prk` 6 | 7 | 8 | ## 使用教程 9 | 10 | 将文件下载到如下目录:`/www/app/Library/Gateway/Pay/EpUSDT` 11 | 12 | (`/www` 为网站所在目录,你需要在 `/www/app/Library/Gateway/Pay` 新建一个名为 `EpUSDT` 的文件夹) 13 | 14 | ``` 15 | /www/app/Library/Gateway/Pay/EpUSDT 16 | ``` 17 | 18 | 文件地址:[https://github.com/Tai7sy/card-gateway/blob/master/Pay/EpUSDT/Api.php](https://github.com/Tai7sy/card-gateway/blob/master/Pay/EpUSDT/Api.php) 19 | 20 | 你也可以使用如下命令一键完成: 21 | 22 | ``` sh 23 | cd /www # 这里改成你网站的相对路径 24 | cd app/Library/Gateway/Pay/EpUSDT 25 | wget https://raw.githubusercontent.com/Tai7sy/card-gateway/master/Pay/EpUSDT/Api.php 26 | ``` 27 | 28 | 下载完成后打开网站后台,找到支付网关,请按照下述说明进行配置: 29 | 30 | ------ 31 | 32 | **名称**:_自己想一个就好_ 33 | 34 | **费率**:_根据需求设定费率_ 35 | 36 | 启用:**√**_你必须要启用才可以使用啊!_ 37 | 38 | **驱动**:`EpUSDT` 39 | 40 | **方式**:_随便写点什么_ 41 | 42 | 备注:_由自己喜好设定_ 43 | 44 | ------ 45 | 46 | 配置部分非常重要,先选择 JSON 然后复制如下内容粘贴进去后,回到 Parse 修改。 47 | 48 | (`gateway` 是支付网关地址,是你搭建 epusdt 的地址,`key` 是你在 epusdt 程序的环境变量中设置的对接密钥) 49 | 50 | ``` json 51 | { 52 | "gateway": "https://example.com", 53 | "key": "abcd1234" 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /Pay/Example/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 15 | $this->url_return = SYS_URL . '/pay/return/' . $id; 16 | } 17 | 18 | 19 | /** 20 | * 提交支付 21 | * @param array $config 支付渠道配置 22 | * @param string $order_no 本系统的订单号 23 | * @param string $subject 商品名称 24 | * @param string $body 商品介绍 25 | * @param int $amount_cent 金额/分 26 | */ 27 | function goPay($config, $order_no, $subject, $body, $amount_cent) 28 | { 29 | $payway = strtolower($config['payway']); 30 | // wechat qq alipay 31 | // 跳转支付页面 32 | header('Location: http://example.com/order?out_trade_no=' . $order_no . '&subject=' . $subject . '&total_fee=' . $amount_cent); 33 | exit; 34 | } 35 | 36 | /** 37 | * 验证支付是否成功
38 | * $config['isNotify'] = true 则为支付成功后后台通知消息
39 | * $config['out_trade_no'] = 'xx' 则可能为二维码查询页面异步查询
40 | * 其余由情况为 支付成功后前台回调 41 | * @param array $config 支付渠道配置 42 | * @param callable $successCallback 成功回调 (系统单号,交易金额/分,支付渠道单号) 43 | * @return true|string true 验证通过 string 失败原因 44 | */ 45 | function verify($config, $successCallback) 46 | { 47 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 48 | 49 | // 如果是异步通知 50 | if ($isNotify) { 51 | // 这里是支付后一步回调步骤 52 | // 在这里需要做一些校验(如签名校验等), 确保通知的合法性 53 | if (verify_notify()) { 54 | echo 'success'; 55 | $order_no = $_REQUEST['']; // 发卡系统内交易单号 56 | $total_fee = $_REQUEST['']; // 实际支付金额, 单位, 分 57 | $pay_trade_no = $_REQUEST['']; // 支付系统内订单号/流水号 58 | $successCallback($order_no, $total_fee, $pay_trade_no); // 成功后记得调用此函数处理订单 59 | return true; 60 | } else { 61 | \Log::error('这里可以记录一些出错信息, 内容保存在 /storage/logs 内'); 62 | echo 'error'; 63 | return false; 64 | } 65 | } 66 | 67 | 68 | // 这里传递了发卡系统内交易单号, 有两种可能来到此步骤 69 | // 1. 用户提交订单后未支付, 重新发起支付, 支付前需要校验是否已经支付 70 | // 2. 此支付方式支持二维码扫码等方式, 二维码页面轮训请求是否支付 71 | if (!empty($config['out_trade_no'])) { 72 | // 通过主动查询方式查询交易是否成功 73 | $order = query_order($config['out_trade_no']); 74 | if ($order['status'] === 'SUCCESS') { 75 | $order_no = $order['']; // 发卡系统内交易单号 76 | $total_fee = $order['']; // 实际支付金额, 单位, 分 77 | $pay_trade_no = $order['']; // 支付系统内订单号/流水号 78 | $successCallback($order_no, $total_fee, $pay_trade_no); // 成功后记得调用此函数处理订单 79 | return true; 80 | } else { 81 | \Log::error('这里可以记录一些出错信息, 内容保存在 /storage/logs 内'); 82 | return false; 83 | } 84 | } 85 | 86 | // 这里是支付后返回的页面调用的步骤, 一般返回页面也会带有支付后的参数 87 | // 因此如果做了校验(如签名校验等), 一样可以认为我们支付成功了 88 | if (verify_return()) { 89 | $order_no = $_REQUEST['']; // 发卡系统内交易单号 90 | $total_fee = $_REQUEST['']; // 实际支付金额, 单位, 分 91 | $pay_trade_no = $_REQUEST['']; // 支付系统内订单号/流水号 92 | $successCallback($order_no, $total_fee, $pay_trade_no); // 成功后记得调用此函数处理订单 93 | return true; 94 | } else { 95 | \Log::error('这里可以记录一些出错信息, 内容保存在 /storage/logs 内'); 96 | return false; 97 | } 98 | } 99 | 100 | 101 | /** 102 | * 退款操作 103 | * @param array $config 支付渠道配置 104 | * @param string $order_no 订单号 105 | * @param string $pay_trade_no 支付渠道流水号 106 | * @param int $amount_cent 金额/分 107 | * @return true|string true 退款成功 string 失败原因 108 | * @throws \Throwable 109 | */ 110 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 111 | { 112 | return "此支付渠道不支持自动退款, 请手动操作"; // 返回字符串代表失败原因 113 | } 114 | } -------------------------------------------------------------------------------- /Pay/Example/README.md: -------------------------------------------------------------------------------- 1 | 2 | https://github.com/Tai7sy/card-system/wiki/%E6%94%AF%E4%BB%98%E6%8E%A5%E5%8F%A3%E6%8E%A5%E5%85%A5%E6%96%87%E6%A1%A3 -------------------------------------------------------------------------------- /Pay/Fakala/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 18 | $this->url_return = SYS_URL . '/pay/return/' . $id; 19 | $this->pay_id = $id; 20 | } 21 | 22 | /** 23 | * @param array $config 24 | * @param string $out_trade_no 25 | * @param string $subject 26 | * @param string $body 27 | * @param int $amount_cent 28 | * @throws \Exception 29 | */ 30 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 31 | { 32 | if (!isset($config['gateway'])) { 33 | throw new \Exception('请填写gateway'); 34 | } 35 | if (!isset($config['api_id'])) { 36 | throw new \Exception('请填写api_id'); 37 | } 38 | if (!isset($config['api_key'])) { 39 | throw new \Exception('请填写api_key'); 40 | } 41 | include_once 'sdk.php'; 42 | $api = new \fakala($config['gateway'], $config['api_id'], $config['api_key']); 43 | 44 | $payway = strtolower($config['payway']); 45 | 46 | $api->goPay($payway, $subject, $out_trade_no, 0, $amount_cent, '', $this->url_return, $this->url_notify); 47 | } 48 | 49 | function verify($config, $successCallback) 50 | { 51 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 52 | include_once 'sdk.php'; 53 | $api = new \fakala($config['gateway'], $config['api_id'], $config['api_key']); 54 | 55 | if ($isNotify) { 56 | $result = $api->notify_verify(); 57 | $out_trade_no = $_POST['out_trade_no']; // 本系统订单号 58 | $total_fee = $_POST['total_fee']; 59 | $fakala_no = $_POST['order_no']; // API渠道订单号 60 | } else { 61 | // 可能是主动查询 62 | if (empty($config['out_trade_no'])) { 63 | $result = $api->return_verify(); 64 | $out_trade_no = $_GET['out_trade_no']; // 本系统订单号 65 | $total_fee = $_GET['total_fee']; 66 | $fakala_no = $_GET['order_no']; // API渠道订单号 67 | }else{ 68 | $order = @$api->get_order($config['out_trade_no']); 69 | if(empty($order['status'])){ 70 | return false; 71 | } 72 | 73 | $result = @$order['status'] === 2; 74 | $out_trade_no = $order['api_out_no']; // 本系统订单号 75 | $total_fee = $order['paid']; 76 | $fakala_no = $order['order_no']; // API渠道订单号 77 | } 78 | } 79 | 80 | if ($result) { 81 | $successCallback($out_trade_no, $total_fee, $fakala_no); 82 | } 83 | 84 | return $result; 85 | } 86 | 87 | /** 88 | * 退款操作 89 | * @param array $config 支付渠道配置 90 | * @param string $order_no 订单号 91 | * @param string $pay_trade_no 支付渠道流水号 92 | * @param int $amount_cent 金额/分 93 | * @return true|string true 退款成功 string 失败原因 94 | */ 95 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 96 | { 97 | return '此支付渠道不支持发起退款, 请手动操作'; 98 | } 99 | } -------------------------------------------------------------------------------- /Pay/Fakala/sdk.php: -------------------------------------------------------------------------------- 1 | gateway = $gateway; 13 | $this->uid = $id; 14 | $this->key = $key; 15 | } 16 | 17 | function getSignStr($params) 18 | { 19 | ksort($params); 20 | $signStr = ''; 21 | foreach ($params as $k => $v) { 22 | if ('sign' !== $k) { 23 | $signStr .= $k . '=' . $v . '&'; 24 | } 25 | } 26 | return $signStr; 27 | } 28 | 29 | function getSign($params, $key, &$out_url = false) 30 | { 31 | $signStr = self::getSignStr($params); 32 | $sign = md5($signStr . 'key=' . $key); 33 | if ($out_url !== false) { 34 | $out_url = $signStr . 'sign=' . $sign; 35 | } 36 | return $sign; 37 | } 38 | 39 | 40 | /** 41 | * @param string $payway 支付方式 42 | * @param string $subject 商品名称 43 | * @param string $out_trade_no 商户系统内唯一订单号 44 | * @param int $cost 商品成本(分), 用于后台统计利润, 不需要可输入0 45 | * @param int $total_fee 支付金额(分) 46 | * @param string $attach 附加信息 47 | * @param string $return_url 前台支付后跳转回的URL 48 | * @param string $notify_url 后台异步通知URL 49 | */ 50 | function goPay($payway, $subject, $out_trade_no, $cost, $total_fee, $attach, $return_url, $notify_url) 51 | { 52 | $params = [ 53 | 'version' => '20190501', 54 | 'uid' => (int)$this->uid, 55 | 'subject' => $subject, 56 | 'out_trade_no' => $out_trade_no, 57 | 'total_fee' => (int)$total_fee, // 单位 分 58 | 'cost' => (int)$cost, // 单位 分 59 | 'payway' => $payway, 60 | 'return_url' => $return_url, 61 | 'notify_url' => $notify_url, 62 | 'attach' => $attach, 63 | ]; 64 | 65 | $params['sign'] = $this->getSign($params, $this->key); 66 | die(' 67 | 68 | 69 | 70 | 71 | 正在转到付款页 72 | 73 | 74 |
75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |
87 | 88 | '); 89 | } 90 | 91 | /** 92 | * 此函数仅供参考, 请务必再次验证付款金额 93 | * $_POST参数列表: uid, out_trade_no, order_no(系统订单号), total_fee, payway, attach 94 | */ 95 | function notify_verify() 96 | { 97 | $params = $_POST; 98 | if ($params['sign'] === $this->getSign($params, $this->key)) { 99 | echo 'success'; 100 | return true; 101 | } else { 102 | echo 'fail'; 103 | return false; 104 | } 105 | } 106 | 107 | /** 108 | * 请尽量在notify中处理逻辑, 因为用户可能支付后关闭了网页, 因此不会跳到return_url 109 | * $_GET参数列表: 同上 110 | */ 111 | function return_verify() 112 | { 113 | $params = $_GET; 114 | if ($params['sign'] === $this->getSign($params, $this->key)) { 115 | return true; 116 | } else { 117 | return false; 118 | } 119 | } 120 | 121 | /** 122 | * 主动调用API查询是否成功, 用于没有服务器接受通知时的操作 123 | * @param $out_trade_no 124 | * @return array 125 | */ 126 | function get_order($out_trade_no) 127 | { 128 | $result = $this->curl_post($this->gateway . '/api/order/query', 129 | 'uid=' . $this->uid . '&out_trade_no=' . $out_trade_no); 130 | $result = @json_decode($result, true); 131 | if (is_array($result) && is_array($result['data']) && isset($result['data']['order'])) { 132 | return $result['data']['order']; 133 | } 134 | return []; 135 | } 136 | 137 | 138 | private function curl_post($url, $data) 139 | { 140 | $curl = curl_init($url); 141 | curl_setopt($curl, CURLOPT_HEADER, 0); 142 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 返回获取的输出文本流 143 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); // SSL证书认证 144 | curl_setopt($curl, CURLOPT_POST, true); // post 145 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // post数据 146 | $response = curl_exec($curl); 147 | // var_dump(curl_error($curl)); // 如果执行curl过程中出现异常,可打开此开关,以便查看异常内容 148 | curl_close($curl); 149 | return $response; 150 | } 151 | } 152 | 153 | 154 | -------------------------------------------------------------------------------- /Pay/Fubei/README.md: -------------------------------------------------------------------------------- 1 | 准备工作 http://docs.51fubei.com/open-api/product/preparatoryWork.html 2 | 3 | 后台添加支付方式 4 | 5 | 支付方式填wechat或alipay 6 | 7 | 驱动填 Fubei 8 | 9 | 配置json格式 10 | ``` 11 | { 12 | "app_id": "你的appid", 13 | "secret": "你的secret", 14 | "store_id": "你的店铺id" 15 | } 16 | ``` 17 | 18 | 示例 19 | ![ali.jpg](https://i.loli.net/2019/07/21/5d34731d6ce6d30921.jpg) 20 | ![wechat.jpg](https://i.loli.net/2019/07/21/5d34731d8849133862.jpg) 21 | -------------------------------------------------------------------------------- /Pay/JCBPay/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 31 | $this->url_return = SYS_URL . '/pay/return/' . $id; 32 | } 33 | 34 | /** 35 | * @param array $config 36 | * @param string $out_trade_no 37 | * @param string $subject 38 | * @param string $body 39 | * @param int $amount_cent 40 | * @throws \Exception 41 | */ 42 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 43 | { 44 | if (!isset($config['url'])) { 45 | throw new \Exception('请填写支付网页 [url]'); 46 | } 47 | if (!isset($config['app_id'])) { 48 | throw new \Exception('请填写APPID [app_id]'); 49 | } 50 | if (!isset($config['app_key'])) { 51 | throw new \Exception('请填写APPKEY [app_key]'); 52 | } 53 | if (!isset($config['key'])) { 54 | throw new \Exception('请填写接口key [key]'); 55 | } 56 | if (!isset($config['md5key'])) { 57 | throw new \Exception('请填写校验key [md5key]'); 58 | } 59 | 60 | // 1=支付宝转账备注 2=支付宝扫码 3=财付通 4=手机QQ支付 5=微信支付 61 | 62 | header('Location: ' . $config['url'] . '/pay/pay.php?appid=' . $config['app_id'] . 63 | '&payno=' . $out_trade_no . 64 | '&typ=' . $config['payway'] . 65 | '&money=' . sprintf('%.2f', ($amount_cent / 100)) . 66 | '&back_url=' . $this->url_return); 67 | exit; 68 | } 69 | 70 | /** 71 | * @param $config 72 | * @param callable $successCallback 73 | * @return bool|string 74 | * @throws \Exception 75 | */ 76 | function verify($config, $successCallback) 77 | { 78 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 79 | 80 | if ($isNotify) { 81 | 82 | $getkey = $_REQUEST['key'];//接收参数key 83 | $tno = $_REQUEST['tno'];//接收参数tno 交易号 84 | $payno = $_REQUEST['payno'];//接收参数payno 一般是用户名 用户ID 85 | $money = $_REQUEST['money'];//接收参数money 付款金额 86 | $sign = $_REQUEST['sign'];//接收参数sign 87 | $typ = (int)$_REQUEST['typ'];//接收参数typ 88 | if ($typ == 1) { 89 | $typname = '手工充值'; 90 | } else if ($typ == 2) { 91 | $typname = '支付宝充值'; 92 | } else if ($typ == 3) { 93 | $typname = '财付通充值'; 94 | } else if ($typ == 4) { 95 | $typname = '手Q充值'; 96 | } else if ($typ == 5) { 97 | $typname = '微信充值'; 98 | } 99 | if (!$tno) exit('没有订单号'); 100 | if (!$payno) exit('没有付款说明'); 101 | if ($getkey !== $config['key']) exit('KEY错误'); 102 | if (strtoupper($sign) !== strtoupper(md5($tno . $payno . $money . $config['md5key']))) exit('签名错误'); 103 | 104 | $order = \App\Order::whereOrderNo($payno)->first(); 105 | if(!$order) exit('订单不存在'); 106 | //此处作逻辑处理 107 | $successCallback($payno, (int)round($money * 100), $tno); 108 | 109 | //处理成功 输出1 110 | exit('1'); 111 | } else { 112 | if (!empty($config['out_trade_no'])) { 113 | // 主动查询接口, 此接口不支持.... 114 | // 此驱动, 不支持主动查询交易结果, 直接返回失败(未支付) 115 | return false; 116 | } 117 | 118 | 119 | // 同步返回接口 120 | if (!isset($_REQUEST['appid']) || !isset($_REQUEST['tno']) || !isset($_REQUEST['payno']) || !isset($_REQUEST['money']) || !isset($_REQUEST['typ']) || !isset($_REQUEST['paytime']) || !isset($_REQUEST['sign'])) { 121 | return false; 122 | } 123 | $appid = (int)$_REQUEST['appid']; 124 | $tno = $_REQUEST['tno'];//交易号 支付宝 微信 财付通 的交易号 125 | $payno = $_REQUEST['payno'];//网站充值的用户名 126 | $money = $_REQUEST['money'];//付款金额 127 | $typ = (int)$_REQUEST['typ']; 128 | $paytime = $_REQUEST['paytime']; 129 | $sign = $_REQUEST['sign']; 130 | if (!$appid || !$tno || !$payno || !$money || !$typ || !$paytime || !$sign) { 131 | exit('参数错误'); 132 | } 133 | if ($config['app_id'] != $appid) exit('appid error'); 134 | //sign 校验 135 | if ($sign != md5($appid . "|" . $config['app_key'] . "|" . $tno . "|" . $payno . "|" . $money . "|" . $paytime . "|" . $typ)) { 136 | exit('签名错误'); 137 | } 138 | 139 | //处理用户充值 140 | if ($typ == 1) { 141 | $typname = '手工充值'; 142 | } else if ($typ == 2) { 143 | $typname = '支付宝充值'; 144 | } else if ($typ == 3) { 145 | $typname = '财付通充值'; 146 | } else if ($typ == 4) { 147 | $typname = '手Q充值'; 148 | } else if ($typ == 5) { 149 | $typname = '微信充值'; 150 | } 151 | 152 | //此处作逻辑处理 153 | $successCallback($payno, (int)round($money * 100), $tno); 154 | 155 | return true; 156 | 157 | } 158 | } 159 | 160 | /** 161 | * 退款操作 162 | * @param array $config 支付渠道配置 163 | * @param string $order_no 订单号 164 | * @param string $pay_trade_no 支付渠道流水号 165 | * @param int $amount_cent 金额/分 166 | * @return true|string true 退款成功 string 失败原因 167 | */ 168 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 169 | { 170 | return '此支付渠道不支持发起退款, 请手动操作'; 171 | } 172 | } -------------------------------------------------------------------------------- /Pay/JiPays/common.php: -------------------------------------------------------------------------------- 1 | $v) { 12 | if ($k == 'sign' || $k == 'sign_type' || strval($v) === '') continue; 13 | $tmp[$k] = $v; 14 | } 15 | 16 | //对数组排序 17 | ksort($tmp); 18 | reset($tmp); 19 | 20 | //把数组所有元素,按照'参数=参数值'的模式用'&'字符拼接成字符串 21 | $arg = ''; 22 | foreach ($tmp as $k => $v) { 23 | $arg .= $k . '=' . strval($v) . '&'; 24 | } 25 | $arg = trim($arg, '&'); 26 | 27 | //如果存在转义字符,那么去掉转义 28 | if (get_magic_quotes_gpc()) $arg = stripslashes($arg); 29 | 30 | return $arg; 31 | } 32 | 33 | /** 34 | * 发送HTTP请求方法 35 | * @param string $url 请求URL 36 | * @param array $params 请求参数 37 | * @param string $method 请求方法GET/POST 38 | * @param array $header 需要发送的请求header 39 | * @return 40 | */ 41 | function curl_http($url, $params = '', $method = 'GET', $header = array()) 42 | { 43 | $opts = array( 44 | CURLOPT_TIMEOUT => 5, 45 | CURLOPT_RETURNTRANSFER => 1,// 显示输出结果 46 | CURLOPT_HEADER => 0,// 过滤HTTP头 47 | CURLOPT_FOLLOWLOCATION => 1,// 跳转选项,如果出现错误码:3, 优先检查这里 48 | CURLOPT_SSL_VERIFYPEER => 0,// SSL证书认证 49 | CURLOPT_SSL_VERIFYHOST => 0,// 证书认证 50 | CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_0,// 强制协议为1.0 51 | CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,// 强制使用IPV4 52 | ); 53 | 54 | //添加header 55 | if ($header) $opts[CURLOPT_HTTPHEADER] = $header; 56 | 57 | if (is_array($params)) $params = http_build_query($params); 58 | /* 根据请求类型设置特定参数 */ 59 | switch (strtoupper($method)) { 60 | case 'GET': 61 | $opts[CURLOPT_URL] = $params ? $url . '?' . $params : $url; 62 | $opts[CURLOPT_CUSTOMREQUEST] = 'GET'; 63 | break; 64 | 65 | case 'POST': 66 | $opts[CURLOPT_URL] = $url; 67 | $opts[CURLOPT_POST] = 1; 68 | $opts[CURLOPT_POSTFIELDS] = $params; 69 | break; 70 | 71 | default: 72 | // 73 | break; 74 | } 75 | 76 | /* 初始化并执行curl请求 */ 77 | $ch = curl_init(); 78 | curl_setopt_array($ch, $opts); 79 | $result = curl_exec($ch); 80 | 81 | /* 判断请求响应 */ 82 | if ($result) { 83 | curl_close($ch); 84 | return $result; 85 | } else { 86 | $error = curl_errno($ch); 87 | curl_close($ch); 88 | exit('请求发起失败,错误码:' . $error); 89 | } 90 | } 91 | 92 | /** 93 | * 生成rsa签名 94 | * $string 待签名的字符串 95 | */ 96 | function create_rsa_sign($string) 97 | { 98 | require('./config.php'); 99 | 100 | ($rsa_private_key) or die('私钥信息尚未配置,请检查'); 101 | 102 | $private_key = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($rsa_private_key, 64, "\n", true) . "\n-----END RSA PRIVATE KEY-----"; 103 | openssl_sign($string, $sign, $private_key, OPENSSL_ALGO_SHA256); 104 | $sign = base64_encode($sign); 105 | return $sign; 106 | } 107 | 108 | 109 | /** 110 | * 判断订单签名 111 | * @param array $params 待签名的数组 112 | * @param string $key 113 | * @return bool 114 | */ 115 | function check_sign($params, $key) 116 | { 117 | if (empty($params)) return false; 118 | if (!is_array($params)) return false; 119 | if (!isset($params['sign'])) return false; 120 | 121 | 122 | //拼接待签名的参数 123 | $string = create_link_string($params); 124 | 125 | //判断签名 126 | switch (strtoupper($params['sign_type'])) { 127 | case 'RSA2': 128 | ($web_public_key) or die('尚未设置网关RSA公钥'); 129 | /** 130 | * 处理base64编码加号变空格的问题 131 | */ 132 | $sign = str_replace(' ', '+', $params['sign']); 133 | /** 134 | * 拼接密钥 135 | */ 136 | $pub_key = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($web_public_key, 64, "\n", true) . "\n-----END PUBLIC KEY-----"; 137 | /** 138 | * 验证签名 139 | */ 140 | $result = (bool)openssl_verify($string, base64_decode($sign), $pub_key, OPENSSL_ALGO_SHA256); 141 | 142 | return $result; 143 | break; 144 | 145 | case 'SHA256': 146 | $sign = hash('sha256', $string . '&key=' . $md5_key); 147 | return boolval($sign == $params['sign']); 148 | break; 149 | 150 | default: 151 | case 'MD5': 152 | $sign = md5($string . '&key=' . $md5_key); 153 | return boolval($sign == $params['sign']); 154 | break; 155 | } 156 | } 157 | 158 | /** 159 | * 判断是否微信访问 160 | * @return bool 161 | */ 162 | function is_weixin() 163 | { 164 | $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; 165 | if (strpos($ua, 'MicroMessenger') !== false) { 166 | return true; 167 | } else { 168 | return false; 169 | } 170 | } 171 | 172 | /** 173 | * 检测是否使用手机访问 174 | * @access public 175 | * @return bool 176 | */ 177 | function is_mobile() 178 | { 179 | if (isset($_SERVER['HTTP_VIA']) && stristr($_SERVER['HTTP_VIA'], "wap")) { 180 | return true; 181 | } elseif (isset($_SERVER['HTTP_ACCEPT']) && strpos(strtoupper($_SERVER['HTTP_ACCEPT']), "VND.WAP.WML")) { 182 | return true; 183 | } elseif (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])) { 184 | return true; 185 | } elseif (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $_SERVER['HTTP_USER_AGENT'])) { 186 | return true; 187 | } else { 188 | return false; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /Pay/Meeol/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 23 | $this->url_return = SYS_URL . '/pay/return/' . $id; 24 | } 25 | 26 | /** 27 | * @param array $config 支付渠道配置 28 | * @param string $out_trade_no 外部订单号 29 | * @param string $subject 商品名称 30 | * @param string $body 商品介绍 31 | * @param int $amount_cent 金额/分 32 | * @throws \Exception 33 | */ 34 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 35 | { 36 | $total_fee = sprintf('%.2f', $amount_cent / 100); // 元为单位 37 | 38 | if (!isset($config['appId'])) { 39 | throw new \Exception('请设置appId'); 40 | } 41 | if (!isset($config['key'])) { 42 | throw new \Exception('请设置key'); 43 | } 44 | $payway = $config['payway']; 45 | $req = [ 46 | 'amount' => $total_fee, 47 | 'appId' => $config['appId'], 48 | 'orderId' => $out_trade_no, 49 | 'random' => md5(random_bytes(16)), 50 | 'tradeType' => $payway, // 微信W01,支付宝A01 51 | ]; 52 | $req['sign'] = strtoupper(md5('amount=' . $req['amount'] . '&appId=' . $config['appId'] . '&key=' . $config['key'] . '&orderId=' . $req['orderId'] . '&random=' . $req['random'] . '&tradeType=' . $req['tradeType'])); 53 | $ret_raw = CurlRequest::post('http://api.meeol.cn/rest/mall/payment/order', json_encode($req)); 54 | $ret = json_decode($ret_raw, true); 55 | if (!isset($ret['status']) || $ret['status'] !== '0') { 56 | Log::error('Pay.Meeol.goPay.order Error: ' . $ret_raw); 57 | throw new \Exception('支付请求失败, 请刷新重试'); 58 | } 59 | if (substr($payway, 0, 1) === 'W') 60 | header('Location: /qrcode/pay/' . $out_trade_no . '/wechat?url=' . urlencode($ret['qrcode'])); 61 | elseif (substr($payway, 0, 1) === 'A') 62 | header('Location: /qrcode/pay/' . $out_trade_no . '/aliqr?url=' . urlencode($ret['qrcode'])); 63 | exit; 64 | } 65 | 66 | /** 67 | * @param $config 68 | * @param callable $successCallback 成功回调 (系统单号,交易金额/分,支付渠道单号) 69 | * @return bool|string true 验证通过 string 失败原因 70 | * @throws \Exception 71 | */ 72 | function verify($config, $successCallback) 73 | { 74 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 75 | if ($isNotify) { 76 | $post = json_decode(file_get_contents('php://input'), true); 77 | $sign = strtoupper(md5('amount=' . $post['amount'] . '&appid=' . $post['appid'] . '&key=' . $config['key'] . '&orderId=' . $post['orderId'] . '&tradeTime=' . $post['tradeTime'] . '&tradeType=' . $post['tradeType'])); 78 | 79 | if ($sign === $post['sign']) { 80 | $total_fee = (int)round($post['amount'] * 100); 81 | $successCallback($post['orderId'], $total_fee, $post['passTradeNo']); 82 | echo 'success'; 83 | return true; 84 | } else { 85 | Log::error('Pay.Meeol.verify notify sign error, post: ' . file_get_contents('php://input')); 86 | echo 'error'; 87 | } 88 | } else { 89 | if (!empty($config['out_trade_no'])) { 90 | $req = [ 91 | 'appId' => $config['appId'], 92 | 'orderId' => $config['out_trade_no'], 93 | 'random' => md5(random_bytes(16)), 94 | ]; 95 | $req['sign'] = strtoupper(md5('appId=' . $config['appId'] . '&key=' . $config['key'] . '&orderId=' . $req['orderId'] . '&random=' . $req['random'])); 96 | $req = json_encode($req); 97 | $ret_raw = CurlRequest::post('http://api.meeol.cn/rest/mall/payment/query', $req); 98 | $ret = json_decode($ret_raw, true); 99 | if (!isset($ret['status'])) { 100 | Log::error('Pay.Meeol.verify Error: ' . $ret_raw); 101 | } 102 | if ($ret['status'] === '0') { 103 | $total_fee = (int)round($ret['amount'] * 100); 104 | $successCallback($ret['orderId'], $total_fee, $ret['passTradeNo']); 105 | return true; 106 | } 107 | Log::debug('Pay.Meeol.verify debug, req:' . $req . 'ret:' . $ret_raw); 108 | return false; 109 | } else { 110 | throw new \Exception('请传递订单编号'); 111 | } 112 | } 113 | return false; 114 | } 115 | 116 | /** 117 | * 退款操作 118 | * @param array $config 支付渠道配置 119 | * @param string $order_no 订单号 120 | * @param string $pay_trade_no 支付渠道流水号 121 | * @param int $amount_cent 金额/分 122 | * @return true|string true 退款成功 string 失败原因 123 | */ 124 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 125 | { 126 | return '此支付渠道不支持发起退款, 请手动操作'; 127 | } 128 | } -------------------------------------------------------------------------------- /Pay/MoTonePay/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 21 | $this->url_return = SYS_URL . '/pay/return/' . $id; 22 | } 23 | 24 | /** 25 | * @param array $config 支付渠道配置 26 | * @param string $out_trade_no 外部订单号 27 | * @param string $subject 商品名称 28 | * @param string $body 商品介绍 29 | * @param int $amount_cent 金额/分 30 | */ 31 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 32 | { 33 | $total_fee = sprintf('%.2f', $amount_cent / 100); // 元为单位 34 | 35 | $version = '1.0'; 36 | $paytype = $config['payway']; 37 | // qzfzfbh5 qzfzfb dlbwxsm dlbwxh5 qqrcode qqwallet 38 | $get_code = '0'; 39 | $sign = md5('version=' . $version . '&customerid=' . $config['id'] . '&total_fee=' . $total_fee . 40 | '&sdorderno=' . $out_trade_no . '¬ifyurl=' . $this->url_notify . '&returnurl=' . $this->url_return . '&' . $config['key']); 41 | 42 | ?> 43 | 44 | 45 | 46 | 47 | 正在转到付款页 48 | 49 | 50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 |
61 | 62 | 63 | “API认证”->“用在后台服务器(SSP等php后台)”,点击“添加密钥”,获得后端认证码(请注意,是”后端“)。获取app_secret,填入card-system配置文件中。 23 | 24 | 25 | ## 认证审核 26 | 请去个人设置中,完成认证工作,点亮笑脸☺。
27 | 28 | 29 | 请确认您已经开通了需要的权限。 30 | 注意,如果你只有 “加密货币”,那只能接受加密货币。如需要开通其他支付方式,请按照该页面的流程操作。 31 | 32 | 33 | 34 | ## FAQ 35 | 可以参考数字货币匿名支付[常见问题](https://github.com/bitpaydev/docs/blob/master/FAQ.md)。 36 | 如果支付遇到问题,可以联系[技术交流群](https://t.me/joinchat/GLKSKhUnE4GvEAPgqtChAQ)。 37 | -------------------------------------------------------------------------------- /Pay/Pay.php: -------------------------------------------------------------------------------- 1 | driver) . '\Api'; 20 | if (!class_exists($driverName)) { 21 | throw new \Exception('支付驱动未找到'); 22 | } 23 | return new $driverName($payway->id); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Pay/PayBeaver/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 19 | $this->url_return = SYS_URL . '/pay/return/' . $id; 20 | $this->pay_id = $id; 21 | } 22 | 23 | private function sign($data, $app_secret) 24 | { 25 | ksort($data); 26 | return md5(http_build_query($data) . $app_secret); 27 | } 28 | 29 | /** 30 | * @param array $config 31 | * @param string $out_trade_no 32 | * @param string $subject 33 | * @param string $body 34 | * @param int $amount_cent 35 | * @throws \Exception 36 | */ 37 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 38 | { 39 | if (!isset($config['gateway'])) { 40 | $config['gateway'] = 'https://api.paybeaver.com'; 41 | } 42 | if (!isset($config['app_id'])) { 43 | throw new \Exception('请填写 app_id'); 44 | } 45 | if (!isset($config['app_secret'])) { 46 | throw new \Exception('请填写 app_secret'); 47 | } 48 | 49 | 50 | $return_url = SYS_URL . '/qrcode/pay/' . $out_trade_no . '/query'; 51 | $data = [ 52 | 'app_id' => $config['app_id'], 53 | 'out_trade_no' => $out_trade_no, 54 | 'total_amount' => $amount_cent, 55 | 'notify_url' => $this->url_notify, 56 | 'return_url' => $return_url, 57 | ]; 58 | 59 | $data['sign'] = $this->sign($data, $config['app_secret']); 60 | 61 | $ret_raw = CurlRequest::post($config['gateway'] . '/v1/gateway/fetch', http_build_query($data)); 62 | $ret = @json_decode($ret_raw, true); 63 | if (!$ret || !isset($ret['code']) || $ret['code'] !== 200) { 64 | Log::error('Pay.PayBeaver.goPay.order, request failed: ' . $ret_raw); 65 | throw new \Exception(@$ret['message'] ?? '获取付款信息超时, 请刷新重试'); 66 | } 67 | 68 | header('location: ' . $ret['data']['pay_url']); 69 | die; 70 | } 71 | 72 | function verify($config, $successCallback) 73 | { 74 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 75 | if (!isset($config['gateway'])) { 76 | $config['gateway'] = 'https://api.paybeaver.com/'; 77 | } 78 | 79 | if ($isNotify) { 80 | 81 | // app_id=kNpZCR87CvdytMyd&out_trade_no=20201219203115K8XjK&sign=a11fdaa1c260ad4d1d9f916769b8f0ff&trade_no=b614e0a2265c443d9618141cd9035dfc 82 | $data = $_POST; 83 | unset($data['sign']); 84 | if ($this->sign($data, $config['app_secret']) === $_POST['sign']) { 85 | echo "success"; 86 | 87 | $order = \App\Order::whereOrderNo($data['out_trade_no'])->first(); 88 | if (!$order) { 89 | echo 'error'; 90 | Log::error('Pay.PayBeaver.verify, cannot find order:', $data); 91 | return false; 92 | } 93 | 94 | $successCallback($data['out_trade_no'], $order->paid, $data['trade_no']); 95 | return true; 96 | } else { 97 | echo "error sign"; 98 | return false; 99 | } 100 | } else { 101 | 102 | if (isset($_GET['out_trade_no'])) { 103 | 104 | // return page 105 | $data = $_GET; 106 | unset($data['sign']); 107 | if ($this->sign($data, $config['app_secret']) === $_POST['sign']) { 108 | $successCallback($data['out_trade_no'], (int)$data['total_amount'], $data['trade_no']); 109 | return true; 110 | } else { 111 | return false; 112 | } 113 | } else { 114 | // 主动查询 115 | // 不支持 116 | return false; 117 | } 118 | } 119 | } 120 | 121 | /** 122 | * 退款操作 123 | * @param array $config 支付渠道配置 124 | * @param string $order_no 订单号 125 | * @param string $pay_trade_no 支付渠道流水号 126 | * @param int $amount_cent 金额/分 127 | * @return true|string true 退款成功 string 失败原因 128 | */ 129 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 130 | { 131 | return '此支付渠道不支持发起退款, 请手动操作'; 132 | } 133 | } -------------------------------------------------------------------------------- /Pay/Payjs/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 20 | $this->url_return = SYS_URL . '/pay/return/' . $id; 21 | } 22 | 23 | /** 24 | * @param array $config 25 | * @param string $out_trade_no 26 | * @param string $subject 27 | * @param string $body 28 | * @param int $amount_cent 29 | * @throws \Exception 30 | */ 31 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 32 | { 33 | if (!isset($config['mchid'])) { 34 | throw new \Exception('请填写mchid'); 35 | } 36 | if (!isset($config['key'])) { 37 | throw new \Exception('请填写key'); 38 | } 39 | 40 | $payjs = new Payjs($config); 41 | 42 | $payway = strtolower($config['payway']); 43 | 44 | 45 | $data = [ 46 | 'total_fee' => $amount_cent, // 金额,单位 分 47 | 'out_trade_no' => $out_trade_no, // 商户订单号, 在用户侧请唯一 48 | 'body' => $out_trade_no, // 订单标题 49 | 'notify_url' => $this->url_notify, 50 | 'callback_url' => SYS_URL.'/pay/result/'. $out_trade_no // 前台地址 51 | ]; 52 | 53 | 54 | 55 | if ($payway === 'native') { 56 | $is_alipay = isset($config['type']) && $config['type'] === 'alipay'; 57 | 58 | if ($is_alipay) $data['type'] = 'alipay'; 59 | 60 | $rst = $payjs->native($data); // 扫码 61 | 62 | if(@(int)$rst['return_code'] !== 1){ 63 | die('

支付渠道出错: '.$rst['msg'].'

'); 64 | } 65 | 66 | if ($is_alipay) 67 | header('location: /qrcode/pay/' . $out_trade_no . '/aliqr?url=' . urlencode($rst['code_url'])); 68 | else 69 | header('location: /qrcode/pay/' . $out_trade_no . '/wechat?url=' . urlencode($rst['code_url'])); 70 | 71 | } elseif ($payway === 'cashier') { 72 | 73 | $rst = $payjs->cashier($data); // 收银台 74 | // header('Location: ' . $rst); 75 | 76 | header('location: /qrcode/pay/' . $out_trade_no . '/wechat?url=' . urlencode($rst)); 77 | } else { 78 | die('

请填写支付方式

'); 79 | } 80 | 81 | echo '正在跳转到支付渠道...

正在跳转到支付渠道...

'; 82 | exit; 83 | 84 | } 85 | 86 | function verify($config, $successCallback) 87 | { 88 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 89 | 90 | $payjs = new Payjs($config); 91 | 92 | if ($isNotify) { 93 | $result = $payjs->checkSign($_POST); 94 | echo $result ? 'success' : 'fail'; 95 | } else { 96 | // 前台返回 没有参数 只能返回失败了 97 | // $result = $payjs->check(); // 这里没文档 不一定成功 98 | // 这里只能等待后台 notify 然后通知前台 99 | $result = false; 100 | } 101 | 102 | if ($result) { 103 | $out_trade_no = $_REQUEST['out_trade_no']; // 本系统订单号 104 | $total_fee = $_REQUEST['total_fee']; 105 | $payjs_order_id = $_REQUEST['payjs_order_id']; // API渠道订单号 106 | $successCallback($out_trade_no, $total_fee, $payjs_order_id); 107 | return true; 108 | } 109 | 110 | return false; 111 | } 112 | 113 | /** 114 | * 退款操作 115 | * @param array $config 支付渠道配置 116 | * @param string $order_no 订单号 117 | * @param string $pay_trade_no 支付渠道流水号 118 | * @param int $amount_cent 金额/分 119 | * @return true|string true 退款成功 string 失败原因 120 | */ 121 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 122 | { 123 | return '此支付渠道不支持发起退款, 请手动操作'; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Pay/Payjs/sdk/Payjs.php: -------------------------------------------------------------------------------- 1 | mchid = $config['mchid']; 23 | $this->key = $config['key']; 24 | $api_url = isset($config['api_url']) ? $config['api_url'] : 'https://payjs.cn/api/'; 25 | 26 | $this->api_url_native = $api_url . 'native'; 27 | $this->api_url_cashier = $api_url . 'cashier'; 28 | $this->api_url_refund = $api_url . 'refund'; 29 | $this->api_url_close = $api_url . 'close'; 30 | $this->api_url_check = $api_url . 'check'; 31 | $this->api_url_user = $api_url . 'user'; 32 | $this->api_url_info = $api_url . 'info'; 33 | $this->api_url_bank = $api_url . 'bank'; 34 | } 35 | 36 | // 扫码支付 37 | public function native(array $data) 38 | { 39 | $this->url = $this->api_url_native; 40 | return $this->post($data); 41 | } 42 | 43 | // 收银台模式 44 | public function cashier(array $data) 45 | { 46 | $this->url = $this->api_url_cashier; 47 | $data = $this->sign($data); 48 | $url = $this->url . '?' . http_build_query($data); 49 | return $url; 50 | } 51 | 52 | // 退款 53 | public function refund($payjs_order_id) 54 | { 55 | $this->url = $this->api_url_refund; 56 | $data = ['payjs_order_id' => $payjs_order_id]; 57 | return $this->post($data); 58 | } 59 | 60 | // 关闭订单 61 | public function close($payjs_order_id) 62 | { 63 | $this->url = $this->api_url_close; 64 | $data = ['payjs_order_id' => $payjs_order_id]; 65 | return $this->post($data); 66 | } 67 | 68 | // 检查订单 69 | public function check($payjs_order_id) 70 | { 71 | $this->url = $this->api_url_check; 72 | $data = ['payjs_order_id' => $payjs_order_id]; 73 | return $this->post($data); 74 | } 75 | 76 | // 用户资料 77 | public function user($openid) 78 | { 79 | $this->url = $this->api_url_user; 80 | $data = ['openid' => $openid]; 81 | return $this->post($data); 82 | } 83 | 84 | // 商户资料 85 | public function info() 86 | { 87 | $this->url = $this->api_url_info; 88 | $data = []; 89 | return $this->post($data); 90 | } 91 | 92 | // 银行资料 93 | public function bank($name) 94 | { 95 | $this->url = $this->api_url_bank; 96 | $data = ['bank' => $name]; 97 | return $this->post($data); 98 | } 99 | 100 | // 异步通知接收 101 | public function notify() 102 | { 103 | $data = $_POST; 104 | if ($this->checkSign($data) === true) { 105 | return $data; 106 | } else { 107 | return '验签失败'; 108 | } 109 | } 110 | 111 | // 数据签名 112 | public function sign(array $data) 113 | { 114 | $data['mchid'] = $this->mchid; 115 | array_filter($data); 116 | ksort($data); 117 | $data['sign'] = strtoupper(md5(urldecode(http_build_query($data) . '&key=' . $this->key))); 118 | return $data; 119 | } 120 | 121 | // 校验数据签名 122 | public function checkSign($data) 123 | { 124 | $in_sign = $data['sign']; 125 | unset($data['sign']); 126 | array_filter($data); 127 | ksort($data); 128 | $sign = strtoupper(md5(urldecode(http_build_query($data) . '&key=' . $this->key))); 129 | return $in_sign == $sign ? true : false; 130 | } 131 | 132 | 133 | private static function curl_post($url, $post_data = '') 134 | { 135 | $headers['Accept'] = "*/*"; 136 | $headers['Referer'] = $url; 137 | $headers['Content-Type'] = "application/x-www-form-urlencoded"; 138 | $headers['User-Agent'] = "ni shi sha bi ba, yi ge sdk hai you di san fang ku"; 139 | 140 | $sendHeaders = array(); 141 | foreach ($headers as $headerName => $headerVal) { 142 | $sendHeaders[] = $headerName . ': ' . $headerVal; 143 | } 144 | $sendHeaders[] = 'Expect:'; 145 | 146 | $ch = curl_init(); 147 | curl_setopt($ch, CURLOPT_URL, $url); 148 | 149 | curl_setopt($ch, CURLOPT_POST, 1); 150 | curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); 151 | 152 | curl_setopt($ch, CURLOPT_TIMEOUT, 10); 153 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); 154 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//返回获取的输出文本流 155 | curl_setopt($ch, CURLOPT_HEADER, 1);//将头文件的信息作为数据流输出 156 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 157 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 158 | curl_setopt($ch, CURLOPT_HTTPHEADER, $sendHeaders); 159 | $response = curl_exec($ch); 160 | 161 | $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 162 | $body = substr($response, $headerSize); 163 | curl_close($ch); 164 | 165 | return $body; 166 | } 167 | 168 | 169 | // 数据发送 170 | public function post($data) 171 | { 172 | $data = $this->sign($data); 173 | 174 | /* 175 | $client = new \GuzzleHttp\Client([ 176 | 'header' => ['User-Agent' => 'PAYJS Larevel Http Client'], 177 | 'timeout' => 10, 178 | 'http_errors' => false, 179 | 'defaults' => ['verify' => false], 180 | ]); 181 | $rst = $client->request('POST', $this->url, ['form_params' => $data]); 182 | */ 183 | return json_decode(self::curl_post($this->url, http_build_query($data)), true); 184 | } 185 | 186 | } 187 | -------------------------------------------------------------------------------- /Pay/QPay/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 19 | } 20 | 21 | /** 22 | * @param array $config 23 | * @param string $out_trade_no 支付系统的订单号, 对于微信来说 是外部订单号 24 | * @param string $subject 25 | * @param string $body 26 | * @param int $amount_cent 27 | * @throws \Exception 28 | */ 29 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 30 | { 31 | if (!isset($config['mch_id']) || !isset($config['mch_key'])) 32 | throw new \Exception('请设置 mch_id 和 mch_key'); 33 | 34 | // Log::debug('Pay.QPay.goPay, order_no:' . $out_trade_no.', step1'); 35 | //入参 36 | $params = array( 37 | 'out_trade_no' => $out_trade_no, 38 | 'body' => $subject, 39 | 'device_info' => 'qq_19060', 40 | 'fee_type' => 'CNY', 41 | 'notify_url' => $this->url_notify, 42 | 'spbill_create_ip' => Helper::getIP(), 43 | 'total_fee' => $amount_cent, 44 | 'trade_type' => 'NATIVE' 45 | ); 46 | //api调用 47 | $qpayApi = new \QpayMchAPI('https://qpay.qq.com/cgi-bin/pay/qpay_unified_order.cgi', null, 10); 48 | $retXml = $qpayApi->req($params, $config); 49 | $result = \QpayMchUtil::xmlToArray($retXml); 50 | 51 | if (!isset($result['code_url'])) { 52 | Log::error('Pay.QPay.goPay, order_no:' . $out_trade_no . ', error:' . json_encode($result)); 53 | 54 | if (isset($result['err_code_des'])) 55 | throw new \Exception($result['err_code_des']); 56 | 57 | if (isset($result['return_msg'])) 58 | throw new \Exception($result['return_msg']); 59 | 60 | throw new \Exception('获取支付数据失败'); 61 | } 62 | // Log::debug('Pay.Wechat.goPay, order_no:' . $out_trade_no.', step4'); 63 | header('location: /qrcode/pay/' . $out_trade_no . '/qq?url=' . urlencode($result['code_url'])); 64 | exit; 65 | } 66 | 67 | 68 | function verify($config, $successCallback) 69 | { 70 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 71 | 72 | $qpayApi = new \QpayMchAPI('https://qpay.qq.com/cgi-bin/pay/qpay_order_query.cgi', null, 10); 73 | 74 | if ($isNotify) { 75 | $params = $qpayApi->notify_params(); 76 | if (!$qpayApi->notify_verify($params, $config)) { 77 | echo 'FAIL'; 78 | return false; 79 | } 80 | call_user_func_array($successCallback, [$params['out_trade_no'], $params['total_fee'], $params['transaction_id']]); 81 | echo 'SUCCESS'; 82 | return true; 83 | } else { 84 | $out_trade_no = @$config['out_trade_no']; 85 | 86 | $params = array( 87 | 'out_trade_no' => $out_trade_no, 88 | ); 89 | //api调用 90 | $retXml = $qpayApi->req($params, $config); 91 | $result = \QpayMchUtil::xmlToArray($retXml); 92 | if (!is_array($result)) { 93 | Log::error('Pay.QPay.verify Error, $retXml' . $retXml); 94 | return false; 95 | } 96 | 97 | if (array_key_exists('trade_state', $result) && $result['trade_state'] == 'SUCCESS') { 98 | call_user_func_array($successCallback, [$result['out_trade_no'], $result['total_fee'], $result['transaction_id']]); 99 | return true; 100 | } else { 101 | return false; 102 | } 103 | } 104 | } 105 | 106 | /** 107 | * 退款操作 108 | * @param array $config 支付渠道配置 109 | * @param string $order_no 订单号 110 | * @param string $pay_trade_no 支付渠道流水号 111 | * @param int $amount_cent 金额/分 112 | * @return true|string true 退款成功 string 失败原因 113 | * @throws \Exception 114 | */ 115 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 116 | { 117 | $qpayApi = new \QpayMchAPI('https://api.qpay.qq.com/cgi-bin/pay/qpay_refund.cgi', true, 10); 118 | 119 | if (!isset($config['ssl_cert']) || !isset($config['ssl_key'])) 120 | throw new \Exception('请设置 ssl_cert(证书文件) 和 ssl_key(证书key)'); 121 | 122 | $tmpFile = tmpfile(); 123 | fwrite($tmpFile, "-----BEGIN CERTIFICATE-----\n" . wordwrap(trim($config['ssl_cert']), 64, "\n", true) . "\n-----END CERTIFICATE-----"); 124 | $config['ssl_cert'] = stream_get_meta_data($tmpFile)['uri']; 125 | $tmpFile2 = tmpfile(); 126 | fwrite($tmpFile2, "-----BEGIN PRIVATE KEY-----\n" . wordwrap(trim($config['ssl_key']), 64, "\n", true) . "\n-----END PRIVATE KEY-----"); 127 | $config['ssl_key'] = stream_get_meta_data($tmpFile2)['uri']; 128 | 129 | if (!isset($config['op_user_id']) || !isset($config['op_user_passwd'])) 130 | throw new \Exception('请设置 op_user_id(操作员) 和 op_user_passwd(密码的MD5) (参考 [操作员账户] https://qpay.qq.com/buss/wiki/38/1207)'); 131 | 132 | $params = array( 133 | 'out_trade_no' => $order_no, 134 | 'out_refund_no' => 'anfaka' . date('YmdHis'), 135 | 'refund_fee' => $amount_cent, 136 | 'op_user_id' => $config['op_user_id'], // 操作员ID 137 | 'op_user_passwd' => $config['op_user_passwd'], // 操作员密码的MD5 138 | ); 139 | 140 | $retXml = $qpayApi->req($params, $config); 141 | $result = \QpayMchUtil::xmlToArray($retXml); 142 | 143 | if ($result['return_code'] !== 'SUCCESS') { 144 | throw new \Exception($result['return_msg']); 145 | } 146 | 147 | if ($result['result_code'] !== 'SUCCESS') { 148 | throw new \Exception($result['err_code_des']); 149 | } 150 | return true; 151 | } 152 | } -------------------------------------------------------------------------------- /Pay/QPay/qpay_mch_sp/qpayMch.config.php: -------------------------------------------------------------------------------- 1 | url = $url; 26 | $this->isSSL = $isSSL; 27 | $this->timeout = $timeout; 28 | } 29 | 30 | public function notify_params() 31 | { 32 | $xml = file_get_contents('php://input'); 33 | return QpayMchUtil::xmlToArray($xml); 34 | } 35 | 36 | public function notify_verify($params, $config) 37 | { 38 | if (!isset($params['sign'])) 39 | return false; 40 | $sign = QpayMchUtil::getSign($params, $config['mch_key']); 41 | return $sign === $params['sign']; 42 | } 43 | 44 | public function req($params, $config) 45 | { 46 | $ret = array(); 47 | //商户号 48 | $params['mch_id'] = $config['mch_id']; 49 | //随机字符串 50 | $params['nonce_str'] = QpayMchUtil::createNoncestr(); 51 | //签名 52 | $params['sign'] = QpayMchUtil::getSign($params, $config['mch_key']); 53 | //生成xml 54 | $xml = QpayMchUtil::arrayToXml($params); 55 | 56 | if (isset($this->isSSL)) { 57 | $ret = QpayMchUtil::reqByCurlSSLPost($xml, $this->url, $this->timeout, $config); 58 | } else { 59 | $ret = QpayMchUtil::reqByCurlNormalPost($xml, $this->url, $this->timeout); 60 | } 61 | return $ret; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /Pay/QPay/qpay_mch_sp/qpayMchUtil.class.php: -------------------------------------------------------------------------------- 1 | $v) { 39 | //参数为空不参与签名 40 | if ($k != 'sign' && $v != "" && !is_array($v)) { 41 | array_push($arrTmp, "$k=$v"); 42 | } 43 | } 44 | return implode('&', $arrTmp); 45 | } 46 | 47 | /** 48 | * 获取参数签名 49 | * @param $params 50 | * 51 | * @param $mch_key 52 | * @return string 53 | */ 54 | public static function getSign($params, $mch_key) 55 | { 56 | //第一步:对参数按照key=value的格式,并按照参数名ASCII字典序排序 57 | ksort($params); 58 | $stringA = QpayMchUtil::buildQueryStr($params); 59 | //第二步:拼接API密钥并md5 60 | $stringA = $stringA . '&key=' . $mch_key; 61 | $stringA = md5($stringA); 62 | //转成大写 63 | $sign = strtoupper($stringA); 64 | return $sign; 65 | } 66 | 67 | /** 68 | * 数组转换成xml字符串 69 | * @param $arr 70 | * @return string 71 | */ 72 | public static function arrayToXml($arr) 73 | { 74 | $xml = ''; 75 | foreach ($arr as $key => $val) { 76 | if (is_numeric($val)) { 77 | $xml .= "<$key>$val"; 78 | } else 79 | $xml .= "<$key>"; 80 | } 81 | $xml .= ''; 82 | return $xml; 83 | } 84 | 85 | /** 86 | * xml转换成数组 87 | * @param $xml 88 | * @return array|mixed|object 89 | */ 90 | public static function xmlToArray($xml) 91 | { 92 | $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); 93 | return $arr; 94 | } 95 | 96 | /** 97 | * 通用curl 请求接口。post方式 98 | * @param $params 99 | * @param $url 100 | * @param int $timeout 101 | * 102 | * @return bool|mixed 103 | */ 104 | public static function reqByCurlNormalPost($params, $url, $timeout = 10) 105 | { 106 | return QpayMchUtil::_reqByCurl($params, $url, $timeout, false); 107 | } 108 | 109 | /** 110 | * 使用ssl证书请求接口。post方式 111 | * @param $params 112 | * @param $url 113 | * @param array $ssl 114 | * @param int $timeout 115 | * @return bool|mixed 116 | */ 117 | public static function reqByCurlSSLPost($params, $url, $timeout, $ssl) 118 | { 119 | return QpayMchUtil::_reqByCurl($params, $url, $timeout, $ssl); 120 | } 121 | 122 | private static function _reqByCurl($params, $url, $timeout = 10, $needSSL = false) 123 | { 124 | $ch = curl_init(); 125 | 126 | curl_setopt($ch, CURLOPT_URL, $url); 127 | curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); 128 | 129 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 130 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); 131 | 132 | curl_setopt($ch, CURLOPT_HEADER, FALSE); 133 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 134 | //是否使用ssl证书 135 | if (isset($needSSL) && is_array($needSSL)) { 136 | curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); 137 | curl_setopt($ch, CURLOPT_SSLCERT, $needSSL['ssl_cert']); 138 | curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM'); 139 | curl_setopt($ch, CURLOPT_SSLKEY, $needSSL['ssl_key']); 140 | } 141 | curl_setopt($ch, CURLOPT_POST, true); 142 | curl_setopt($ch, CURLOPT_POSTFIELDS, $params); 143 | $ret = curl_exec($ch); 144 | if ($ret) { 145 | curl_close($ch); 146 | //log($ret); //业务记录交互流水。注:流水日志影响性能,如请求量过大,请慎重设计日志。 147 | return $ret; 148 | } else { 149 | $error = curl_errno($ch); 150 | // log($error); //业务记录错误日志 151 | // print_r($error); 152 | curl_close($ch); 153 | throw new Exception('curl_exec failed with ' . $error); 154 | } 155 | } 156 | 157 | } 158 | -------------------------------------------------------------------------------- /Pay/SwiftPass/Utils.class.php: -------------------------------------------------------------------------------- 1 | '; 11 | forEach ($array as $k => $v) { 12 | $xml .= '<' . $k . '>'; 13 | } 14 | $xml .= ''; 15 | return $xml; 16 | } 17 | 18 | public static function dataRecodes($title, $data) 19 | { 20 | $handler = fopen('result.txt', 'a+'); 21 | $content = "================" . $title . "===================\n"; 22 | if (is_string($data) === true) { 23 | $content .= $data . "\n"; 24 | } 25 | if (is_array($data) === true) { 26 | forEach ($data as $k => $v) { 27 | 28 | $content .= '<' . $k . '>' . "\n"; 29 | } 30 | } 31 | $flag = fwrite($handler, $content); 32 | fclose($handler); 33 | return $flag; 34 | } 35 | 36 | public static function parseXML($xmlSrc) 37 | { 38 | if (empty($xmlSrc)) { 39 | return false; 40 | } 41 | $array = array(); 42 | libxml_disable_entity_loader(true); 43 | $xml = simplexml_load_string($xmlSrc); 44 | $encode = Utils::getXmlEncode($xmlSrc); 45 | 46 | if ($xml && $xml->children()) { 47 | foreach ($xml->children() as $node) { 48 | //有子节点 49 | if ($node->children()) { 50 | $k = $node->getName(); 51 | $nodeXml = $node->asXML(); 52 | $v = substr($nodeXml, strlen($k) + 2, strlen($nodeXml) - 2 * strlen($k) - 5); 53 | 54 | } else { 55 | $k = $node->getName(); 56 | $v = (string)$node; 57 | } 58 | 59 | if ($encode != "" && $encode != "UTF-8") { 60 | $k = iconv("UTF-8", $encode, $k); 61 | $v = iconv("UTF-8", $encode, $v); 62 | } 63 | $array[$k] = $v; 64 | } 65 | } 66 | return $array; 67 | } 68 | 69 | //获取xml编码 70 | public static function getXmlEncode($xml) 71 | { 72 | $ret = preg_match("/]* encoding=\"(.*)\"[^>]* ?>/i", $xml, $arr); 73 | if ($ret) { 74 | return strtoupper($arr[1]); 75 | } else { 76 | return ""; 77 | } 78 | } 79 | } 80 | 81 | ?> -------------------------------------------------------------------------------- /Pay/SwiftPass/class/ClientResponseHandler.class.php: -------------------------------------------------------------------------------- 1 | ClientResponseHandler(); 39 | } 40 | 41 | function ClientResponseHandler() { 42 | $this->key = ""; 43 | $this->public_rsa_key = ""; 44 | $this->signtype = ""; 45 | $this->parameters = array(); 46 | $this->debugInfo = ""; 47 | $this->content = ""; 48 | } 49 | 50 | /** 51 | *获取密钥 52 | */ 53 | function getKey() { 54 | return $this->key; 55 | } 56 | 57 | /** 58 | *设置密钥 59 | */ 60 | function setKey($key) { 61 | $this->key = $key; 62 | } 63 | 64 | /*设置平台公钥*/ 65 | function setRSAKey($key) { 66 | $this->public_rsa_key = $key; 67 | } 68 | 69 | function setSignType($type) { 70 | $this->signtype = $type; 71 | } 72 | 73 | //设置原始内容 74 | function setContent($content) { 75 | $this->content = $content; 76 | 77 | libxml_disable_entity_loader(true); 78 | $xml = simplexml_load_string($this->content); 79 | $encode = $this->getXmlEncode($this->content); 80 | 81 | if($xml && $xml->children()) { 82 | foreach ($xml->children() as $node){ 83 | //有子节点 84 | if($node->children()) { 85 | $k = $node->getName(); 86 | $nodeXml = $node->asXML(); 87 | $v = substr($nodeXml, strlen($k)+2, strlen($nodeXml)-2*strlen($k)-5); 88 | 89 | } else { 90 | $k = $node->getName(); 91 | $v = (string)$node; 92 | } 93 | 94 | if($encode!="" && $encode != "UTF-8") { 95 | $k = iconv("UTF-8", $encode, $k); 96 | $v = iconv("UTF-8", $encode, $v); 97 | } 98 | 99 | $this->setParameter($k, $v); 100 | } 101 | } 102 | } 103 | 104 | //获取原始内容 105 | function getContent() { 106 | return $this->content; 107 | } 108 | 109 | /** 110 | *获取参数值 111 | */ 112 | function getParameter($parameter) { 113 | return isset($this->parameters[$parameter])?$this->parameters[$parameter] : ''; 114 | } 115 | 116 | /** 117 | *设置参数值 118 | */ 119 | function setParameter($parameter, $parameterValue) { 120 | $this->parameters[$parameter] = $parameterValue; 121 | } 122 | 123 | /** 124 | *获取所有请求的参数 125 | *@return array 126 | */ 127 | function getAllParameters() { 128 | return $this->parameters; 129 | } 130 | 131 | /** 132 | *是否平台签名,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 133 | *true:是 134 | *false:否 135 | */ 136 | function isTenpaySign() { 137 | $swiftpassSign = strtolower($this->getParameter("sign")); 138 | if ($this->getParameter('sign_type') == 'MD5') { 139 | return $this->getMD5Sign() == $swiftpassSign; 140 | } else if ($this->getParameter('sign_type') == 'RSA_1_1' || $this->getParameter('sign_type') == 'RSA_1_256') { 141 | return $this->verifyRSASign(); 142 | } 143 | } 144 | 145 | function getMD5Sign() { 146 | $signPars = ""; 147 | ksort($this->parameters); 148 | foreach($this->parameters as $k => $v) { 149 | if("sign" != $k && "" != $v) { 150 | $signPars .= $k . "=" . $v . "&"; 151 | } 152 | } 153 | $signPars .= "key=" . $this->getKey(); 154 | 155 | return strtolower(md5($signPars)); 156 | } 157 | 158 | function verifyRSASign() { 159 | $signPars = ""; 160 | ksort($this->parameters); 161 | foreach($this->parameters as $k => $v) { 162 | if("sign" != $k && "" != $v) { 163 | $signPars .= $k . "=" . $v . "&"; 164 | } 165 | } 166 | 167 | $signPars = substr($signPars, 0, strlen($signPars) - 1); 168 | $res = openssl_get_publickey($this->public_rsa_key); 169 | if ($this->getParameter('sign_type') == 'RSA_1_1') { 170 | $result = (bool)openssl_verify($signPars, base64_decode($this->getParameter("sign")), $res); 171 | openssl_free_key($res); 172 | return $result; 173 | } else if($this->getParameter('sign_type') == 'RSA_1_256') { 174 | $result = (bool)openssl_verify($signPars, base64_decode($this->getParameter("sign")), $res, OPENSSL_ALGO_SHA256); 175 | openssl_free_key($res); 176 | return $result; 177 | } 178 | } 179 | 180 | /** 181 | *获取debug信息 182 | */ 183 | function getDebugInfo() { 184 | return $this->debugInfo; 185 | } 186 | 187 | //获取xml编码 188 | function getXmlEncode($xml) { 189 | $ret = preg_match ("/]* encoding=\"(.*)\"[^>]* ?>/i", $xml, $arr); 190 | if($ret) { 191 | return strtoupper ( $arr[1] ); 192 | } else { 193 | return ""; 194 | } 195 | } 196 | 197 | /** 198 | *设置debug信息 199 | */ 200 | function _setDebugInfo($debugInfo) { 201 | $this->debugInfo = $debugInfo; 202 | } 203 | 204 | /** 205 | * 是否财付通签名 206 | * @param signParameterArray 签名的参数数组 207 | * @return boolean 208 | */ 209 | function _isTenpaySign($signParameterArray) { 210 | 211 | $signPars = ""; 212 | foreach($signParameterArray as $k) { 213 | $v = $this->getParameter($k); 214 | if("sign" != $k && "" != $v) { 215 | $signPars .= $k . "=" . $v . "&"; 216 | } 217 | } 218 | $signPars .= "key=" . $this->getKey(); 219 | 220 | $sign = strtolower(md5($signPars)); 221 | 222 | $tenpaySign = strtolower($this->getParameter("sign")); 223 | 224 | //debug信息 225 | $this->_setDebugInfo($signPars . " => sign:" . $sign . 226 | " tenpaySign:" . $this->getParameter("sign")); 227 | 228 | return $sign == $tenpaySign; 229 | 230 | 231 | } 232 | 233 | } 234 | 235 | 236 | ?> -------------------------------------------------------------------------------- /Pay/SwiftPass/class/PayHttpClient.class.php: -------------------------------------------------------------------------------- 1 | PayHttpClient(); 40 | } 41 | 42 | 43 | function PayHttpClient() { 44 | //$this->reqContent = ""; 45 | $this->url=""; 46 | $this->data=""; 47 | $this->resContent = ""; 48 | 49 | $this->errInfo = ""; 50 | 51 | $this->timeOut = 120; 52 | 53 | $this->responseCode = 0; 54 | 55 | } 56 | 57 | //设置请求内容 58 | function setReqContent($url,$data) { 59 | $this->url=$url; 60 | $this->data=$data; 61 | } 62 | 63 | //获取结果内容 64 | function getResContent() { 65 | return $this->resContent; 66 | } 67 | 68 | //获取错误信息 69 | function getErrInfo() { 70 | return $this->errInfo; 71 | } 72 | 73 | //设置超时时间,单位秒 74 | function setTimeOut($timeOut) { 75 | $this->timeOut = $timeOut; 76 | } 77 | 78 | //执行http调用 79 | function call() { 80 | //启动一个CURL会话 81 | $ch = curl_init(); 82 | 83 | // 设置curl允许执行的最长秒数 84 | curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeOut); 85 | curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); 86 | curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false); 87 | // 获取的信息以文件流的形式返回,而不是直接输出。 88 | curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); 89 | 90 | //发送一个常规的POST请求。 91 | curl_setopt($ch, CURLOPT_POST, 1); 92 | curl_setopt($ch, CURLOPT_URL, $this->url); 93 | //要传送的所有数据 94 | curl_setopt($ch, CURLOPT_POSTFIELDS, $this->data); 95 | 96 | // 执行操作 97 | $res = curl_exec($ch); 98 | $this->responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 99 | 100 | if ($res == NULL) { 101 | $this->errInfo = "call http err :" . curl_errno($ch) . " - " . curl_error($ch) ; 102 | curl_close($ch); 103 | return false; 104 | } else if($this->responseCode != "200") { 105 | $this->errInfo = "call http err httpcode=" . $this->responseCode ; 106 | curl_close($ch); 107 | return false; 108 | } 109 | 110 | curl_close($ch); 111 | $this->resContent = $res; 112 | 113 | 114 | return true; 115 | } 116 | 117 | function getResponseCode() { 118 | return $this->responseCode; 119 | } 120 | 121 | } 122 | ?> -------------------------------------------------------------------------------- /Pay/SwiftPass/class/RequestHandler.class.php: -------------------------------------------------------------------------------- 1 | RequestHandler(); 38 | } 39 | 40 | function RequestHandler() { 41 | $this->gateUrl = ""; 42 | $this->key = ""; 43 | $this->private_rsa_key = ""; 44 | $this->signtype = ""; 45 | $this->parameters = array(); 46 | $this->debugInfo = ""; 47 | } 48 | 49 | /** 50 | *初始化函数。 51 | */ 52 | function init() { 53 | //nothing to do 54 | } 55 | 56 | /** 57 | *获取入口地址,不包含参数值 58 | */ 59 | function getGateURL() { 60 | return $this->gateUrl; 61 | } 62 | 63 | /** 64 | *设置入口地址,不包含参数值 65 | */ 66 | function setGateURL($gateUrl) { 67 | $this->gateUrl = $gateUrl; 68 | } 69 | 70 | function setSignType($type) { 71 | $this->signtype = $type; 72 | } 73 | 74 | /** 75 | *获取MD5密钥 76 | */ 77 | function getKey() { 78 | return $this->key; 79 | } 80 | 81 | /** 82 | *设置MD5密钥 83 | */ 84 | function setKey($key) { 85 | $this->key = $key; 86 | } 87 | 88 | /*设置RSA私钥*/ 89 | function setRSAKey($key) { 90 | $this->private_rsa_key = $key; 91 | } 92 | 93 | /** 94 | *获取参数值 95 | */ 96 | function getParameter($parameter) { 97 | return isset($this->parameters[$parameter])?$this->parameters[$parameter]:''; 98 | } 99 | 100 | /** 101 | *设置参数值 102 | */ 103 | function setParameter($parameter, $parameterValue) { 104 | $this->parameters[$parameter] = $parameterValue; 105 | } 106 | 107 | /** 108 | * 一次性设置参数 109 | */ 110 | function setReqParams($post,$filterField=null){ 111 | if($filterField !== null){ 112 | forEach($filterField as $k=>$v){ 113 | unset($post[$v]); 114 | } 115 | } 116 | 117 | //判断是否存在空值,空值不提交 118 | forEach($post as $k=>$v){ 119 | if(empty($v)){ 120 | unset($post[$k]); 121 | } 122 | } 123 | 124 | $this->parameters = $post; 125 | } 126 | 127 | /** 128 | *获取所有请求的参数 129 | *@return array 130 | */ 131 | function getAllParameters() { 132 | return $this->parameters; 133 | } 134 | 135 | /** 136 | *获取带参数的请求URL 137 | */ 138 | function getRequestURL() { 139 | 140 | $this->createSign(); 141 | 142 | $reqPar = ""; 143 | ksort($this->parameters); 144 | foreach($this->parameters as $k => $v) { 145 | $reqPar .= $k . "=" . urlencode($v) . "&"; 146 | } 147 | 148 | //去掉最后一个& 149 | $reqPar = substr($reqPar, 0, strlen($reqPar)-1); 150 | 151 | $requestURL = $this->getGateURL() . "?" . $reqPar; 152 | 153 | return $requestURL; 154 | 155 | } 156 | 157 | /** 158 | *获取debug信息 159 | */ 160 | function getDebugInfo() { 161 | return $this->debugInfo; 162 | } 163 | 164 | /** 165 | *创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 166 | */ 167 | function createSign() { 168 | if($this->signtype == 'MD5') { 169 | $this->createMD5Sign(); 170 | } else { 171 | $this->createRSASign(); 172 | } 173 | } 174 | 175 | function createMD5Sign() { 176 | $signPars = ""; 177 | ksort($this->parameters); 178 | foreach($this->parameters as $k => $v) { 179 | if("" != $v && "sign" != $k) { 180 | $signPars .= $k . "=" . $v . "&"; 181 | } 182 | } 183 | $signPars .= "key=" . $this->getKey(); 184 | $sign = strtoupper(md5($signPars)); 185 | $this->setParameter("sign", $sign); 186 | 187 | //debug信息 188 | $this->_setDebugInfo($signPars . " => sign:" . $sign); 189 | } 190 | 191 | function createRSASign() { 192 | $signPars = ""; 193 | ksort($this->parameters); 194 | foreach($this->parameters as $k => $v) { 195 | if("" != $v && "sign" != $k) { 196 | $signPars .= $k . "=" . $v . "&"; 197 | } 198 | } 199 | 200 | $signPars = substr($signPars, 0, strlen($signPars) - 1); 201 | 202 | $res = openssl_get_privatekey($this->private_rsa_key); 203 | if ($this->signtype == 'RSA_1_1') { 204 | openssl_sign($signPars, $sign, $res); 205 | } else if ($this->signtype == 'RSA_1_256') { 206 | openssl_sign($signPars, $sign, $res, OPENSSL_ALGO_SHA256); 207 | } 208 | openssl_free_key($res); 209 | $sign = base64_encode($sign); 210 | $this->setParameter("sign", $sign); 211 | 212 | //debug信息 213 | $this->_setDebugInfo($signPars . " => sign:" . $sign); 214 | } 215 | 216 | /** 217 | *设置debug信息 218 | */ 219 | function _setDebugInfo($debugInfo) { 220 | $this->debugInfo = $debugInfo; 221 | } 222 | 223 | } 224 | 225 | ?> -------------------------------------------------------------------------------- /Pay/U9Pay/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 24 | $this->url_return = SYS_URL . '/pay/return/' . $id; 25 | } 26 | 27 | /** 28 | * @param array $config 29 | * @param string $out_trade_no 30 | * @param string $subject 31 | * @param string $body 32 | * @param int $amount_cent 33 | * @throws \Exception 34 | */ 35 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 36 | { 37 | if (!isset($config['id'])) { 38 | throw new \Exception('请填写id'); 39 | } 40 | if (!isset($config['key'])) { 41 | throw new \Exception('请填写key'); 42 | } 43 | if (!isset($config['gateway'])) { 44 | $gateway = 'http://1.u9clouds.com'; 45 | } else { 46 | $gateway = $config['gateway']; 47 | } 48 | $amount = sprintf('%.2f', $amount_cent / 100); // 元为单位 49 | $payway = $config['payway']; 50 | 51 | $params = [ 52 | 'pay_memberid' => $config['id'], // 商户id,由恒隆支付分配 53 | 'pay_orderid' => $out_trade_no, // 网站订单号 54 | 'pay_applydate' => date('Y-m-d H:i:s'), // 时间格式 55 | 'pay_bankcode' => $payway, 56 | 'pay_notifyurl' => $this->url_notify, 57 | 'pay_callbackurl' => $this->url_return . '/' . $out_trade_no, //这里 是微信 or 支付宝 支付完毕跳转的地址, 轮训等待成功 58 | 'pay_amount' => $amount, // 单位元(人民币) 59 | ]; 60 | 61 | $params['pay_md5sign'] = $this->getSign($params, $config['key']); 62 | $params['pay_productname'] = $subject; // 用户自定义商品名称, 不参与签名 63 | 64 | ?> 65 | 66 | 67 | 68 | 69 | 正在转到付款页 70 | 71 | 72 |
73 | $val) { 75 | echo ''; 76 | } 77 | ?> 78 |
79 | 80 | getSign($params, $config['key']) !== $_REQUEST['sign']) { 103 | Log::error('Pay.U9Pay.verify.notify, sign error $post:' . json_encode($_REQUEST)); 104 | echo 'sign error'; 105 | return false; 106 | } 107 | 108 | $order_no = $_REQUEST['orderid']; //上行过程中商户系统传入的商户系统订单 109 | $pay_trade_no = $_REQUEST['transaction_id']; //支付流水号 110 | $successCallback($order_no, (int)round($_REQUEST['amount'] * 100), $pay_trade_no); 111 | 112 | echo 'ok'; 113 | return true; 114 | } else { 115 | if (!empty($config['out_trade_no'])) { 116 | // 主动查询接口, 此接口不支持.... 117 | // 此驱动, 不支持主动查询交易结果, 直接返回失败(未支付) 118 | return false; 119 | } 120 | 121 | // return page 122 | $sign_column = ['memberid', 'orderid', 'transaction_id', 'amount', 'datetime', 'returncode']; 123 | $params = []; 124 | foreach ($sign_column as $column) 125 | $params[$column] = $_REQUEST[$column]; 126 | 127 | if ($this->getSign($params, $config['key']) !== $_REQUEST['sign']) { 128 | Log::error('Pay.U9Pay.verify.return, sign error $_REQUEST:' . json_encode($_REQUEST)); 129 | echo 'sign error'; 130 | return false; 131 | } 132 | 133 | $order_no = $_REQUEST['orderid']; //上行过程中商户系统传入的商户系统订单 134 | $pay_trade_no = $_REQUEST['transaction_id']; //支付流水号 135 | $successCallback($order_no, (int)round($_REQUEST['amount'] * 100), $pay_trade_no); 136 | 137 | return true; 138 | } 139 | } 140 | 141 | private function getSign($params, $key) 142 | { 143 | ksort($params); 144 | $tmp = array(); 145 | foreach ($params as $k => $v) { 146 | // 参数为空不参与签名 147 | if ($v !== '' && !is_array($v)) { 148 | array_push($tmp, "$k=$v"); 149 | } 150 | } 151 | $params = implode('&', $tmp); 152 | $sign_data = $params . '&key=' . $key; 153 | return strtoupper(md5($sign_data)); 154 | } 155 | 156 | /** 157 | * 退款操作 158 | * @param array $config 支付渠道配置 159 | * @param string $order_no 订单号 160 | * @param string $pay_trade_no 支付渠道流水号 161 | * @param int $amount_cent 金额/分 162 | * @return true|string true 退款成功 string 失败原因 163 | */ 164 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 165 | { 166 | return '此支付渠道不支持发起退款, 请手动操作'; 167 | } 168 | } -------------------------------------------------------------------------------- /Pay/UigPay/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 26 | $this->url_return = SYS_URL . '/pay/return/' . $id; 27 | } 28 | 29 | /** 30 | * @param array $config 31 | * @param string $out_trade_no 32 | * @param string $subject 33 | * @param string $body 34 | * @param int $amount_cent 35 | * @throws \Exception 36 | */ 37 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 38 | { 39 | if (empty($config['id'])) { 40 | throw new \Exception('请填写商户编号 [id]'); 41 | } 42 | if (empty($config['key'])) { 43 | throw new \Exception('请填写商户密钥 [key]'); 44 | } 45 | 46 | $params = [ 47 | 'version' => '1.0', 48 | 'customerid' => $config['id'], 49 | 'sdorderno' => $out_trade_no, 50 | 'total_fee' => sprintf('%.2f', $amount_cent / 100), 51 | 'notifyurl' => $this->url_notify, 52 | 'returnurl' => $this->url_return, 53 | 'remark' => $subject 54 | ]; 55 | 56 | $params['sign'] = md5("version={$params['version']}&customerid={$params['customerid']}&total_fee={$params['total_fee']}&sdorderno={$params['sdorderno']}¬ifyurl={$params['notifyurl']}&returnurl={$params['returnurl']}&{$config['key']}"); 57 | die(' 58 | 59 | 60 | 61 | 62 | 正在转到付款页 63 | 64 | 65 |
66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
75 | 76 | '); 77 | } 78 | 79 | function verify($config, $successCallback) 80 | { 81 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 82 | 83 | if ($isNotify) { 84 | $sign = md5("customerid={$_POST['customerid']}&status={$_POST['status']}&sdpayno={$_POST['sdpayno']}&sdorderno={$_POST['sdorderno']}&total_fee={$_POST['total_fee']}&paytype={$_POST['paytype']}&{$config['key']}"); 85 | if ($sign !== $_POST['sign']) { 86 | echo 'sign_error'; 87 | return false; 88 | } 89 | echo 'success'; 90 | 91 | if ( $_POST['status'] === '1') { 92 | $order_no = $_POST['sdorderno']; // 本系统订单号 93 | $total_fee = (int)round($_POST['total_fee'] * 100); 94 | $pay_no = $_POST['sdpayno']; // API渠道订单号 95 | $successCallback($order_no, $total_fee, $pay_no); 96 | return true; 97 | } 98 | 99 | return false; 100 | } 101 | 102 | 103 | // 可能是主动查询 104 | if (!empty($config['out_trade_no'])) { 105 | $data = [ 106 | 'customerid' => $config['id'], 107 | 'sdorderno' => $config['out_trade_no'], 108 | 'reqtime' => date('YmdHis'), 109 | ]; 110 | $data['sign'] = md5("customerid={$data['customerid']}&sdorderno={$data['sdorderno']}&reqtime={$data['reqtime']}&{$config['key']}"); 111 | $ret_raw = CurlRequest::post('http://www.guupay.com/apiorderquery' , http_build_query($data)); 112 | $ret = @json_decode($ret_raw, true); 113 | if (!$ret || !isset($ret['status'])) { 114 | Log::error('Pay.UigPay.verify, request failed', ['response' => $ret_raw]); 115 | return false; 116 | } 117 | if($ret['status'] === 1){ 118 | $order_no = $ret['sdorderno']; // 本系统订单号 119 | $total_fee = (int)round($ret['total_fee'] * 100); 120 | $pay_no = $ret['sdpayno']; // API渠道订单号 121 | $successCallback($order_no, $total_fee, $pay_no); 122 | return true; 123 | } 124 | return false; 125 | } 126 | 127 | $sign = md5("customerid={$_GET['customerid']}&status={$_GET['status']}&sdpayno={$_GET['sdpayno']}&sdorderno={$_GET['sdorderno']}&total_fee={$_GET['total_fee']}&paytype={$_GET['paytype']}&{$config['key']}"); 128 | if ($sign !== $_GET['sign']) { 129 | echo 'sign_error'; 130 | return false; 131 | } 132 | echo 'success'; 133 | 134 | if ( $_GET['status'] === '1') { 135 | $order_no = $_GET['sdorderno']; // 本系统订单号 136 | $total_fee = (int)round($_GET['total_fee'] * 100); 137 | $pay_no = $_GET['sdpayno']; // API渠道订单号 138 | $successCallback($order_no, $total_fee, $pay_no); 139 | return true; 140 | } 141 | 142 | return false; 143 | } 144 | 145 | /** 146 | * 退款操作 147 | * @param array $config 支付渠道配置 148 | * @param string $order_no 订单号 149 | * @param string $pay_trade_no 支付渠道流水号 150 | * @param int $amount_cent 金额/分 151 | * @return true|string true 退款成功 string 失败原因 152 | */ 153 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 154 | { 155 | return '此支付渠道不支持发起退款, 请手动操作'; 156 | } 157 | } -------------------------------------------------------------------------------- /Pay/Unk1Pay/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 34 | $this->url_return = SYS_URL . '/pay/return/' . $id; 35 | } 36 | 37 | /** 38 | * @param array $config 支付渠道配置 39 | * @param string $out_trade_no 外部订单号 40 | * @param string $subject 商品名称 41 | * @param string $body 商品介绍 42 | * @param int $amount_cent 金额/分 43 | * @throws \Exception 44 | */ 45 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 46 | { 47 | $total_fee = sprintf('%.2f', $amount_cent / 100); // 元为单位 48 | 49 | if (!isset($config['appid'])) { 50 | throw new \Exception('请设置appid'); 51 | } 52 | if (!isset($config['appsecret'])) { 53 | throw new \Exception('请设置appsecret'); 54 | } 55 | if (!isset($config['gateway'])) { 56 | throw new \Exception('请设置gateway'); 57 | } 58 | 59 | $data = array( 60 | 'amount' => $amount_cent, 61 | 'payway' => $config['payway'], // 1支付宝 2微信 62 | 'appid' => $config['appid'], 63 | 'sign' => md5($config['appid'] . md5($amount_cent) . md5($config['appsecret'])), 64 | 'extension' => $out_trade_no 65 | ); 66 | 67 | $ret_raw = CurlRequest::post($config['gateway'] . '/api3/needQrcode', http_build_query($data)); 68 | $ret = @json_decode($ret_raw, true); 69 | if (!$ret || !isset($ret['code']) || $ret['code'] !== 200) { 70 | Log::error('Pay.Unk1Pay.goPay.order, request failed', ['response' => $ret_raw]); 71 | throw new \Exception('获取付款信息超时, 请刷新重试'); 72 | } 73 | 74 | 75 | Log::debug('Pay.Unk1Pay.goPay.order', ['response' => $ret]); 76 | switch (strtoupper($config['payway'])) { 77 | case 1: 78 | header('location: /qrcode/pay/' . $out_trade_no . '/aliqr?url=' . urlencode($ret['data']['qrcode'])); 79 | break; 80 | case 2: 81 | header('location: /qrcode/pay/' . $out_trade_no . '/wechat?url=' . urlencode($ret['data']['qrcode'])); 82 | break; 83 | default: 84 | throw new \Exception('支付方式错误'); 85 | } 86 | exit(0); 87 | } 88 | 89 | /** 90 | * @param $config 91 | * @param callable $successCallback 成功回调 (系统单号,交易金额/分,支付渠道单号) 92 | * @return bool|string true 验证通过 string 失败原因 93 | * @throws \Exception 94 | */ 95 | function verify($config, $successCallback) 96 | { 97 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 98 | if ($isNotify) { 99 | if (!isset($_POST['sign'])) { 100 | return false; 101 | } 102 | 103 | Log::debug('Pay.Unk1Pay.verify', ['$_POST' => $_POST]); 104 | 105 | if ($_POST['sign'] === md5($config['appid'] . md5($_POST['orderid']) . $config['appsecret'])) { 106 | $successCallback($_POST['extension'], (int)$_POST['amount'], $_POST['orderid']); 107 | echo 'success'; 108 | return true; 109 | } 110 | 111 | echo 'fail'; 112 | return false; 113 | } else { 114 | // 主动查询交易结果 115 | if (!empty($config['out_trade_no'])) { 116 | $order_no = @$config['out_trade_no']; //商户订单号 117 | return false; // 不支持 118 | } 119 | // 暂无 120 | return false; 121 | } 122 | } 123 | 124 | /** 125 | * 退款操作 126 | * @param array $config 支付渠道配置 127 | * @param string $order_no 订单号 128 | * @param string $pay_trade_no 支付渠道流水号 129 | * @param int $amount_cent 金额/分 130 | * @return true|string true 退款成功 string 失败原因 131 | */ 132 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 133 | { 134 | return '此支付渠道不支持发起退款, 请手动操作'; 135 | } 136 | } -------------------------------------------------------------------------------- /Pay/VPay/README.md: -------------------------------------------------------------------------------- 1 | # V免签 2 | VPay / vmq 3 | 4 | 5 | ## 安装 6 | 7 | 测试通过的后台: https://github.com/dreamncn/VPay 8 | 9 | 1. 下载 10 | 2. 按照教程进行安装 11 | 3. 系统设置-随机生成通讯密钥 12 | 4. 系统设置-上传微信/支付宝二维码 13 | 5. 监控端配置-手机APP( [V免签监控端](https://github.com/szvone/vmqApk/releases) )扫码 14 | 15 | ## 发卡系统内配置 16 | 17 | 1. 驱动安装 (3.14以及更高版本无需) 18 | - `Api.php` 放入 `app/Library/Gateway/Pay/VPay/Api.php` 19 | - `vpay_alipay.blade.php` 放入 `resources/views/pay/vpay_alipay.blade.php` 20 | - `vpay_wechat.blade.php` 放入 `resources/views/pay/vpay_wechat.blade.php` 21 | 22 | 23 | 2. 后台添加支付子渠道 24 | - 驱动: VPay 25 | - 支付方式: 微信填`1`, 支付宝填`2` 26 | - 配置 (JSON格式): 27 | ```json 28 | { 29 | "gateway": "你的VPay网站地址, 如[http://xxx.example.com] (末尾不带/)", 30 | "id": "你的VPay后台应用[ID]", 31 | "key": "你的VPay后台应用[通讯密钥]" 32 | } 33 | ``` 34 | ![如图所示](example.png) 35 | 36 | 37 | 3. V免签后台-应用管理, 修改同步回调/异步回调为子渠道最后一个按钮点开显示的地址 (支付宝和微信任意子渠道均可) 38 | 4. 前台支付加入一下刚添加的子渠道, 配置完毕 39 | 40 | 41 | 42 | ## 常见问题 43 | 44 | 1. 提示"该时间段订单量过大,请换个时间尝试重试" 45 | 46 | V免签根据支付金额来判断支付用户, 当同时多个用户付款时根据不同金额区分用户, 默认规则为金额递减, 减到一定程序会提示此错误, 可以改为金额递增 47 | 48 | 49 | 50 | 2. 订单不通知 51 | - 参考问题1, 可能用户支付了错误的金额导致判断失败, 手动进后台补单吧! 52 | - apk很久没人维护了, 各种BUG, 这个自己参考 https://github.com/szvone/vmqApk/issues 尝试解决 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Pay/VPay/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tai7sy/card-gateway/c13a0c7201bd1c2f9d4dbe2e996f3225e00e4202/Pay/VPay/example.png -------------------------------------------------------------------------------- /Pay/VPay/vpay_wechat.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 微信支付 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |

16 | 微信支付 17 |

18 |
19 |
20 |
请输入准确的付款金额(精确到分)
21 |
¥{{ $_GET["real_price"] }}
22 |
23 |
24 | 请截屏此界面或保存二维码,打开微信扫码,选择相册图片 25 | 点击打开微信 26 |
27 |
28 | 38 | 39 |
40 |
41 | 42 | 43 |
44 |
45 |

请使用微信扫一扫

46 |

扫描二维码完成支付

47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |

, 有疑问请联系客服

55 |
56 |
57 |
58 | 59 | 115 | 116 | -------------------------------------------------------------------------------- /Pay/WeChat/PayNotifyCallBack.php: -------------------------------------------------------------------------------- 1 | successCallback = $successCallback; 19 | } 20 | 21 | //查询订单 22 | public function QueryOrder($transaction_id) 23 | { 24 | $input = new \WxPayOrderQuery(); 25 | $input->SetTransaction_id($transaction_id); 26 | $result = \WxPayApi::orderQuery($input); 27 | \WxLog::DEBUG('query:' . json_encode($result)); 28 | if (array_key_exists('return_code', $result) && 29 | array_key_exists('result_code', $result) && 30 | $result['return_code'] == 'SUCCESS' && 31 | $result['result_code'] == 'SUCCESS') { 32 | return true; 33 | } 34 | return false; 35 | } 36 | 37 | //重写回调处理函数 38 | public function NotifyProcess($data, &$msg) 39 | { 40 | \WxLog::DEBUG('call back:' . json_encode($data)); 41 | 42 | if (!array_key_exists('transaction_id', $data)) { 43 | $msg = '输入参数不正确'; 44 | \WxLog::DEBUG('begin process 输入参数不正确'); 45 | return false; 46 | } 47 | //查询订单,判断订单真实性 48 | if (!$this->QueryOrder($data['transaction_id'])) { 49 | $msg = '订单查询失败'; 50 | \WxLog::DEBUG('begin process 订单查询失败'); 51 | return false; 52 | } 53 | //貌似是这里处理流程? 卧槽他大爷的微信开发者 54 | //\WxLog::DEBUG('begin process:'.$data['attach'].'--'.$data['total_fee'].'--'.$data['out_trade_no']); 55 | 56 | if($this->successCallback){ 57 | call_user_func_array($this->successCallback,[$data['out_trade_no'],$data['total_fee'],$data['transaction_id']]); 58 | } 59 | return true; 60 | } 61 | } 62 | 63 | //\WxLog::DEBUG('begin notify'); 64 | -------------------------------------------------------------------------------- /Pay/WeChat/README.md: -------------------------------------------------------------------------------- 1 | 2 | # WeChat 官方接口 3 | 4 | 使用说明 5 | * 驱动 WeChat 6 | * 方式 NATIVE / MWEB / JSAPI 7 | - NATIVE 扫码支付 8 | - MWEB H5支付(需开通权限) 9 | - JSAPI 微信内支付(此方式无序手动配置, 会自动检测在微信内从而自动使用此方式) 10 | * 配置 (JSON格式) 11 | ```json 12 | { 13 | "APPID": "APPID", 14 | "APPSECRET": "APP_SECRET", 15 | "MCHID": "商户ID", 16 | "KEY": "KEY", 17 | "sub_mch_id": "子商户ID(可选)", 18 | "sub_appid": "子商户APPID(可选)", 19 | } 20 | ``` 21 | -------------------------------------------------------------------------------- /Pay/WeChat/WxLog.php: -------------------------------------------------------------------------------- 1 | $val) { 21 | if (array_key_exists("file", $val)) { 22 | $stack .= ",file:" . $val["file"]; 23 | } 24 | if (array_key_exists("line", $val)) { 25 | $stack .= ",line:" . $val["line"]; 26 | } 27 | if (array_key_exists("function", $val)) { 28 | $stack .= ",function:" . $val["function"]; 29 | } 30 | } 31 | $stack .= "]"; 32 | \Illuminate\Support\Facades\Log::error($stack . $msg); 33 | } 34 | 35 | public static function INFO($msg) 36 | { 37 | \Illuminate\Support\Facades\Log::info($msg); 38 | } 39 | } 40 | 41 | 42 | -------------------------------------------------------------------------------- /Pay/WeChat/WxPay.NativePay.php: -------------------------------------------------------------------------------- 1 | SetProduct_id($productId); 23 | $values = WxpayApi::bizpayurl($biz); 24 | $url = "weixin://wxpay/bizpayurl?" . $this->ToUrlParams($values); 25 | return $url; 26 | } 27 | 28 | /** 29 | * 30 | * 参数数组转换为url参数 31 | * @param array $urlObj 32 | * @return string 33 | */ 34 | private function ToUrlParams($urlObj) 35 | { 36 | $buff = ""; 37 | foreach ($urlObj as $k => $v) { 38 | $buff .= $k . "=" . $v . "&"; 39 | } 40 | 41 | $buff = trim($buff, "&"); 42 | return $buff; 43 | } 44 | 45 | /** 46 | * 统一下单 47 | * @param \WxPayUnifiedOrder $input 48 | * @return string|成功时返回,其他抛异常 49 | * @throws WxPayException 50 | */ 51 | public function unifiedOrder($input) 52 | { 53 | return WxPayApi::unifiedOrder($input); 54 | } 55 | } -------------------------------------------------------------------------------- /Pay/WeChat/cert/apiclient_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEdjCCA9+gAwIBAgICdTcwDQYJKoZIhvcNAQEFBQAwgYoxCzAJBgNVBAYTAkNO 3 | MRIwEAYDVQQIEwlHdWFuZ2RvbmcxETAPBgNVBAcTCFNoZW56aGVuMRAwDgYDVQQK 4 | EwdUZW5jZW50MQwwCgYDVQQLEwNXWEcxEzARBgNVBAMTCk1tcGF5bWNoQ0ExHzAd 5 | BgkqhkiG9w0BCQEWEG1tcGF5bWNoQHRlbmNlbnQwHhcNMTQxMjExMTE0ODA1WhcN 6 | MjQxMjA4MTE0ODA1WjCBpzELMAkGA1UEBhMCQ04xEjAQBgNVBAgTCUd1YW5nZG9u 7 | ZzERMA8GA1UEBxMIU2hlbnpoZW4xEDAOBgNVBAoTB1RlbmNlbnQxDjAMBgNVBAsT 8 | BU1NUGF5MTwwOgYDVQQDFDPkuK3lm73lnLDotKjlpKflrabvvIjmrabmsYnvvInm 9 | lZnogrLlj5HlsZXln7rph5HkvJoxETAPBgNVBAQTCDEwMDYwMjY4MIIBIjANBgkq 10 | hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2lfWB/a41ppF+siCZkCVwYyLxRixuOwq 11 | EcajtHCS0zqCzF4/LHHX9yDZJqETWtPbPX2UYJIaug2/yMT/wzK0kxrDi1LOIqYo 12 | 13wIJ0sntE6Bvb48JTfO6RtjOXD+Xane2pPzkMkpy7MAN+bXCjYWHuQ/4jj2bF8I 13 | y31j0AcS10kjI6O2athkMSRQ/JNMNyGCiuHe2gbLfbGTeG+3m14gxWcYJMbVxd7j 14 | SRpb7uh90wHqOVaYpsgd2SXulbXqHvPYUuJZdecn1gAbN1OFnnHyJfovbX5x2TK+ 15 | rBr1xC7JHbvqfNTC9RdGjjCwdV1m7x3UsX61Sljt1fZ0666NzaUwjwIDAQABo4IB 16 | RjCCAUIwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdIkNFUy1DQSBHZW5lcmF0 17 | ZSBDZXJ0aWZpY2F0ZSIwHQYDVR0OBBYEFDa6vd5UCEPP9qL20yo0+PsLMKnvMIG/ 18 | BgNVHSMEgbcwgbSAFD4FJvYiYrQVW4jNZH6w1GKn5YZ0oYGQpIGNMIGKMQswCQYD 19 | VQQGEwJDTjESMBAGA1UECBMJR3Vhbmdkb25nMREwDwYDVQQHEwhTaGVuemhlbjEQ 20 | MA4GA1UEChMHVGVuY2VudDEMMAoGA1UECxMDV1hHMRMwEQYDVQQDEwpNbXBheW1j 21 | aENBMR8wHQYJKoZIhvcNAQkBFhBtbXBheW1jaEB0ZW5jZW50ggkAu1SXK7wA6Fcw 22 | DgYDVR0PAQH/BAQDAgbAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3 23 | DQEBBQUAA4GBAEiS/XnCrRXJG2NKJpW/l/7eu1yqi5XAQ3OiTilSQGiD1Pu3uuUy 24 | 141ZGSoRxtsdPelOSfYKhLFHzDoqK82UsviMfUpeZq7vW3ZoTL7bMKgI3GJnGsRk 25 | 4Wb/0JkmQJckhSKqM6FSEWrCFENK7HuPirlaztLhGRcZwXtPXqBLfooa 26 | -----END CERTIFICATE----- 27 | -------------------------------------------------------------------------------- /Pay/WeChat/cert/apiclient_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA2lfWB/a41ppF+siCZkCVwYyLxRixuOwqEcajtHCS0zqCzF4/ 3 | LHHX9yDZJqETWtPbPX2UYJIaug2/yMT/wzK0kxrDi1LOIqYo13wIJ0sntE6Bvb48 4 | JTfO6RtjOXD+Xane2pPzkMkpy7MAN+bXCjYWHuQ/4jj2bF8Iy31j0AcS10kjI6O2 5 | athkMSRQ/JNMNyGCiuHe2gbLfbGTeG+3m14gxWcYJMbVxd7jSRpb7uh90wHqOVaY 6 | psgd2SXulbXqHvPYUuJZdecn1gAbN1OFnnHyJfovbX5x2TK+rBr1xC7JHbvqfNTC 7 | 9RdGjjCwdV1m7x3UsX61Sljt1fZ0666NzaUwjwIDAQABAoIBAQDEATXR0Fn9zGAl 8 | 0Pm+cRv+s/yE4rYoG1lou7kZsjUcCdqBO9naPBhzcLl/Q/nr/2NAwAsC5iW3/7+6 9 | q54tzMbth4ki+SKzWBYx2tY27/CknBU8EBpODttfx4Y7eoPd8TBtZ4Ou5ebvRbFc 10 | fY1tTUBuWtg+bIRKpMVwZw/DH5Z6SzUHrDZNCY7h57GVKZVgjeq1upDfvy+fIf+x 11 | 42KW1byhSi2WirD6D547u3pDk9KBxmnPXjJxkDQ5iHRKM1zG3yxTBQ56SHMJ7uw1 12 | AV9dtGDzO4TQGBLS16gfKVyGdjfkM4zmZDvOXxYB5Rbv0iJuTwEA/SENCkaYnBxv 13 | +byughqBAoGBAPBVmJjM8SS/fkinJ4K9ka9BiWyo8xmi2RIslyx32zuZI3XfzMfn 14 | 2j0URN2IgpPL+4S1rdjYrJ35cbPhN9wIF9J/bb2lsOlno/+9dSbN1nO0nHpmQwKv 15 | +dh+rwdlDaV58p9hdjFXKDd8uv6hfJjpkwsmZubJPXrPGFOF22FhRRojAoGBAOiT 16 | Ru4GVj414mEvW94J8YaMFwrT7Cb3YjjxL0Xj1zE9OOq+JxEeanhYgf2sTpB4HzOA 17 | JKsg4F2CAd4G0mgQ47ykzYJneGV6iPydzdnXRloi/LBQI9HWZWjUBUHrMmmiWBVQ 18 | w7hQvsqx9bDmtMs8HpkEUB84uIAsPi/Tl4WkkMilAoGADLA4Mjj/sjT58dQBXgGs 19 | I1iObNIuo3fZhgAcqxhY1rirCpoaMaOn/fmH+TovyqXGTadZ2kz2MBDvU9PcIx26 20 | RD6+CHkq8eeq3OGfwcC0Rb+PU1b6yrWHt0pY60cGhWn+yTNYDhrP4L4REUhtT5Vl 21 | Uf1hCWYufMFaQ26ZunZsM4kCgYBO/QYP/RL5We+itiTrSlE/MwD4anU/3rD7Sd6W 22 | TAVf8b0M7Lvz8nKSoOy1LPoZ0tI1+YV6oVXSLD9aGtMHCQVvokEx0tZvEKjJswag 23 | v55jKpLLhsxDjh8u9SM7+hdLDRoBU0bFqJbD3KDnDdPFWovByFc141u2HFCaibBi 24 | cTvDCQKBgHCRbP/p9/8CJeFGWGdBIUDhJWLg39HQgSfIdN9qg3CJ7GMwO3MN5leL 25 | qT2v8GfNfzrnCKyCuV17U82D1MiWAR/LVW9/OwOoQG9l1QYLNhuPoNW72MtCuxtA 26 | HQD/8706yQZzLwdnDzUTuhQxJJtb1++pnNOBwi4NL0VfuYsO0/t1 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /Pay/WeChat/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 微信支付样例 6 | 54 | 55 | 56 |
57 | 67 |
68 | 69 | -------------------------------------------------------------------------------- /Pay/WeChat/lib/WxPay.Config.php: -------------------------------------------------------------------------------- 1 | getMessage(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Pay/WeChat/lib/WxPay.Notify.php: -------------------------------------------------------------------------------- 1 | SetReturn_code("FAIL"); 22 | $this->SetReturn_msg($msg); 23 | $this->ReplyNotify(false); 24 | return; 25 | } else { 26 | //该分支在成功回调到NotifyCallBack方法,处理完成之后流程 27 | $this->SetReturn_code("SUCCESS"); 28 | $this->SetReturn_msg("OK"); 29 | } 30 | $this->ReplyNotify($needSign); 31 | } 32 | 33 | /** 34 | * 35 | * 回调方法入口,子类可重写该方法 36 | * 注意: 37 | * 1、微信回调超时时间为2s,建议用户使用异步处理流程,确认成功之后立刻回复微信服务器 38 | * 2、微信服务器在调用失败或者接到回包为非确认包的时候,会发起重试,需确保你的回调是可以重入 39 | * @param array $data 回调解释出的参数 40 | * @param string $msg 如果回调处理失败,可以将错误信息输出到该方法 41 | * @return true 回调出来完成不需要继续回调,false回调处理未完成需要继续回调 42 | */ 43 | public function NotifyProcess($data, &$msg) 44 | { 45 | //TO2DO 用户基础该类之后需要重写该方法,成功的时候返回true,失败返回false 46 | return true; 47 | } 48 | 49 | /** 50 | * 51 | * notify回调方法,该方法中需要赋值需要输出的参数,不可重写 52 | * @param array $data 53 | * @return true 回调出来完成不需要继续回调,false回调处理未完成需要继续回调 54 | */ 55 | final public function NotifyCallBack($data) 56 | { 57 | $msg = "OK"; 58 | $result = $this->NotifyProcess($data, $msg); 59 | 60 | if($result == true){ 61 | $this->SetReturn_code("SUCCESS"); 62 | $this->SetReturn_msg("OK"); 63 | } else { 64 | $this->SetReturn_code("FAIL"); 65 | $this->SetReturn_msg($msg); 66 | } 67 | return $result; 68 | } 69 | 70 | /** 71 | * 72 | * 回复通知 73 | * @param bool $needSign 是否需要签名输出 74 | * @throws WxPayException 75 | */ 76 | final private function ReplyNotify($needSign = true) 77 | { 78 | //如果需要签名 79 | if($needSign == true && $this->GetReturn_code() == "SUCCESS") { 80 | $this->SetSign(); 81 | } 82 | WxpayApi::replyNotify($this->ToXml()); 83 | } 84 | } -------------------------------------------------------------------------------- /Pay/WeChat/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /Pay/Yeke/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 17 | $this->url_return = SYS_URL . '/pay/return/' . $id; 18 | } 19 | 20 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 21 | { 22 | $amount = sprintf("%.2f", $amount_cent / 100); 23 | 24 | define('yeke_USER_ID', $config['id']);//接入商户ID 25 | define('yeke_USER_KEY', $config['key']);//接入密钥 26 | define('yeke_USER_LOG_PREFIX', 'log'); 27 | define('yeke_API_GATE', 'http://www.yekepay.com/api/ApiGo.php');//网关地址 28 | 29 | $bankType = strtolower($config['payway']); 30 | $yekePayType = ''; 31 | $yekePayGate = ''; 32 | if ($bankType == 'alipay' || $bankType == 'alipay_wap') { 33 | $yekePayType = 'alipay'; 34 | $yekePayGate = 'ALIPAY'; 35 | } elseif ($bankType == 'tenpay' || $bankType == 'tenpay_wap') { 36 | $yekePayType = 'tenpay'; 37 | $yekePayGate = 'TENPAY'; 38 | } elseif ($bankType == 'weixin') { 39 | $yekePayType = 'weixin'; 40 | $yekePayGate = 'WEIXIN'; 41 | } elseif ($bankType == 'weixin_wap') { 42 | $yekePayType = 'wxwap'; 43 | $yekePayGate = 'wxwap'; 44 | } elseif ($bankType == 'qq' || $bankType == 'qq_wap') { 45 | $yekePayType = 'sqzf'; 46 | $yekePayGate = 'sqzf'; 47 | } elseif ($bankType == 'qq_wap') { 48 | $yekePayType = 'sqzfqb'; 49 | $yekePayGate = 'sqzfqb'; 50 | } 51 | 52 | 53 | require 'yekeApiLib.php'; 54 | require 'HttpClient.php'; 55 | 56 | 57 | $subject = mb_substr($subject, 0, 50, 'UTF-8'); 58 | $body = mb_substr($body, 0, 100, 'UTF-8'); 59 | 60 | $params = array( 61 | 'P_orderid' => $out_trade_no, //外部订单号 62 | 'P_paymoney' => $amount, //充值金额,格式为 18.60 63 | 'P_productname' => urlencode($subject), //商品名称,最多支持100个字符 64 | 'P_productinfo' => urlencode($body), //商品简介,最多支持200个字符 65 | 'P_remark' => urlencode($out_trade_no), //备注说明,最多支持300个字符 66 | 'P_custom_1' => urlencode($yekePayGate), //自定义内容一,最多支持100个字符 67 | 'P_custom_2' => '', //自定义内容二,最多支持100个字符 68 | 'P_contact' => urlencode(SYS_NAME), //联系方式 69 | 'P_paytype' => $yekePayType, //充值方式 70 | 'P_gateway' => $yekePayGate, //充值网关 71 | 'P_cardnum' => '', 72 | 'P_cardpwd' => '', 73 | 'P_cardvalue' => '', 74 | 'P_notify_url' => $this->url_notify, 75 | 'P_return_url' => $this->url_return . '/' . $out_trade_no, 76 | ); 77 | $API = new \yekeAPI(); 78 | $result = $API->payGate($params); 79 | echo $result; 80 | } 81 | 82 | function verify($config, $successCallback) 83 | { 84 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 85 | define('yeke_USER_ID', $config['id']);//接入商户ID 86 | define('yeke_USER_KEY', $config['key']);//接入密钥 87 | define('yeke_USER_LOG_PREFIX', 'log'); 88 | define('yeke_API_GATE', 'http://www.yekepay.com/api/ApiGo.php');//网关地址 89 | require 'HttpClient.php'; 90 | require 'yekeApiLib.php'; 91 | 92 | //验证订单 93 | $API = new \yekeAPI(); 94 | if ($isNotify) { 95 | $result = $API->verifyNotify();// 高能 这个函数里面异常吃屎的又 urlencode了一次 96 | } else { 97 | $result = $API->verifyReturn();// 高能 这个函数里面异常吃屎的又 urlencode了一次 98 | } 99 | 100 | if ($result) { 101 | $P_orderid = $_REQUEST['P_orderid'];//API交易订单号 102 | $P_api_orderid = $_REQUEST['P_api_orderid'];//商户订单号 103 | $P_money = $_REQUEST['P_money']; 104 | // $attach = urldecode($_POST['P_remark']); 105 | // $P_custom_1 = $_POST['P_custom_1']; 106 | // 订单成功状态 107 | if ($_REQUEST['P_status'] == 'SUCCESS') { 108 | $successCallback($P_api_orderid, (int)round($P_money * 100), $P_orderid); 109 | if ($isNotify) echo 'success'; 110 | return true; 111 | } else { 112 | if ($isNotify) echo '失败订单'; 113 | } 114 | } else { 115 | if ($isNotify) echo '验证失败'; 116 | } 117 | 118 | return false; 119 | } 120 | 121 | /** 122 | * 退款操作 123 | * @param array $config 支付渠道配置 124 | * @param string $order_no 订单号 125 | * @param string $pay_trade_no 支付渠道流水号 126 | * @param int $amount_cent 金额/分 127 | * @return true|string true 退款成功 string 失败原因 128 | */ 129 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 130 | { 131 | return '此支付渠道不支持发起退款, 请手动操作'; 132 | } 133 | } -------------------------------------------------------------------------------- /Pay/Youzan/Open/Client.php: -------------------------------------------------------------------------------- 1 | accessToken = $accessToken; 16 | } 17 | 18 | public function get($method, $apiVersion, $params = array()) 19 | { 20 | return $this->parseResponse( 21 | Http::get($this->url($method, $apiVersion), $this->buildRequestParams($method, $params)) 22 | ); 23 | } 24 | 25 | public function post($method, $apiVersion, $params = array(), $files = array()) 26 | { 27 | return $this->parseResponse( 28 | Http::post($this->url($method, $apiVersion), $this->buildRequestParams($method, $params), $files) 29 | ); 30 | } 31 | 32 | public function url($method, $apiVersion) 33 | { 34 | $method_array = explode(".", $method); 35 | $method = '/' . $apiVersion . '/' . $method_array[count($method_array) - 1]; 36 | array_pop($method_array); 37 | $method = implode(".", $method_array) . $method; 38 | $url = self::$requestUrl . $method; 39 | return $url; 40 | } 41 | 42 | private function parseResponse($responseData) 43 | { 44 | $data = json_decode($responseData, true); 45 | if (null === $data) throw new Exception('response invalid, data: ' . $responseData); 46 | return $data; 47 | } 48 | 49 | private function buildRequestParams($method, $apiParams) 50 | { 51 | if (!is_array($apiParams)) $apiParams = array(); 52 | $pairs = $this->getCommonParams($this->accessToken, $method); 53 | foreach ($apiParams as $k => $v) { 54 | if (isset($pairs[$k])) throw new Exception('参数名冲突'); 55 | $pairs[$k] = $v; 56 | } 57 | 58 | return $pairs; 59 | } 60 | 61 | private function getCommonParams($accessToken, $method) 62 | { 63 | $params = array(); 64 | $params[Protocol::TOKEN_KEY] = $accessToken; 65 | $params[Protocol::METHOD_KEY] = $method; 66 | return $params; 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /Pay/Youzan/Open/Http.php: -------------------------------------------------------------------------------- 1 | $value) { 74 | $multipartBody .= $MPBoundary . "\r\n"; 75 | $multipartBody .= 'content-disposition: form-data; name="' . $key . "\"\r\n\r\n"; 76 | $multipartBody .= $value . "\r\n"; 77 | } 78 | 79 | foreach ($files as $key => $value) { 80 | if (!$value) { 81 | continue; 82 | } 83 | 84 | if (is_array($value)) { 85 | $url = $value['url']; 86 | if (isset($value['name'])) { 87 | $filename = $value['name']; 88 | } else { 89 | $parts = explode('?', basename($value['url'])); 90 | $filename = $parts[0]; 91 | } 92 | $field = isset($value['field']) ? $value['field'] : $key; 93 | } else { 94 | $url = $value; 95 | $parts = explode('?', basename($url)); 96 | $filename = $parts[0]; 97 | $field = $key; 98 | } 99 | $content = file_get_contents($url); 100 | 101 | $multipartBody .= $MPBoundary . "\r\n"; 102 | $multipartBody .= 'Content-Disposition: form-data; name="' . $field . '"; filename="' . $filename . '"' . "\r\n"; 103 | $multipartBody .= "Content-Type: image/unknown\r\n\r\n"; 104 | $multipartBody .= $content . "\r\n"; 105 | } 106 | 107 | $multipartBody .= $endMPBoundary; 108 | return $multipartBody; 109 | } 110 | } -------------------------------------------------------------------------------- /Pay/Youzan/Open/Protocol.php: -------------------------------------------------------------------------------- 1 | $v) { 36 | $text .= $k . $v; 37 | } 38 | 39 | return self::hash($method, $appSecret . $text . $appSecret); 40 | } 41 | 42 | private static function hash($method, $text) 43 | { 44 | switch ($method) { 45 | case 'md5': 46 | default: 47 | $signature = md5($text); 48 | break; 49 | } 50 | return $signature; 51 | } 52 | 53 | public static function allowedSignMethods() 54 | { 55 | return array('md5'); 56 | } 57 | 58 | public static function allowedFormat() 59 | { 60 | return array('json'); 61 | } 62 | } -------------------------------------------------------------------------------- /Pay/Youzan/Open/Token.php: -------------------------------------------------------------------------------- 1 | clientId = $clientId; 19 | $this->clientSecret = $clientSecret; 20 | $this->accessToken = $accessToken; 21 | $this->refreshToken = $refreshToken; 22 | } 23 | 24 | /** 25 | * 获取access_token 26 | * 27 | * @param $type 28 | * @param array $keys 29 | * 30 | * @return mixed 31 | */ 32 | public function getToken($type, $keys = array()) 33 | { 34 | $params = array(); 35 | $params['client_id'] = $this->clientId; 36 | $params['client_secret'] = $this->clientSecret; 37 | if ($type === 'oauth') { 38 | $params['grant_type'] = 'authorization_code'; 39 | $params['code'] = $keys['code']; 40 | $params['redirect_uri'] = $keys['redirect_uri']; 41 | } elseif ($type === 'refresh_token') { 42 | $params['grant_type'] = 'refresh_token'; 43 | $params['refresh_token'] = $keys['refresh_token']; 44 | } elseif ($type === 'self') { 45 | $params['grant_type'] = 'silent'; 46 | $params['kdt_id'] = $keys['kdt_id']; 47 | } elseif ($type === 'platform_init') { 48 | $params['grant_type'] = 'authorize_platform'; 49 | } elseif ($type === 'platform') { 50 | $params['grant_type'] = 'authorize_platform'; 51 | $params['kdt_id'] = $keys['kdt_id']; 52 | } 53 | 54 | return $this->parseResponse( 55 | Http::post(self::$requestUrl, $params) 56 | ); 57 | } 58 | 59 | private function parseResponse($responseData) 60 | { 61 | $data = json_decode($responseData, true); 62 | if (null === $data) throw new Exception('response invalid, data: ' . $responseData); 63 | return $data; 64 | } 65 | } -------------------------------------------------------------------------------- /Pay/ZhaPay/Api.php: -------------------------------------------------------------------------------- 1 | url_notify = SYS_URL_API . '/pay/notify/' . $id; 32 | $this->url_return = SYS_URL . '/pay/return/' . $id; 33 | } 34 | 35 | /** 36 | * @param array $config 支付渠道配置 37 | * @param string $out_trade_no 外部订单号 38 | * @param string $subject 商品名称 39 | * @param string $body 商品介绍 40 | * @param int $amount_cent 金额/分 41 | * @throws \Exception 42 | */ 43 | function goPay($config, $out_trade_no, $subject, $body, $amount_cent) 44 | { 45 | $total_fee = sprintf('%.2f', $amount_cent / 100); // 元为单位 46 | 47 | if (!isset($config['id'])) { 48 | throw new \Exception('请设置id'); 49 | } 50 | if (!isset($config['key'])) { 51 | throw new \Exception('请设置key'); 52 | } 53 | if (!isset($config['gateway'])) { 54 | throw new \Exception('请设置gateway'); 55 | } 56 | 57 | $mch_id = $config['id']; 58 | $mch_key = $config['key']; 59 | $data = array( 60 | "mch_uid" => $mch_id, 61 | "out_trade_no" => $out_trade_no, 62 | "pay_type_id" => $config['payway'], // 1微信支付 2支付宝 63 | "mepay_type" => '2', // 收款方式:2 个人收款码 64 | "total_fee" => $total_fee,//金额 65 | "notify_url" => $this->url_notify, 66 | "return_url" => $this->url_return . '/' . $out_trade_no, // 由于没有同步通知, 这里同步过程需要拿着订单号看下是否订单处理完了 67 | ); 68 | 69 | ksort($data); 70 | reset($data); 71 | $sign_str = ''; 72 | $urls = ''; 73 | foreach ($data AS $key => $val) { 74 | if ($val == '' || $key == 'sign') continue; 75 | if ($sign_str != '') { //后面追加&拼接URL 76 | $sign_str .= "&"; 77 | $urls .= "&"; 78 | } 79 | $sign_str .= "$key=$val"; 80 | $urls .= "$key=" . urlencode($val); 81 | } 82 | $query = $urls . '&sign=' . md5($sign_str . $mch_key); 83 | header('Location: ' . $config['gateway'] . '?' . $query); //跳转到支付页面 84 | exit(0); 85 | } 86 | 87 | /** 88 | * @param $config 89 | * @param callable $successCallback 成功回调 (系统单号,交易金额/分,支付渠道单号) 90 | * @return bool|string true 验证通过 string 失败原因 91 | * @throws \Exception 92 | */ 93 | function verify($config, $successCallback) 94 | { 95 | $isNotify = isset($config['isNotify']) && $config['isNotify']; 96 | if ($isNotify) { 97 | // 异步通知交易结果 98 | ksort($_POST); 99 | reset($_POST); 100 | $mch_key = $config['key']; 101 | $sign_str = ''; 102 | foreach ($_POST AS $key => $val) { //遍历POST参数 103 | if ($val == '' || $key == 'sign') continue; //跳过这些不签名 104 | if ($sign_str) $sign_str .= '&'; //第一个字符串签名不加& 其他加&连接起来参数 105 | $sign_str .= "$key=$val"; //拼接为url参数形式 106 | } 107 | if (!$_POST['transaction_id'] || md5($sign_str . $mch_key) !== $_POST['sign'] || $_POST['status'] != 1) { //不合法的数据 108 | echo 'fail'; 109 | return false; 110 | } else { 111 | //合法的数据, 进行业务处理 112 | $successCallback($_POST['out_trade_no'], (int)round((float)$_POST['total_fee'] * 100), $_POST['transaction_id']); 113 | echo 'success'; 114 | return true; 115 | } 116 | } else { 117 | // 主动查询交易结果 118 | if (!empty($config['out_trade_no'])) { 119 | $order_no = @$config['out_trade_no']; //商户订单号 120 | return false; // 不支持 121 | } 122 | 123 | // // 同步返回页面 124 | // ksort($_GET); 125 | // reset($_GET); 126 | // $mch_key = $config['key']; 127 | // $sign_str = ''; 128 | // foreach ($_GET AS $key => $val) { //遍历POST参数 129 | // if ($val == '' || $key == 'sign') continue; //跳过这些不签名 130 | // if ($sign_str) $sign_str .= '&'; //第一个字符串签名不加& 其他加&连接起来参数 131 | // $sign_str .= "$key=$val"; //拼接为url参数形式 132 | // } 133 | 134 | // // http://127.0.0.4/pay/return/15?mepay_total=0.01&order=20200105143614Mypoz&out_trade_no=20200105143614Mypoz&pay_type=1&paytime=1578206222&status=1&total_fee=0.01&transaction_id=1000020200105143634178647&sign=ab0bfcd4348aa271241d1508286d1e99 135 | // // mepay_total=0.01&order=20200105143614Mypoz&out_trade_no=20200105143614Mypoz&pay_type=1&paytime=1578206222&status=1&total_fee=0.01&transaction_id=10000202001051436341786471 136 | // var_dump($sign_str . $mch_key); 137 | // var_dump(md5($sign_str . $mch_key)); 138 | // if (!$_GET['transaction_id'] || md5($sign_str . $mch_key) !== $_GET['sign'] || $_GET['status'] !== '1') { //不合法的数据 139 | // return false; 140 | // } else { 141 | // //合法的数据, 进行业务处理 142 | // $successCallback($_GET['out_trade_no'], (int)round((float)$_GET['total_fee'] * 100), $_GET['transaction_id']); 143 | // return true; 144 | // } 145 | 146 | // 根据作者所说不需要同步 147 | return false; 148 | } 149 | } 150 | 151 | /** 152 | * 退款操作 153 | * @param array $config 支付渠道配置 154 | * @param string $order_no 订单号 155 | * @param string $pay_trade_no 支付渠道流水号 156 | * @param int $amount_cent 金额/分 157 | * @return true|string true 退款成功 string 失败原因 158 | */ 159 | function refund($config, $order_no, $pay_trade_no, $amount_cent) 160 | { 161 | return '此支付渠道不支持发起退款, 请手动操作'; 162 | } 163 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Card-Gateways 2 | 3 | The Gateways of [card-system](https://github.com/Tai7sy/card-system) 4 | 5 | Support Alipay, WechatPay, JCBPay, Paypal, [MugglePay](https://github.com/Tai7sy/card-gateway/tree/master/Pay/MugglePay), etc, [ZFBJK](http://www.zfbjk.com/show.asp?g=2&id=37214). 6 | --------------------------------------------------------------------------------