提示信息
# 同伴 App — 微信 SDK + 支付宝 SDK 接入
> 微信:登录 + 分享 + 支付 | 支付宝:App 支付
---
## 一、微信 SDK(WechatOpenSDK-XCFramework)
### 1.1 配置参数
| 参数 | 值 |
|------|-----|
| App ID | `wx146a6f748a99a0da` |
| Universal Link | `https://www.tongban.wang/app/` |
| Pod | `WechatOpenSDK-XCFramework`, `~> 2.0` |
### 1.2 Info.plist 配置
```xml
<!-- URL Schemes -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>wx146a6f748a99a0da</string>
</array>
<key>CFBundleURLName</key>
<string>weixin</string>
</dict>
</array>
<!-- LSApplicationQueriesSchemes -->
<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
<string>wechat</string>
<string>weixinULAPI</string>
</array>
```
### 1.3 Associated Domains
Xcode → Signing & Capabilities → Associated Domains:
```
applinks:www.tongban.wang
```
### 1.4 SDK 注册(AppDelegate)
```swift
import WechatOpenSDK
// didFinishLaunchingWithOptions 中注册
WXApi.registerApp(
AppConfig.wechatAppId,
universalLink: AppConfig.wechatUniversalLink
)
```
### 1.5 处理回调
```swift
// AppDelegate 或 SceneDelegate
func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
if url.scheme == AppConfig.wechatAppId {
return WXApi.handleOpen(url, delegate: WechatManager.shared)
}
return false
}
// Universal Link 回调
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
return WXApi.handleOpenUniversalLink(userActivity, delegate: WechatManager.shared)
}
```
### 1.6 微信登录
```swift
// WechatManager.swift
final class WechatManager: NSObject {
static let shared = WechatManager()
private var loginContinuation: CheckedContinuation<String, Error>?
/// 发起微信授权登录,返回 code
func requestLogin() async throws -> String {
guard WXApi.isWXAppInstalled() else {
throw AppAPIError(code: -1, message: "未安装微信")
}
return try await withCheckedThrowingContinuation { continuation in
self.loginContinuation = continuation
let req = SendAuthReq()
req.scope = "snsapi_userinfo"
req.state = UUID().uuidString
WXApi.send(req)
}
}
}
extension WechatManager: WXApiDelegate {
func onResp(_ resp: BaseResp) {
if let authResp = resp as? SendAuthResp {
if authResp.errCode == 0, let code = authResp.code {
loginContinuation?.resume(returning: code)
} else {
loginContinuation?.resume(throwing: AppAPIError(
code: Int(authResp.errCode),
message: authResp.errStr ?? "微信授权失败"
))
}
loginContinuation = nil
}
}
}
```
### 1.7 微信支付
```swift
extension WechatManager {
/// 发起微信支付
/// 参数从服务端 /pay/wechat/create 接口返回
func pay(
partnerId: String,
prepayId: String,
nonceStr: String,
timeStamp: UInt32,
package: String,
sign: String
) async throws {
return try await withCheckedThrowingContinuation { continuation in
let req = PayReq()
req.partnerId = partnerId
req.prepayId = prepayId
req.nonceStr = nonceStr
req.timeStamp = timeStamp
req.package = package
req.sign = sign
// 存储 continuation 并发送请求
self.payContinuation = continuation
WXApi.send(req)
}
}
}
```
---
## 二、支付宝 SDK(AlipaySDK_No_UTDID)
### 2.1 配置参数
| 参数 | 值 |
|------|-----|
| URL Scheme | `tongban` |
| Pod | `AlipaySDK_No_UTDID`(避免 UTDID 冲突) |
### 2.2 Info.plist 配置
```xml
<!-- URL Schemes -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>tongban</string>
</array>
<key>CFBundleURLName</key>
<string>alipay</string>
</dict>
</array>
<!-- LSApplicationQueriesSchemes -->
<key>LSApplicationQueriesSchemes</key>
<array>
<string>alipay</string>
<string>alipays</string>
</array>
```
### 2.3 发起支付
```swift
// PaymentAdapter.swift
import AlipaySDK
enum PaymentAdapter {
/// 支付宝 App 支付
/// orderString 由服务端 /pay/alipay/create 接口返回(已签名)
static func alipay(orderString: String) async throws {
return try await withCheckedThrowingContinuation { continuation in
AlipaySDK.defaultService().payOrder(
orderString,
fromScheme: "tongban"
) { result in
guard let dict = result as? [String: Any],
let status = dict["resultStatus"] as? String else {
continuation.resume(throwing: AppAPIError(code: -1, message: "支付宝返回异常"))
return
}
switch status {
case "9000": // 支付成功
continuation.resume()
case "6001": // 用户取消
continuation.resume(throwing: AppAPIError(code: 6001, message: "用户取消支付"))
case "4000": // 支付失败
continuation.resume(throwing: AppAPIError(code: 4000, message: "支付失败"))
default:
let msg = dict["memo"] as? String ?? "支付异常"
continuation.resume(throwing: AppAPIError(code: Int(status) ?? -1, message: msg))
}
}
}
}
}
```
### 2.4 处理回调
```swift
// AppDelegate 或 SceneDelegate
func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
if url.scheme == "tongban" {
AlipaySDK.defaultService().processOrder(
withPaymentResult: url
) { result in
// 支付结果已在 payOrder 回调中处理
}
return true
}
return false
}
```
### 2.5 支付宝结果状态码
| resultStatus | 含义 |
|--------------|------|
| `9000` | 支付成功 |
| `8000` | 正在处理中(支付结果未知,需查询) |
| `4000` | 支付失败 |
| `5000` | 重复请求 |
| `6001` | 用户取消 |
| `6002` | 网络连接出错 |
| `6004` | 支付结果未知(需查询) |
---
## 三、统一支付入口
```swift
// PaymentAdapter.swift — 统一支付入口
extension PaymentAdapter {
enum PaymentMethod {
case wechat
case alipay
}
/// 统一支付入口
/// 1. 调用服务端创建订单
/// 2. 根据支付方式调用对应 SDK
static func pay(
orderId: String,
method: PaymentMethod
) async throws {
switch method {
case .wechat:
// 服务端返回微信支付参数
let params: [String: Any] = try await APIClient.shared.post(
"/pay/wechat/create",
body: ["order_id": orderId]
)
try await WechatManager.shared.pay(
partnerId: params["partnerId"] as? String ?? "",
prepayId: params["prepayId"] as? String ?? "",
nonceStr: params["nonceStr"] as? String ?? "",
timeStamp: params["timeStamp"] as? UInt32 ?? 0,
package: params["package"] as? String ?? "",
sign: params["sign"] as? String ?? ""
)
case .alipay:
// 服务端返回支付宝签名字符串
let result: [String: Any] = try await APIClient.shared.post(
"/pay/alipay/create",
body: ["order_id": orderId]
)
let orderString = result["order_string"] as? String ?? ""
try await alipay(orderString: orderString)
}
}
}
```