1、微支付
准备工作
1.1 在微信开放平台(https://open.weixin.qq.com)注册并认证成为开发者账号
1.2 在移动应用内创建移动应用,审核通过后获取到该应用的AppID和AppSecret
1.3 点击微支付后面的申请进入微支付申请流程,这里分为已有微商户和没有微商户两种,没有微商户的直接申请即可;已有微商户的需要进行APPID授权(产品中心→APP支付→appid授权),进行授权以后说明这个app就可以调用app支付了;
1.4 HBuilderX manifest.json文件配置APP SDK选项勾选微信支付,填入微信开放平台获取到的appid;
1.5 准备后端代码,这里我使用的是thinkphp5.0作为后端api接口关键控制器如下
<?php
namespace app\api\controller;
use app\common\model\Wxpaylog;
use xcxwxpay\database\WxPayUnifiedOrder;
use xcxwxpay\database\WxPayTransferPayment;
use xcxwxpay\WxPayApi;
use app\api\common\orderlogic;
use xcxwxpay\database\WxPayResults;
use xcxwxpay\WxPayConfig;
class Wxapppay extends Filter{
public function index(){
$action = input("get.a","");
switch ($action){
case "payinfo":
$oid = input("post.oid",-1);
if(empty($oid)||$oid==""||!is_numeric($oid)||$oid==-1) $this->apireturn(0,"invalid oid");
$result = $this->payinfo($oid);
if($result["errors"]!="") $this->apireturn(0,$result["errors"]);
$ostring = $result["orderstring"];
$this->apireturn(1,"请求成功",$ostring);
break;
default:
$this->apireturn(0,"invalid action");
break;
}
}
private function payinfo($oid){
$orderlogic = new orderlogic();
$info = $orderlogic->getOrderInfo($oid);
// 统一下单获取预支付订单信息
$response = $this->getOrderstring("你app的名称-订单支付",$info["number"],$info["paymoney"]["values"]);
// 生成调起支付请求的参数
$input = new WxPayTransferPayment();
$input->setPrepayId($response["prepay_id"]);
if(!$input->isPrepayIdSet()){
return ["errors"=>"缺少调起支付必填参数prepayid"];
}
$input->setAppid(WxPayConfig::$APPID);
$input->setPartnerId(WxPayConfig::$MCHID);
$input->setPackage("Sign=WXPay");
$input->setNonceStr(self::getNonceStr());//随机字符串
$input->setTimeStamt(time());
$arr = array(
"appid" => $input->getAppid(),
"partnerid"=>$input->getPartnerId(),
"prepayid"=>$input->getPrepayId(),
"package"=>"Sign=WXPay",
"noncestr"=>$input->getNonceStr(),
"timestamp" => $input->getTimeStamt(),
);
$sign = $this->makeSign($arr);
$data = array(
"appid" => $input->getAppid(),
"partnerid"=>$input->getPartnerId(),
"prepayid"=>$input->getPrepayId(),
"package"=>"Sign=WXPay",
"noncestr"=>$input->getNonceStr(),
"timestamp" => $input->getTimeStamt(),
"paySign" => $sign
);
return ["errors"=>"","orderstring"=>$data];
}
// 统一下单
private function getOrderstring($body,$out_trade_no,$total_amount)
{
//统一下单
$money = $total_amount;
$money = 0.01;
$input = new WxPayUnifiedOrder();
$input->setBody($body);
$input->setAttach("");
$input->setOutTradeNo($out_trade_no);
$input->setTotalFee($money * 100);
$input->setTimeStart(date("YmdHis"));
$input->setTimeExpire(date("YmdHis", time() + 3*24*60*60));
$input->setNotifyUrl("https://xxxxxxx.com/api/wxapppay/notify.html");
$input->setTradeType("APP");
$order = WxPayApi::unifiedOrder($input);
return $order;
}
public function notify()
{
$xml = file_get_contents("php://input");
$result = WxPayResults::Init($xml);
Writef("wxpaylog.txt",$xml);
if($result["result_code"]=="SUCCESS"){
$ordernumber = $result["out_trade_no"];
$paytime = formateTimeStamp(time());
$orderlogic = new orderlogic();
$orderlogic->payOrder($ordernumber,$paytime,"微支付");
$arr = array("return_code"=>"SUCCESS","return_msg"=>"OK");
echo $this->toXml($arr);
}
$this->writepaylog($result);
}
private function writepaylog($result){
$wxlog = new Wxpaylog();
$wxlog["appid"] = $result["appid"];
$wxlog["bank_type"] = $result["bank_type"];
$wxlog["cash_fee"] = $result["cash_fee"];
$wxlog["fee_type"] = $result["fee_type"];
$wxlog["is_subscribe"] = $result["is_subscribe"];
$wxlog["mch_id"] = $result["mch_id"];
$wxlog["nonce_str"] = $result["nonce_str"];
$wxlog["openid"] = $result["openid"];
$wxlog["out_trade_no"] = $result["out_trade_no"];
$wxlog["result_code"] = $result["result_code"];
$wxlog["return_code"] = $result["return_code"];
$wxlog["sign"] = $result["sign"];
$wxlog["time_end"] = $result["time_end"];
$wxlog["total_fee"] = $result["total_fee"];
$wxlog["trade_type"] = $result["trade_type"];
$wxlog["transaction_id"] = $result["transaction_id"];
$wxlog->save();
}
/**
* 输出xml字符
**/
private function toXml($arr)
{
if (!is_array($arr)
|| count($arr) <= 0
) {
return "";
}
$xml = "<xml>";
foreach ($arr as $key => $val) {
if (is_numeric($val)) {
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
} else {
$xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
}
}
$xml .= "</xml>";
return $xml;
}
/**
* 格式化参数格式化成url参数
*/
private function toUrlParams($arr)
{
$buff = "";
foreach ($arr as $k => $v) {
if ($k != "sign" && $v != "" && !is_array($v)) {
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
/**
* 生成签名
* @return string 签名,本函数不覆盖sign成员变量,如要设置签名需要调用setSign方法赋值
*/
private function makeSign($arr)
{
//签名步骤一:按字典序排序参数
ksort($arr);
$string = $this->toUrlParams($arr);
//签名步骤二:在string后加入KEY
$string = $string . "&key=" . WxPayConfig::$KEY;
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
/**
*
* 产生随机字符串,不长于32位
* @param int $length
* @return string 产生的随机字符串
*/
private static function getNonceStr($length = 32)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
}
1.6 前端uni-app代码如下,点击支付后执行如下代码
var uri = "Wxapppay/index.html?a=payinfo";
var param = {oid:that.orderinfo.oid};
that.$post(uri,param,"POST",function(res){
var jsondata = res.data;
//console.log(JSON.stringify(jsondata));
if(jsondata.code==1){
var orderinfo = jsondata.data;
if(orderinfo){
uni.requestPayment({
provider:"wxpay",
timeStamp:orderinfo.timestamp,
nonceStr:orderinfo.noncestr,
package:orderinfo.package,
signType:"MD5",
paySign:orderinfo.paySign,
orderInfo:{
appid:orderinfo.appid,
noncestr:orderinfo.noncestr,
package:"Sign=WXPay",
partnerid:orderinfo.partnerid,
prepayid:orderinfo.prepayid,
timestamp:orderinfo.timestamp,
sign:orderinfo.paySign,
},
success:function(res){
uni.showToast({
title:"支付成功",
icon:"success",
duration:2000,
complete:function(){
uni.reLaunch({
url:"showresult?paytype=1"
});
}
});
},
fail:function(res){
// console.log(JSON.stringify(res));
uni.showToast({
title: '支付失败,请到订单中心重新支付',
icon: "none",
duration: 2000,
complete: function () {
wx.reLaunch({
url: 'showresult?paytype=3',
});
}
});
}
});
}
}else{
}
},function(){},function(){});
注意 注意 注意:如果是默认基座的话会提示:HBuilder mainifest.json中配置的支付appid和生成订单使用的appid不一致,如果是HB调试请在线打包,http://ask.dcloud.net.cn/article/282",必须使用自定义基座才能真机调试支付
2、支付宝支付
准备工作
1.1 在支付宝平台注册商户用户
1.2 在支付宝商户后台产品中心签约app支付
1.3 在蚂蚁金服开放平台(https://open.alipay.com)开发中心→网页和移动应用 新增app应用,通过以后设置好应用公钥,系统会自动生成支付宝公钥 注意新增的时候 iOS bundle ID一定要填写正确
1.4 HBuilder mainifest.json中设置支付宝ios scheme用于支付完成跳转回应用。
1.5 后台代码参考支付宝示例代码
<?php
namespace app\api\controller;
use app\api\common\orderlogic;
class Alipay extends Filter{
public function index(){
$action = input("get.a","");
switch ($action){
case "payinfo":
$oid = input("post.oid",-1);
if(empty($oid)||$oid==""||!is_numeric($oid)||$oid==-1) $this->apireturn(0,"invalid oid");
$result = $this->payinfo($oid);
$this->apireturn(1,"请求成功",$result);
break;
default:
$this->apireturn(0,"invalid action");
break;
}
}
private function payinfo($oid){
$orderlogic = new orderlogic();
$info = $orderlogic->getOrderInfo($oid);
Vendor('aop.AopClient');
$aop = new \AopClient();
$alipayConfig = config("alipayinfo");
$aop->gatewayUrl = $alipayConfig["gatewayUrl"];
$aop->appId = $alipayConfig["appid"];
$aop->rsaPrivateKey = $alipayConfig["privateKey"];
$aop->format = "json";
$aop->charset = "utf-8";
$aop->signType = "RSA2";
$aop->alipayrsaPublicKey = $alipayConfig["publicKey"];
Vendor("aop.request.AlipayTradeAppPayRequest");
$request = new \AlipayTradeAppPayRequest();
$request->setNotifyUrl($alipayConfig["notifyUrl"]);
$body = "你的app名称订单支付";
$out_trade_no = $info["number"];
$total_amount = formatMoney($info["paymoney"]["values"]);
$total_amount = 0.01;// 实际上线后注释掉
$bizcontent = "{\"body\":\"$body\","
. "\"subject\": \"你的app名称-订单支付\","
. "\"out_trade_no\": \"$out_trade_no\","
. "\"timeout_express\": \"30m\","
. "\"total_amount\": \"$total_amount\","
. "\"product_code\":\"QUICK_MSECURITY_PAY\""
. "}";
$request->setBizContent($bizcontent);
$response = $aop->sdkExecute($request);
return $response;
}
public function notify()
{
$data = input("post.");
$str = ToUrlParams($data);
Vendor('aop.AopClient');
$aop = new \AopClient();
$alipayConfig = config("alipayinfo");
$aop->alipayrsaPublicKey = $alipayConfig["publicKey"];
$flag = $aop->rsaCheckV1(input("post."), NULL, "RSA2");
if($flag){
// 消息验证通过,更改订单状态
$states = input("post.trade_status");
if($states == "TRADE_SUCCESS"){
$ordernumber = input("post.out_trade_no");
$paytime = input("post.gmt_payment");
$orderlogic = new orderlogic();
$orderlogic->payOrder($ordernumber,$paytime,"支付宝");
}
echo "success";
}
echo 'filed';
}
}
1.6 uni-app前端代码
var uri = "Alipay/index.html?a=payinfo";
var param = {oid:that.orderinfo.oid}
that.$post(uri,param,"POST",function(res){
var jsondata = res.data;
// console.log(JSON.stringify(jsondata));
if(jsondata.code==1){
var orderinfo = jsondata.data;
if(orderinfo){
uni.requestPayment({
provider:"alipay",
orderInfo:orderinfo,
success:function(res){
uni.showToast({
title:"支付成功",
icon:"success",
duration:2000,
complete:function(){
uni.reLaunch({
url:"showresult?paytype=1"
});
}
});
},
fail:function(res){
uni.showToast({
title: '支付失败,请到订单中心重新支付',
icon: "none",
duration: 2000,
complete: function () {
wx.reLaunch({
url: 'showresult?paytype=3',
});
}
});
}
});
}else{
}
}else{
}
},function(){},function(){});