摘要:本文主要向大家介绍了C#编程之微信app支付android客户端以及.net服务端实现,通过具体的内容向大家展示,希望对大家学习C#编程有所帮助。
本文主要向大家介绍了C#编程之微信app支付android客户端以及.net服务端实现,通过具体的内容向大家展示,希望对大家学习C#编程有所帮助。
由于公司运营需要,需要在客户端(android/ios)增加微信以及支付宝支付,在调用微信app支付时遇到一些问题,也算是一些踩过的坑,记录下来
,希望能对.net开发者服务端网站更快的集成微信app支付。
1.开发所需资料:微信开放平台应用的appid以及appsecert,商户平台的商户号以及api安全里面里面设置的key,详见 微信支付账户相关信息;
2.微信开发者平台完善应用平台的相关信息,android应用签名必须用打包签名过的发布版本apk(这一步很重用),包名必须一致,可以用微信提供的签名工具获得,签名工具下载地址https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk
以下是交互时序图,统一下单API、支付结果通知API和查询订单API等都涉及签名过程,调用都必须在商户服务器端完成(来源微信支付开发文档):
商户系统和微信支付支付系统主要交互:
步骤1:用户在商户APP中选择商品,提交订单,选择微信支付。商户后台收到订单时需要调用微信的同意下单接口,生成预支付单;
C#大概代码如下(相关代码参考自JeffreySu/WeiXinMPSDK ):
private WechatPayResult generatePayResult(string mchappid,string mchid
,string body,string orderno,int total,string ip,string notify,string mchkey,string nonce)
{
DateTime start = DateTime.Now,end= DateTime.Now.AddMinutes(15);
var xmlDataInfo = new TenPayV3UnifiedorderRequestData(mchappid
,mchid, body, orderno, total
,ip,notify, TenPayV3Type.APP
, null, mchkey, nonce, null,start,end);
var result = TenPayV3.Unifiedorder(xmlDataInfo);//调用统一订单接口
return new WechatPayResult
{
appid=mchappid,
body=body,
CreatedOn=DateTime.Now,
mch_id=mchid,
prepay_id=result.prepay_id,
spbill_create_ip=ip,
nonce_str=nonce,
timeStamp= TenPayV3Util.GetTimestamp(),
out_trade_no=orderno,
time_start=start,
time_expire=end,
total_fee=total,
trade_type=result.trade_type
};
}
View Code
public class RequestHandler
{
public RequestHandler()
{
Parameters = new Hashtable();
}
public RequestHandler(HttpContext httpContext)
{
Parameters = new Hashtable();
this.HttpContext = httpContext ?? HttpContext.Current;
}
///
private string Key;
protected HttpContext HttpContext;
///
protected Hashtable Parameters;
///
private string DebugInfo;
///
public virtual void Init()
{
}
///
///
public String GetDebugInfo()
{
return DebugInfo;
}
///
///
public string GetKey()
{
return Key;
}
///
///
public void SetKey(string key)
{
this.Key = key;
}
///
///
///
public void SetParameter(string parameter, string parameterValue)
{
if (parameter != null && parameter != "")
{
if (Parameters.Contains(parameter))
{
Parameters.Remove(parameter);
}
Parameters.Add(parameter, parameterValue);
}
}
///
///
///
public void SetParameterWhenNotNull(string parameter, string parameterValue)
{
if (!string.IsNullOrEmpty(parameterValue))
{
SetParameter(parameter, parameterValue);
}
}
///
///
参数名
///
参数值
/// key和value通常用于填充最后一组参数
///
public virtual string CreateMd5Sign(string key, string value)
{
StringBuilder sb = new StringBuilder();
ArrayList akeys = new ArrayList(Parameters.Keys);
akeys.Sort();
foreach (string k in akeys)
{
string v = (string)Parameters[k];
if (null != v && "".CompareTo(v) != 0
&& "sign".CompareTo(k) != 0
//&& "sign_type".CompareTo(k) != 0
&& "key".CompareTo(k) != 0)
{
sb.Append(k + "=" + v + "&");
}
}
sb.Append(key + "=" + value);
string sign = EncryptHelper.GetMD5(sb.ToString(), GetCharset()).ToUpper();
//string sign = MD5UtilHelper.GetMD5(sb.ToString(), GetCharset()).ToUpper();
return sign;
}
public virtual string CreateMd5Sign()
{
StringBuilder sb = new StringBuilder();
ArrayList akeys = new ArrayList(Parameters.Keys);
akeys.Sort();
foreach (string k in akeys)
{
string v = (string)Parameters[k];
if (null != v && "".CompareTo(v) != 0
&& "sign".CompareTo(k) != 0
//&& "sign_type".CompareTo(k) != 0
&& "key".CompareTo(k) != 0)
{
sb.Append(k + "=" + v + "&");
}
}
string sign = EncryptHelper.GetMD5(sb.ToString().Substring(0,sb.Length-1), GetCharset()).ToUpper();
return sign;
}
///
///
public string ParseXML()
{
StringBuilder sb = new StringBuilder();
sb.Append("
");
return sb.ToString();
}
///
///
public void SetDebugInfo(String debugInfo)
{
this.DebugInfo = debugInfo;
}
public Hashtable GetAllParameters()
{
return this.Parameters;
}
protected virtual string GetCharset()
{
if (this.HttpContext == null)
{
return Encoding.UTF8.BodyName;
}
return this.HttpContext.Request.ContentEncoding.BodyName;
}
}
View Code
///
public class TenPayV3UnifiedorderRequestData
{
///
public string AppId { get; set; }
///
public string MchId { get; set; }
///
public string DeviceInfo { get; set; }
///
public string NonceStr { get; set; }
///
public string SignType { get; set; }
///
public string Body { get; set; }
///
public string Detail { get; set; }
///
public string Attach { get; set; }
///
public string FeeType { get; set; }
///
public string OutTradeNo { get; set; }
///
public int TotalFee { get; set; }
///
public string SpbillCreateIP { get; set; }
///
public string TimeStart { get; set; }
///
public string TimeExpire { get; set; }
///
public string GoodsTag { get; set; }
///
public string NotifyUrl { get; set; }
///
public TenPayV3Type TradeType { get; set; }
///
public string ProductId { get; set; }
///
public string LimitPay { get; set; }
///
public string OpenId { get; set; }
///
public string Key { get; set; }
public readonly RequestHandler PackageRequestHandler;
public readonly string Sign;
///
///
///
///
///
///
单位:分
///
///
///
///
///
///
///
自定义参数,可以为终端设备号(门店号或收银设备ID),PC网页或公众号内支付可以传"WEB",String(32)如:013467007045764
///
订单生成时间,如果为空,则默认为当前服务器时间
///
订单失效时间,留空则不设置失效时间
///
商品详细列表
///
附加数据
///
符合ISO 4217标准的三位字母代码,默认人民币:CNY
///
商品标记,使用代金券或立减优惠功能时需要的参数,说明详见代金券或立减优惠。String(32),如:WXG
///
trade_type=NATIVE时(即扫码支付),此参数必传。此参数为二维码中包含的商品ID,商户自行定义。String(32),如:12235413214070356458058
///
是否限制用户不能使用信用卡支付
public TenPayV3UnifiedorderRequestData(string appId, string mchId, string body, string outTradeNo, int totalFee, string spbillCreateIp,
string notifyUrl, TenPayV3Type tradeType, string openid, string key, string nonceStr,
string deviceInfo = null, DateTime? timeStart = null, DateTime? timeExpire = null,
string detail = null, string attach = null, string feeType = "CNY", string goodsTag = null, string productId = null, bool limitPay = false)
{
AppId = appId;
MchId = mchId;
DeviceInfo = deviceInfo;
NonceStr = nonceStr;
SignType = "MD5";
Body = body ?? "";
Detail = detail;
Attach = attach;
OutTradeNo = outTradeNo;
FeeType = feeType;
TotalFee = totalFee;
SpbillCreateIP = spbillCreateIp;
TimeStart = (timeStart ?? DateTime.Now).ToString("yyyyMMddHHmmss");
TimeExpire = timeExpire.HasValue ? timeExpire.Value.ToString("yyyyMMddHHmmss") : null;
GoodsTag = goodsTag;
NotifyUrl = notifyUrl;
TradeType = tradeType;
ProductId = productId;
LimitPay = limitPay ? "no_credit" : null;
OpenId = openid;
Key = key;
#region 设置RequestHandler
//创建支付应答对象
PackageRequestHandler = new RequestHandler(null);
//初始化
PackageRequestHandler.Init();
//设置package订单参数
//以下设置顺序按照官方文档排序,方便维护:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
PackageRequestHandler.SetParameter("appid", this.AppId); //公众账号ID
PackageRequestHandler.SetParameter("mch_id", this.MchId); //商户号
PackageRequestHandler.SetParameterWhenNotNull("device_info", this.DeviceInfo); //自定义参数
PackageRequestHandler.SetParameter("nonce_str", this.NonceStr); //随机字符串
PackageRequestHandler.SetParameterWhenNotNull("sign_type", this.SignType); //签名类型,默认为MD5
PackageRequestHandler.SetParameter("body", this.Body); //商品信息
PackageRequestHandler.SetParameterWhenNotNull("detail", this.Detail); //商品详细列表
PackageRequestHandler.SetParameterWhenNotNull("attach", this.Attach); //附加数据
PackageRequestHandler.SetParameter("out_trade_no", this.OutTradeNo); //商家订单号
PackageRequestHandler.SetParameterWhenNotNull("fee_type", this.FeeType); //符合ISO 4217标准的三位字母代码,默认人民币:CNY
PackageRequestHandler.SetParameter("total_fee", this.TotalFee.ToString()); //商品金额,以分为单位(money * 100).ToString()
PackageRequestHandler.SetParameter("spbill_create_ip", this.SpbillCreateIP); //用户的公网ip,不是商户服务器IP
PackageRequestHandler.SetParameterWhenNotNull("time_start", this.TimeStart); //订单生成时间
PackageRequestHandler.SetParameterWhenNotNull("time_expire", this.TimeExpire); //订单失效时间
PackageRequestHandler.SetParameterWhenNotNull("goods_tag", this.GoodsTag); //商品标记
PackageRequestHandler.SetParameter("notify_url", this.NotifyUrl); //接收财付通通知的URL
PackageRequestHandler.SetParameter("trade_type", this.TradeType.ToString()); //交易类型
PackageRequestHandler.SetParameterWhenNotNull("product_id", this.ProductId); //trade_type=NATIVE时(即扫码支付),此参数必传。
PackageRequestHandler.SetParameterWhenNotNull("limit_pay", this.LimitPay); //上传此参数no_credit--可限制用户不能使用信用卡支付
PackageRequestHandler.SetParameter("openid", this.OpenId); //用户的openId,trade_type=JSAPI时(即公众号支付),此参数必传
Sign = PackageRequestHandler.CreateMd5Sign("key", this.Key);
PackageRequestHandler.SetParameter("sign", Sign); //签名
#endregion
}
}
统一下单
///
///
微信支付需要post的Data数据
///
///
public static UnifiedorderResult Unifiedorder(TenPayV3UnifiedorderRequestData dataInfo, int timeOut = Config.TIME_OUT)
{
var urlFormat = "https://api.mch.weixin.qq.com/pay/unifiedorder";
var data = dataInfo.PackageRequestHandler.ParseXML();//获取XML
//throw new Exception(data.HtmlEncode());
MemoryStream ms = new MemoryStream();
var formDataBytes = data == null ? new byte[0] : Encoding.UTF8.GetBytes(data);
ms.Write(formDataBytes, 0, formDataBytes.Length);
ms.Seek(0, SeekOrigin.Begin);//设置指针读取位置
var resultXml = RequestUtility.HttpPost(urlFormat, null, ms, timeOut: timeOut);
return new UnifiedorderResult(resultXml);
}
统一支付接口
步骤2:统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay,签名的字段数量必须跟你app调起微信支付所传的参数一致:
///
///
///
///
///
///
///
///
///
///
public static string GetAppPaySign(string appId
, string timeStamp, string nonceStr, string package,
string key,string partnerid,string prepayid,string signType = "MD5"
)
{
RequestHandler paySignReqHandler = new RequestHandler(null);
paySignReqHandler.SetParameter("appid", appId.Trim());
paySignReqHandler.SetParameter("timestamp", timeStamp.Trim());
paySignReqHandler.SetParameter("noncestr", nonceStr.Trim());
paySignReqHandler.SetParameter("partnerid", partnerid);
paySignReqHandler.SetParameter("prepayid", prepayid);
paySignReqHandler.SetParameter("package", package.Trim());
//paySignReqHandler.SetParameter("signtype", "MD5");
var paySign = paySignReqHandler.CreateMd5Sign("key", key);
return paySign;
}
生成微信app支付签名
步骤3:商户APP调起微信支付。详细介绍参见微信支付官方文档
关键代码如下:
public static IWXAPI api;
api= WXAPIFactory.createWXAPI(this, Constants.APP_ID,true);
api.registerApp(Constants.APP_ID);
Result result = JSON.parseObject(bytes, Result.class);
if (null != result) {
if (result.isSuccess()) {
prepay prepay = JSON.parseObject(result.getData().toString(), prepay.class);
PayReq request = new PayReq();
request.appId = prepay.getAppid();
request.partnerId =prepay.getPartnerid();
request.prepayId= prepay.getPrepayid();
request.packageValue = prepay.getPackages();
request.nonceStr= prepay.getNoncestr();
request.timeStamp=prepay.getTimestamp();
request.sign= prepay.getSign();
api.sendReq(request);
}
}
android调起支付相关代码
其中result.getData()表示服务端返回的预支付订单的相关参数,用这参数调用微信支付,该activity必须实现接口IWXAPIEventHandler,并实现
@Overridepublic void onResp(BaseResp baseResp) { if(baseResp.getType()== ConstantsAPI.COMMAND_PAY_BY_WX){ Log.d("dd","onPayFinish,errCode="+baseResp.errCode); }}用于判断微信支付结果,安全起见,建议微信app回调后请求商户api相关接口确定支付结果支付成功时微信后台会请求生成预支付单时传递的通知url(即payProvider.TenpayNotify)通知商户支付结果,商户后台校验相关信息
[AllowAnonymous]
public ActionResult PayResult()
{
ResponseHandler resHandler = new ResponseHandler(null);
string return_code = resHandler.GetParameter("return_code");
string return_msg = resHandler.GetParameter("return_msg");
string res = null;
EngineContext.Current.Resolve
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C#.NET频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号