微信公眾號+vue+微信支付
在上一篇文章中本人講述了微信公眾號的授權以及獲取使用者資訊,在此基礎上今天這篇部落格跟大家分享一下微信支付的流程及程式碼,還有自己在開發時的一些坑。
1、在進行微信支付時,除了需要一個公眾號之外,你還需要一個微信商戶。根據商戶申請規則進行商戶申請
2、開始配置開發所需要的引數如下所示:
這是公眾號的基本開發配置,這裡在微信授權的時候就已經需要配置了 但是注意AppSecret在你第一次配置的時候就需要備份下來,如果沒有備份那麼下次使用的話你就需要去重置它
網頁域名授權,你需要填寫正確的可以訪問的專案域名,確保微信可以訪問
3、公眾號配置好後我們需要開始配置微信商戶平臺的內容了
商戶平臺需要進行的配置是:商戶號,支付金鑰
商戶號一般都是和自己公眾號的商戶號是一樣的
主要是一個支付金鑰的配置
然後是域名配置 和公眾號差不多
配置支付的引數完成之後就可以開始進行開發了 不過在支付開發中可能會有些許的麻煩 那就是你不能線上下本機測試,因為IP白名單的限制 除非你將自己的本機地址進行地址對映,但是對映操作比較繁瑣,如果自己的專案不是很大的話那就自己麻煩一點部署專案然後進行測試吧,如果你想進行對映之後本機測試這裡可以推薦一個元件給你訪問連結https://natapp.cn/
4、開始正式的程式碼書寫 這裡使用的SDK是()
(1)後臺進行支付配置:
//例項配置
var config = new WeChatConfig(){
AppId = "wx7a87835d950f228f",
AppSecret = "97d8581300ed49326c53db5373e07104",
MchId = "1502779501",
Notify = "http://medicalapi.xin-lai.com/PayNotify/0/wechat",//這是支付回撥路徑(不是前端路徑,這個很坑)
TenPayKey = "wlsoftnewhissong3355180meiyanfei",
PayAppId = "wx7a87835d950f228f"
};
WeChatSDKBuilder.Create()
//設定日誌記錄
.WithLoggerAction((tag, message) =>
{
logger.Debug(string.Format("Tag:{0}\tMessage:{1}", tag, message));
})
//註冊Key。不再需要各個控制註冊
.Register(WeChatFrameworkFuncTypes.GetKey, model =>
{
return "wx8370799bb85178a8";
}
)
//註冊獲取配置函式:根據Key獲取微信配置(載入一次後續將快取)
.Register(WeChatFrameworkFuncTypes.Config_GetWeChatConfigByKey,
model =>
{
return config;
})
//註冊微信支付配置
.Register(WeChatFrameworkFuncTypes.Config_GetWeChatPayConfigByKey, model =>
{
return config;
}
)
.Build();
你可以將config寫在專案的配置檔案中然後進行獲取 我這裡是直接例項化直接了當
(2)支付還需要配置回撥處理邏輯:
//支付回撥設定
PayNotifyBuilder
.Create()
//設定日誌記錄
.WithLoggerAction((tag, message) =>
{
logger.Debug(string.Format("Tag:{0}\tMessage:{1}", tag, message));
}).WithPayNotifyFunc(async(input) =>
{
switch (input.Provider)
{
case "wechat":
{
var api = new WeChatPayApi();
var output = api.PayNotifyHandler(input.Request.Body);
if (output.IsSuccess())
{
bool theresult = true;
var resultLog = output.ToJsonString();
logger.Debug("微信支付處理成功: " + resultLog);
//判斷支付類別並編輯處理
if (output.Attach.StartsWith("門診"))
{
OutpatientsAppService outpatientsAppService = new OutpatientsAppService(new XmlSerializeAppService());
theresult= await outpatientsAppService.LoadChargeListInfo(new Outpatients.Dto.LoadChargeListInfoinput()
{
patCardNo = output.Attach.Substring(2),
psOrdNum = output.TransactionId,
hisOrdNum = output.OutTradeNo,
payMode = "WXPay",
payAmt = Convert.ToDecimal(output.TotalFee) % 100,
payTime =output.TimeEnd,
patCardType= "院內診療卡",
agtOrdNum= output.Attach.Substring(2),
});
}
else if (output.Attach.StartsWith("住院"))
{
logger.Debug("進入住院繳費!");
}
else if (output.Attach.StartsWith("掛號"))
{
RegistrationsAppService registrationsAppService = new RegistrationsAppService(new XmlSerializeAppService());
theresult= await registrationsAppService.RegistPay(output.Attach.Substring(2));
}
if (theresult == true)
{
logger.Debug(output.Attach.Substring(0, 2) + "繳費支付完成!");
logger.Debug("繳費卡號!"+output.Attach.Substring(2));
}
else
{
logger.Debug(output.Attach.Substring(0,2)+"繳費支付未完成!");
}
}
else
{
//此處編寫失敗處理邏輯
var failLog = output.ToJsonString();
logger.Error("微信支付處理失敗: " + failLog);
return await Task.FromResult("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[回撥處理失敗]]></return_msg></xml>");
}
}
break;
default:
break;
}
return null;
}).Build();
(3)支付介面的封裝與呼叫
先是進行微信統一下單
/// <summary>
/// 支付介面實現類
/// </summary>
[Produces("application/json")]
[Route(ApiPrefix + "[controller]")]
public class WhechatPayAppService : AppServiceBase, IwhechatPayAppService
{
/// <summary>
/// 依賴注入
/// </summary>
private readonly IHttpContextAccessor _httpContextAccessor;
public WhechatPayAppService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
/// <summary>
/// 下單 獲取微信支付授權
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[AbpAllowAnonymous]
[HttpPost("GetPayurl")]
public async Task<UnifiedorderResult> GetPayurl(Payinfoinput input)
{
//獲取實際IP
string clientIp = null;
if (clientIp.IsNullOrWhiteSpace())
clientIp = _httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress?.ToString();
clientIp = clientIp ?? "8.8.8.8";
using (UnitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant, AbpDataFilters.MustHaveTenant))
{
var config = WeChatConfigManager.Current.GetPayConfig();
var result = WeChatApisContext.Current.TenPayV3Api.Unifiedorder(new WeChat.SDK.Pays.TenPayV3.UnifiedorderRequest
{
Body = input.Body,
OpenId = input.OpenId,
TimeStart = DateTime.Now.ToString("yyyyMMddHHmmss"),
TimeExpire = DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"),
TradeType = "JSAPI",
DeviceInfo = "WEB",
TotalFee =Convert.ToInt32(input.Cash * 100).ToString(),
OutTradeNo = input.OutTradeNo,
SpbillCreateIp = clientIp,
Attach=input.Attach,
});
if (result.ReturnCode == "FAIL")
throw new UserFriendlyException(result.Message);
var dict = new Dictionary<string, string>
{
{"appId", result.AppId},
{"timeStamp", PayUtil.GetTimestamp()},
{"nonceStr", result.NonceStr},
{"package", "prepay_id=" + result.PrepayId},
{"signType", "MD5"}
};
dict.Add("paySign", PayUtil.CreateMd5Sign(dict, WeChatConfigManager.Current.GetPayConfig().TenPayKey));
return new UnifiedorderResult
{
MWebUrl = null,
PrepayId = "prepay_id=" + result.PrepayId,
TradeType = result.TradeType,
AppId = result.AppId,
paySign= dict["paySign"],
nonceStr = result.NonceStr,
timeStamp= dict["timeStamp"],
msg=result.ErrCodeDes,
};
}
}
前端呼叫統一下單介面 發起支付
統一下單完成之後 用完成返回的引數喚起支付
前端js會返回支付的結果給你 同時後臺會非同步的根據你配置的url返回支付回撥的資訊
坑:當微信支付完成頁面收起之後,會回到你原來的頁面 但是這時你的這個頁面是沒有路徑的
在這裡一般前端只做簡單的頁面處理,後臺進行具體業務處理如上述支付回撥配置所述 這樣你的支付就完成了
相比微信授權來說 公眾號的內容就比較好理解了!