目錄
Xamarin.Forms 微信支付寶支付接口
背景
服務端已寫好的,這裏的是手機端的調用。
SDK 已轉譯好了,==鏈接還沒寫好==
接口實現
微信接口
1. 在xamarin.forms工程中添加接口
public interface IWeChat
{
void WXPay(Xamarin.AppFramework.WxPayReqItem req);
}
1.1 微信支付請求參數的構成:以下代碼using內容一樣
using System;
using System.Collections.Generic;
using System.Text;
/// <summary>
/// 微信客戶端付款請求參數:從服務器返回的。
/// 字段名稱根據服務端定義的參數自行修改
/// </summary>
public class WxPayReqItem
{
public string prepay_id { get; set; }
public string nonceStr { get; set; }
public string sign
{
get
{
return WxInfo.SecSign(prepay_id, nonceStr,timestamp);
}
}
public string timestamp
{
get
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalSeconds).ToString();
}
}
}
/// <summary>
/// 微信信息
/// </summary>
public class WxInfo
{
/// <summary>
/// 微信appid
/// </summary>
public static string AppId = "";
/// <summary>
/// 商戶號
/// </summary>
public static string PartnerId = " ";
/// <summary>
/// /商戶平臺API密鑰
/// </summary>
public static string outkey = " ";
/// <summary>
/// 支付結果回調 ,回調結果裏面帶上支付方式和支付標誌。
/// </summary>
public static AsyncMsg am_支付結果 = new AsyncMsg();
public static WxUserInfo wxUserInfo = new WxUserInfo();
/// <summary>
/// 微信支付簽名算法
/// </summary>
/// <param name="parameters"></param>
/// <returns></returns>
static string GetSignContent(IDictionary<string, string> parameters)
{
// 第一步:把字典按Key的字母順序排序
IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters);
IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();
// 第二步:把所有參數名和參數值串在一起
StringBuilder query = new StringBuilder("");
while (dem.MoveNext())
{
string key = dem.Current.Key;
string value = dem.Current.Value;
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
{
query.Append(key).Append("=").Append(value).Append("&");
}
}
string content = query.ToString().Substring(0, query.Length - 1);
return content;
}
/// <summary>
/// 微信支付二次簽名
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string SecSign(string prepayid, string noncestr,string timestamp)
{
//二次簽名
Dictionary<string, string> parameters1 = new Dictionary<string, string>();
parameters1.Add("appid", AppId);
parameters1.Add("partnerid", PartnerId);
parameters1.Add("prepayid", prepayid);
parameters1.Add("noncestr", noncestr);
parameters1.Add("timestamp", timestamp);
parameters1.Add("package", "Sign=WXPay");
string content = GetSignContent(parameters1);
//,在stringA最後拼接上key得到stringSignTemp字符串,並對stringSignTemp進行MD5運算,再將得到的字符串所有字符轉換爲大寫,得到sign值signValue。
//stringSignTemp=stringA+"&key=192006250b4c09247ec02edce69f6a2d" //注:key爲商戶平臺設置的密鑰key
string signResult =Xamarin.AppFramework.Helpers.CryptHelper.GetMD5(content + "&key=" + outkey).ToUpper();
return signResult;
}
}
上面用到了MD5加密:
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
namespace Xamarin.AppFramework.Helpers
{
public class CryptHelper
{
private static readonly MD5 md5Hasher = MD5.Create();
public static string CreateMD5(string text)
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(text));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
public static string GetMD5(string encypStr)
{
char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
try
{
byte[] btInput = System.Text.Encoding.Default.GetBytes(encypStr);
// 獲得MD5摘要算法的 MessageDigest 對象
MD5 mdInst = System.Security.Cryptography.MD5.Create();
// 使用指定的字節更新摘要
mdInst.ComputeHash(btInput);
// 獲得密文
byte[] md = mdInst.Hash;
// 把密文轉換成十六進制的字符串形式
int j = md.Length;
char[] str = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++)
{
byte byte0 = md[i];
str[k++] = hexDigits[(int)(((byte)byte0) >> 4) & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new string(str);
}
catch (Exception e)
{
Console.Error.WriteLine(e.StackTrace);
return null;
}
}
}
}
2. android平臺下實現:用到了plugin.currentActivity,需要nuget下載引用。 2.1 2.1 實現接口
using Android.Content;
using Android.Graphics;
using Android.Widget;
using AndroidHUD;
using Com.Tencent.MM.Sdk.Modelmsg;
using Com.Tencent.MM.Sdk.Openapi;
using System;
using System.IO;
using Saobag.Droid;
[assembly: Xamarin.Forms.Dependency(typeof(Interface.Droid.WeChat))]
namespace Interface.Droid
{
/// <summary>
/// 微信相關
/// </summary>
class WeChat : Xamarin.AppFramework.Interface.IWeChat
{
Context CurrentContext => Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity;
/// <summary>
/// 微信支付
/// </summary>
public void WXPay(Xamarin.AppFramework.WxPayReqItem wxreq)
{
try
{
wxapi.Droid.WXPayEntryActivity.wxpay(wxreq);
}
catch (Exception ex)
{
Android.Widget.Toast.MakeText(CurrentContext, "支付異常:" + ex.Message, ToastLength.Long).Show();
}
}
}
}
2.2 微信支付及回調接口
using Android.App;
using Android.Content;
using Android.OS;
using Android.Widget;
using Com.Tencent.MM.Sdk.Modelbase;
using Com.Tencent.MM.Sdk.Openapi;
using Com.Tencent.MM.Sdk.Modelpay;
using Xamarin.Forms;
namespace wxapi.Droid
{
//xamarin對於Activity的路徑是根據Name來發起的, 本身命名空間和類名只是工程內部使用。
//微信回調的根據是這裏的Name: 應用包名+.wxapi.WXPayEntryActivity 構成,不能有差錯,否則無法回調。
[Activity(Label = "WXPayEntryActivity", Name = "com.cstc.Saobag.wxapi.WXPayEntryActivity", Theme = "@android:style/Theme.Translucent", LaunchMode = Android.Content.PM.LaunchMode.SingleTop, Exported = true)]
///微信支付回調
public class WXPayEntryActivity : Activity, IWXAPIEventHandler
{
private static IWXAPI wxApi;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
wxApi = WXAPIFactory.CreateWXAPI(this, Xamarin.AppFramework.WxInfo.AppId);
wxApi.HandleIntent(Intent, this);
}
public void OnReq(BaseReq req)
{
// throw new NotImplementedException();
}
public void OnResp(BaseResp resp)
{
switch (resp.MyErrCode)
{
case BaseResp.ErrCode.ErrOk:
Device.BeginInvokeOnMainThread(() =>
{
Toast.MakeText(this.BaseContext, "支付成功", ToastLength.Short).Show();
});
Xamarin.AppFramework.WxInfo.am_支付結果.OnCompletion(null, "充值");
Finish();
break;
case BaseResp.ErrCode.ErrAuthDenied:
Device.BeginInvokeOnMainThread(() =>
{
Toast.MakeText(this.BaseContext, "支付失敗", ToastLength.Short).Show();
});
Xamarin.AppFramework.WxInfo.am_支付結果.OnCancel(null, "充值");
Finish();
break;
case BaseResp.ErrCode.ErrUserCancel:
Device.BeginInvokeOnMainThread(() =>
{
Toast.MakeText(this.BaseContext, "取消支付", ToastLength.Short).Show();
});
Xamarin.AppFramework.WxInfo.am_支付結果.OnCancel(null, "充值");
Finish();
break;
}
}
/// <summary>
/// 調用微信支付
/// </summary>
/// <param name="req"></param>
public static void wxpay(Xamarin.AppFramework.WxPayReqItem req)
{
if (wxApi == null)
{
//不同工程使用的時候記得修改命名空間。
wxApi = WXAPIFactory.CreateWXAPI(Saobag.Droid.MainActivity.mainActivity, Xamarin.AppFramework.WxInfo.AppId);
}
wxApi.RegisterApp(Xamarin.AppFramework.WxInfo.AppId);
PayReq payReq = new PayReq();
payReq.AppId = Xamarin.AppFramework.WxInfo.AppId;
payReq.PartnerId = Xamarin.AppFramework.WxInfo.PartnerId;
payReq.PrepayId = req.prepay_id;
payReq.PackageValue = "Sign=WXPay";
payReq.NonceStr = req.nonceStr;
payReq.TimeStamp = req.timestamp;
payReq.Sign = req.sign;
bool isflag = wxApi.SendReq(payReq); }
}
}
2.3 支付寶android直接實現接口,處理回調值。
using Android.Content;
using Android.Widget;
using System;
using Xamarin.Forms;
using Saobag.Droid;
[assembly: Xamarin.Forms.Dependency(typeof(Interface.Droid.Ali))]
namespace Interface.Droid
{
public class Ali : Xamarin.AppFramework.Interface.IAli
{
/// <summary>
/// Android 實現支付寶支付
/// </summary>
/// <param name="orderInfo">訂單信息</param>
public void AliPay(string orderInfo)
{
Com.Alipay.Sdk.App.PayTask pa = new Com.Alipay.Sdk.App.PayTask(MainActivity.mainActivity);
string result = pa.Pay(orderInfo);
if (result.Contains("6001"))
{
Device.BeginInvokeOnMainThread(() =>
{
Toast.MakeText(MainActivity.mainActivity, "取消支付", ToastLength.Short).Show();
});
Xamarin.AppFramework.AliInfo.am_支付結果.OnCancel(null, "充值");
}
else if (result.Contains("9000"))
{
Device.BeginInvokeOnMainThread(() =>
{
Toast.MakeText(MainActivity.mainActivity, "支付成功", ToastLength.Short).Show();
});
Xamarin.AppFramework.AliInfo.am_支付結果.OnCompletion(null, "充值");
}
else if (result.Contains("4000"))
{
Device.BeginInvokeOnMainThread(() =>
{
Toast.MakeText(MainActivity.mainActivity, "支付失敗", ToastLength.Short).Show();
});
Xamarin.AppFramework.AliInfo.am_支付結果.OnCancel(null, "充值");
}
}
}
}
3. IOS平臺下實現:
首先要配置:infolist,高級裏面要添加url類型,用於支付後跳回程序。微信爲appid,支付寶爲scheme,也就是向支付寶申請支付填的包名
3.1 實現接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Foundation;
using UIKit;
using Xamarin.Forms;
using WeChatBinding;
[assembly: Xamarin.Forms.Dependency(typeof(Interface.iOS.WeChat))]
namespace Interface.iOS
{
public class WeChat : Xamarin.AppFramework.Interface.IWeChat
{
public static WXApi WXapi;
public void WXPay(Xamarin.AppFramework.WxPayReqItem req)
{
PayReq request = new PayReq();
request.PartnerId = Xamarin.AppFramework.WxInfo.PartnerId;
request.PrepayId = req.prepay_id;
request.Package = @"Sign=WXPay";
request.NonceStr = req.nonceStr;
request.TimeStamp = Convert.ToUInt32(req.timestamp);
request.Sign = req.sign;
WXApi.SendReq(request);
}
}
}
using AlipaySDKBinding;
using Xamarin.Forms;
[assembly: Xamarin.Forms.Dependency(typeof(Interface.iOS.Ali))]
namespace Interface.iOS
{
public class Ali : Xamarin.AppFramework.Interface.IAli
{
/// <summary>
/// 支付報支付
/// </summary>
/// <param name="orderInfo">訂單明細</param>
public void AliPay(string orderInfo)
{
//支付寶回調實際上不走這裏的CompletionBlock,而是走appdelegate裏面的openurl
//注意scheme需要在infolist--高級,urltype那裏添加軟件的標識符,這裏調用傳入,支付成功後才能返回軟件
AlipaySDKBinding.AlipaySDK.DefaultService.PayOrder(orderInfo, "com.cstc.sample",
new CompletionBlock(aa => { }));
}
}
}
3.2 微信回調委託
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Foundation;
using UIKit;
using WeChatBinding;
using BigTed;
using Xamarin.Forms;
using System.Threading.Tasks;
namespace wxapi
{
public class WxDelegate : WXApiDelegate
{
public override void OnReq(BaseReq req)
{
//base.OnReq(req);
}
public override void OnResp(BaseResp resp)
{
if (resp is PayResp)
{
#region 微信支付回調
PayResp response = (PayResp)resp;
switch (response.ErrCode)
{
case 0:
Show_Toast("支付成功");
Xamarin.AppFramework.WxInfo.am_支付結果.OnCompletion(null, "充值");
break;
default:
Xamarin.AppFramework.WxInfo.am_支付結果.OnCancel(null, "充值");
Show_Toast("支付失敗");
break;
}
#endregion
}
}
}
}
}
3.3 支付回調
using System;
using System.Collections.Generic;
using System.Linq;
using Foundation;
using UIKit;
using WeChatBinding;
using BigTed;
namespace Saobag.iOS
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
Xamarin.AppFramework.MConfig.screenWidth = UIScreen.MainScreen.Bounds.Width; //屏幕寬度
WXApi.RegisterApp(Xamarin.AppFramework.WxInfo.AppId);
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
/// <summary>
/// 支付寶支付回調, IOS9.3以上
/// </summary>
/// <param name="app"></param>
/// <param name="url"></param>
/// <param name="options"></param>
/// <returns></returns>
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
return ThirpartyResult(url);
}
/// <summary>
/// 微信回調,IOS9.3以下支付寶支付回調
/// </summary>
/// <param name="application"></param>
/// <param name="url"></param>
/// <param name="sourceApplication"></param>
/// <param name="annotation"></param>
/// <returns></returns>
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
return ThirpartyResult(url);
}
private bool ThirpartyResult(NSUrl url)
{
Xamarin.AppFramework.MConfig.WriteLog(url.ToString());
if (url.Scheme.Equals(Xamarin.AppFramework.WxInfo.AppId))
{
wxapi.WxDelegate d = new wxapi.WxDelegate();
bool b = WXApi.HandleOpenURL(url, d);
return b;
}
else if (url.Host.Equals("safepay"))
{
return AliPayResult(url);
}
else
return true;
}
private bool AliPayResult(NSUrl url)
{
if (url.Host.Equals("safepay"))
{
string resultStatus = "";
try
{
Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
{
AlipaySDKBinding.AlipaySDK.DefaultService.ProcessOrderWithPaymentResult(url,
new AlipaySDKBinding.CompletionBlock(aa =>
{
try
{
string result = System.Web.HttpUtility.UrlDecode(url.ToString());
string[] lists = result.Split("?"); //分解獲取?後面的內容
Xamarin.AppFramework.AliResponse user = (Xamarin.AppFramework.AliResponse)Newtonsoft.Json.JsonConvert.DeserializeObject(lists[1], typeof(Xamarin.AppFramework.AliResponse));
resultStatus = user.memo.ResultStatus;
}
catch (Exception ex)
{
BTProgressHUD.ShowToast("支付失敗", true, 2000);
Xamarin.AppFramework.AliInfo.am_支付結果.OnCancel(null, "支付寶支付");
}
}));
////如果支付失敗
if (!resultStatus.Equals("9000"))
{
BTProgressHUD.ShowToast("支付失敗", true, 2000);
Xamarin.AppFramework.AliInfo.am_支付結果.OnCancel(null, "支付寶支付");
}
else
{
BTProgressHUD.ShowToast("支付成功", true, 2000);
//如果支付成功
Xamarin.AppFramework.AliInfo.am_支付結果.OnCompletion(null, "支付寶支付");
}
});
}
catch (Exception ex)
{
return false;
}
}
return true;
}
}
}