文章目录
2023年3月8日 修正
好了,正文开始,希望能给需要的人看到,我离秃瓢又近了一步。
本文主要阐述的是C#发起jsapi支付的爬坑经历。也可以是H5页面发起的支付。
一、下载demo
https://pay.weixin.qq.com/wiki/doc/api/download/WxPayAPI_CS.zip
PS:我下的是cs_sdk_v3.0.9:
.NET C# 【微信支付】API对应的SDK和调用示例 付款码支付、JSAPI支付、Native支付
二、搭建环境
1、复制demo的 bussiness和lib到自己项目,然后需要nuget一下Newtonsoft.Json
2、因为只用到了支付,所以只需要一个页面JsApiPayPage.aspx,复制到项目(我改名为ApiPay.aspx)
三、微信支付参数
1、参数主要在lib目录下的DemoConfig.cs里修改:
必须有的GetAppID()、GetMchID、GetKey、GetAppSecret、GetNotifyUrl、GetIp.类里都有参数说明我就不赘述了。
2、微信设置,主要有两个地方。
授权支付目录:商户平台-->产品中心-->开发配置
授权网页访问接口:开发者中心-->网页授权获取用户信息-->修改
这两个地方都只需要填写ApiPay.aspx的上级目录(外网可访问的),比如:https://host/api/ApiPay.aspx,填写https://host/api/就行 ,不同的是网页授权要拷贝一个TXT
四、主要业务流程(看看了解一下就行)
如果上面的参数设置正确,恭喜你成功了一半。先讲下实现流程,在贴主要业务代码
1、前端H5支付跳到后端(支付金额是必须的)
2、获取openid:jsApiPay.GetOpenidAndAccessToken();这里是有个回调,先发送请求取得code,再验证网页权限去解析code 取得openid.
3、统一下单:jsApiPay.GetUnifiedOrderResult(),可以理解为让微信创建订单。
4、H5发起jsapi:jsApiPay.GetJsApiParameters(); 这里的prepay_id订单号要跟上一步返回的对应。不然会出错。
五、代码
其实代码上的改动只有ApiPay.aspx(因为就是复制过来的JsApiPayPage.aspx)
1、ApiPay.aspx前端:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ApiPay.aspx.cs" Inherits="Web.api.ApiPay" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="../js/jquery-1.9.1.min.js"></script>
<script src="../js/jweixin-1.0.0.js"></script>
<title>微信支付</title>
</head>
<script type="text/javascript">
//调用微信JS api 支付
function jsApiCall()
{
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
<%=wxJsApiParam%>//josn串
function (res) {
switch (res.err_msg) {
case "get_brand_wcpay_request:ok":
$('#btn').click();
//支付成功,写入数据库;
break;
case "get_brand_wcpay_request:cancel":
alert("支付取消");
break;
default:
alert("支付失败");
break;
}
}
);
}
function callpay() {
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
}
else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
}
else {
jsApiCall();
}
}
</script>
<body>
<form runat="server">
<div align="center" style="display: none;">
<asp:Button ID="submit" runat="server" Text="立即支付" OnClientClick="callpay();return false;" Style="width: 210px; height: 50px; border-radius: 15px; background-color: #00CD00; border: 0px #FE6714 solid; cursor: pointer; color: white; font-size: 16px;" />
<asp:Button ID="btn" runat="server" Text="写入数据库" Style="width: 210px; height: 50px; border-radius: 15px; background-color: #00CD00; border: 0px #FE6714 solid; cursor: pointer; color: white; font-size: 16px;" OnClick="btn_Click" />
</div>
</form>
</body>
</html>
2、ApiPay.aspx.cs
using System;
using WxPayAPI;
using System.Text;
namespace Web.api
{
public partial class ApiPay : System.Web.UI.Page
{
public static string wxJsApiParam { get; set; } //H5调起JS API参数
public string uid { get; set; }//用户ID
public string oid { get; set; }//订单ID
public string amount { get; set; }//支付金额
public string openid{ get; set; }//支付用户的openid
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["fee"] != null)
{
amount = Request.QueryString["fee"];
}
if (Request.QueryString["uid"] != null)
{
uid = Request.QueryString["uid"];
}
if (Request.QueryString["oid"] != null)
{
oid = Request.QueryString["oid"];
}
//-----------------因为多次回调,必须写!IsPostBack外才能获取-----------------------------
if (!IsPostBack)
{
JsApiPay jsApiPay = new JsApiPay(this);
if (Request.QueryString["fee"] != null)
{
double amt = double.Parse(Request.QueryString["fee"])*100;
jsApiPay.total_fee = int.Parse(amt.ToString());
amount = Request.QueryString["fee"];
}
if (string.IsNullOrEmpty(openid))//1、微信登录验证
{
//获取openid
jsApiPay.GetOpenidAndAccessToken();
openid = jsApiPay.openid;
}
//检测是否给当前页面传递了相关参数
if (string.IsNullOrEmpty(openid))
{
return;
}
else
{
jsApiPay.openid= openid;
}
//JSAPI支付预处理
try
{
WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult();//2、发起统一支付
wxJsApiParam = jsApiPay.GetJsApiParameters();//3、获取H5调起JS API参数
}
catch (Exception ex)
{
Response.Write("<span style='color:#FF0000;font-size:20px'>" + "下单失败,请返回重试</span>");
return;
}
doPay();//4、发起支付
}
}
//H5请求支付 之前2统一下单创建的订单
public void doPay()
{
StringBuilder sb = new StringBuilder();
sb.Append("<script language='javascript'>");
sb.Append("$('#submit').click();");
sb.Append("</script>");
ClientScript.RegisterStartupScript(this.GetType(), "LoadPicScript", sb.ToString());
}
//5、支付成功后的业务逻辑(按自己的程序修改就行)
protected void btn_Click(object sender, EventArgs e)
{
string str = string.Format("{0},{1},{2}", oid, uid, amount);
if (saveinmysql(str)) {//支付成功状态写入数据库saveinmysql是唯一属于我的函数了
yesPay();
}
}
//6、支付成功,业务流程全部完事,可以跑路了
public void yesPay()
{
StringBuilder sb = new StringBuilder();
sb.Append("<script language='javascript'>");
sb.Append("alert('支付成功');window.location.href ='支付成功跳出支付.html");
sb.Append("</script>");
ClientScript.RegisterStartupScript(this.GetType(), "LoadPicScript", sb.ToString());
}
}
}
3、因为我前端传了fee(total_fee)、uid(我的)、oid(我的)三个参数,所以微信登录回调会弄掉,需要修改(注意修改 host ):
\business\JsApiPay.cs的GetOpenidAndAccessToken()
string host = page.Request.Url.Host;//这里改成域名如 www.xxx.com
string path = page.Request.Path;
string requt = page.Request.Url.Query;//主要是这里和下一句,把?后的也加入回调地址
string redirect_uri = HttpUtility.UrlEncode("http://" + host + path+ requt);
六、大坑插眼:
认真执行一、二、三、五,基本支付就成功了。这里对大坑进行插眼,秃瓢警告,嘤嘤嘤
1、前端一定要传 total_fee(本文的fee),且记得100倍
2、三、2的两个授权页面一定要到位,不然坑死
3、微信开发者工具,需要公众号设置开发者权限,虽然支付后面的无法调试,还是能看到JS错误
4、用手机微信测试的话,一定要在手机、设置、应用、微信,里清一下缓存,不然你会发现太他瞄的坑了
5、GetNotifyUrl这个一定要填,公网能访问就行,虽然也没啥用(非扫码支付不跳那的)。
6、这个最坑,demo自带的bug:在五、1里(代码)有个jweixin-1.0.0.js,我是下载到本地的,实际路径为:``http://res.wx.qq.com/open/js/jweixin-1.0.0.js
(<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>)
这个不调用,你会发现,支付成功,回调没卵用(这蛋疼的问题卡我一晚上,离秃瓢又近了一步)
7、附上签名测试工具,感觉没啥用,唯一有用的是测试你的key和appid是否匹配。毕竟签名封装都是写好的,不用改
8、统一下单 和 发起支付,签名加密方式要一致,我都用的SIGN_TYPE_HMAC_SHA256(HMAC-SHA256),一个MD5.一个HMAC-SHA256肯定报错的
WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult();//2、发起统一支付
wxJsApiParam = jsApiPay.GetJsApiParameters();//3、获取H5调起JS API参数
--------------end-----------------
再次吐槽,微信的工作人员太偷工减料了,只看API文档会被坑死,码农何必为难码农,诶。
已经尽量写得很详细了,第一次发帖,如果有帮到你,记得给个赞