接上两篇支付宝支付和微信支付,下面我这边讲的是QQ支付:

下面简单介绍下QQApp支付后端的实现(这边是用php实现的):
一、 一些琐碎的申请和设置的方式就不说明了,这些微信上都有说,但相比于支付宝吗,微信和QQ的文档相比差之千里,太简单太low了,并且没有SDKDEMO,但小伙伴们不用担心,下面是我这边封装好的一个类,可供直接使用,都有标注说明
一、封装好的QQ调用类库:(这个不管是app支付还是其他支付都可共用)
<?php
/*** Created by PhpStorm.* User: wyb* Date: 2017/3/29* Time: 10:17*/
class qqAppPay
{//接口API URL前缀const API_URL_PREFIX = 'https://qpay.qq.com';//下单地址URLconst UNIFIEDORDER_URL = "/cgi-bin/pay/qpay_unified_order.cgi";//查询订单URLconst ORDERQUERY_URL = "/cgi-bin/pay/qpay_order_query.cgi";//关闭订单URLconst CLOSEORDER_URL = "/cgi-bin/pay/qpay_close_order.cgi";//应用号IDprivate $appid;//商户号private $mch_id ='1452072601';//随机字符串private $nonce_str;//签名private $sign;//商品描述private $body;//商户订单号private $out_trade_no;//支付总金额private $total_fee;//终端IPprivate $spbill_create_ip;//支付结果回调通知地址private $notify_url ='http://apps.ifeimo.com/Sysj218/Recharge/qqpayNotify'; //不能写固定于该文件内,后续变更为外部传入//交易类型private $trade_type;//支付密钥private $key='F1DAB8538EC979F99C062F3BE308062C';// 表单提交字符集编码public $postCharset = "UTF-8";//签名类型public $signType = "HMAC-SHA1";//证书路径private $SSLCERT_PATH;private $SSLKEY_PATH;//所有参数private $params = array();public function __construct($wxappid){$this->appid = $wxappid;
//        $this->mch_id = $mch_id;
//        $this->notify_url = $notify_url;
//        $this->key = $key;}/*** 下单方法* @param   $params 下单参数*/public function unifiedOrder( $params ){//        $this->body = $params['body'];
//        $this->out_trade_no = $params['out_trade_no'];
//        $this->total_fee = $params['total_fee'];
//        $this->trade_type = $params['trade_type'];
//        $this->nonce_str = $this->genRandomString();$this->spbill_create_ip = $_SERVER['REMOTE_ADDR'];$this->params['appid'] = $this->appid;$this->params['mch_id'] = $this->mch_id;$this->params['nonce_str'] = $this->nonce_str = $this->genRandomString();$this->params['body'] = $this->body = $params['body'];$this->params['out_trade_no'] = $this->out_trade_no = $params['out_trade_no'];$this->params['total_fee'] = $this->total_fee = $params['total_fee'];$this->params['spbill_create_ip'] = $this->spbill_create_ip;$this->params['notify_url'] = $params['notify_url'] ? $params['notify_url'] : $this->notify_url;$this->params['trade_type'] = $this->trade_type = $params['trade_type'];//获取签名数据$this->sign = $this->MakeSign( $this->params );$this->params['sign'] = $this->sign;$xml = $this->data_to_xml($this->params);$response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::UNIFIEDORDER_URL);if( !$response ){return false;}$result = $this->xml_to_data( $response );if( !empty($result['result_code']) && !empty($result['err_code']) ){$result['err_msg'] = $this->error_code( $result['err_code'] );}return $result;}/*** 查询订单信息* @param $out_trade_no     订单号* @return array*/public function orderQuery( $out_trade_no ){$this->params['appid'] = $this->appid;$this->params['mch_id'] = $this->mch_id;$this->params['nonce_str'] = $this->genRandomString();$this->params['out_trade_no'] = $out_trade_no;//获取签名数据$this->sign = $this->MakeSign( $this->params );$this->params['sign'] = $this->sign;$xml = $this->data_to_xml($this->params);$response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::ORDERQUERY_URL);if( !$response ){return false;}$result = $this->xml_to_data( $response );if( !empty($result['result_code']) && !empty($result['err_code']) ){$result['err_msg'] = $this->error_code( $result['err_code'] );}return $result;}/*** 关闭订单* @param $out_trade_no     订单号* @return array*/public function closeOrder( $out_trade_no ){$this->params['appid'] = $this->appid;$this->params['mch_id'] = $this->mch_id;$this->params['nonce_str'] = $this->genRandomString();$this->params['out_trade_no'] = $out_trade_no;//获取签名数据$this->sign = $this->MakeSign( $this->params );$this->params['sign'] = $this->sign;$xml = $this->data_to_xml($this->params);$response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::CLOSEORDER_URL);if( !$response ){return false;}$result = $this->xml_to_data( $response );return $result;}/*** 生成用于调用收银台SDK的字符串* @param $request SDK接口的请求参数对象* @return string* @author guofa.tgf*/public function sdkExecute($request) {$this->setupCharsets($request);$params['appid'] =  $request['appid'];$params['bargainorId'] = $request['bargainorId'];$params['tokenId']     = $request['tokenId'];$params['nonce']       = $request['nonce'];$params['timestamp']   = time();$params['sign']        = $request['sign'];$params['sigType']     = $this->signType;$params['completion']  = $this->notify_url;foreach ($params as &$value) {$value = $this->characet($value, $params['charset']);}return http_build_query($params);}/*** 校验$value是否非空*  if not set ,return true;*    if is null , return true;**/protected function checkEmpty($value) {if (!isset($value))return true;if ($value === null)return true;if (trim($value) === "")return true;return false;}/*** 转换字符集编码* @param $data* @param $targetCharset* @return string*/function characet($data, $targetCharset) {if (!empty($data)) {$fileType = $this->fileCharset;if (strcasecmp($fileType, $targetCharset) != 0) {$data = mb_convert_encoding($data, $targetCharset, $fileType);//              $data = iconv($fileType, $targetCharset.'//IGNORE', $data);}}return $data;}private function setupCharsets($request) {if ($this->checkEmpty($this->postCharset)) {$this->postCharset = 'UTF-8';}$str = preg_match('/[\x80-\xff]/', $this->appId) ? $this->appId : print_r($request, true);$this->fileCharset = mb_detect_encoding($str, "UTF-8, GBK") == 'UTF-8' ? 'UTF-8' : 'GBK';}/**** 获取支付结果通知数据* return array*/public function getNotifyData(){//获取通知的数据$xml = $GLOBALS['HTTP_RAW_POST_DATA'];$data = array();if( empty($xml) ){return false;}$data = $this->xml_to_data( $xml );if( !empty($data['return_code']) ){if( $data['return_code'] == 'FAIL' ){return false;}}return $data;}/*** 接收通知成功后应答输出XML数据* @param string $xml*/public function replyNotify(){$data['return_code'] = 'SUCCESS';$data['return_msg'] = 'OK';$xml = $this->data_to_xml( $data );echo $xml;die();}/*** 生成APP端支付参数* @param  $prepayid   预支付id*/public function getAppPayParams( $prepayid ){$data['appid'] = $this->appid;$data['partnerid'] = $this->mch_id;$data['prepayid'] = $prepayid;$data['package'] = 'Sign=WXPay';$data['noncestr'] = $this->genRandomString();$data['timestamp'] = time();$data['sign'] = $this->MakeSign( $data );return $data;}/*** 生成签名*  @return 签名*/public function MakeSign( $params ){//签名步骤一:按字典序排序数组参数ksort($params);$string = $this->ToUrlParams($params);//签名步骤二:在string后加入KEY$string = $string . "&key=".$this->key;//签名步骤三:MD5加密$string = md5($string);//签名步骤四:所有字符转为大写$result = strtoupper($string);return $result;}/*** 将参数拼接为url: key=value&key=value* @param   $params* @return  string*/public function ToUrlParams( $params ){$string = '';if( !empty($params) ){$array = array();foreach( $params as $key => $value ){
//                if(!$value){//                    $array[] = $key.'='.$value;
//                }$array[] = $key.'='.$value;}$string = implode("&",$array);}return $string;
//        dump($string);die;}/*** app生成签名*  @return 签名*/public function appMakeSign( $params,$appkey ){//签名步骤一:按字典序排序数组参数ksort($params);$string = $this->ToUrlParams($params);
//        dump($string);die;//签名步骤二:在string后加入KEY$appkey = $appkey.'&';$result  = base64_encode(hash_hmac("sha1", $string, $appkey, true));return $result;}/*** 输出xml字符* @param   $params     参数名称* return   string      返回组装的xml**/public function data_to_xml( $params ){if(!is_array($params)|| count($params) <= 0){return false;}$xml = "<xml>";foreach ($params as $key=>$val){if (is_numeric($val)){$xml.="<".$key.">".$val."</".$key.">";}else{$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";}}$xml.="</xml>";return $xml;}/*** 将xml转为array* @param string $xml* return array*/public function xml_to_data($xml){if(!$xml){return false;}//将XML转为array//禁止引用外部xml实体libxml_disable_entity_loader(true);$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);return $data;}/*** 验证签名* @param string $xml* return array*/public function validationSignature($params){//签名步骤一:按字典序排序数组参数ksort($params);$string = $this->ToUrlParams($params);return $string;//签名步骤二:在string后加入KEY$string = $string . "&key=".$this->key;//签名步骤三:MD5加密$string = md5($string);//签名步骤四:所有字符转为大写$result = strtoupper($string);return $result;}/*** 获取毫秒级别的时间戳*/private static function getMillisecond(){//获取毫秒的时间戳$time = explode ( " ", microtime () );$time = $time[1] . ($time[0] * 1000);$time2 = explode( ".", $time );$time = $time2[0];return $time;}/*** 产生一个指定长度的随机字符串,并返回给用户* @param type $len 产生字符串的长度* @return string 随机字符串*/private function genRandomString($len = 32) {$chars = array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k","l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v","w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G","H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R","S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2","3", "4", "5", "6", "7", "8", "9");$charsLen = count($chars) - 1;// 将数组打乱shuffle($chars);$output = "";for ($i = 0; $i < $len; $i++) {$output .= $chars[mt_rand(0, $charsLen)];}return $output;}/*** 以post方式提交xml到对应的接口url** @param string $xml  需要post的xml数据* @param string $url  url* @param bool $useCert 是否需要证书,默认不需要* @param int $second   url执行超时时间,默认30s* @throws WxPayException*/private function postXmlCurl($xml, $url, $useCert = false, $second = 30){$ch = curl_init();//设置超时curl_setopt($ch, CURLOPT_TIMEOUT, $second);curl_setopt($ch,CURLOPT_URL, $url);curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//设置headercurl_setopt($ch, CURLOPT_HEADER, FALSE);//要求结果为字符串且输出到屏幕上curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);if($useCert == true){//设置证书//使用证书:cert 与 key 分别属于两个.pem文件curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');//curl_setopt($ch,CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH);curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');//curl_setopt($ch,CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH);}//post提交方式curl_setopt($ch, CURLOPT_POST, TRUE);curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);//运行curl$data = curl_exec($ch);//返回结果if($data){curl_close($ch);return $data;} else {$error = curl_errno($ch);curl_close($ch);return false;}}/*** 错误代码* @param  $code       服务器输出的错误代码* return string*/public function error_code( $code ){$errList = array('LACK_PARAMS'           =>  '缺少必要的请求参数','NOAUTH'                =>  '商户未开通此接口权限','NOTENOUGH'             =>  '用户帐号余额不足','ORDERNOTEXIST'         =>  '订单号不存在','ORDERPAID'             =>  '商户订单已支付,无需重复操作','ORDERCLOSED'           =>  '当前订单已关闭,无法支付','SYSTEMERROR'           =>  '系统错误!系统超时','APPID_NOT_EXIST'       =>  '参数中缺少APPID','MCHID_NOT_EXIST'       =>  '参数中缺少MCHID','APPID_MCHID_NOT_MATCH' =>  'appid和mch_id不匹配','LACK_PARAMS'           =>  '缺少必要的请求参数','OUT_TRADE_NO_USED'     =>  '同一笔交易不能多次提交','SIGNERROR'             =>  '参数签名结果不正确','XML_FORMAT_ERROR'      =>  'XML格式错误','REQUIRE_POST_METHOD'   =>  '未使用post传递参数 ','POST_DATA_EMPTY'       =>  'post数据不能为空','NOT_UTF8'              =>  '未使用指定编码格式',);if( array_key_exists( $code , $errList ) ){return $errList[$code];}}}
二、封装好的微信调用类库的工具类:
<?php/*** @encoding UTF-8* @author wyb* @datetime 2017/320* @Description QQ钱包APP支付控制器,不对外访问*/namespace Pay\Controller;use Think\Controller;/*** @name * Class QQAppPayController*/
class QQAppPayController extends Controller {//这是appId,对应的产品有对应的APPidprivate $appidByTarget = ['app标识' => '1232133213','app标识' => '1232133213','app标识' => '1232133213','app标识' => '1232133213','app标识' => '1232133213','app标识' => '1232133213',];//这是appId,对应的产品有对应的APPkeyprivate $appKeyByTarget = ['app标识' => 'sd24sdfsdfsdfdfs','app标识' => 'sd24sdfsdfsdfdfs','app标识' => 'sd24sdfsdfsdfdfs','app标识' => 'sd24sdfsdfsdfdfs','app标识' => 'sd24sdfsdfsdfdfs','app标识' => 'sd24sdfsdfsdfdfs',];public function _initialize(){}/*** 传入订单数据,进行整理、签名后,返回前端APP支付调起SDK信息* @param array $order 待支付的订单信息,数组中的必要信息如下:*  $order['id'] : 订单ID*  $order['price'] : 实付金额,单位:元*  $order['notifyUrl'] : 支付端异步通知地址,用于接受订单的支付结果*  $order['target'] : 支付请求的来源,根据不同的来源,需要使用不同的支付账号信息*  $order['description'] : 订单介绍*  $order['time'] : 订单提交时间*/public function getCallSDKInfo($order){//做简单的参数检查if(!$order || !is_array($order) || !$order['id'] || !$order['price'] || !$order['notifyUrl'] || !$order['target']){return false;}//      $time=time();$wxappid = $this->appidByTarget[$order['target']];//应用ID 字符串Vendor('qqPay.qqpay');$QQPay = new \qqAppPay($wxappid);$params = ['body' => $order['description'], //必填项 商品描述'out_trade_no' => $order['id'], //商家订单ID'total_fee' => ($order['price']*100), //必填项 订单金额'time_start' => date('yyyyMMddHHmmss',$order['add_time']), //可支付有效时间,超过则无效,需要重新请求'time_expire' => date('yyyyMMddHHmmss',($order['add_time']+1800)), //可支付有效时间,超过则无效,需要重新请求'trade_type' => 'APP', //必填项 交易类型固定写  APP'fee_type' => 'CNY', //货币的类型'notify_url' => $order['notifyUrl'],];$result = $QQPay->unifiedOrder($params);$sign_array=['appId' => $result['appid'],//注意 $sign_array['appid'] 里的参数名必须是appid'bargainorId' => $result['mch_id'],//注意 $sign_array['partnerid'] 里的参数名必须是partnerid'tokenId' => $result['prepay_id'],//注意 $sign_array['prepayid'] 里的参数名必须是prepayid'nonce' => $result['nonce_str'],//注意 $sign_array['noncestr'] 里的参数名必须是noncestr'pubAcc' => ''];$sign_array['sign'] = $QQPay->appMakeSign($sign_array, $this->appKeyByTarget[$order['target']]);//appMakeSign()函数生成sign$sign_array['timestamp'] = $order['add_time'];return $sign_array;}
}
三、接下来你就可以根据你的相关产品订单信息进行调用相应的类方法,下面我就简单的写一下:
<?php
/*** 根据相应的场景而写的支付接口* Created by PhpStorm.* User: wyb* Date: 2017/3/22* Time: 13:51*/class productPayController extents Controller{public function paymentAction(){IS_POST ||$this->returnError();    //判断是否是POST$parameters  = I('post.');         //接收所以参数,相应的参数校验我这里就不写,如果有问题可以给我留言反馈$QqPay = new WechatAppPayController();//实例QQ的APP控制器类$order['notifyUrl'] = 'http://xxxxxxxxxxxxxxx;//微信的回调接口$data = $QqPay->getCallSDKInfo($order);//调用QQ生成预订单并整理好返回验签参数,这里调用上面的类封装的方法return $data //这里可以根据你们前端定义接受什么数据类型进行转化} }
php后端实现支付宝APP支付,请点击这里:GO
php后端实现微信APP支付,请点击这里:GO

注:这个就是我php后端实现支付的业务的相关代码,若有什么问题反馈请指出,谢谢,(这里并附上我自己的博客地址:blog.taobaoroom.cn,若有什么问题可根据博客上赋有的QQ群地址联系我哦!!

实现APP支付QQ,微信,支付宝三方的后端服务------php实现QQAPP支付相关推荐

  1. 三方支付与微信,支付宝支付有什么优势

    西米支付网(www.45ri.com) 首先我们来看一下,财付通 (又称微信支付).支付宝支付 ,三方支付的相同之处与关联 (1)三方支付又称非银行清算机构,是除了银行之外能够合理合法进行收付款服务 ...

  2. 聚合支付、单商户多商户支付、微信/支付宝/PayPal支付流程、支付政策法规

    目录 一.聚合支付 聚合支付的基本概念 如何选择合适的支付模式 政策相关 常见的聚合支付平台 二.多商户和单商户 多商户单商户区别 多商户入驻流程 多商户模式中常见的支付流程 普通支付 合单支付 留个 ...

  3. 亲测全套支付可用(微信支付宝)复制粘贴即可跑

    亲测全套支付可用(微信支付宝包括退款)复制粘贴即可跑 /*** @Auther: tjr* @Date: 2020/9/30 15:11* @Description: 支付宝后台接口*/ @Slf4j ...

  4. Java前后端分离第三方登录_网站前后端分离情况下如何实现QQ微信等第三方登陆-Fun言...

    前言 最近在弄第三方登录,实现起来很简单,就是调几个接口获取个人信息即可,详细了解:maven项目整合QQauth2.0第三方登录详细说明,然后因为本网站是前后端分离的,所以不能再回调接口那里直接跳转 ...

  5. 刷微信点击量的php,PHP一键刷QQ微信支付宝步数代码

    PHP一键刷QQ微信支付宝步数代码,账号密码步数填好直接地址栏回车,想要自动刷就设定计划任务.每天自动刷,步数不要太多,容易封运动,导致步数别人看不到! 使用说明:http://域名/?mobile= ...

  6. 网站前后端分离情况下如何实现QQ微信等第三方登陆

    本文转自Fun言网:https://funyan.cn/p/1705.html 前言 最近在弄第三方登录,实现起来很简单,就是调几个接口获取个人信息即可,详细了解:maven项目整合QQauth2.0 ...

  7. 第三方支付接入(微信,支付宝)

    第三方API 时间 2022年3月30 目前很多企业在做支付的时候为了方便已经开始直接对接第四方了 但是也有一些开源大神们对支付甚至是整个微信开发提供了API 笔者公司的微信支付目前使用的第三方API ...

  8. 开发笔记 | Springboot整合多平台支付(微信/支付宝)

    目录 微信支付 开发前准备 支付程序编写 (1)创建订单 (2)微信的支付回调 (3)查询订单状态 (4)退款 (5)退款查询与关闭订单 (5)退款回调 alipay-sdk沙箱模拟支付宝支付 官方参 ...

  9. 小程序服务器端端接口,微信小程序:后端服务接口(WordPress)

    微信的小程序相当于是一套前端(Frontend)应用的框架,让它变成一个真正能用的 App,我们还得给它提供一个后端服务,或者叫应用后台(Backend).几乎所有的后端应用框架都支持为小程序提供后端 ...

最新文章

  1. IronPython2.7 C# 4.0 互调用备忘
  2. (011) java后台开发之泛型类
  3. 046_byte的值在计算机中的表示
  4. 小波的秘密9_图像处理应用:图像增强
  5. 【零基础入门数据挖掘】-模型融合
  6. 千位分隔符转换为数字
  7. 老牌社交网站Friends Reunited宣布关闭
  8. vscode 乱码_如何使用VS Code 编辑Keil项目(51/STM32)
  9. 数据库热备份 Xtrabackup安装及使用
  10. Enterprise Library 3.1 简化使用范例一
  11. 关于事务开启与否对数据库插入数据所需时间的影响的讨论
  12. 瑞斯康达nms_瑞斯康达接入网设备维护标准手册.docx
  13. 程序员表白技巧:程序员木讷? 我反手就是一串代码
  14. 测试基础知识考试题目(答案)
  15. verilog写的三分频
  16. 16年,悲痛又收获的一年
  17. 利用JavaScript生成点名册
  18. Golang context.Context
  19. CSS 选择器及常用属性介绍
  20. 知识丨软件定义汽车下的整车开发

热门文章

  1. windows文件夹中的哪些文件可以删除
  2. java设置table表头方向_table表头固定
  3. 云计算扎根宿州的N个理由
  4. maven中央私库的搭建和项目的引用
  5. 计算机科学基础知识入门
  6. 浏览器 缓存 面试 参数解析 Cache-Control Expires ETag Last-Modified
  7. css transparent张鑫旭,js/css 张鑫旭.md at master · baipu/js · GitHub
  8. php mysqli 添加,php添加mysqli扩展
  9. vue-router.mjs:798 Uncaught (in promise) Error: No match for
  10. glob匹配多级目录