关于使用Abp.WeChat的记录
官方文档其实写的很清楚了 但是因为是小白第一次做,还是有很多读不懂的地方 下面做一个简单的记录
官方地址:https://github.com/EasyAbp/Abp.WeChat
官方使用说明:https://github.com/EasyAbp/Abp.WeChat/blob/master/docs/WeChatPay.md
微信支付:后端所需要的工作
1 前端访问支付用户同意授权,获取code,有两种情况:
(1)snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
(2)授权成功后,页面将跳转至 redirect_uri/?code=CODE&state=STATE
(3)此时前端将获取的code上送给后台
2 后台通过code获取openid
public static string getopenid(string code)
{
string strJson = " ";
string url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx75550f6c7370fbc7&secret=41051f79b41945423195c72d3df54131&code=" + code + "&grant_type=authorization_code";
//获取openid
// //// 链接地址
////https://open.weixin.qq.com/connect/oauth2/authorize?appid=11111111111111111111111111111&redirect_uri=22222222222222222&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
//int id = Convert.ToInt32(Request.QueryString["ID"]);
//string code = Request["code"].ToString();
string html = string.Empty;
//string url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=11111111111111111111111111111111111&secret=2222222222222222222222228&code=" + code + "&grant_type=authorization_code";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = "GET";
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
Stream ioStream = response.GetResponseStream();
StreamReader sr = new StreamReader(ioStream, Encoding.UTF8);
html = sr.ReadToEnd();
sr.Close();
ioStream.Close();
response.Close();
string key = "\"openid\":\"";
int startIndex = html.IndexOf(key);
if (startIndex != -1)
{
int endIndex = html.IndexOf("\",", startIndex);
string openid = html.Substring(startIndex + key.Length, endIndex - startIndex - key.Length);
//MyOpenId.Value=openid;
return openid;
}
else
{
return "找不到OpenidID";
}
}
3 获取openid后,后台进行统一下单(我是叫前端直接传code和金额,后台获取penid后直接统一下单,把这两步放在了一个接口里面)
[HttpGet]
public async Task<UnifiedOrderResultDto> UnifiedOrder([FromQuery] UnifiedOrderDto input)
{
//元转分
int money = int.Parse((input.Money * 100).ToString("0"));
//
string openid = GetOpenId.getopenid(input.Code);
if (openid == "找不到OpenidID")
{
//return null;
throw new ArgumentException($"当交易类型为 JsApi 时,参数 {nameof(openid)} 必须传递有效值。");
}
//订单号(当前时间和随机数)
var ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
var times = Convert.ToInt64(ts.TotalSeconds).ToString();
Random rd = new Random();
var num = rd.Next().ToString();
var OrderNum = times + num;
var result = _ordinaryMerchantPayService.UnifiedOrderAsync(
"你的 AppId",
"你的商户 Id",
"订单的描述信息",
"附加数据",
OrderNum,//"20150806125346",//"订单号", 订单号需要你自己生成,长度不超过 32 位。
money, // 支付金额,单位是分。
TradeType.JsApi,// 交易类型。
openid//你的openId
).Result;
var str = result.OuterXml;
//加个判断 是成功还是失败
string[] sArray1 = str.ToString().Split(new string[] { "<return_code><![CDATA[", "]]></return_code>" }, StringSplitOptions.RemoveEmptyEntries);
if(sArray1[1]== "FAIL")
{
throw new ArgumentException($"当交易类型为 JsApi 时,统一下单失败。");
}
//成功 //截取id
string[] sArray = str.Split(new string[] { "<prepay_id><![CDATA[", "]]></prepay_id>" }, StringSplitOptions.RemoveEmptyEntries);
//返回值
UnifiedOrderResultDto dto = new UnifiedOrderResultDto();
dto.appId = "你的 AppId";
dto.prepayId = sArray[1];
return dto;
}
对应的实体:
public class UnifiedOrderDto
{
public string Code { get; set; }
public double Money { get; set; }
}
public class UnifiedOrderResultDto
{
public string appId { get; set; }
public string prepayId { get; set; }
}
4 通过统一下单可以获取到预支付id(prepayId),通过ABP.WECHAT的原生接口/wechatpay/wechat-pay/js-sdk-config-parameters,获取签名及前端调起支付所需的参数
返回值:
5 前端根据官方文档进行JSAPI调起支付
6 支付完成
所遇到的问题:
1 配置文件要匹配对,否则会报签名匹配失败的错误
2 订单号,code,随机数之类的值, 每一次都必须是新的不能重复使用,会报错
3 接口和发布都得在80端口下,接口我们是读的域名