最近做大二商城项目时需要使用支付宝支付,就百度了一下支付宝支付的方法。发现七成以上是java的,.NET Core真的是寥寥无几,不禁感叹 .Net在中国真的那么少用吗?
现在开始准备开发吧
调用支付宝接口前需要做以下准备:
1.需要有蚂蚁金服申请的APPID
2.需要创建私钥与公钥
首先,我们先登录到 蚂蚁金服开发者平台 如下登录成功后的:
因为我也不是企业账号,没有那个什么证书 没法申请签约在线支付,,所以我们使用下方的研发模式,也就是沙盒模式。
现在我们来生成秘钥 ,在 文档 中输入 如何生成rsa:
进入,点击 如何生成RSA2密钥 ,进入如下页面:
下载对应操作系统的应用,下载完成 安装后(安装可能较慢,耐心等待)打开:
现在我们打开生成的文件路径:
回到开发者平台,现在我们开始上传秘钥与下载支付宝公钥,上一步有一个地方说错了,上传的应该是公钥,私钥是留在后面接口调用时使用的
如果是第一次上传,一个只有一个设置,打开即可
复制应用公钥是切记不要做其他输入操作,特别注意别不小心输入了一个空格什么的,必须是原封不动的复制粘贴
加签完成,打个码 寻求点心里安慰,哈哈哈哈
最好将应用秘钥和支付宝公钥放在一个文件夹里,好找
若有不明白,可以 查阅支付宝的接入文档 不明白就看文档(一个无奈的选择)
好的,选择支付宝这边的准备工作已经完成,现在我们开始接入支付接口
在这里我选择的是 Essensoft.AspNetCore.Payment 提供的开源方法,开源地址 想了解更多的同学可以下载他们的开源项目进行研究,里面的事例也很明白简洁,注释也写得很好,就是有些找不到(怪我眼瞎…)值得主要的是 他的开发环境配置文件在这个下面
好了,回到正题
现在我们需要下载他们已经封装好的dll了,在浏览中搜索Essensoft.AspNetCore.Payment下载最新版的即可,这里有一个坑 大家注意下,当我们下载这个包的时候 就需要卸载掉支付宝的payment包,他们只能存在一个,不然调用支付接口时会报错 说方法指定不明确(我怀疑是他们的方法名一样,参数也一样 但是调用不明确,这个问题找了我一个多小时,差点想放弃)
安装完成后,我们继续如下配置,我这里是配置开发环境,生产环境也是如此,只需要上线时做对应修改即可
对应填写即可 uid表示的是商户id,就是你进行收钱的地方。
注意AlipayPublicKey和AppPrivateKey 不能换行 不能换行 不能换行
AppPrivateKey就是生成的应用私钥
AlipayPublicKey是上面保存的支付宝公钥
//阿里支付 配置
"Alipay": {
//此处为蚂蚁金服开放平台上创建的APPID,而非老版本的商户号
"AppId": "",
// 支付宝公钥
"AlipayPublicKey": "",
// 商户私钥
"AppPrivateKey": "",
"CharSet": "UTF-8",
"Gatewayurl": "https://openapi.alipaydev.com/gateway.do",
"ServerUrl": "https://openapi.alipaydev.com/gateway.do",
"SignType": "RSA2",
"Uid": ""
}
下面来到Startup 进行支付宝的依赖注入
// 添加支付宝客户端依赖注入
// 引入Payment 依赖注入
services.AddAlipay();
//微信的
//services.AddWeChatPay();
var t = Configuration.GetSection("Alipay");
// 在 appsettings.json(开发环境:appsettings.Development.json) 中 配置选项
services.Configure<AlipayOptions>(Configuration.GetSection("Alipay"));
//services.Configure<WeChatPayOptions>(Configuration.GetSection("WeChatPay"))
然后我们创建如下控制器:
其实我只是进行了第一个的使用,余下两个需要接收支付宝的通知,因为内网穿透实在是太慢了,就没进行测试使用
现在我们来到支付控制器
这是我的代码,请按照自己的项目修改,推荐先去下载研究一下这个开源项目 真的蛮好,里面还有很多其他的支付方式,并可支持最新的技术
仅做参考 后面有使用说明
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Essensoft.AspNetCore.Payment.Alipay;
using Essensoft.AspNetCore.Payment.Alipay.Domain;
using Essensoft.AspNetCore.Payment.Alipay.Request;
using MallApi.Helpers;
using MallApi.ModelHelper.OnlinePay;
using MallApi.Models;
using MallApi.ResultModel;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace MallApi.Controllers.OnlinePay
{
[Microsoft.AspNetCore.Cors.EnableCors("any")]
[Route("api/[controller]")]
// [ServiceFilter(typeof(API.TokenFilter))]
public class AlipayController : ControllerBase
{
private readonly IAlipayClient _client;
private readonly IOptions<AlipayOptions> _optionsAccessor;
public AlipayController(IAlipayClient client, IOptions<AlipayOptions> optionsAccessor)
{
_client = client;
_optionsAccessor = optionsAccessor;
}
private readonly BaseResultModel models = new BaseResultModel();
private readonly ShopappContext db = new ShopappContext();
private readonly AliPayInfo aliPayInfo = new AliPayInfo();
/// <summary>
/// 电脑网站支付
/// </summary>
/// <param name="viewModel"></param>
[HttpPost]
[Route("pcPay")]
public async Task<IActionResult> PagePay(AlipayTradePagePayViewModel viewModel)
{
var model = new AlipayTradePagePayModel
{
Body = viewModel.Body,
Subject = viewModel.Subject,
TotalAmount = viewModel.TotalAmount,
OutTradeNo = viewModel.OutTradeNo,
ProductCode = viewModel.ProductCode
};
AlipayTradePagePayRequest req = new AlipayTradePagePayRequest();
req.SetBizModel(model);
req.SetNotifyUrl(viewModel.NotifyUrl);
req.SetReturnUrl(viewModel.ReturnUrl);
var response = await _client.PageExecuteAsync(req, _optionsAccessor.Value);
return Content(response.Body, "text/html", Encoding.UTF8);
}
/// <summary>
/// 手机网站支付
/// </summary>
[HttpPost]
[Route("appWebPay")]
public async Task<IActionResult> WapPay(AlipayTradeWapPayViewModel viewMode)
{
try
{
//通过订单编号获得商品的标题
SpOrder spOrder = db.SpOrder.FirstOrDefault(p => p.OrderNumber == viewMode.OutTradeNo && p.OrderPay == 0);
if (spOrder == null)
{
models.Code = 404;
models.msg = "订单不存在或已支付";
return Ok(models);
}
SpOrderGoods spOrderGoods = db.SpOrderGoods.FirstOrDefault(p => p.OrderId == spOrder.OrderId);
SpGoodsInf spGoodsInf = db.SpGoodsInf.FirstOrDefault(p => p.GoodsId == spOrderGoods.GoodsId );
if (spGoodsInf == null)
{
models.Code = 404;
models.msg = "该商品不存在或已下架";
return Ok(models);
}
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel
{
Body = viewMode.Body,
Subject = spGoodsInf.GoodsName,
TotalAmount = viewMode.TotalAmount,
OutTradeNo = viewMode.OutTradeNo.Trim(),
ProductCode = viewMode.ProductCode,
QuitUrl= "http://www.hj0819.top:8081/#/order/1",
};
var req = new AlipayTradeWapPayRequest();
req.SetBizModel(model);
//支付宝服务器主动通知商户服务器里指定的页面http/https路径。
// req.SetNotifyUrl("http:///www.hj0819.top:4436/alipay/notify/wappay");
//可实现支付成功后跳转到商家页面的功能,而且跳转后的return_url页面的地址栏中会返回同步通知参数。
req.SetReturnUrl("http://www.hj0819.top:8081/#/aliPayIsok");
var response = await _client.PageExecuteAsync(req, _optionsAccessor.Value);
if (response.IsError)
{
//错误时
models.Code = 203;
models.msg = "支付宝对接错误:"+response.Msg;
}
models.Code = 201;
models.msg = "支付宝对接成功";
models.data = response.Body;
return Ok(models);
}
catch (Exception e)
{
models.Code = 519;
models.msg = "发生内部错误:" + e.Message;
return Ok(models);
throw;
}
}
/// <summary>
/// 交易查询
/// </summary>
[HttpPost]
[Route("ExecuteAliPay")]
public async Task<IActionResult> ExecuteAsync(AlipayTradeQueryViewModel viewMode)
{
//判断该笔订单是否被支付
SpOrder spOrder = db.SpOrder.FirstOrDefault(p => p.OrderNumber == viewMode.OutTradeNo.Trim() && p.OrderPay == 0);
if (spOrder == null)
{
models.Code = 200;
models.msg = "订单被支付";
models.data = spOrder;
return Ok(models);
}
var model = new AlipayTradeQueryModel
{
OutTradeNo = viewMode.OutTradeNo.Trim(),
TradeNo = viewMode.TradeNo
};
var req = new AlipayTradeQueryRequest();
req.SetBizModel(model);
var response = await _client.ExecuteAsync(req, _optionsAccessor.Value);
//转换为json
JObject jos = (JObject)JsonConvert.DeserializeObject(((AlipayResponse)response).Body);
string aliPay = jos["alipay_trade_query_response"].ToString();
JObject jo = (JObject)JsonConvert.DeserializeObject(aliPay);
string code = jo["code"].ToString();
//解析信息
if(code != "10000")
{
//一般错误为 交易不存在
models.Code = 202;
models.msg = jo["sub_msg"].ToString();
return Ok(models);
}
//解析支付宝的交易流水
string trade_no = jo["trade_no"].ToString();
return Ok(aliPayInfo.PayOrder(viewMode.OutTradeNo, trade_no));
}
}
}
使用说明:
成功请求,支付宝给我们返回一个表单(html代码),response.Body中,,我们后端只需要将这个返回给前端即可。
好的,现在我们后端的支付请求已经基本结束了,现在我们切换到前端做处理。
我前端是用vue做的
直接看代码
//进行后端请求
this.$api.onlinePay
.appWebPay({
//直接的订单编号
OutTradeNo: this.order_num,
Subject: "手机网站支付测试",
//这里的请求方式是固定的 手机网站支付方式
ProductCode: "QUICK_WAP_WAY",
body: "手机网站支付描述信息",
//价格
TotalAmount: this.payOrder.goodsPrice
})
.then(res => {
loading.close();
if (res.data.code === 201) {
//返回的是一个表单
//我们需要创建一个新的页面 将代码展示上去,然后点击表单的提交按钮,这样就可以跳转到支付宝的支付页面了 可以选择唤起支付宝支付和进行网页支付
//有一个注意点 沙盒模式,必须使用沙盒账号进行支付,普通账号会支付失败
this.html = res.data.data;
var form = res.data.data;
const div = document.createElement("div");
div.innerHTML = form; //此处form就是后台返回接收到的数据
document.body.appendChild(div);
//进行表单提交 跳转
document.forms[0].submit();
} else {
return this.$message.error(res.data.msg);
}
})
.catch(err => {
loading.close();
return this.$message.error("服务器连接异常");
});
到此,我们的支付已经完成了,,,要想知道怎么获得支付状态,可以选择异步或同步,我没完成,,就选择了手动查询,进行在支付宝支付完成后跳转到一个页面 页面有一个按钮 用来向后端发送一个请求,查询是否支付成功 ,
前端的请求如下:
注意 当OutTradeNo和TradeNo同时存在时,支付宝将优先选择使用TradeNo
// 查询支付状态
payCode() {
const loading = this.$loading({
lock: true,
text: "支付结果查询中....",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)"
});
this.$api.onlinePay
.ExecuteAliPay({
//自己的订单编号(存在自己数据库中的)
OutTradeNo: this.order_num,
//阿里云返回的交易流水 因为我们没有,所有选择为空
TradeNo: ""
})
.then(res => {
loading.close();
if (res.data.code === 201) {
Toast.success(res.data.msg);
} else {
Toast.fail(res.data.msg);
}
})
.catch(err => {
loading.close();
Toast.fail("服务器连接异常");
});
},
后端的如下:
/// <summary>
/// 交易查询
/// </summary>
[HttpPost]
[Route("ExecuteAliPay")]
public async Task<IActionResult> ExecuteAsync(AlipayTradeQueryViewModel viewMode)
{
//判断该笔订单是否被支付
SpOrder spOrder = db.SpOrder.FirstOrDefault(p => p.OrderNumber == viewMode.OutTradeNo.Trim() && p.OrderPay == 0);
if (spOrder == null)
{
models.Code = 200;
models.msg = "订单被支付";
models.data = spOrder;
return Ok(models);
}
var model = new AlipayTradeQueryModel
{
OutTradeNo = viewMode.OutTradeNo.Trim(),
TradeNo = viewMode.TradeNo
};
var req = new AlipayTradeQueryRequest();
req.SetBizModel(model);
var response = await _client.ExecuteAsync(req, _optionsAccessor.Value);
//转换为json
JObject jos = (JObject)JsonConvert.DeserializeObject(((AlipayResponse)response).Body);
string aliPay = jos["alipay_trade_query_response"].ToString();
JObject jo = (JObject)JsonConvert.DeserializeObject(aliPay);
string code = jo["code"].ToString();
//解析信息
if(code != "10000")
{
//一般错误为 交易不存在
models.Code = 202;
models.msg = jo["sub_msg"].ToString();
return Ok(models);
}
//code == "10000" 表示支付成功
//解析支付宝的交易流水
//以下就可以进行自己的业务处理了
string trade_no = jo["trade_no"].ToString();
return Ok(aliPayInfo.PayOrder(viewMode.OutTradeNo, trade_no));
}
好了,到这里已经结束啦,,,谢谢你的阅读
若有错误,还望海涵 也请指正
若有用语不当影响了阅读 在此表示抱歉